i2c-mux-gpio.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * I2C multiplexer using GPIO API
  3. *
  4. * Copyright 2017 NXP
  5. *
  6. * Peng Fan <peng.fan@nxp.com>
  7. *
  8. * SPDX-License-Identifier: GPL-2.0+
  9. */
  10. #include <asm/io.h>
  11. #include <asm-generic/gpio.h>
  12. #include <common.h>
  13. #include <dm.h>
  14. #include <dm/pinctrl.h>
  15. #include <fdtdec.h>
  16. #include <i2c.h>
  17. #include <linux/errno.h>
  18. DECLARE_GLOBAL_DATA_PTR;
  19. /**
  20. * struct i2c_mux_gpio_priv - private data for i2c mux gpio
  21. *
  22. * @values: the reg value of each child node
  23. * @n_values: num of regs
  24. * @gpios: the mux-gpios array
  25. * @n_gpios: num of gpios in mux-gpios
  26. * @idle: the value of idle-state
  27. */
  28. struct i2c_mux_gpio_priv {
  29. u32 *values;
  30. int n_values;
  31. struct gpio_desc *gpios;
  32. int n_gpios;
  33. u32 idle;
  34. };
  35. static int i2c_mux_gpio_select(struct udevice *dev, struct udevice *bus,
  36. uint channel)
  37. {
  38. struct i2c_mux_gpio_priv *priv = dev_get_priv(dev);
  39. int i, ret;
  40. for (i = 0; i < priv->n_gpios; i++) {
  41. ret = dm_gpio_set_value(&priv->gpios[i], (channel >> i) & 1);
  42. if (ret)
  43. return ret;
  44. }
  45. return 0;
  46. }
  47. static int i2c_mux_gpio_deselect(struct udevice *dev, struct udevice *bus,
  48. uint channel)
  49. {
  50. struct i2c_mux_gpio_priv *priv = dev_get_priv(dev);
  51. int i, ret;
  52. for (i = 0; i < priv->n_gpios; i++) {
  53. ret = dm_gpio_set_value(&priv->gpios[i], (priv->idle >> i) & 1);
  54. if (ret)
  55. return ret;
  56. }
  57. return 0;
  58. }
  59. static int i2c_mux_gpio_probe(struct udevice *dev)
  60. {
  61. const void *fdt = gd->fdt_blob;
  62. int node = dev_of_offset(dev);
  63. struct i2c_mux_gpio_priv *mux = dev_get_priv(dev);
  64. struct gpio_desc *gpios;
  65. u32 *values;
  66. int i = 0, subnode, ret;
  67. mux->n_values = fdtdec_get_child_count(fdt, node);
  68. values = devm_kzalloc(dev, sizeof(*mux->values) * mux->n_values,
  69. GFP_KERNEL);
  70. if (!values) {
  71. dev_err(dev, "Cannot alloc values array");
  72. return -ENOMEM;
  73. }
  74. fdt_for_each_subnode(subnode, fdt, node) {
  75. *(values + i) = fdtdec_get_uint(fdt, subnode, "reg", -1);
  76. i++;
  77. }
  78. mux->values = values;
  79. mux->idle = fdtdec_get_uint(fdt, node, "idle-state", -1);
  80. mux->n_gpios = gpio_get_list_count(dev, "mux-gpios");
  81. if (mux->n_gpios < 0) {
  82. dev_err(dev, "Missing mux-gpios property\n");
  83. return -EINVAL;
  84. }
  85. gpios = devm_kzalloc(dev, sizeof(struct gpio_desc) * mux->n_gpios,
  86. GFP_KERNEL);
  87. if (!gpios) {
  88. dev_err(dev, "Cannot allocate gpios array\n");
  89. return -ENOMEM;
  90. }
  91. ret = gpio_request_list_by_name(dev, "mux-gpios", gpios, mux->n_gpios,
  92. GPIOD_IS_OUT_ACTIVE);
  93. if (ret <= 0) {
  94. dev_err(dev, "Failed to request mux-gpios\n");
  95. return ret;
  96. }
  97. mux->gpios = gpios;
  98. return 0;
  99. }
  100. static const struct i2c_mux_ops i2c_mux_gpio_ops = {
  101. .select = i2c_mux_gpio_select,
  102. .deselect = i2c_mux_gpio_deselect,
  103. };
  104. static const struct udevice_id i2c_mux_gpio_ids[] = {
  105. { .compatible = "i2c-mux-gpio", },
  106. {}
  107. };
  108. U_BOOT_DRIVER(i2c_mux_gpio) = {
  109. .name = "i2c_mux_gpio",
  110. .id = UCLASS_I2C_MUX,
  111. .of_match = i2c_mux_gpio_ids,
  112. .ops = &i2c_mux_gpio_ops,
  113. .probe = i2c_mux_gpio_probe,
  114. .priv_auto_alloc_size = sizeof(struct i2c_mux_gpio_priv),
  115. };