root/drivers/i2c/muxes/i2c-mux-ltc4306.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ltc4306_is_volatile_reg
  2. ltc4306_gpio_get
  3. ltc4306_gpio_set
  4. ltc4306_gpio_get_direction
  5. ltc4306_gpio_direction_input
  6. ltc4306_gpio_direction_output
  7. ltc4306_gpio_set_config
  8. ltc4306_gpio_init
  9. ltc4306_select_mux
  10. ltc4306_deselect_mux
  11. ltc4306_probe
  12. ltc4306_remove

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

/* [<][>][^][v][top][bottom][index][help] */