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