i2c-demux-pinctrl.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. #include <linux/i2c.h>
  15. #include <linux/init.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/pinctrl/consumer.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/pm_runtime.h>
  21. #include <linux/slab.h>
  22. #include <linux/sysfs.h>
  23. struct i2c_demux_pinctrl_chan {
  24. struct device_node *parent_np;
  25. struct i2c_adapter *parent_adap;
  26. struct of_changeset chgset;
  27. };
  28. struct i2c_demux_pinctrl_priv {
  29. int cur_chan;
  30. int num_chan;
  31. struct device *dev;
  32. const char *bus_name;
  33. struct i2c_adapter cur_adap;
  34. struct i2c_algorithm algo;
  35. struct i2c_demux_pinctrl_chan chan[];
  36. };
  37. static int i2c_demux_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
  38. {
  39. struct i2c_demux_pinctrl_priv *priv = adap->algo_data;
  40. struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap;
  41. return __i2c_transfer(parent, msgs, num);
  42. }
  43. static u32 i2c_demux_functionality(struct i2c_adapter *adap)
  44. {
  45. struct i2c_demux_pinctrl_priv *priv = adap->algo_data;
  46. struct i2c_adapter *parent = priv->chan[priv->cur_chan].parent_adap;
  47. return parent->algo->functionality(parent);
  48. }
  49. static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan)
  50. {
  51. struct i2c_adapter *adap;
  52. struct pinctrl *p;
  53. int ret;
  54. ret = of_changeset_apply(&priv->chan[new_chan].chgset);
  55. if (ret)
  56. goto err;
  57. adap = of_find_i2c_adapter_by_node(priv->chan[new_chan].parent_np);
  58. if (!adap) {
  59. ret = -ENODEV;
  60. goto err_with_revert;
  61. }
  62. /*
  63. * Check if there are pinctrl states at all. Note: we cant' use
  64. * devm_pinctrl_get_select() because we need to distinguish between
  65. * the -ENODEV from devm_pinctrl_get() and pinctrl_lookup_state().
  66. */
  67. p = devm_pinctrl_get(adap->dev.parent);
  68. if (IS_ERR(p)) {
  69. ret = PTR_ERR(p);
  70. /* continue if just no pinctrl states (e.g. i2c-gpio), otherwise exit */
  71. if (ret != -ENODEV)
  72. goto err_with_put;
  73. } else {
  74. /* there are states. check and use them */
  75. struct pinctrl_state *s = pinctrl_lookup_state(p, priv->bus_name);
  76. if (IS_ERR(s)) {
  77. ret = PTR_ERR(s);
  78. goto err_with_put;
  79. }
  80. ret = pinctrl_select_state(p, s);
  81. if (ret < 0)
  82. goto err_with_put;
  83. }
  84. priv->chan[new_chan].parent_adap = adap;
  85. priv->cur_chan = new_chan;
  86. /* Now fill out current adapter structure. cur_chan must be up to date */
  87. priv->algo.master_xfer = i2c_demux_master_xfer;
  88. priv->algo.functionality = i2c_demux_functionality;
  89. snprintf(priv->cur_adap.name, sizeof(priv->cur_adap.name),
  90. "i2c-demux (master i2c-%d)", i2c_adapter_id(adap));
  91. priv->cur_adap.owner = THIS_MODULE;
  92. priv->cur_adap.algo = &priv->algo;
  93. priv->cur_adap.algo_data = priv;
  94. priv->cur_adap.dev.parent = &adap->dev;
  95. priv->cur_adap.class = adap->class;
  96. priv->cur_adap.retries = adap->retries;
  97. priv->cur_adap.timeout = adap->timeout;
  98. priv->cur_adap.quirks = adap->quirks;
  99. priv->cur_adap.dev.of_node = priv->dev->of_node;
  100. ret = i2c_add_adapter(&priv->cur_adap);
  101. if (ret < 0)
  102. goto err_with_put;
  103. return 0;
  104. err_with_put:
  105. i2c_put_adapter(adap);
  106. err_with_revert:
  107. of_changeset_revert(&priv->chan[new_chan].chgset);
  108. err:
  109. dev_err(priv->dev, "failed to setup demux-adapter %d (%d)\n", new_chan, ret);
  110. priv->cur_chan = -EINVAL;
  111. return ret;
  112. }
  113. static int i2c_demux_deactivate_master(struct i2c_demux_pinctrl_priv *priv)
  114. {
  115. int ret, cur = priv->cur_chan;
  116. if (cur < 0)
  117. return 0;
  118. i2c_del_adapter(&priv->cur_adap);
  119. i2c_put_adapter(priv->chan[cur].parent_adap);
  120. ret = of_changeset_revert(&priv->chan[cur].chgset);
  121. priv->chan[cur].parent_adap = NULL;
  122. priv->cur_chan = -EINVAL;
  123. return ret;
  124. }
  125. static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv *priv, u32 new_chan)
  126. {
  127. int ret;
  128. if (new_chan == priv->cur_chan)
  129. return 0;
  130. ret = i2c_demux_deactivate_master(priv);
  131. if (ret)
  132. return ret;
  133. return i2c_demux_activate_master(priv, new_chan);
  134. }
  135. static ssize_t available_masters_show(struct device *dev,
  136. struct device_attribute *attr,
  137. char *buf)
  138. {
  139. struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
  140. int count = 0, i;
  141. for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++)
  142. count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%pOF%c",
  143. i, priv->chan[i].parent_np,
  144. i == priv->num_chan - 1 ? '\n' : ' ');
  145. return count;
  146. }
  147. static DEVICE_ATTR_RO(available_masters);
  148. static ssize_t current_master_show(struct device *dev,
  149. struct device_attribute *attr,
  150. char *buf)
  151. {
  152. struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
  153. return sprintf(buf, "%d\n", priv->cur_chan);
  154. }
  155. static ssize_t current_master_store(struct device *dev,
  156. struct device_attribute *attr,
  157. const char *buf, size_t count)
  158. {
  159. struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
  160. unsigned int val;
  161. int ret;
  162. ret = kstrtouint(buf, 0, &val);
  163. if (ret < 0)
  164. return ret;
  165. if (val >= priv->num_chan)
  166. return -EINVAL;
  167. ret = i2c_demux_change_master(priv, val);
  168. return ret < 0 ? ret : count;
  169. }
  170. static DEVICE_ATTR_RW(current_master);
  171. static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
  172. {
  173. struct device_node *np = pdev->dev.of_node;
  174. struct i2c_demux_pinctrl_priv *priv;
  175. struct property *props;
  176. int num_chan, i, j, err;
  177. num_chan = of_count_phandle_with_args(np, "i2c-parent", NULL);
  178. if (num_chan < 2) {
  179. dev_err(&pdev->dev, "Need at least two I2C masters to switch\n");
  180. return -EINVAL;
  181. }
  182. priv = devm_kzalloc(&pdev->dev, sizeof(*priv)
  183. + num_chan * sizeof(struct i2c_demux_pinctrl_chan), GFP_KERNEL);
  184. props = devm_kcalloc(&pdev->dev, num_chan, sizeof(*props), GFP_KERNEL);
  185. if (!priv || !props)
  186. return -ENOMEM;
  187. err = of_property_read_string(np, "i2c-bus-name", &priv->bus_name);
  188. if (err)
  189. return err;
  190. for (i = 0; i < num_chan; i++) {
  191. struct device_node *adap_np;
  192. adap_np = of_parse_phandle(np, "i2c-parent", i);
  193. if (!adap_np) {
  194. dev_err(&pdev->dev, "can't get phandle for parent %d\n", i);
  195. err = -ENOENT;
  196. goto err_rollback;
  197. }
  198. priv->chan[i].parent_np = adap_np;
  199. props[i].name = devm_kstrdup(&pdev->dev, "status", GFP_KERNEL);
  200. props[i].value = devm_kstrdup(&pdev->dev, "ok", GFP_KERNEL);
  201. props[i].length = 3;
  202. of_changeset_init(&priv->chan[i].chgset);
  203. of_changeset_update_property(&priv->chan[i].chgset, adap_np, &props[i]);
  204. }
  205. priv->num_chan = num_chan;
  206. priv->dev = &pdev->dev;
  207. platform_set_drvdata(pdev, priv);
  208. pm_runtime_no_callbacks(&pdev->dev);
  209. /* switch to first parent as active master */
  210. i2c_demux_activate_master(priv, 0);
  211. err = device_create_file(&pdev->dev, &dev_attr_available_masters);
  212. if (err)
  213. goto err_rollback;
  214. err = device_create_file(&pdev->dev, &dev_attr_current_master);
  215. if (err)
  216. goto err_rollback_available;
  217. return 0;
  218. err_rollback_available:
  219. device_remove_file(&pdev->dev, &dev_attr_available_masters);
  220. err_rollback:
  221. i2c_demux_deactivate_master(priv);
  222. for (j = 0; j < i; j++) {
  223. of_node_put(priv->chan[j].parent_np);
  224. of_changeset_destroy(&priv->chan[j].chgset);
  225. }
  226. return err;
  227. }
  228. static int i2c_demux_pinctrl_remove(struct platform_device *pdev)
  229. {
  230. struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev);
  231. int i;
  232. device_remove_file(&pdev->dev, &dev_attr_current_master);
  233. device_remove_file(&pdev->dev, &dev_attr_available_masters);
  234. i2c_demux_deactivate_master(priv);
  235. for (i = 0; i < priv->num_chan; i++) {
  236. of_node_put(priv->chan[i].parent_np);
  237. of_changeset_destroy(&priv->chan[i].chgset);
  238. }
  239. return 0;
  240. }
  241. static const struct of_device_id i2c_demux_pinctrl_of_match[] = {
  242. { .compatible = "i2c-demux-pinctrl", },
  243. {},
  244. };
  245. MODULE_DEVICE_TABLE(of, i2c_demux_pinctrl_of_match);
  246. static struct platform_driver i2c_demux_pinctrl_driver = {
  247. .driver = {
  248. .name = "i2c-demux-pinctrl",
  249. .of_match_table = i2c_demux_pinctrl_of_match,
  250. },
  251. .probe = i2c_demux_pinctrl_probe,
  252. .remove = i2c_demux_pinctrl_remove,
  253. };
  254. module_platform_driver(i2c_demux_pinctrl_driver);
  255. MODULE_DESCRIPTION("pinctrl-based I2C demux driver");
  256. MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
  257. MODULE_LICENSE("GPL v2");
  258. MODULE_ALIAS("platform:i2c-demux-pinctrl");