dev_pin_ofw.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-11-26 GuEe-GUI first version
  9. */
  10. #include <dt-bindings/pin/pin.h>
  11. #include "dev_pin_dm.h"
  12. static const char * const gpio_suffixes[] =
  13. {
  14. "gpios", "gpio"
  15. };
  16. rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index,
  17. rt_uint8_t *out_mode, rt_uint8_t *out_value)
  18. {
  19. rt_ssize_t pin = -1;
  20. rt_uint8_t mode;
  21. rt_uint8_t value;
  22. rt_uint32_t flags;
  23. char gpios_name[64];
  24. struct rt_device_pin *pin_dev = 0;
  25. struct rt_ofw_node *pin_dev_np = 0;
  26. struct rt_ofw_cell_args pin_args = {0};
  27. if (!np && index < 0)
  28. {
  29. return -RT_EINVAL;
  30. }
  31. for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i)
  32. {
  33. if (propname)
  34. {
  35. rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]);
  36. }
  37. else
  38. {
  39. rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]);
  40. }
  41. pin = rt_ofw_parse_phandle_cells(np, gpios_name, "#gpio-cells", index, &pin_args);
  42. if (pin >= 0)
  43. {
  44. break;
  45. }
  46. }
  47. if (pin < 0)
  48. {
  49. return pin;
  50. }
  51. pin_dev_np = pin_args.data;
  52. if (!rt_ofw_data(pin_dev_np))
  53. {
  54. rt_platform_ofw_request(pin_dev_np);
  55. }
  56. pin_dev = rt_ofw_data(pin_dev_np);
  57. if (!pin_dev)
  58. {
  59. pin = -RT_ERROR;
  60. goto _out_converts;
  61. }
  62. value = PIN_LOW;
  63. mode = PIN_MODE_OUTPUT;
  64. if (pin_dev->ops->pin_parse)
  65. {
  66. pin = pin_dev->ops->pin_parse(&pin_dev->parent, &pin_args, &flags);
  67. }
  68. else
  69. {
  70. /*
  71. * We always assume that the args[0] is the pin number if driver not
  72. * implemented `pin_parse`.
  73. */
  74. pin = pin_args.args[0];
  75. goto _out_converts;
  76. }
  77. if (out_mode)
  78. {
  79. if (flags & PIN_OPEN_DRAIN)
  80. {
  81. mode = PIN_MODE_OUTPUT_OD;
  82. }
  83. switch (flags & RT_GENMASK(6, 4))
  84. {
  85. case PIN_PULL_UP:
  86. mode = PIN_MODE_INPUT_PULLUP;
  87. break;
  88. case PIN_PULL_DOWN:
  89. mode = PIN_MODE_INPUT_PULLDOWN;
  90. break;
  91. case PIN_PULL_DISABLE:
  92. mode = PIN_MODE_INPUT;
  93. break;
  94. }
  95. }
  96. if (out_value)
  97. {
  98. if ((flags & 1) == PIN_ACTIVE_HIGH)
  99. {
  100. value = PIN_HIGH;
  101. }
  102. else if ((flags & 1) == PIN_ACTIVE_LOW)
  103. {
  104. value = PIN_LOW;
  105. }
  106. }
  107. _out_converts:
  108. rt_ofw_node_put(pin_dev_np);
  109. if (pin >= 0)
  110. {
  111. /* Get virtual pin */
  112. pin += pin_dev->pin_start;
  113. if (out_mode)
  114. {
  115. *out_mode = mode;
  116. }
  117. if (out_value)
  118. {
  119. *out_value = value;
  120. }
  121. }
  122. return pin;
  123. }
  124. rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname)
  125. {
  126. char gpios_name[64];
  127. rt_ssize_t count = 0;
  128. if (!np)
  129. {
  130. return -RT_EINVAL;
  131. }
  132. for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i)
  133. {
  134. if (propname)
  135. {
  136. rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]);
  137. }
  138. else
  139. {
  140. rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]);
  141. }
  142. count = rt_ofw_count_phandle_cells(np, propname, "#gpio-cells");
  143. if (count > 0)
  144. {
  145. break;
  146. }
  147. }
  148. return count;
  149. }