Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Pinctrl based I2C DeMultiplexer
0004  *
0005  * Copyright (C) 2015-16 by Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
0006  * Copyright (C) 2015-16 by Renesas Electronics Corporation
0007  *
0008  * See the bindings doc for DTS setup and the sysfs doc for usage information.
0009  * (look for filenames containing 'i2c-demux-pinctrl' in Documentation/)
0010  */
0011 
0012 #include <linux/i2c.h>
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/pinctrl/consumer.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/slab.h>
0020 #include <linux/sysfs.h>
0021 
0022 struct i2c_demux_pinctrl_chan {
0023     struct device_node *parent_np;
0024     struct i2c_adapter *parent_adap;
0025     struct of_changeset chgset;
0026 };
0027 
0028 struct i2c_demux_pinctrl_priv {
0029     int cur_chan;
0030     int num_chan;
0031     struct device *dev;
0032     const char *bus_name;
0033     struct i2c_adapter cur_adap;
0034     struct i2c_algorithm algo;
0035     struct i2c_demux_pinctrl_chan chan[];
0036 };
0037 
0038 static int i2c_demux_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
0039 {
0040     struct i2c_demux_pinctrl_priv *priv = adap->algo_data;
0041     struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap;
0042 
0043     return __i2c_transfer(parent, msgs, num);
0044 }
0045 
0046 static u32 i2c_demux_functionality(struct i2c_adapter *adap)
0047 {
0048     struct i2c_demux_pinctrl_priv *priv = adap->algo_data;
0049     struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap;
0050 
0051     return parent->algo->functionality(parent);
0052 }
0053 
0054 static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan)
0055 {
0056     struct i2c_adapter *adap;
0057     struct pinctrl *p;
0058     int ret;
0059 
0060     ret = of_changeset_apply(&priv->chan[new_chan].chgset);
0061     if (ret)
0062         goto err;
0063 
0064     adap = of_find_i2c_adapter_by_node(priv->chan[new_chan].parent_np);
0065     if (!adap) {
0066         ret = -ENODEV;
0067         goto err_with_revert;
0068     }
0069 
0070     /*
0071      * Check if there are pinctrl states at all. Note: we cant' use
0072      * devm_pinctrl_get_select() because we need to distinguish between
0073      * the -ENODEV from devm_pinctrl_get() and pinctrl_lookup_state().
0074      */
0075     p = devm_pinctrl_get(adap->dev.parent);
0076     if (IS_ERR(p)) {
0077         ret = PTR_ERR(p);
0078         /* continue if just no pinctrl states (e.g. i2c-gpio), otherwise exit */
0079         if (ret != -ENODEV)
0080             goto err_with_put;
0081     } else {
0082         /* there are states. check and use them */
0083         struct pinctrl_state *s = pinctrl_lookup_state(p, priv->bus_name);
0084 
0085         if (IS_ERR(s)) {
0086             ret = PTR_ERR(s);
0087             goto err_with_put;
0088         }
0089         ret = pinctrl_select_state(p, s);
0090         if (ret < 0)
0091             goto err_with_put;
0092     }
0093 
0094     priv->chan[new_chan].parent_adap = adap;
0095     priv->cur_chan = new_chan;
0096 
0097     /* Now fill out current adapter structure. cur_chan must be up to date */
0098     priv->algo.master_xfer = i2c_demux_master_xfer;
0099     if (adap->algo->master_xfer_atomic)
0100         priv->algo.master_xfer_atomic = i2c_demux_master_xfer;
0101     priv->algo.functionality = i2c_demux_functionality;
0102 
0103     snprintf(priv->cur_adap.name, sizeof(priv->cur_adap.name),
0104          "i2c-demux (master i2c-%d)", i2c_adapter_id(adap));
0105     priv->cur_adap.owner = THIS_MODULE;
0106     priv->cur_adap.algo = &priv->algo;
0107     priv->cur_adap.algo_data = priv;
0108     priv->cur_adap.dev.parent = &adap->dev;
0109     priv->cur_adap.class = adap->class;
0110     priv->cur_adap.retries = adap->retries;
0111     priv->cur_adap.timeout = adap->timeout;
0112     priv->cur_adap.quirks = adap->quirks;
0113     priv->cur_adap.dev.of_node = priv->dev->of_node;
0114     ret = i2c_add_adapter(&priv->cur_adap);
0115     if (ret < 0)
0116         goto err_with_put;
0117 
0118     return 0;
0119 
0120  err_with_put:
0121     i2c_put_adapter(adap);
0122  err_with_revert:
0123     of_changeset_revert(&priv->chan[new_chan].chgset);
0124  err:
0125     dev_err(priv->dev, "failed to setup demux-adapter %d (%d)\n", new_chan, ret);
0126     priv->cur_chan = -EINVAL;
0127     return ret;
0128 }
0129 
0130 static int i2c_demux_deactivate_master(struct i2c_demux_pinctrl_priv *priv)
0131 {
0132     int ret, cur = priv->cur_chan;
0133 
0134     if (cur < 0)
0135         return 0;
0136 
0137     i2c_del_adapter(&priv->cur_adap);
0138     i2c_put_adapter(priv->chan[cur].parent_adap);
0139 
0140     ret = of_changeset_revert(&priv->chan[cur].chgset);
0141 
0142     priv->chan[cur].parent_adap = NULL;
0143     priv->cur_chan = -EINVAL;
0144 
0145     return ret;
0146 }
0147 
0148 static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan)
0149 {
0150     int ret;
0151 
0152     if (new_chan == priv->cur_chan)
0153         return 0;
0154 
0155     ret = i2c_demux_deactivate_master(priv);
0156     if (ret)
0157         return ret;
0158 
0159     return i2c_demux_activate_master(priv, new_chan);
0160 }
0161 
0162 static ssize_t available_masters_show(struct device *dev,
0163                       struct device_attribute *attr,
0164                       char *buf)
0165 {
0166     struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
0167     int count = 0, i;
0168 
0169     for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++)
0170         count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%pOF%c",
0171                    i, priv->chan[i].parent_np,
0172                    i == priv->num_chan - 1 ? '\n' : ' ');
0173 
0174     return count;
0175 }
0176 static DEVICE_ATTR_RO(available_masters);
0177 
0178 static ssize_t current_master_show(struct device *dev,
0179                    struct device_attribute *attr,
0180                    char *buf)
0181 {
0182     struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
0183 
0184     return sprintf(buf, "%d\n", priv->cur_chan);
0185 }
0186 
0187 static ssize_t current_master_store(struct device *dev,
0188                     struct device_attribute *attr,
0189                     const char *buf, size_t count)
0190 {
0191     struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
0192     unsigned int val;
0193     int ret;
0194 
0195     ret = kstrtouint(buf, 0, &val);
0196     if (ret < 0)
0197         return ret;
0198 
0199     if (val >= priv->num_chan)
0200         return -EINVAL;
0201 
0202     ret = i2c_demux_change_master(priv, val);
0203 
0204     return ret < 0 ? ret : count;
0205 }
0206 static DEVICE_ATTR_RW(current_master);
0207 
0208 static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
0209 {
0210     struct device_node *np = pdev->dev.of_node;
0211     struct i2c_demux_pinctrl_priv *priv;
0212     struct property *props;
0213     int num_chan, i, j, err;
0214 
0215     num_chan = of_count_phandle_with_args(np, "i2c-parent", NULL);
0216     if (num_chan < 2) {
0217         dev_err(&pdev->dev, "Need at least two I2C masters to switch\n");
0218         return -EINVAL;
0219     }
0220 
0221     priv = devm_kzalloc(&pdev->dev, struct_size(priv, chan, num_chan),
0222                 GFP_KERNEL);
0223 
0224     props = devm_kcalloc(&pdev->dev, num_chan, sizeof(*props), GFP_KERNEL);
0225 
0226     if (!priv || !props)
0227         return -ENOMEM;
0228 
0229     err = of_property_read_string(np, "i2c-bus-name", &priv->bus_name);
0230     if (err)
0231         return err;
0232 
0233     for (i = 0; i < num_chan; i++) {
0234         struct device_node *adap_np;
0235 
0236         adap_np = of_parse_phandle(np, "i2c-parent", i);
0237         if (!adap_np) {
0238             dev_err(&pdev->dev, "can't get phandle for parent %d\n", i);
0239             err = -ENOENT;
0240             goto err_rollback;
0241         }
0242         priv->chan[i].parent_np = adap_np;
0243 
0244         props[i].name = devm_kstrdup(&pdev->dev, "status", GFP_KERNEL);
0245         props[i].value = devm_kstrdup(&pdev->dev, "ok", GFP_KERNEL);
0246         props[i].length = 3;
0247 
0248         of_changeset_init(&priv->chan[i].chgset);
0249         of_changeset_update_property(&priv->chan[i].chgset, adap_np, &props[i]);
0250     }
0251 
0252     priv->num_chan = num_chan;
0253     priv->dev = &pdev->dev;
0254 
0255     platform_set_drvdata(pdev, priv);
0256 
0257     pm_runtime_no_callbacks(&pdev->dev);
0258 
0259     /* switch to first parent as active master */
0260     i2c_demux_activate_master(priv, 0);
0261 
0262     err = device_create_file(&pdev->dev, &dev_attr_available_masters);
0263     if (err)
0264         goto err_rollback_activation;
0265 
0266     err = device_create_file(&pdev->dev, &dev_attr_current_master);
0267     if (err)
0268         goto err_rollback_available;
0269 
0270     return 0;
0271 
0272 err_rollback_available:
0273     device_remove_file(&pdev->dev, &dev_attr_available_masters);
0274 err_rollback_activation:
0275     i2c_demux_deactivate_master(priv);
0276 err_rollback:
0277     for (j = 0; j < i; j++) {
0278         of_node_put(priv->chan[j].parent_np);
0279         of_changeset_destroy(&priv->chan[j].chgset);
0280     }
0281 
0282     return err;
0283 }
0284 
0285 static int i2c_demux_pinctrl_remove(struct platform_device *pdev)
0286 {
0287     struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev);
0288     int i;
0289 
0290     device_remove_file(&pdev->dev, &dev_attr_current_master);
0291     device_remove_file(&pdev->dev, &dev_attr_available_masters);
0292 
0293     i2c_demux_deactivate_master(priv);
0294 
0295     for (i = 0; i < priv->num_chan; i++) {
0296         of_node_put(priv->chan[i].parent_np);
0297         of_changeset_destroy(&priv->chan[i].chgset);
0298     }
0299 
0300     return 0;
0301 }
0302 
0303 static const struct of_device_id i2c_demux_pinctrl_of_match[] = {
0304     { .compatible = "i2c-demux-pinctrl", },
0305     {},
0306 };
0307 MODULE_DEVICE_TABLE(of, i2c_demux_pinctrl_of_match);
0308 
0309 static struct platform_driver i2c_demux_pinctrl_driver = {
0310     .driver = {
0311         .name = "i2c-demux-pinctrl",
0312         .of_match_table = i2c_demux_pinctrl_of_match,
0313     },
0314     .probe  = i2c_demux_pinctrl_probe,
0315     .remove = i2c_demux_pinctrl_remove,
0316 };
0317 module_platform_driver(i2c_demux_pinctrl_driver);
0318 
0319 MODULE_DESCRIPTION("pinctrl-based I2C demux driver");
0320 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
0321 MODULE_LICENSE("GPL v2");
0322 MODULE_ALIAS("platform:i2c-demux-pinctrl");