318 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Linear Technology LTC4306 and LTC4305 I2C multiplexer/switch4 *5 * Copyright (C) 2017 Analog Devices Inc.6 *7 * Based on: i2c-mux-pca954x.c8 *9 * Datasheet: http://cds.linear.com/docs/en/datasheet/4306.pdf10 */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 223#define LTC4306_MAX_NCHANS 424 25#define LTC_REG_STATUS 0x026#define LTC_REG_CONFIG 0x127#define LTC_REG_MODE 0x228#define LTC_REG_SWITCH 0x329 30#define LTC_DOWNSTREAM_ACCL_EN BIT(6)31#define LTC_UPSTREAM_ACCL_EN BIT(7)32 33#define LTC_GPIO_ALL_INPUT 0xC034#define LTC_SWITCH_MASK 0xF035 36enum ltc_type {37 ltc_4305,38 ltc_4306,39};40 41struct chip_desc {42 u8 nchans;43 u8 num_gpios;44};45 46struct ltc4306 {47 struct regmap *regmap;48 struct gpio_chip gpiochip;49 const struct chip_desc *chip;50};51 52static 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 62static bool ltc4306_is_volatile_reg(struct device *dev, unsigned int reg)63{64 return reg == LTC_REG_CONFIG;65}66 67static 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 75static 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 88static 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 97static 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 111static 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 120static 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 130static 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 151static 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 177static 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 185static 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 193static const struct i2c_device_id ltc4306_id[] = {194 { "ltc4305", ltc_4305 },195 { "ltc4306", ltc_4306 },196 { }197};198MODULE_DEVICE_TABLE(i2c, ltc4306_id);199 200static 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};205MODULE_DEVICE_TABLE(of, ltc4306_of_match);206 207static 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 verify257 * that the mux is in fact present. This also258 * 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 296static 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 303static 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 313module_i2c_driver(ltc4306_driver);314 315MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");316MODULE_DESCRIPTION("Linear Technology LTC4306, LTC4305 I2C mux/switch driver");317MODULE_LICENSE("GPL v2");318