tegra186_gpio.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright (c) 2010-2016, NVIDIA CORPORATION.
  3. * (based on tegra_gpio.c)
  4. *
  5. * SPDX-License-Identifier: GPL-2.0
  6. */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <malloc.h>
  10. #include <errno.h>
  11. #include <fdtdec.h>
  12. #include <asm/io.h>
  13. #include <asm/bitops.h>
  14. #include <asm/gpio.h>
  15. #include <dm/device-internal.h>
  16. #include <dt-bindings/gpio/gpio.h>
  17. #include "tegra186_gpio_priv.h"
  18. DECLARE_GLOBAL_DATA_PTR;
  19. struct tegra186_gpio_port_data {
  20. const char *name;
  21. uint32_t offset;
  22. };
  23. struct tegra186_gpio_ctlr_data {
  24. const struct tegra186_gpio_port_data *ports;
  25. uint32_t port_count;
  26. };
  27. struct tegra186_gpio_platdata {
  28. const char *name;
  29. uint32_t *regs;
  30. };
  31. static uint32_t *tegra186_gpio_reg(struct udevice *dev, uint32_t reg,
  32. uint32_t gpio)
  33. {
  34. struct tegra186_gpio_platdata *plat = dev->platdata;
  35. uint32_t index = (reg + (gpio * TEGRA186_GPIO_PER_GPIO_STRIDE)) / 4;
  36. return &(plat->regs[index]);
  37. }
  38. static int tegra186_gpio_set_out(struct udevice *dev, unsigned offset,
  39. bool output)
  40. {
  41. uint32_t *reg;
  42. uint32_t rval;
  43. reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_CONTROL, offset);
  44. rval = readl(reg);
  45. if (output)
  46. rval &= ~TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
  47. else
  48. rval |= TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
  49. writel(rval, reg);
  50. reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
  51. rval = readl(reg);
  52. if (output)
  53. rval |= TEGRA186_GPIO_ENABLE_CONFIG_OUT;
  54. else
  55. rval &= ~TEGRA186_GPIO_ENABLE_CONFIG_OUT;
  56. rval |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;
  57. writel(rval, reg);
  58. return 0;
  59. }
  60. static int tegra186_gpio_set_val(struct udevice *dev, unsigned offset, bool val)
  61. {
  62. uint32_t *reg;
  63. uint32_t rval;
  64. reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE, offset);
  65. rval = readl(reg);
  66. if (val)
  67. rval |= TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
  68. else
  69. rval &= ~TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
  70. writel(rval, reg);
  71. return 0;
  72. }
  73. static int tegra186_gpio_direction_input(struct udevice *dev, unsigned offset)
  74. {
  75. return tegra186_gpio_set_out(dev, offset, false);
  76. }
  77. static int tegra186_gpio_direction_output(struct udevice *dev, unsigned offset,
  78. int value)
  79. {
  80. int ret;
  81. ret = tegra186_gpio_set_val(dev, offset, value != 0);
  82. if (ret)
  83. return ret;
  84. return tegra186_gpio_set_out(dev, offset, true);
  85. }
  86. static int tegra186_gpio_get_value(struct udevice *dev, unsigned offset)
  87. {
  88. uint32_t *reg;
  89. uint32_t rval;
  90. reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
  91. rval = readl(reg);
  92. if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
  93. reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE,
  94. offset);
  95. else
  96. reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_INPUT, offset);
  97. rval = readl(reg);
  98. return !!rval;
  99. }
  100. static int tegra186_gpio_set_value(struct udevice *dev, unsigned offset,
  101. int value)
  102. {
  103. return tegra186_gpio_set_val(dev, offset, value != 0);
  104. }
  105. static int tegra186_gpio_get_function(struct udevice *dev, unsigned offset)
  106. {
  107. uint32_t *reg;
  108. uint32_t rval;
  109. reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
  110. rval = readl(reg);
  111. if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
  112. return GPIOF_OUTPUT;
  113. else
  114. return GPIOF_INPUT;
  115. }
  116. static int tegra186_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
  117. struct fdtdec_phandle_args *args)
  118. {
  119. int gpio, port, ret;
  120. gpio = args->args[0];
  121. port = gpio / TEGRA186_GPIO_PER_GPIO_COUNT;
  122. ret = device_get_child(dev, port, &desc->dev);
  123. if (ret)
  124. return ret;
  125. desc->offset = gpio % TEGRA186_GPIO_PER_GPIO_COUNT;
  126. desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
  127. return 0;
  128. }
  129. static const struct dm_gpio_ops tegra186_gpio_ops = {
  130. .direction_input = tegra186_gpio_direction_input,
  131. .direction_output = tegra186_gpio_direction_output,
  132. .get_value = tegra186_gpio_get_value,
  133. .set_value = tegra186_gpio_set_value,
  134. .get_function = tegra186_gpio_get_function,
  135. .xlate = tegra186_gpio_xlate,
  136. };
  137. /**
  138. * We have a top-level GPIO device with no actual GPIOs. It has a child device
  139. * for each port within the controller.
  140. */
  141. static int tegra186_gpio_bind(struct udevice *parent)
  142. {
  143. struct tegra186_gpio_platdata *parent_plat = parent->platdata;
  144. struct tegra186_gpio_ctlr_data *ctlr_data =
  145. (struct tegra186_gpio_ctlr_data *)dev_get_driver_data(parent);
  146. uint32_t *regs;
  147. int port, ret;
  148. /* If this is a child device, there is nothing to do here */
  149. if (parent_plat)
  150. return 0;
  151. regs = (uint32_t *)dev_get_addr_name(parent, "gpio");
  152. if (regs == (uint32_t *)FDT_ADDR_T_NONE)
  153. return -ENODEV;
  154. for (port = 0; port < ctlr_data->port_count; port++) {
  155. struct tegra186_gpio_platdata *plat;
  156. struct udevice *dev;
  157. plat = calloc(1, sizeof(*plat));
  158. if (!plat)
  159. return -ENOMEM;
  160. plat->name = ctlr_data->ports[port].name;
  161. plat->regs = &(regs[ctlr_data->ports[port].offset / 4]);
  162. ret = device_bind(parent, parent->driver, plat->name, plat,
  163. -1, &dev);
  164. if (ret)
  165. return ret;
  166. dev->of_offset = parent->of_offset;
  167. }
  168. return 0;
  169. }
  170. static int tegra186_gpio_probe(struct udevice *dev)
  171. {
  172. struct tegra186_gpio_platdata *plat = dev->platdata;
  173. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  174. /* Only child devices have ports */
  175. if (!plat)
  176. return 0;
  177. uc_priv->gpio_count = TEGRA186_GPIO_PER_GPIO_COUNT;
  178. uc_priv->bank_name = plat->name;
  179. return 0;
  180. }
  181. static const struct tegra186_gpio_port_data tegra186_gpio_main_ports[] = {
  182. {"A", 0x2000},
  183. {"B", 0x3000},
  184. {"C", 0x3200},
  185. {"D", 0x3400},
  186. {"E", 0x2200},
  187. {"F", 0x2400},
  188. {"G", 0x4200},
  189. {"H", 0x1000},
  190. {"I", 0x0800},
  191. {"J", 0x5000},
  192. {"K", 0x5200},
  193. {"L", 0x1200},
  194. {"M", 0x5600},
  195. {"N", 0x0000},
  196. {"O", 0x0200},
  197. {"P", 0x4000},
  198. {"Q", 0x0400},
  199. {"R", 0x0a00},
  200. {"T", 0x0600},
  201. {"X", 0x1400},
  202. {"Y", 0x1600},
  203. {"BB", 0x2600},
  204. {"CC", 0x5400},
  205. };
  206. static const struct tegra186_gpio_ctlr_data tegra186_gpio_main_data = {
  207. .ports = tegra186_gpio_main_ports,
  208. .port_count = ARRAY_SIZE(tegra186_gpio_main_ports),
  209. };
  210. static const struct tegra186_gpio_port_data tegra186_gpio_aon_ports[] = {
  211. {"S", 0x0200},
  212. {"U", 0x0400},
  213. {"V", 0x0800},
  214. {"W", 0x0a00},
  215. {"Z", 0x0e00},
  216. {"AA", 0x0c00},
  217. {"EE", 0x0600},
  218. {"FF", 0x0000},
  219. };
  220. static const struct tegra186_gpio_ctlr_data tegra186_gpio_aon_data = {
  221. .ports = tegra186_gpio_aon_ports,
  222. .port_count = ARRAY_SIZE(tegra186_gpio_aon_ports),
  223. };
  224. static const struct udevice_id tegra186_gpio_ids[] = {
  225. {
  226. .compatible = "nvidia,tegra186-gpio",
  227. .data = (ulong)&tegra186_gpio_main_data,
  228. },
  229. {
  230. .compatible = "nvidia,tegra186-gpio-aon",
  231. .data = (ulong)&tegra186_gpio_aon_data,
  232. },
  233. { }
  234. };
  235. U_BOOT_DRIVER(tegra186_gpio) = {
  236. .name = "tegra186_gpio",
  237. .id = UCLASS_GPIO,
  238. .of_match = tegra186_gpio_ids,
  239. .bind = tegra186_gpio_bind,
  240. .probe = tegra186_gpio_probe,
  241. .ops = &tegra186_gpio_ops,
  242. .flags = DM_FLAG_PRE_RELOC,
  243. };