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 struct property status_okay = { .name = "status", .length = 3, .value = "ok" }; 41 42 static int i2c_demux_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) 43 { 44 struct i2c_demux_pinctrl_priv *priv = adap->algo_data; 45 struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap; 46 47 return __i2c_transfer(parent, msgs, num); 48 } 49 50 static u32 i2c_demux_functionality(struct i2c_adapter *adap) 51 { 52 struct i2c_demux_pinctrl_priv *priv = adap->algo_data; 53 struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap; 54 55 return parent->algo->functionality(parent); 56 } 57 58 static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan) 59 { 60 struct i2c_adapter *adap; 61 struct pinctrl *p; 62 int ret; 63 64 ret = of_changeset_apply(&priv->chan[new_chan].chgset); 65 if (ret) 66 goto err; 67 68 adap = of_find_i2c_adapter_by_node(priv->chan[new_chan].parent_np); 69 if (!adap) { 70 ret = -ENODEV; 71 goto err; 72 } 73 74 p = devm_pinctrl_get_select(adap->dev.parent, priv->bus_name); 75 if (IS_ERR(p)) { 76 ret = PTR_ERR(p); 77 goto err_with_put; 78 } 79 80 priv->chan[new_chan].parent_adap = adap; 81 priv->cur_chan = new_chan; 82 83 /* Now fill out current adapter structure. cur_chan must be up to date */ 84 priv->algo.master_xfer = i2c_demux_master_xfer; 85 priv->algo.functionality = i2c_demux_functionality; 86 87 snprintf(priv->cur_adap.name, sizeof(priv->cur_adap.name), 88 "i2c-demux (master i2c-%d)", i2c_adapter_id(adap)); 89 priv->cur_adap.owner = THIS_MODULE; 90 priv->cur_adap.algo = &priv->algo; 91 priv->cur_adap.algo_data = priv; 92 priv->cur_adap.dev.parent = priv->dev; 93 priv->cur_adap.class = adap->class; 94 priv->cur_adap.retries = adap->retries; 95 priv->cur_adap.timeout = adap->timeout; 96 priv->cur_adap.quirks = adap->quirks; 97 priv->cur_adap.dev.of_node = priv->dev->of_node; 98 ret = i2c_add_adapter(&priv->cur_adap); 99 if (ret < 0) 100 goto err_with_put; 101 102 return 0; 103 104 err_with_put: 105 i2c_put_adapter(adap); 106 err: 107 dev_err(priv->dev, "failed to setup demux-adapter %d (%d)\n", new_chan, ret); 108 return ret; 109 } 110 111 static int i2c_demux_deactivate_master(struct i2c_demux_pinctrl_priv *priv) 112 { 113 int ret, cur = priv->cur_chan; 114 115 if (cur < 0) 116 return 0; 117 118 i2c_del_adapter(&priv->cur_adap); 119 i2c_put_adapter(priv->chan[cur].parent_adap); 120 121 ret = of_changeset_revert(&priv->chan[cur].chgset); 122 123 priv->chan[cur].parent_adap = NULL; 124 priv->cur_chan = -EINVAL; 125 126 return ret; 127 } 128 129 static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan) 130 { 131 int ret; 132 133 if (new_chan == priv->cur_chan) 134 return 0; 135 136 ret = i2c_demux_deactivate_master(priv); 137 if (ret) 138 return ret; 139 140 return i2c_demux_activate_master(priv, new_chan); 141 } 142 143 static ssize_t cur_master_show(struct device *dev, struct device_attribute *attr, 144 char *buf) 145 { 146 struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev); 147 int count = 0, i; 148 149 for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++) 150 count += scnprintf(buf + count, PAGE_SIZE - count, "%c %d - %s\n", 151 i == priv->cur_chan ? '*' : ' ', i, 152 priv->chan[i].parent_np->full_name); 153 154 return count; 155 } 156 157 static ssize_t cur_master_store(struct device *dev, struct device_attribute *attr, 158 const char *buf, size_t count) 159 { 160 struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev); 161 unsigned int val; 162 int ret; 163 164 ret = kstrtouint(buf, 0, &val); 165 if (ret < 0) 166 return ret; 167 168 if (val >= priv->num_chan) 169 return -EINVAL; 170 171 ret = i2c_demux_change_master(priv, val); 172 173 return ret < 0 ? ret : count; 174 } 175 static DEVICE_ATTR_RW(cur_master); 176 177 static int i2c_demux_pinctrl_probe(struct platform_device *pdev) 178 { 179 struct device_node *np = pdev->dev.of_node; 180 struct i2c_demux_pinctrl_priv *priv; 181 int num_chan, i, j, err; 182 183 num_chan = of_count_phandle_with_args(np, "i2c-parent", NULL); 184 if (num_chan < 2) { 185 dev_err(&pdev->dev, "Need at least two I2C masters to switch\n"); 186 return -EINVAL; 187 } 188 189 priv = devm_kzalloc(&pdev->dev, sizeof(*priv) 190 + num_chan * sizeof(struct i2c_demux_pinctrl_chan), GFP_KERNEL); 191 if (!priv) 192 return -ENOMEM; 193 194 err = of_property_read_string(np, "i2c-bus-name", &priv->bus_name); 195 if (err) 196 return err; 197 198 for (i = 0; i < num_chan; i++) { 199 struct device_node *adap_np; 200 201 adap_np = of_parse_phandle(np, "i2c-parent", i); 202 if (!adap_np) { 203 dev_err(&pdev->dev, "can't get phandle for parent %d\n", i); 204 err = -ENOENT; 205 goto err_rollback; 206 } 207 priv->chan[i].parent_np = adap_np; 208 209 of_changeset_init(&priv->chan[i].chgset); 210 of_changeset_update_property(&priv->chan[i].chgset, adap_np, &status_okay); 211 } 212 213 priv->num_chan = num_chan; 214 priv->dev = &pdev->dev; 215 216 platform_set_drvdata(pdev, priv); 217 218 /* switch to first parent as active master */ 219 i2c_demux_activate_master(priv, 0); 220 221 err = device_create_file(&pdev->dev, &dev_attr_cur_master); 222 if (err) 223 goto err_rollback; 224 225 return 0; 226 227 err_rollback: 228 for (j = 0; j < i; j++) { 229 of_node_put(priv->chan[j].parent_np); 230 of_changeset_destroy(&priv->chan[j].chgset); 231 } 232 233 return err; 234 } 235 236 static int i2c_demux_pinctrl_remove(struct platform_device *pdev) 237 { 238 struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev); 239 int i; 240 241 device_remove_file(&pdev->dev, &dev_attr_cur_master); 242 243 i2c_demux_deactivate_master(priv); 244 245 for (i = 0; i < priv->num_chan; i++) { 246 of_node_put(priv->chan[i].parent_np); 247 of_changeset_destroy(&priv->chan[i].chgset); 248 } 249 250 return 0; 251 } 252 253 static const struct of_device_id i2c_demux_pinctrl_of_match[] = { 254 { .compatible = "i2c-demux-pinctrl", }, 255 {}, 256 }; 257 MODULE_DEVICE_TABLE(of, i2c_demux_pinctrl_of_match); 258 259 static struct platform_driver i2c_demux_pinctrl_driver = { 260 .driver = { 261 .name = "i2c-demux-pinctrl", 262 .of_match_table = i2c_demux_pinctrl_of_match, 263 }, 264 .probe = i2c_demux_pinctrl_probe, 265 .remove = i2c_demux_pinctrl_remove, 266 }; 267 module_platform_driver(i2c_demux_pinctrl_driver); 268 269 MODULE_DESCRIPTION("pinctrl-based I2C demux driver"); 270 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>"); 271 MODULE_LICENSE("GPL v2"); 272 MODULE_ALIAS("platform:i2c-demux-pinctrl"); 273