1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Analog Devices LTC4283 GPIO driver 4 * 5 * Copyright 2025 Analog Devices Inc. 6 */ 7 8 #include <linux/auxiliary_bus.h> 9 #include <linux/bitfield.h> 10 #include <linux/bitmap.h> 11 #include <linux/bits.h> 12 #include <linux/device.h> 13 #include <linux/gpio/driver.h> 14 #include <linux/mod_devicetable.h> 15 #include <linux/module.h> 16 #include <linux/regmap.h> 17 18 #define LTC4283_PINS_MAX 8 19 #define LTC4283_PGIOX_START_NR 4 20 #define LTC4283_INPUT_STATUS 0x02 21 #define LTC4283_PGIO_CONFIG 0x10 22 #define LTC4283_PGIO_CFG_MASK(pin) \ 23 GENMASK(((pin) - LTC4283_PGIOX_START_NR) * 2 + 1, (((pin) - LTC4283_PGIOX_START_NR) * 2)) 24 #define LTC4283_PGIO_CONFIG_2 0x11 25 26 #define LTC4283_ADIO_CONFIG 0x12 27 /* starts at bit 4 */ 28 #define LTC4283_ADIOX_CONFIG_MASK(pin) BIT((pin) + 4) 29 #define LTC4283_PGIO_DIR_IN 3 30 #define LTC4283_PGIO_DIR_OUT 2 31 32 struct ltc4283_gpio { 33 struct gpio_chip gpio_chip; 34 struct regmap *regmap; 35 }; 36 37 static int ltc4283_pgio_get_direction(const struct ltc4283_gpio *st, unsigned int off) 38 { 39 unsigned int val; 40 int ret; 41 42 ret = regmap_read(st->regmap, LTC4283_PGIO_CONFIG, &val); 43 if (ret) 44 return ret; 45 46 val = field_get(LTC4283_PGIO_CFG_MASK(off), val); 47 if (val == LTC4283_PGIO_DIR_IN) 48 return GPIO_LINE_DIRECTION_IN; 49 50 return GPIO_LINE_DIRECTION_OUT; 51 } 52 53 static int ltc4283_gpio_get_direction(struct gpio_chip *gc, unsigned int off) 54 { 55 struct ltc4283_gpio *st = gpiochip_get_data(gc); 56 unsigned int val; 57 int ret; 58 59 if (off >= LTC4283_PGIOX_START_NR) 60 return ltc4283_pgio_get_direction(st, off); 61 62 ret = regmap_read(st->regmap, LTC4283_ADIO_CONFIG, &val); 63 if (ret) 64 return ret; 65 66 if (val & LTC4283_ADIOX_CONFIG_MASK(off)) 67 return GPIO_LINE_DIRECTION_IN; 68 69 return GPIO_LINE_DIRECTION_OUT; 70 } 71 72 static int ltc4283_gpio_direction_set(const struct ltc4283_gpio *st, 73 unsigned int off, bool input) 74 { 75 if (off >= LTC4283_PGIOX_START_NR) { 76 unsigned int val = LTC4283_PGIO_DIR_OUT; 77 78 if (input) 79 val = LTC4283_PGIO_DIR_IN; 80 81 val = field_prep(LTC4283_PGIO_CFG_MASK(off), val); 82 return regmap_update_bits(st->regmap, LTC4283_PGIO_CONFIG, 83 LTC4283_PGIO_CFG_MASK(off), val); 84 } 85 86 return regmap_update_bits(st->regmap, LTC4283_ADIO_CONFIG, 87 LTC4283_ADIOX_CONFIG_MASK(off), 88 field_prep(LTC4283_ADIOX_CONFIG_MASK(off), input)); 89 } 90 91 static int __ltc4283_gpio_set_value(const struct ltc4283_gpio *st, 92 unsigned int off, int val) 93 { 94 u32 reg = off < LTC4283_PGIOX_START_NR ? LTC4283_ADIO_CONFIG : LTC4283_PGIO_CONFIG_2; 95 96 return regmap_update_bits(st->regmap, reg, BIT(off), 97 field_prep(BIT(off), !!val)); 98 } 99 100 static int ltc4283_gpio_direction_input(struct gpio_chip *gc, unsigned int off) 101 { 102 struct ltc4283_gpio *st = gpiochip_get_data(gc); 103 104 return ltc4283_gpio_direction_set(st, off, true); 105 } 106 107 static int ltc4283_gpio_direction_output(struct gpio_chip *gc, unsigned int off, int val) 108 { 109 struct ltc4283_gpio *st = gpiochip_get_data(gc); 110 int ret; 111 112 ret = ltc4283_gpio_direction_set(st, off, false); 113 if (ret) 114 return ret; 115 116 return __ltc4283_gpio_set_value(st, off, val); 117 } 118 119 static int ltc4283_gpio_get_value(struct gpio_chip *gc, unsigned int off) 120 { 121 struct ltc4283_gpio *st = gpiochip_get_data(gc); 122 unsigned int val, reg; 123 int ret, dir; 124 125 dir = ltc4283_gpio_get_direction(gc, off); 126 if (dir < 0) 127 return dir; 128 129 if (dir == GPIO_LINE_DIRECTION_IN) { 130 ret = regmap_read(st->regmap, LTC4283_INPUT_STATUS, &val); 131 if (ret) 132 return ret; 133 134 /* ADIO1 is at bit 3. */ 135 if (off < LTC4283_PGIOX_START_NR) 136 return !!(val & BIT(3 - off)); 137 138 /* PGIO1 is at bit 7. */ 139 return !!(val & BIT(7 - (off - LTC4283_PGIOX_START_NR))); 140 } 141 142 if (off < LTC4283_PGIOX_START_NR) 143 reg = LTC4283_ADIO_CONFIG; 144 else 145 reg = LTC4283_PGIO_CONFIG_2; 146 147 ret = regmap_read(st->regmap, reg, &val); 148 if (ret) 149 return ret; 150 151 return !!(val & BIT(off)); 152 } 153 154 static int ltc4283_gpio_set_value(struct gpio_chip *gc, unsigned int off, int val) 155 { 156 struct ltc4283_gpio *st = gpiochip_get_data(gc); 157 158 return __ltc4283_gpio_set_value(st, off, val); 159 } 160 161 static int ltc4283_init_valid_mask(struct gpio_chip *gc, unsigned long *valid_mask, 162 unsigned int ngpios) 163 { 164 unsigned long *mask = dev_get_platdata(gc->parent); 165 166 bitmap_copy(valid_mask, mask, ngpios); 167 return 0; 168 } 169 170 static int ltc4283_gpio_probe(struct auxiliary_device *adev, 171 const struct auxiliary_device_id *id) 172 { 173 struct device *dev = &adev->dev; 174 struct ltc4283_gpio *st; 175 struct gpio_chip *gc; 176 177 st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); 178 if (!st) 179 return -ENOMEM; 180 181 st->regmap = dev_get_regmap(dev->parent, NULL); 182 if (!st->regmap) 183 return dev_err_probe(dev, -ENODEV, 184 "Failed to get regmap\n"); 185 186 gc = &st->gpio_chip; 187 gc->parent = dev; 188 gc->get_direction = ltc4283_gpio_get_direction; 189 gc->direction_input = ltc4283_gpio_direction_input; 190 gc->direction_output = ltc4283_gpio_direction_output; 191 gc->get = ltc4283_gpio_get_value; 192 gc->set = ltc4283_gpio_set_value; 193 gc->init_valid_mask = ltc4283_init_valid_mask; 194 gc->can_sleep = true; 195 196 gc->base = -1; 197 gc->ngpio = LTC4283_PINS_MAX; 198 gc->label = adev->name; 199 gc->owner = THIS_MODULE; 200 201 return devm_gpiochip_add_data(dev, &st->gpio_chip, st); 202 } 203 204 static const struct auxiliary_device_id ltc4283_aux_id_table[] = { 205 { "ltc4283.gpio" }, 206 { } 207 }; 208 MODULE_DEVICE_TABLE(auxiliary, ltc4283_aux_id_table); 209 210 static struct auxiliary_driver ltc4283_gpio_driver = { 211 .probe = ltc4283_gpio_probe, 212 .id_table = ltc4283_aux_id_table, 213 }; 214 module_auxiliary_driver(ltc4283_gpio_driver); 215 216 MODULE_AUTHOR("Nuno Sá <nuno.sa@analog.com>"); 217 MODULE_DESCRIPTION("GPIO LTC4283 Driver"); 218 MODULE_LICENSE("GPL"); 219