s5p_gpio.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2009 Samsung Electronics
  4. * Minkyu Kang <mk7.kang@samsung.com>
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <errno.h>
  9. #include <fdtdec.h>
  10. #include <log.h>
  11. #include <malloc.h>
  12. #include <asm/global_data.h>
  13. #include <asm/io.h>
  14. #include <asm/gpio.h>
  15. #include <dm/device-internal.h>
  16. DECLARE_GLOBAL_DATA_PTR;
  17. #define S5P_GPIO_GET_PIN(x) (x % GPIO_PER_BANK)
  18. #define CON_MASK(val) (0xf << ((val) << 2))
  19. #define CON_SFR(gpio, cfg) ((cfg) << ((gpio) << 2))
  20. #define CON_SFR_UNSHIFT(val, gpio) ((val) >> ((gpio) << 2))
  21. #define DAT_MASK(gpio) (0x1 << (gpio))
  22. #define DAT_SET(gpio) (0x1 << (gpio))
  23. #define PULL_MASK(gpio) (0x3 << ((gpio) << 1))
  24. #define PULL_MODE(gpio, pull) ((pull) << ((gpio) << 1))
  25. #define DRV_MASK(gpio) (0x3 << ((gpio) << 1))
  26. #define DRV_SET(gpio, mode) ((mode) << ((gpio) << 1))
  27. #define RATE_MASK(gpio) (0x1 << (gpio + 16))
  28. #define RATE_SET(gpio) (0x1 << (gpio + 16))
  29. /* Platform data for each bank */
  30. struct exynos_gpio_plat {
  31. struct s5p_gpio_bank *bank;
  32. const char *bank_name; /* Name of port, e.g. 'gpa0" */
  33. };
  34. /* Information about each bank at run-time */
  35. struct exynos_bank_info {
  36. struct s5p_gpio_bank *bank;
  37. };
  38. static struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned int gpio)
  39. {
  40. const struct gpio_info *data;
  41. unsigned int upto;
  42. int i, count;
  43. data = get_gpio_data();
  44. count = get_bank_num();
  45. upto = 0;
  46. for (i = 0; i < count; i++) {
  47. debug("i=%d, upto=%d\n", i, upto);
  48. if (gpio < data->max_gpio) {
  49. struct s5p_gpio_bank *bank;
  50. bank = (struct s5p_gpio_bank *)data->reg_addr;
  51. bank += (gpio - upto) / GPIO_PER_BANK;
  52. debug("gpio=%d, bank=%p\n", gpio, bank);
  53. return bank;
  54. }
  55. upto = data->max_gpio;
  56. data++;
  57. }
  58. return NULL;
  59. }
  60. static void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
  61. {
  62. unsigned int value;
  63. value = readl(&bank->con);
  64. value &= ~CON_MASK(gpio);
  65. value |= CON_SFR(gpio, cfg);
  66. writel(value, &bank->con);
  67. }
  68. static void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
  69. {
  70. unsigned int value;
  71. value = readl(&bank->dat);
  72. value &= ~DAT_MASK(gpio);
  73. if (en)
  74. value |= DAT_SET(gpio);
  75. writel(value, &bank->dat);
  76. }
  77. #ifdef CONFIG_SPL_BUILD
  78. /* Common GPIO API - SPL does not support driver model yet */
  79. int gpio_set_value(unsigned gpio, int value)
  80. {
  81. s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
  82. s5p_gpio_get_pin(gpio), value);
  83. return 0;
  84. }
  85. #else
  86. static int s5p_gpio_get_cfg_pin(struct s5p_gpio_bank *bank, int gpio)
  87. {
  88. unsigned int value;
  89. value = readl(&bank->con);
  90. value &= CON_MASK(gpio);
  91. return CON_SFR_UNSHIFT(value, gpio);
  92. }
  93. static unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
  94. {
  95. unsigned int value;
  96. value = readl(&bank->dat);
  97. return !!(value & DAT_MASK(gpio));
  98. }
  99. #endif /* CONFIG_SPL_BUILD */
  100. static void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
  101. {
  102. unsigned int value;
  103. value = readl(&bank->pull);
  104. value &= ~PULL_MASK(gpio);
  105. switch (mode) {
  106. case S5P_GPIO_PULL_DOWN:
  107. case S5P_GPIO_PULL_UP:
  108. value |= PULL_MODE(gpio, mode);
  109. break;
  110. default:
  111. break;
  112. }
  113. writel(value, &bank->pull);
  114. }
  115. static void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
  116. {
  117. unsigned int value;
  118. value = readl(&bank->drv);
  119. value &= ~DRV_MASK(gpio);
  120. switch (mode) {
  121. case S5P_GPIO_DRV_1X:
  122. case S5P_GPIO_DRV_2X:
  123. case S5P_GPIO_DRV_3X:
  124. case S5P_GPIO_DRV_4X:
  125. value |= DRV_SET(gpio, mode);
  126. break;
  127. default:
  128. return;
  129. }
  130. writel(value, &bank->drv);
  131. }
  132. static void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
  133. {
  134. unsigned int value;
  135. value = readl(&bank->drv);
  136. value &= ~RATE_MASK(gpio);
  137. switch (mode) {
  138. case S5P_GPIO_DRV_FAST:
  139. case S5P_GPIO_DRV_SLOW:
  140. value |= RATE_SET(gpio);
  141. break;
  142. default:
  143. return;
  144. }
  145. writel(value, &bank->drv);
  146. }
  147. int s5p_gpio_get_pin(unsigned gpio)
  148. {
  149. return S5P_GPIO_GET_PIN(gpio);
  150. }
  151. /* Driver model interface */
  152. #ifndef CONFIG_SPL_BUILD
  153. /* set GPIO pin 'gpio' as an input */
  154. static int exynos_gpio_direction_input(struct udevice *dev, unsigned offset)
  155. {
  156. struct exynos_bank_info *state = dev_get_priv(dev);
  157. /* Configure GPIO direction as input. */
  158. s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_INPUT);
  159. return 0;
  160. }
  161. /* set GPIO pin 'gpio' as an output, with polarity 'value' */
  162. static int exynos_gpio_direction_output(struct udevice *dev, unsigned offset,
  163. int value)
  164. {
  165. struct exynos_bank_info *state = dev_get_priv(dev);
  166. /* Configure GPIO output value. */
  167. s5p_gpio_set_value(state->bank, offset, value);
  168. /* Configure GPIO direction as output. */
  169. s5p_gpio_cfg_pin(state->bank, offset, S5P_GPIO_OUTPUT);
  170. return 0;
  171. }
  172. /* read GPIO IN value of pin 'gpio' */
  173. static int exynos_gpio_get_value(struct udevice *dev, unsigned offset)
  174. {
  175. struct exynos_bank_info *state = dev_get_priv(dev);
  176. return s5p_gpio_get_value(state->bank, offset);
  177. }
  178. /* write GPIO OUT value to pin 'gpio' */
  179. static int exynos_gpio_set_value(struct udevice *dev, unsigned offset,
  180. int value)
  181. {
  182. struct exynos_bank_info *state = dev_get_priv(dev);
  183. s5p_gpio_set_value(state->bank, offset, value);
  184. return 0;
  185. }
  186. #endif /* nCONFIG_SPL_BUILD */
  187. /*
  188. * There is no common GPIO API for pull, drv, pin, rate (yet). These
  189. * functions are kept here to preserve function ordering for review.
  190. */
  191. void gpio_set_pull(int gpio, int mode)
  192. {
  193. s5p_gpio_set_pull(s5p_gpio_get_bank(gpio),
  194. s5p_gpio_get_pin(gpio), mode);
  195. }
  196. void gpio_set_drv(int gpio, int mode)
  197. {
  198. s5p_gpio_set_drv(s5p_gpio_get_bank(gpio),
  199. s5p_gpio_get_pin(gpio), mode);
  200. }
  201. void gpio_cfg_pin(int gpio, int cfg)
  202. {
  203. s5p_gpio_cfg_pin(s5p_gpio_get_bank(gpio),
  204. s5p_gpio_get_pin(gpio), cfg);
  205. }
  206. void gpio_set_rate(int gpio, int mode)
  207. {
  208. s5p_gpio_set_rate(s5p_gpio_get_bank(gpio),
  209. s5p_gpio_get_pin(gpio), mode);
  210. }
  211. #ifndef CONFIG_SPL_BUILD
  212. static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
  213. {
  214. struct exynos_bank_info *state = dev_get_priv(dev);
  215. int cfg;
  216. cfg = s5p_gpio_get_cfg_pin(state->bank, offset);
  217. if (cfg == S5P_GPIO_OUTPUT)
  218. return GPIOF_OUTPUT;
  219. else if (cfg == S5P_GPIO_INPUT)
  220. return GPIOF_INPUT;
  221. else
  222. return GPIOF_FUNC;
  223. }
  224. static const struct dm_gpio_ops gpio_exynos_ops = {
  225. .direction_input = exynos_gpio_direction_input,
  226. .direction_output = exynos_gpio_direction_output,
  227. .get_value = exynos_gpio_get_value,
  228. .set_value = exynos_gpio_set_value,
  229. .get_function = exynos_gpio_get_function,
  230. };
  231. static int gpio_exynos_probe(struct udevice *dev)
  232. {
  233. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  234. struct exynos_bank_info *priv = dev_get_priv(dev);
  235. struct exynos_gpio_plat *plat = dev_get_plat(dev);
  236. /* Only child devices have ports */
  237. if (!plat)
  238. return 0;
  239. priv->bank = plat->bank;
  240. uc_priv->gpio_count = GPIO_PER_BANK;
  241. uc_priv->bank_name = plat->bank_name;
  242. return 0;
  243. }
  244. /**
  245. * We have a top-level GPIO device with no actual GPIOs. It has a child
  246. * device for each Exynos GPIO bank.
  247. */
  248. static int gpio_exynos_bind(struct udevice *parent)
  249. {
  250. struct exynos_gpio_plat *plat = dev_get_plat(parent);
  251. struct s5p_gpio_bank *bank, *base;
  252. const void *blob = gd->fdt_blob;
  253. int node;
  254. /* If this is a child device, there is nothing to do here */
  255. if (plat)
  256. return 0;
  257. base = dev_read_addr_ptr(parent);
  258. for (node = fdt_first_subnode(blob, dev_of_offset(parent)), bank = base;
  259. node > 0;
  260. node = fdt_next_subnode(blob, node), bank++) {
  261. struct exynos_gpio_plat *plat;
  262. struct udevice *dev;
  263. fdt_addr_t reg;
  264. int ret;
  265. if (!fdtdec_get_bool(blob, node, "gpio-controller"))
  266. continue;
  267. plat = calloc(1, sizeof(*plat));
  268. if (!plat)
  269. return -ENOMEM;
  270. plat->bank_name = fdt_get_name(blob, node, NULL);
  271. ret = device_bind(parent, parent->driver, plat->bank_name, plat,
  272. offset_to_ofnode(node), &dev);
  273. if (ret)
  274. return ret;
  275. reg = dev_read_addr(dev);
  276. if (reg != FDT_ADDR_T_NONE)
  277. bank = (struct s5p_gpio_bank *)((ulong)base + reg);
  278. plat->bank = bank;
  279. debug("dev at %p: %s\n", bank, plat->bank_name);
  280. }
  281. return 0;
  282. }
  283. static const struct udevice_id exynos_gpio_ids[] = {
  284. { .compatible = "samsung,s5pc100-pinctrl" },
  285. { .compatible = "samsung,s5pc110-pinctrl" },
  286. { .compatible = "samsung,exynos4210-pinctrl" },
  287. { .compatible = "samsung,exynos4x12-pinctrl" },
  288. { .compatible = "samsung,exynos5250-pinctrl" },
  289. { .compatible = "samsung,exynos5420-pinctrl" },
  290. { }
  291. };
  292. U_BOOT_DRIVER(gpio_exynos) = {
  293. .name = "gpio_exynos",
  294. .id = UCLASS_GPIO,
  295. .of_match = exynos_gpio_ids,
  296. .bind = gpio_exynos_bind,
  297. .probe = gpio_exynos_probe,
  298. .priv_auto = sizeof(struct exynos_bank_info),
  299. .ops = &gpio_exynos_ops,
  300. };
  301. #endif