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