1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Linear Technology LTC4306 and LTC4305 I2C multiplexer/switch 4 * 5 * Copyright (C) 2017 Analog Devices Inc. 6 * 7 * Based on: i2c-mux-pca954x.c 8 * 9 * Datasheet: http://cds.linear.com/docs/en/datasheet/4306.pdf 10 */ 11 12 #include <linux/gpio/consumer.h> 13 #include <linux/gpio/driver.h> 14 #include <linux/i2c-mux.h> 15 #include <linux/i2c.h> 16 #include <linux/module.h> 17 #include <linux/of.h> 18 #include <linux/property.h> 19 #include <linux/regmap.h> 20 #include <linux/slab.h> 21 22 #define LTC4305_MAX_NCHANS 2 23 #define LTC4306_MAX_NCHANS 4 24 25 #define LTC_REG_STATUS 0x0 26 #define LTC_REG_CONFIG 0x1 27 #define LTC_REG_MODE 0x2 28 #define LTC_REG_SWITCH 0x3 29 30 #define LTC_DOWNSTREAM_ACCL_EN BIT(6) 31 #define LTC_UPSTREAM_ACCL_EN BIT(7) 32 33 #define LTC_GPIO_ALL_INPUT 0xC0 34 #define LTC_SWITCH_MASK 0xF0 35 36 enum ltc_type { 37 ltc_4305, 38 ltc_4306, 39 }; 40 41 struct chip_desc { 42 u8 nchans; 43 u8 num_gpios; 44 }; 45 46 struct ltc4306 { 47 struct regmap *regmap; 48 struct gpio_chip gpiochip; 49 const struct chip_desc *chip; 50 }; 51 52 static const struct chip_desc chips[] = { 53 [ltc_4305] = { 54 .nchans = LTC4305_MAX_NCHANS, 55 }, 56 [ltc_4306] = { 57 .nchans = LTC4306_MAX_NCHANS, 58 .num_gpios = 2, 59 }, 60 }; 61 62 static bool ltc4306_is_volatile_reg(struct device *dev, unsigned int reg) 63 { 64 return reg == LTC_REG_CONFIG; 65 } 66 67 static const struct regmap_config ltc4306_regmap_config = { 68 .reg_bits = 8, 69 .val_bits = 8, 70 .max_register = LTC_REG_SWITCH, 71 .volatile_reg = ltc4306_is_volatile_reg, 72 .cache_type = REGCACHE_FLAT, 73 }; 74 75 static int ltc4306_gpio_get(struct gpio_chip *chip, unsigned int offset) 76 { 77 struct ltc4306 *data = gpiochip_get_data(chip); 78 unsigned int val; 79 int ret; 80 81 ret = regmap_read(data->regmap, LTC_REG_CONFIG, &val); 82 if (ret < 0) 83 return ret; 84 85 return !!(val & BIT(1 - offset)); 86 } 87 88 static void ltc4306_gpio_set(struct gpio_chip *chip, unsigned int offset, 89 int value) 90 { 91 struct ltc4306 *data = gpiochip_get_data(chip); 92 93 regmap_update_bits(data->regmap, LTC_REG_CONFIG, BIT(5 - offset), 94 value ? BIT(5 - offset) : 0); 95 } 96 97 static int ltc4306_gpio_get_direction(struct gpio_chip *chip, 98 unsigned int offset) 99 { 100 struct ltc4306 *data = gpiochip_get_data(chip); 101 unsigned int val; 102 int ret; 103 104 ret = regmap_read(data->regmap, LTC_REG_MODE, &val); 105 if (ret < 0) 106 return ret; 107 108 return !!(val & BIT(7 - offset)); 109 } 110 111 static int ltc4306_gpio_direction_input(struct gpio_chip *chip, 112 unsigned int offset) 113 { 114 struct ltc4306 *data = gpiochip_get_data(chip); 115 116 return regmap_update_bits(data->regmap, LTC_REG_MODE, 117 BIT(7 - offset), BIT(7 - offset)); 118 } 119 120 static int ltc4306_gpio_direction_output(struct gpio_chip *chip, 121 unsigned int offset, int value) 122 { 123 struct ltc4306 *data = gpiochip_get_data(chip); 124 125 ltc4306_gpio_set(chip, offset, value); 126 return regmap_update_bits(data->regmap, LTC_REG_MODE, 127 BIT(7 - offset), 0); 128 } 129 130 static int ltc4306_gpio_set_config(struct gpio_chip *chip, 131 unsigned int offset, unsigned long config) 132 { 133 struct ltc4306 *data = gpiochip_get_data(chip); 134 unsigned int val; 135 136 switch (pinconf_to_config_param(config)) { 137 case PIN_CONFIG_DRIVE_OPEN_DRAIN: 138 val = 0; 139 break; 140 case PIN_CONFIG_DRIVE_PUSH_PULL: 141 val = BIT(4 - offset); 142 break; 143 default: 144 return -ENOTSUPP; 145 } 146 147 return regmap_update_bits(data->regmap, LTC_REG_MODE, 148 BIT(4 - offset), val); 149 } 150 151 static int ltc4306_gpio_init(struct ltc4306 *data) 152 { 153 struct device *dev = regmap_get_device(data->regmap); 154 155 if (!data->chip->num_gpios) 156 return 0; 157 158 data->gpiochip.label = dev_name(dev); 159 data->gpiochip.base = -1; 160 data->gpiochip.ngpio = data->chip->num_gpios; 161 data->gpiochip.parent = dev; 162 data->gpiochip.can_sleep = true; 163 data->gpiochip.get_direction = ltc4306_gpio_get_direction; 164 data->gpiochip.direction_input = ltc4306_gpio_direction_input; 165 data->gpiochip.direction_output = ltc4306_gpio_direction_output; 166 data->gpiochip.get = ltc4306_gpio_get; 167 data->gpiochip.set = ltc4306_gpio_set; 168 data->gpiochip.set_config = ltc4306_gpio_set_config; 169 data->gpiochip.owner = THIS_MODULE; 170 171 /* gpiolib assumes all GPIOs default input */ 172 regmap_write(data->regmap, LTC_REG_MODE, LTC_GPIO_ALL_INPUT); 173 174 return devm_gpiochip_add_data(dev, &data->gpiochip, data); 175 } 176 177 static int ltc4306_select_mux(struct i2c_mux_core *muxc, u32 chan) 178 { 179 struct ltc4306 *data = i2c_mux_priv(muxc); 180 181 return regmap_update_bits(data->regmap, LTC_REG_SWITCH, 182 LTC_SWITCH_MASK, BIT(7 - chan)); 183 } 184 185 static int ltc4306_deselect_mux(struct i2c_mux_core *muxc, u32 chan) 186 { 187 struct ltc4306 *data = i2c_mux_priv(muxc); 188 189 return regmap_update_bits(data->regmap, LTC_REG_SWITCH, 190 LTC_SWITCH_MASK, 0); 191 } 192 193 static const struct i2c_device_id ltc4306_id[] = { 194 { "ltc4305", ltc_4305 }, 195 { "ltc4306", ltc_4306 }, 196 { } 197 }; 198 MODULE_DEVICE_TABLE(i2c, ltc4306_id); 199 200 static const struct of_device_id ltc4306_of_match[] = { 201 { .compatible = "lltc,ltc4305", .data = &chips[ltc_4305] }, 202 { .compatible = "lltc,ltc4306", .data = &chips[ltc_4306] }, 203 { } 204 }; 205 MODULE_DEVICE_TABLE(of, ltc4306_of_match); 206 207 static int ltc4306_probe(struct i2c_client *client) 208 { 209 struct i2c_adapter *adap = client->adapter; 210 const struct chip_desc *chip; 211 struct i2c_mux_core *muxc; 212 struct ltc4306 *data; 213 struct gpio_desc *gpio; 214 bool idle_disc; 215 unsigned int val = 0; 216 int num, ret; 217 218 chip = of_device_get_match_data(&client->dev); 219 220 if (!chip) 221 chip = &chips[i2c_match_id(ltc4306_id, client)->driver_data]; 222 223 idle_disc = device_property_read_bool(&client->dev, 224 "i2c-mux-idle-disconnect"); 225 226 muxc = i2c_mux_alloc(adap, &client->dev, 227 chip->nchans, sizeof(*data), 228 I2C_MUX_LOCKED, ltc4306_select_mux, 229 idle_disc ? ltc4306_deselect_mux : NULL); 230 if (!muxc) 231 return -ENOMEM; 232 data = i2c_mux_priv(muxc); 233 data->chip = chip; 234 235 i2c_set_clientdata(client, muxc); 236 237 data->regmap = devm_regmap_init_i2c(client, <c4306_regmap_config); 238 if (IS_ERR(data->regmap)) { 239 ret = PTR_ERR(data->regmap); 240 dev_err(&client->dev, "Failed to allocate register map: %d\n", 241 ret); 242 return ret; 243 } 244 245 /* Reset and enable the mux if an enable GPIO is specified. */ 246 gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); 247 if (IS_ERR(gpio)) 248 return PTR_ERR(gpio); 249 250 if (gpio) { 251 udelay(1); 252 gpiod_set_value(gpio, 1); 253 } 254 255 /* 256 * Write the mux register at addr to verify 257 * that the mux is in fact present. This also 258 * initializes the mux to disconnected state. 259 */ 260 if (regmap_write(data->regmap, LTC_REG_SWITCH, 0) < 0) { 261 dev_warn(&client->dev, "probe failed\n"); 262 return -ENODEV; 263 } 264 265 if (device_property_read_bool(&client->dev, 266 "ltc,downstream-accelerators-enable")) 267 val |= LTC_DOWNSTREAM_ACCL_EN; 268 269 if (device_property_read_bool(&client->dev, 270 "ltc,upstream-accelerators-enable")) 271 val |= LTC_UPSTREAM_ACCL_EN; 272 273 if (regmap_write(data->regmap, LTC_REG_CONFIG, val) < 0) 274 return -ENODEV; 275 276 ret = ltc4306_gpio_init(data); 277 if (ret < 0) 278 return ret; 279 280 /* Now create an adapter for each channel */ 281 for (num = 0; num < chip->nchans; num++) { 282 ret = i2c_mux_add_adapter(muxc, 0, num); 283 if (ret) { 284 i2c_mux_del_adapters(muxc); 285 return ret; 286 } 287 } 288 289 dev_info(&client->dev, 290 "registered %d multiplexed busses for I2C switch %s\n", 291 num, client->name); 292 293 return 0; 294 } 295 296 static void ltc4306_remove(struct i2c_client *client) 297 { 298 struct i2c_mux_core *muxc = i2c_get_clientdata(client); 299 300 i2c_mux_del_adapters(muxc); 301 } 302 303 static struct i2c_driver ltc4306_driver = { 304 .driver = { 305 .name = "ltc4306", 306 .of_match_table = of_match_ptr(ltc4306_of_match), 307 }, 308 .probe = ltc4306_probe, 309 .remove = ltc4306_remove, 310 .id_table = ltc4306_id, 311 }; 312 313 module_i2c_driver(ltc4306_driver); 314 315 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 316 MODULE_DESCRIPTION("Linear Technology LTC4306, LTC4305 I2C mux/switch driver"); 317 MODULE_LICENSE("GPL v2"); 318