rpi3_gpio.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright (c) 2019, Linaro Limited
  3. * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include <string.h>
  8. #include <assert.h>
  9. #include <lib/mmio.h>
  10. #include <drivers/delay_timer.h>
  11. #include <drivers/rpi3/gpio/rpi3_gpio.h>
  12. #include <platform_def.h>
  13. static uintptr_t reg_base;
  14. static int rpi3_gpio_get_direction(int gpio);
  15. static void rpi3_gpio_set_direction(int gpio, int direction);
  16. static int rpi3_gpio_get_value(int gpio);
  17. static void rpi3_gpio_set_value(int gpio, int value);
  18. static void rpi3_gpio_set_pull(int gpio, int pull);
  19. static const gpio_ops_t rpi3_gpio_ops = {
  20. .get_direction = rpi3_gpio_get_direction,
  21. .set_direction = rpi3_gpio_set_direction,
  22. .get_value = rpi3_gpio_get_value,
  23. .set_value = rpi3_gpio_set_value,
  24. .set_pull = rpi3_gpio_set_pull,
  25. };
  26. /**
  27. * Get selection of GPIO pinmux settings.
  28. *
  29. * @param gpio The pin number of GPIO. From 0 to 53.
  30. * @return The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input,
  31. * RPI3_GPIO_FUNC_OUTPUT: output,
  32. * RPI3_GPIO_FUNC_ALT0: alt-0,
  33. * RPI3_GPIO_FUNC_ALT1: alt-1,
  34. * RPI3_GPIO_FUNC_ALT2: alt-2,
  35. * RPI3_GPIO_FUNC_ALT3: alt-3,
  36. * RPI3_GPIO_FUNC_ALT4: alt-4,
  37. * RPI3_GPIO_FUNC_ALT5: alt-5
  38. */
  39. int rpi3_gpio_get_select(int gpio)
  40. {
  41. int ret;
  42. int regN = gpio / 10;
  43. int shift = 3 * (gpio % 10);
  44. uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN);
  45. uint32_t sel = mmio_read_32(reg_sel);
  46. ret = (sel >> shift) & 0x07;
  47. return ret;
  48. }
  49. /**
  50. * Set selection of GPIO pinmux settings.
  51. *
  52. * @param gpio The pin number of GPIO. From 0 to 53.
  53. * @param fsel The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input,
  54. * RPI3_GPIO_FUNC_OUTPUT: output,
  55. * RPI3_GPIO_FUNC_ALT0: alt-0,
  56. * RPI3_GPIO_FUNC_ALT1: alt-1,
  57. * RPI3_GPIO_FUNC_ALT2: alt-2,
  58. * RPI3_GPIO_FUNC_ALT3: alt-3,
  59. * RPI3_GPIO_FUNC_ALT4: alt-4,
  60. * RPI3_GPIO_FUNC_ALT5: alt-5
  61. */
  62. void rpi3_gpio_set_select(int gpio, int fsel)
  63. {
  64. int regN = gpio / 10;
  65. int shift = 3 * (gpio % 10);
  66. uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN);
  67. uint32_t sel = mmio_read_32(reg_sel);
  68. uint32_t mask = U(0x07) << shift;
  69. sel = (sel & (~mask)) | ((fsel << shift) & mask);
  70. mmio_write_32(reg_sel, sel);
  71. }
  72. static int rpi3_gpio_get_direction(int gpio)
  73. {
  74. int result = rpi3_gpio_get_select(gpio);
  75. if (result == RPI3_GPIO_FUNC_INPUT)
  76. return GPIO_DIR_IN;
  77. else if (result == RPI3_GPIO_FUNC_OUTPUT)
  78. return GPIO_DIR_OUT;
  79. return GPIO_DIR_IN;
  80. }
  81. static void rpi3_gpio_set_direction(int gpio, int direction)
  82. {
  83. switch (direction) {
  84. case GPIO_DIR_IN:
  85. rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_INPUT);
  86. break;
  87. case GPIO_DIR_OUT:
  88. rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_OUTPUT);
  89. break;
  90. }
  91. }
  92. static int rpi3_gpio_get_value(int gpio)
  93. {
  94. int regN = gpio / 32;
  95. int shift = gpio % 32;
  96. uintptr_t reg_lev = reg_base + RPI3_GPIO_GPLEV(regN);
  97. uint32_t value = mmio_read_32(reg_lev);
  98. if ((value >> shift) & 0x01)
  99. return GPIO_LEVEL_HIGH;
  100. return GPIO_LEVEL_LOW;
  101. }
  102. static void rpi3_gpio_set_value(int gpio, int value)
  103. {
  104. int regN = gpio / 32;
  105. int shift = gpio % 32;
  106. uintptr_t reg_set = reg_base + RPI3_GPIO_GPSET(regN);
  107. uintptr_t reg_clr = reg_base + RPI3_GPIO_GPSET(regN);
  108. switch (value) {
  109. case GPIO_LEVEL_LOW:
  110. mmio_write_32(reg_clr, U(1) << shift);
  111. break;
  112. case GPIO_LEVEL_HIGH:
  113. mmio_write_32(reg_set, U(1) << shift);
  114. break;
  115. }
  116. }
  117. static void rpi3_gpio_set_pull(int gpio, int pull)
  118. {
  119. int regN = gpio / 32;
  120. int shift = gpio % 32;
  121. uintptr_t reg_pud = reg_base + RPI3_GPIO_GPPUD;
  122. uintptr_t reg_clk = reg_base + RPI3_GPIO_GPPUDCLK(regN);
  123. switch (pull) {
  124. case GPIO_PULL_NONE:
  125. mmio_write_32(reg_pud, 0x0);
  126. break;
  127. case GPIO_PULL_UP:
  128. mmio_write_32(reg_pud, 0x2);
  129. break;
  130. case GPIO_PULL_DOWN:
  131. mmio_write_32(reg_pud, 0x1);
  132. break;
  133. }
  134. mdelay(150);
  135. mmio_write_32(reg_clk, U(1) << shift);
  136. mdelay(150);
  137. mmio_write_32(reg_clk, 0x0);
  138. mmio_write_32(reg_pud, 0x0);
  139. }
  140. void rpi3_gpio_init(void)
  141. {
  142. reg_base = RPI3_GPIO_BASE;
  143. gpio_init(&rpi3_gpio_ops);
  144. }