linux/drivers/i2c/muxes/i2c-mux-ltc4306.c
<<
>>
Prefs
   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
  37enum ltc_type {
  38        ltc_4305,
  39        ltc_4306,
  40};
  41
  42struct chip_desc {
  43        u8 nchans;
  44        u8 num_gpios;
  45};
  46
  47struct ltc4306 {
  48        struct regmap *regmap;
  49        struct gpio_chip gpiochip;
  50        const struct chip_desc *chip;
  51};
  52
  53static 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
  63static bool ltc4306_is_volatile_reg(struct device *dev, unsigned int reg)
  64{
  65        return (reg == LTC_REG_CONFIG) ? true : false;
  66}
  67
  68static 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
  76static 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
  89static 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
  98static 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
 112static 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
 121static 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
 131static 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
 152static 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
 178static 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
 186static 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
 194static const struct i2c_device_id ltc4306_id[] = {
 195        { "ltc4305", ltc_4305 },
 196        { "ltc4306", ltc_4306 },
 197        { }
 198};
 199MODULE_DEVICE_TABLE(i2c, ltc4306_id);
 200
 201static 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};
 206MODULE_DEVICE_TABLE(of, ltc4306_of_match);
 207
 208static 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
 297static 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
 306static 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
 316module_i2c_driver(ltc4306_driver);
 317
 318MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
 319MODULE_DESCRIPTION("Linear Technology LTC4306, LTC4305 I2C mux/switch driver");
 320MODULE_LICENSE("GPL v2");
 321