s5p_gpio.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * (C) Copyright 2009 Samsung Electronics
  3. * Minkyu Kang <mk7.kang@samsung.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <asm/io.h>
  9. #include <asm/gpio.h>
  10. #include <asm/arch/gpio.h>
  11. #define S5P_GPIO_GET_PIN(x) (x % GPIO_PER_BANK)
  12. #define CON_MASK(x) (0xf << ((x) << 2))
  13. #define CON_SFR(x, v) ((v) << ((x) << 2))
  14. #define DAT_MASK(x) (0x1 << (x))
  15. #define DAT_SET(x) (0x1 << (x))
  16. #define PULL_MASK(x) (0x3 << ((x) << 1))
  17. #define PULL_MODE(x, v) ((v) << ((x) << 1))
  18. #define DRV_MASK(x) (0x3 << ((x) << 1))
  19. #define DRV_SET(x, m) ((m) << ((x) << 1))
  20. #define RATE_MASK(x) (0x1 << (x + 16))
  21. #define RATE_SET(x) (0x1 << (x + 16))
  22. #define name_to_gpio(n) s5p_name_to_gpio(n)
  23. static inline int s5p_name_to_gpio(const char *name)
  24. {
  25. unsigned num, irregular_set_number, irregular_bank_base;
  26. const struct gpio_name_num_table *tabp;
  27. char this_bank, bank_name, irregular_bank_name;
  28. char *endp;
  29. /*
  30. * The gpio name starts with either 'g' or 'gp' followed by the bank
  31. * name character. Skip one or two characters depending on the prefix.
  32. */
  33. if (name[0] == 'g' && name[1] == 'p')
  34. name += 2;
  35. else if (name[0] == 'g')
  36. name++;
  37. else
  38. return -1; /* Name must start with 'g' */
  39. bank_name = *name++;
  40. if (!*name)
  41. return -1; /* At least one digit is required/expected. */
  42. /*
  43. * On both exynos5 and exynos5420 architectures there is a bank of
  44. * GPIOs which does not fall into the regular address pattern. Those
  45. * banks are c4 on Exynos5 and y7 on Exynos5420. The rest of the below
  46. * assignments help to handle these irregularities.
  47. */
  48. #if defined(CONFIG_EXYNOS4) || defined(CONFIG_EXYNOS5)
  49. if (cpu_is_exynos5()) {
  50. if (proid_is_exynos5420()) {
  51. tabp = exynos5420_gpio_table;
  52. irregular_bank_name = 'y';
  53. irregular_set_number = '7';
  54. irregular_bank_base = EXYNOS5420_GPIO_Y70;
  55. } else {
  56. tabp = exynos5_gpio_table;
  57. irregular_bank_name = 'c';
  58. irregular_set_number = '4';
  59. irregular_bank_base = EXYNOS5_GPIO_C40;
  60. }
  61. } else {
  62. if (proid_is_exynos4412())
  63. tabp = exynos4x12_gpio_table;
  64. else
  65. tabp = exynos4_gpio_table;
  66. irregular_bank_name = 0;
  67. irregular_set_number = 0;
  68. irregular_bank_base = 0;
  69. }
  70. #else
  71. if (cpu_is_s5pc110())
  72. tabp = s5pc110_gpio_table;
  73. else
  74. tabp = s5pc100_gpio_table;
  75. irregular_bank_name = 0;
  76. irregular_set_number = 0;
  77. irregular_bank_base = 0;
  78. #endif
  79. this_bank = tabp->bank;
  80. do {
  81. if (bank_name == this_bank) {
  82. unsigned pin_index; /* pin number within the bank */
  83. if ((bank_name == irregular_bank_name) &&
  84. (name[0] == irregular_set_number)) {
  85. pin_index = name[1] - '0';
  86. /* Irregular sets have 8 pins. */
  87. if (pin_index >= GPIO_PER_BANK)
  88. return -1;
  89. num = irregular_bank_base + pin_index;
  90. } else {
  91. pin_index = simple_strtoul(name, &endp, 8);
  92. pin_index -= tabp->bank_offset;
  93. /*
  94. * Sanity check: bunk 'z' has no set number,
  95. * for all other banks there must be exactly
  96. * two octal digits, and the resulting number
  97. * should not exceed the number of pins in the
  98. * bank.
  99. */
  100. if (((bank_name != 'z') && !name[1]) ||
  101. *endp ||
  102. (pin_index >= tabp->bank_size))
  103. return -1;
  104. num = tabp->base + pin_index;
  105. }
  106. return num;
  107. }
  108. this_bank = (++tabp)->bank;
  109. } while (this_bank);
  110. return -1;
  111. }
  112. static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
  113. {
  114. unsigned int value;
  115. value = readl(&bank->con);
  116. value &= ~CON_MASK(gpio);
  117. value |= CON_SFR(gpio, cfg);
  118. writel(value, &bank->con);
  119. }
  120. static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
  121. {
  122. unsigned int value;
  123. value = readl(&bank->dat);
  124. value &= ~DAT_MASK(gpio);
  125. if (en)
  126. value |= DAT_SET(gpio);
  127. writel(value, &bank->dat);
  128. }
  129. static void s5p_gpio_direction_output(struct s5p_gpio_bank *bank,
  130. int gpio, int en)
  131. {
  132. s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_OUTPUT);
  133. s5p_gpio_set_value(bank, gpio, en);
  134. }
  135. static void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
  136. {
  137. s5p_gpio_cfg_pin(bank, gpio, S5P_GPIO_INPUT);
  138. }
  139. static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
  140. {
  141. unsigned int value;
  142. value = readl(&bank->dat);
  143. return !!(value & DAT_MASK(gpio));
  144. }
  145. static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
  146. {
  147. unsigned int value;
  148. value = readl(&bank->pull);
  149. value &= ~PULL_MASK(gpio);
  150. switch (mode) {
  151. case S5P_GPIO_PULL_DOWN:
  152. case S5P_GPIO_PULL_UP:
  153. value |= PULL_MODE(gpio, mode);
  154. break;
  155. default:
  156. break;
  157. }
  158. writel(value, &bank->pull);
  159. }
  160. static void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
  161. {
  162. unsigned int value;
  163. value = readl(&bank->drv);
  164. value &= ~DRV_MASK(gpio);
  165. switch (mode) {
  166. case S5P_GPIO_DRV_1X:
  167. case S5P_GPIO_DRV_2X:
  168. case S5P_GPIO_DRV_3X:
  169. case S5P_GPIO_DRV_4X:
  170. value |= DRV_SET(gpio, mode);
  171. break;
  172. default:
  173. return;
  174. }
  175. writel(value, &bank->drv);
  176. }
  177. static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
  178. {
  179. unsigned int value;
  180. value = readl(&bank->drv);
  181. value &= ~RATE_MASK(gpio);
  182. switch (mode) {
  183. case S5P_GPIO_DRV_FAST:
  184. case S5P_GPIO_DRV_SLOW:
  185. value |= RATE_SET(gpio);
  186. break;
  187. default:
  188. return;
  189. }
  190. writel(value, &bank->drv);
  191. }
  192. struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
  193. {
  194. const struct gpio_info *data;
  195. unsigned int upto;
  196. int i, count;
  197. data = get_gpio_data();
  198. count = get_bank_num();
  199. upto = 0;
  200. for (i = 0; i < count; i++) {
  201. debug("i=%d, upto=%d\n", i, upto);
  202. if (gpio < data->max_gpio) {
  203. struct s5p_gpio_bank *bank;
  204. bank = (struct s5p_gpio_bank *)data->reg_addr;
  205. bank += (gpio - upto) / GPIO_PER_BANK;
  206. debug("gpio=%d, bank=%p\n", gpio, bank);
  207. return bank;
  208. }
  209. upto = data->max_gpio;
  210. data++;
  211. }
  212. return NULL;
  213. }
  214. int s5p_gpio_get_pin(unsigned gpio)
  215. {
  216. return S5P_GPIO_GET_PIN(gpio);
  217. }
  218. /* Common GPIO API */
  219. int gpio_request(unsigned gpio, const char *label)
  220. {
  221. return 0;
  222. }
  223. int gpio_free(unsigned gpio)
  224. {
  225. return 0;
  226. }
  227. int gpio_direction_input(unsigned gpio)
  228. {
  229. s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
  230. s5p_gpio_get_pin(gpio));
  231. return 0;
  232. }
  233. int gpio_direction_output(unsigned gpio, int value)
  234. {
  235. s5p_gpio_direction_output(s5p_gpio_get_bank(gpio),
  236. s5p_gpio_get_pin(gpio), value);
  237. return 0;
  238. }
  239. int gpio_get_value(unsigned gpio)
  240. {
  241. return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio),
  242. s5p_gpio_get_pin(gpio));
  243. }
  244. int gpio_set_value(unsigned gpio, int value)
  245. {
  246. s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
  247. s5p_gpio_get_pin(gpio), value);
  248. return 0;
  249. }
  250. void gpio_set_pull(int gpio, int mode)
  251. {
  252. s5p_gpio_set_pull(s5p_gpio_get_bank(gpio),
  253. s5p_gpio_get_pin(gpio), mode);
  254. }
  255. void gpio_set_drv(int gpio, int mode)
  256. {
  257. s5p_gpio_set_drv(s5p_gpio_get_bank(gpio),
  258. s5p_gpio_get_pin(gpio), mode);
  259. }
  260. void gpio_cfg_pin(int gpio, int cfg)
  261. {
  262. s5p_gpio_cfg_pin(s5p_gpio_get_bank(gpio),
  263. s5p_gpio_get_pin(gpio), cfg);
  264. }
  265. void gpio_set_rate(int gpio, int mode)
  266. {
  267. s5p_gpio_set_rate(s5p_gpio_get_bank(gpio),
  268. s5p_gpio_get_pin(gpio), mode);
  269. }