s5p_gpio.c 8.4 KB

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