1 /* 2 * Pinctrl based I2C DeMultiplexer 3 * 4 * Copyright (C) 2015-16 by Wolfram Sang, Sang Engineering <wsa@sang-engineering.com> 5 * Copyright (C) 2015-16 by Renesas Electronics Corporation 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; version 2 of the License. 10 * 11 * See the bindings doc for DTS setup and the sysfs doc for usage information. 12 * (look for filenames containing 'i2c-demux-pinctrl' in Documentation/) 13 */ 14 15 #include <linux/i2c.h> 16 #include <linux/init.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/pinctrl/consumer.h> 20 #include <linux/platform_device.h> 21 #include <linux/slab.h> 22 #include <linux/sysfs.h> 23 24 struct i2c_demux_pinctrl_chan { 25 struct device_node *parent_np; 26 struct i2c_adapter *parent_adap; 27 struct of_changeset chgset; 28 }; 29 30 struct i2c_demux_pinctrl_priv { 31 int cur_chan; 32 int num_chan; 33 struct device *dev; 34 const char *bus_name; 35 struct i2c_adapter cur_adap; 36 struct i2c_algorithm algo; 37 struct i2c_demux_pinctrl_chan chan[]; 38 }; 39 40 static int i2c_demux_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) 41 { 42 struct i2c_demux_pinctrl_priv *priv = adap->algo_data; 43 struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap; 44 45 return __i2c_transfer(parent, msgs, num); 46 } 47 48 static u32 i2c_demux_functionality(struct i2c_adapter *adap) 49 { 50 struct i2c_demux_pinctrl_priv *priv = adap->algo_data; 51 struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap; 52 53 return parent->algo->functionality(parent); 54 } 55 56 static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan) 57 { 58 struct i2c_adapter *adap; 59 struct pinctrl *p; 60 int ret; 61 62 ret = of_changeset_apply(&priv->chan[new_chan].chgset); 63 if (ret) 64 goto err; 65 66 adap = of_find_i2c_adapter_by_node(priv->chan[new_chan].parent_np); 67 if (!adap) { 68 ret = -ENODEV; 69 goto err_with_revert; 70 } 71 72 p = devm_pinctrl_get_select(adap->dev.parent, priv->bus_name); 73 if (IS_ERR(p)) { 74 ret = PTR_ERR(p); 75 goto err_with_put; 76 } 77 78 priv->chan[new_chan].parent_adap = adap; 79 priv->cur_chan = new_chan; 80 81 /* Now fill out current adapter structure. cur_chan must be up to date */ 82 priv->algo.master_xfer = i2c_demux_master_xfer; 83 priv->algo.functionality = i2c_demux_functionality; 84 85 snprintf(priv->cur_adap.name, sizeof(priv->cur_adap.name), 86 "i2c-demux (master i2c-%d)", i2c_adapter_id(adap)); 87 priv->cur_adap.owner = THIS_MODULE; 88 priv->cur_adap.algo = &priv->algo; 89 priv->cur_adap.algo_data = priv; 90 priv->cur_adap.dev.parent = priv->dev; 91 priv->cur_adap.class = adap->class; 92 priv->cur_adap.retries = adap->retries; 93 priv->cur_adap.timeout = adap->timeout; 94 priv->cur_adap.quirks = adap->quirks; 95 priv->cur_adap.dev.of_node = priv->dev->of_node; 96 ret = i2c_add_adapter(&priv->cur_adap); 97 if (ret < 0) 98 goto err_with_put; 99 100 return 0; 101 102 err_with_put: 103 i2c_put_adapter(adap); 104 err_with_revert: 105 of_changeset_revert(&priv->chan[new_chan].chgset); 106 err: 107 dev_err(priv->dev, "failed to setup demux-adapter %d (%d)\n", new_chan, ret); 108 priv->cur_chan = -EINVAL; 109 return ret; 110 } 111 112 static int i2c_demux_deactivate_master(struct i2c_demux_pinctrl_priv *priv) 113 { 114 int ret, cur = priv->cur_chan; 115 116 if (cur < 0) 117 return 0; 118 119 i2c_del_adapter(&priv->cur_adap); 120 i2c_put_adapter(priv->chan[cur].parent_adap); 121 122 ret = of_changeset_revert(&priv->chan[cur].chgset); 123 124 priv->chan[cur].parent_adap = NULL; 125 priv->cur_chan = -EINVAL; 126 127 return ret; 128 } 129 130 static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan) 131 { 132 int ret; 133 134 if (new_chan == priv->cur_chan) 135 return 0; 136 137 ret = i2c_demux_deactivate_master(priv); 138 if (ret) 139 return ret; 140 141 return i2c_demux_activate_master(priv, new_chan); 142 } 143 144 static ssize_t available_masters_show(struct device *dev, 145 struct device_attribute *attr, 146 char *buf) 147 { 148 struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev); 149 int count = 0, i; 150 151 for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++) 152 count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%s%c", 153 i, priv->chan[i].parent_np->full_name, 154 i == priv->num_chan - 1 ? '\n' : ' '); 155 156 return count; 157 } 158 static DEVICE_ATTR_RO(available_masters); 159 160 static ssize_t current_master_show(struct device *dev, 161 struct device_attribute *attr, 162 char *buf) 163 { 164 struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev); 165 166 return sprintf(buf, "%d\n", priv->cur_chan); 167 } 168 169 static ssize_t current_master_store(struct device *dev, 170 struct device_attribute *attr, 171 const char *buf, size_t count) 172 { 173 struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev); 174 unsigned int val; 175 int ret; 176 177 ret = kstrtouint(buf, 0, &val); 178 if (ret < 0) 179 return ret; 180 181 if (val >= priv->num_chan) 182 return -EINVAL; 183 184 ret = i2c_demux_change_master(priv, val); 185 186 return ret < 0 ? ret : count; 187 } 188 static DEVICE_ATTR_RW(current_master); 189 190 static int i2c_demux_pinctrl_probe(struct platform_device *pdev) 191 { 192 struct device_node *np = pdev->dev.of_node; 193 struct i2c_demux_pinctrl_priv *priv; 194 struct property *props; 195 int num_chan, i, j, err; 196 197 num_chan = of_count_phandle_with_args(np, "i2c-parent", NULL); 198 if (num_chan < 2) { 199 dev_err(&pdev->dev, "Need at least two I2C masters to switch\n"); 200 return -EINVAL; 201 } 202 203 priv = devm_kzalloc(&pdev->dev, sizeof(*priv) 204 + num_chan * sizeof(struct i2c_demux_pinctrl_chan), GFP_KERNEL); 205 206 props = devm_kcalloc(&pdev->dev, num_chan, sizeof(*props), GFP_KERNEL); 207 208 if (!priv || !props) 209 return -ENOMEM; 210 211 err = of_property_read_string(np, "i2c-bus-name", &priv->bus_name); 212 if (err) 213 return err; 214 215 for (i = 0; i < num_chan; i++) { 216 struct device_node *adap_np; 217 218 adap_np = of_parse_phandle(np, "i2c-parent", i); 219 if (!adap_np) { 220 dev_err(&pdev->dev, "can't get phandle for parent %d\n", i); 221 err = -ENOENT; 222 goto err_rollback; 223 } 224 priv->chan[i].parent_np = adap_np; 225 226 props[i].name = devm_kstrdup(&pdev->dev, "status", GFP_KERNEL); 227 props[i].value = devm_kstrdup(&pdev->dev, "ok", GFP_KERNEL); 228 props[i].length = 3; 229 230 of_changeset_init(&priv->chan[i].chgset); 231 of_changeset_update_property(&priv->chan[i].chgset, adap_np, &props[i]); 232 } 233 234 priv->num_chan = num_chan; 235 priv->dev = &pdev->dev; 236 237 platform_set_drvdata(pdev, priv); 238 239 /* switch to first parent as active master */ 240 i2c_demux_activate_master(priv, 0); 241 242 err = device_create_file(&pdev->dev, &dev_attr_available_masters); 243 if (err) 244 goto err_rollback; 245 246 err = device_create_file(&pdev->dev, &dev_attr_current_master); 247 if (err) 248 goto err_rollback_available; 249 250 return 0; 251 252 err_rollback_available: 253 device_remove_file(&pdev->dev, &dev_attr_available_masters); 254 err_rollback: 255 for (j = 0; j < i; j++) { 256 of_node_put(priv->chan[j].parent_np); 257 of_changeset_destroy(&priv->chan[j].chgset); 258 } 259 260 return err; 261 } 262 263 static int i2c_demux_pinctrl_remove(struct platform_device *pdev) 264 { 265 struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev); 266 int i; 267 268 device_remove_file(&pdev->dev, &dev_attr_current_master); 269 device_remove_file(&pdev->dev, &dev_attr_available_masters); 270 271 i2c_demux_deactivate_master(priv); 272 273 for (i = 0; i < priv->num_chan; i++) { 274 of_node_put(priv->chan[i].parent_np); 275 of_changeset_destroy(&priv->chan[i].chgset); 276 } 277 278 return 0; 279 } 280 281 static const struct of_device_id i2c_demux_pinctrl_of_match[] = { 282 { .compatible = "i2c-demux-pinctrl", }, 283 {}, 284 }; 285 MODULE_DEVICE_TABLE(of, i2c_demux_pinctrl_of_match); 286 287 static struct platform_driver i2c_demux_pinctrl_driver = { 288 .driver = { 289 .name = "i2c-demux-pinctrl", 290 .of_match_table = i2c_demux_pinctrl_of_match, 291 }, 292 .probe = i2c_demux_pinctrl_probe, 293 .remove = i2c_demux_pinctrl_remove, 294 }; 295 module_platform_driver(i2c_demux_pinctrl_driver); 296 297 MODULE_DESCRIPTION("pinctrl-based I2C demux driver"); 298 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>"); 299 MODULE_LICENSE("GPL v2"); 300 MODULE_ALIAS("platform:i2c-demux-pinctrl"); 301