pin_ofw.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 "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. pin_dev = rt_ofw_data(pin_dev_np);
  53. if (!pin_dev)
  54. {
  55. pin = -RT_ERROR;
  56. goto _out_converts;
  57. }
  58. value = PIN_LOW;
  59. mode = PIN_MODE_OUTPUT;
  60. if (pin_dev->ops->pin_parse)
  61. {
  62. pin = pin_dev->ops->pin_parse(&pin_dev->parent, &pin_args, &flags);
  63. }
  64. else
  65. {
  66. /*
  67. * We always assume that the args[0] is the pin number if driver not
  68. * implemented `pin_parse`.
  69. */
  70. pin = pin_args.args[0];
  71. goto _out_converts;
  72. }
  73. if (out_mode)
  74. {
  75. if (flags & PIN_OPEN_DRAIN)
  76. {
  77. mode = PIN_MODE_OUTPUT_OD;
  78. }
  79. switch (flags & RT_GENMASK(6, 4))
  80. {
  81. case PIN_PULL_UP:
  82. mode = PIN_MODE_INPUT_PULLUP;
  83. break;
  84. case PIN_PULL_DOWN:
  85. mode = PIN_MODE_INPUT_PULLDOWN;
  86. break;
  87. case PIN_PULL_DISABLE:
  88. mode = PIN_MODE_INPUT;
  89. break;
  90. }
  91. }
  92. if (out_value)
  93. {
  94. if (flags == (PIN_ACTIVE_HIGH | PIN_PUSH_PULL))
  95. {
  96. value = PIN_HIGH;
  97. }
  98. else if (flags == (PIN_ACTIVE_LOW | PIN_PUSH_PULL))
  99. {
  100. value = PIN_LOW;
  101. }
  102. }
  103. _out_converts:
  104. rt_ofw_node_put(pin_dev_np);
  105. if (out_mode)
  106. {
  107. *out_mode = mode;
  108. }
  109. if (out_value)
  110. {
  111. *out_value = value;
  112. }
  113. return pin;
  114. }
  115. rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname)
  116. {
  117. char gpios_name[64];
  118. rt_ssize_t count = 0;
  119. if (!np || !propname)
  120. {
  121. return -RT_EINVAL;
  122. }
  123. for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i)
  124. {
  125. if (propname)
  126. {
  127. rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]);
  128. }
  129. else
  130. {
  131. rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]);
  132. }
  133. count = rt_ofw_count_phandle_cells(np, propname, "#gpio-cells");
  134. if (count > 0)
  135. {
  136. break;
  137. }
  138. }
  139. return count;
  140. }