i2c-arb-gpio-challenge.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2015 Google, Inc
  4. * Written by Simon Glass <sjg@chromium.org>
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <errno.h>
  9. #include <i2c.h>
  10. #include <asm/gpio.h>
  11. DECLARE_GLOBAL_DATA_PTR;
  12. struct i2c_arbitrator_priv {
  13. struct gpio_desc ap_claim;
  14. struct gpio_desc ec_claim;
  15. uint slew_delay_us;
  16. uint wait_retry_ms;
  17. uint wait_free_ms;
  18. };
  19. int i2c_arbitrator_deselect(struct udevice *mux, struct udevice *bus,
  20. uint channel)
  21. {
  22. struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
  23. int ret;
  24. debug("%s: %s\n", __func__, mux->name);
  25. ret = dm_gpio_set_value(&priv->ap_claim, 0);
  26. udelay(priv->slew_delay_us);
  27. return ret;
  28. }
  29. int i2c_arbitrator_select(struct udevice *mux, struct udevice *bus,
  30. uint channel)
  31. {
  32. struct i2c_arbitrator_priv *priv = dev_get_priv(mux);
  33. unsigned start;
  34. int ret;
  35. debug("%s: %s\n", __func__, mux->name);
  36. /* Start a round of trying to claim the bus */
  37. start = get_timer(0);
  38. do {
  39. unsigned start_retry;
  40. int waiting = 0;
  41. /* Indicate that we want to claim the bus */
  42. ret = dm_gpio_set_value(&priv->ap_claim, 1);
  43. if (ret)
  44. goto err;
  45. udelay(priv->slew_delay_us);
  46. /* Wait for the EC to release it */
  47. start_retry = get_timer(0);
  48. while (get_timer(start_retry) < priv->wait_retry_ms) {
  49. ret = dm_gpio_get_value(&priv->ec_claim);
  50. if (ret < 0) {
  51. goto err;
  52. } else if (!ret) {
  53. /* We got it, so return */
  54. return 0;
  55. }
  56. if (!waiting)
  57. waiting = 1;
  58. }
  59. /* It didn't release, so give up, wait, and try again */
  60. ret = dm_gpio_set_value(&priv->ap_claim, 0);
  61. if (ret)
  62. goto err;
  63. mdelay(priv->wait_retry_ms);
  64. } while (get_timer(start) < priv->wait_free_ms);
  65. /* Give up, release our claim */
  66. printf("I2C: Could not claim bus, timeout %lu\n", get_timer(start));
  67. ret = -ETIMEDOUT;
  68. ret = 0;
  69. err:
  70. return ret;
  71. }
  72. static int i2c_arbitrator_probe(struct udevice *dev)
  73. {
  74. struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
  75. const void *blob = gd->fdt_blob;
  76. int node = dev_of_offset(dev);
  77. int ret;
  78. debug("%s: %s\n", __func__, dev->name);
  79. priv->slew_delay_us = fdtdec_get_int(blob, node, "slew-delay-us", 0);
  80. priv->wait_retry_ms = fdtdec_get_int(blob, node, "wait-retry-us", 0) /
  81. 1000;
  82. priv->wait_free_ms = fdtdec_get_int(blob, node, "wait-free-us", 0) /
  83. 1000;
  84. ret = gpio_request_by_name(dev, "our-claim-gpio", 0, &priv->ap_claim,
  85. GPIOD_IS_OUT);
  86. if (ret)
  87. goto err;
  88. ret = gpio_request_by_name(dev, "their-claim-gpios", 0, &priv->ec_claim,
  89. GPIOD_IS_IN);
  90. if (ret)
  91. goto err_ec_gpio;
  92. return 0;
  93. err_ec_gpio:
  94. dm_gpio_free(dev, &priv->ap_claim);
  95. err:
  96. debug("%s: ret=%d\n", __func__, ret);
  97. return ret;
  98. }
  99. static int i2c_arbitrator_remove(struct udevice *dev)
  100. {
  101. struct i2c_arbitrator_priv *priv = dev_get_priv(dev);
  102. dm_gpio_free(dev, &priv->ap_claim);
  103. dm_gpio_free(dev, &priv->ec_claim);
  104. return 0;
  105. }
  106. static const struct i2c_mux_ops i2c_arbitrator_ops = {
  107. .select = i2c_arbitrator_select,
  108. .deselect = i2c_arbitrator_deselect,
  109. };
  110. static const struct udevice_id i2c_arbitrator_ids[] = {
  111. { .compatible = "i2c-arb-gpio-challenge" },
  112. { }
  113. };
  114. U_BOOT_DRIVER(i2c_arbitrator) = {
  115. .name = "i2c_arbitrator",
  116. .id = UCLASS_I2C_MUX,
  117. .of_match = i2c_arbitrator_ids,
  118. .probe = i2c_arbitrator_probe,
  119. .remove = i2c_arbitrator_remove,
  120. .ops = &i2c_arbitrator_ops,
  121. .priv_auto_alloc_size = sizeof(struct i2c_arbitrator_priv),
  122. };