Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: mpfs: add CoreGPIO support

coreGPIO, which the "hard" core in PolarFire SoC is based on, has
different offsets for inp/outp. Add some match_data handling to account
for the differences.

Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20241113-jovial-atlantic-cd07f05eb2e5@spud
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

authored by

Conor Dooley and committed by
Bartosz Golaszewski
65e93637 8bcbd037

+33 -5
+33 -5
drivers/gpio/gpio-mpfs.c
··· 12 12 #include <linux/init.h> 13 13 #include <linux/mod_devicetable.h> 14 14 #include <linux/platform_device.h> 15 + #include <linux/property.h> 15 16 #include <linux/regmap.h> 16 17 #include <linux/spinlock.h> 17 18 ··· 31 30 #define MPFS_GPIO_TYPE_INT_LEVEL_HIGH 0x00 32 31 #define MPFS_GPIO_TYPE_INT_MASK GENMASK(7, 5) 33 32 #define MPFS_IRQ_REG 0x80 33 + 34 34 #define MPFS_INP_REG 0x84 35 + #define COREGPIO_INP_REG 0x90 35 36 #define MPFS_OUTP_REG 0x88 37 + #define COREGPIO_OUTP_REG 0xA0 38 + 39 + struct mpfs_gpio_reg_offsets { 40 + u8 inp; 41 + u8 outp; 42 + }; 36 43 37 44 struct mpfs_gpio_chip { 38 45 struct regmap *regs; 46 + const struct mpfs_gpio_reg_offsets *offsets; 39 47 struct gpio_chip gc; 40 48 }; 41 49 ··· 70 60 71 61 regmap_update_bits(mpfs_gpio->regs, MPFS_GPIO_CTRL(gpio_index), 72 62 MPFS_GPIO_DIR_MASK, MPFS_GPIO_EN_IN); 73 - regmap_update_bits(mpfs_gpio->regs, MPFS_OUTP_REG, BIT(gpio_index), 63 + regmap_update_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, BIT(gpio_index), 74 64 value << gpio_index); 75 65 76 66 return 0; ··· 94 84 struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); 95 85 96 86 if (mpfs_gpio_get_direction(gc, gpio_index) == GPIO_LINE_DIRECTION_OUT) 97 - return regmap_test_bits(mpfs_gpio->regs, MPFS_OUTP_REG, BIT(gpio_index)); 87 + return regmap_test_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, BIT(gpio_index)); 98 88 else 99 - return regmap_test_bits(mpfs_gpio->regs, MPFS_INP_REG, BIT(gpio_index)); 89 + return regmap_test_bits(mpfs_gpio->regs, mpfs_gpio->offsets->inp, BIT(gpio_index)); 100 90 } 101 91 102 92 static void mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int value) ··· 105 95 106 96 mpfs_gpio_get(gc, gpio_index); 107 97 108 - regmap_update_bits(mpfs_gpio->regs, MPFS_OUTP_REG, BIT(gpio_index), 98 + regmap_update_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, BIT(gpio_index), 109 99 value << gpio_index); 110 100 111 101 mpfs_gpio_get(gc, gpio_index); ··· 122 112 mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL); 123 113 if (!mpfs_gpio) 124 114 return -ENOMEM; 115 + 116 + mpfs_gpio->offsets = device_get_match_data(&pdev->dev); 125 117 126 118 base = devm_platform_ioremap_resource(pdev, 0); 127 119 if (IS_ERR(base)) ··· 157 145 return devm_gpiochip_add_data(dev, &mpfs_gpio->gc, mpfs_gpio); 158 146 } 159 147 148 + static const struct mpfs_gpio_reg_offsets mpfs_reg_offsets = { 149 + .inp = MPFS_INP_REG, 150 + .outp = MPFS_OUTP_REG, 151 + }; 152 + 153 + static const struct mpfs_gpio_reg_offsets coregpio_reg_offsets = { 154 + .inp = COREGPIO_INP_REG, 155 + .outp = COREGPIO_OUTP_REG, 156 + }; 157 + 160 158 static const struct of_device_id mpfs_gpio_of_ids[] = { 161 - { .compatible = "microchip,mpfs-gpio", }, 159 + { 160 + .compatible = "microchip,mpfs-gpio", 161 + .data = &mpfs_reg_offsets, 162 + }, { 163 + .compatible = "microchip,coregpio-rtl-v3", 164 + .data = &coregpio_reg_offsets, 165 + }, 162 166 { /* end of list */ } 163 167 }; 164 168