sunxi_gpio.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
  4. *
  5. * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c:
  6. *
  7. * (C) Copyright 2007-2011
  8. * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  9. * Tom Cubie <tangliang@allwinnertech.com>
  10. */
  11. #include <common.h>
  12. #include <dm.h>
  13. #include <errno.h>
  14. #include <fdtdec.h>
  15. #include <malloc.h>
  16. #include <asm/arch/gpio.h>
  17. #include <asm/io.h>
  18. #include <asm/gpio.h>
  19. #include <dm/device-internal.h>
  20. #include <dt-bindings/gpio/gpio.h>
  21. #define SUNXI_GPIOS_PER_BANK SUNXI_GPIO_A_NR
  22. struct sunxi_gpio_platdata {
  23. struct sunxi_gpio *regs;
  24. const char *bank_name; /* Name of bank, e.g. "B" */
  25. int gpio_count;
  26. };
  27. #if !CONFIG_IS_ENABLED(DM_GPIO)
  28. static int sunxi_gpio_output(u32 pin, u32 val)
  29. {
  30. u32 dat;
  31. u32 bank = GPIO_BANK(pin);
  32. u32 num = GPIO_NUM(pin);
  33. struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
  34. dat = readl(&pio->dat);
  35. if (val)
  36. dat |= 0x1 << num;
  37. else
  38. dat &= ~(0x1 << num);
  39. writel(dat, &pio->dat);
  40. return 0;
  41. }
  42. static int sunxi_gpio_input(u32 pin)
  43. {
  44. u32 dat;
  45. u32 bank = GPIO_BANK(pin);
  46. u32 num = GPIO_NUM(pin);
  47. struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
  48. dat = readl(&pio->dat);
  49. dat >>= num;
  50. return dat & 0x1;
  51. }
  52. int gpio_request(unsigned gpio, const char *label)
  53. {
  54. return 0;
  55. }
  56. int gpio_free(unsigned gpio)
  57. {
  58. return 0;
  59. }
  60. int gpio_direction_input(unsigned gpio)
  61. {
  62. sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
  63. return 0;
  64. }
  65. int gpio_direction_output(unsigned gpio, int value)
  66. {
  67. sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
  68. return sunxi_gpio_output(gpio, value);
  69. }
  70. int gpio_get_value(unsigned gpio)
  71. {
  72. return sunxi_gpio_input(gpio);
  73. }
  74. int gpio_set_value(unsigned gpio, int value)
  75. {
  76. return sunxi_gpio_output(gpio, value);
  77. }
  78. int sunxi_name_to_gpio(const char *name)
  79. {
  80. int group = 0;
  81. int groupsize = 9 * 32;
  82. long pin;
  83. char *eptr;
  84. if (*name == 'P' || *name == 'p')
  85. name++;
  86. if (*name >= 'A') {
  87. group = *name - (*name > 'a' ? 'a' : 'A');
  88. groupsize = 32;
  89. name++;
  90. }
  91. pin = simple_strtol(name, &eptr, 10);
  92. if (!*name || *eptr)
  93. return -1;
  94. if (pin < 0 || pin > groupsize || group >= 9)
  95. return -1;
  96. return group * 32 + pin;
  97. }
  98. #endif /* DM_GPIO */
  99. int sunxi_name_to_gpio_bank(const char *name)
  100. {
  101. int group = 0;
  102. if (*name == 'P' || *name == 'p')
  103. name++;
  104. if (*name >= 'A') {
  105. group = *name - (*name > 'a' ? 'a' : 'A');
  106. return group;
  107. }
  108. return -1;
  109. }
  110. #if CONFIG_IS_ENABLED(DM_GPIO)
  111. /* TODO(sjg@chromium.org): Remove this function and use device tree */
  112. int sunxi_name_to_gpio(const char *name)
  113. {
  114. unsigned int gpio;
  115. int ret;
  116. #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
  117. char lookup[8];
  118. if (strcasecmp(name, "AXP0-VBUS-DETECT") == 0) {
  119. sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
  120. SUNXI_GPIO_AXP0_VBUS_DETECT);
  121. name = lookup;
  122. } else if (strcasecmp(name, "AXP0-VBUS-ENABLE") == 0) {
  123. sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
  124. SUNXI_GPIO_AXP0_VBUS_ENABLE);
  125. name = lookup;
  126. }
  127. #endif
  128. ret = gpio_lookup_name(name, NULL, NULL, &gpio);
  129. return ret ? ret : gpio;
  130. }
  131. static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset)
  132. {
  133. struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
  134. sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_INPUT);
  135. return 0;
  136. }
  137. static int sunxi_gpio_direction_output(struct udevice *dev, unsigned offset,
  138. int value)
  139. {
  140. struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
  141. u32 num = GPIO_NUM(offset);
  142. sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
  143. clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
  144. return 0;
  145. }
  146. static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
  147. {
  148. struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
  149. u32 num = GPIO_NUM(offset);
  150. unsigned dat;
  151. dat = readl(&plat->regs->dat);
  152. dat >>= num;
  153. return dat & 0x1;
  154. }
  155. static int sunxi_gpio_set_value(struct udevice *dev, unsigned offset,
  156. int value)
  157. {
  158. struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
  159. u32 num = GPIO_NUM(offset);
  160. clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
  161. return 0;
  162. }
  163. static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
  164. {
  165. struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
  166. int func;
  167. func = sunxi_gpio_get_cfgbank(plat->regs, offset);
  168. if (func == SUNXI_GPIO_OUTPUT)
  169. return GPIOF_OUTPUT;
  170. else if (func == SUNXI_GPIO_INPUT)
  171. return GPIOF_INPUT;
  172. else
  173. return GPIOF_FUNC;
  174. }
  175. static int sunxi_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
  176. struct ofnode_phandle_args *args)
  177. {
  178. int ret;
  179. ret = device_get_child(dev, args->args[0], &desc->dev);
  180. if (ret)
  181. return ret;
  182. desc->offset = args->args[1];
  183. desc->flags = args->args[2] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
  184. return 0;
  185. }
  186. static const struct dm_gpio_ops gpio_sunxi_ops = {
  187. .direction_input = sunxi_gpio_direction_input,
  188. .direction_output = sunxi_gpio_direction_output,
  189. .get_value = sunxi_gpio_get_value,
  190. .set_value = sunxi_gpio_set_value,
  191. .get_function = sunxi_gpio_get_function,
  192. .xlate = sunxi_gpio_xlate,
  193. };
  194. /**
  195. * Returns the name of a GPIO bank
  196. *
  197. * GPIO banks are named A, B, C, ...
  198. *
  199. * @bank: Bank number (0, 1..n-1)
  200. * @return allocated string containing the name
  201. */
  202. static char *gpio_bank_name(int bank)
  203. {
  204. char *name;
  205. name = malloc(3);
  206. if (name) {
  207. name[0] = 'P';
  208. name[1] = 'A' + bank;
  209. name[2] = '\0';
  210. }
  211. return name;
  212. }
  213. static int gpio_sunxi_probe(struct udevice *dev)
  214. {
  215. struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
  216. struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  217. /* Tell the uclass how many GPIOs we have */
  218. if (plat) {
  219. uc_priv->gpio_count = plat->gpio_count;
  220. uc_priv->bank_name = plat->bank_name;
  221. }
  222. return 0;
  223. }
  224. struct sunxi_gpio_soc_data {
  225. int start;
  226. int no_banks;
  227. };
  228. /**
  229. * We have a top-level GPIO device with no actual GPIOs. It has a child
  230. * device for each Sunxi bank.
  231. */
  232. static int gpio_sunxi_bind(struct udevice *parent)
  233. {
  234. struct sunxi_gpio_soc_data *soc_data =
  235. (struct sunxi_gpio_soc_data *)dev_get_driver_data(parent);
  236. struct sunxi_gpio_platdata *plat = parent->platdata;
  237. struct sunxi_gpio_reg *ctlr;
  238. int bank, ret;
  239. /* If this is a child device, there is nothing to do here */
  240. if (plat)
  241. return 0;
  242. ctlr = (struct sunxi_gpio_reg *)devfdt_get_addr(parent);
  243. for (bank = 0; bank < soc_data->no_banks; bank++) {
  244. struct sunxi_gpio_platdata *plat;
  245. struct udevice *dev;
  246. plat = calloc(1, sizeof(*plat));
  247. if (!plat)
  248. return -ENOMEM;
  249. plat->regs = &ctlr->gpio_bank[bank];
  250. plat->bank_name = gpio_bank_name(soc_data->start + bank);
  251. plat->gpio_count = SUNXI_GPIOS_PER_BANK;
  252. ret = device_bind(parent, parent->driver,
  253. plat->bank_name, plat, -1, &dev);
  254. if (ret)
  255. return ret;
  256. dev_set_of_offset(dev, dev_of_offset(parent));
  257. }
  258. return 0;
  259. }
  260. static const struct sunxi_gpio_soc_data soc_data_a_all = {
  261. .start = 0,
  262. .no_banks = SUNXI_GPIO_BANKS,
  263. };
  264. static const struct sunxi_gpio_soc_data soc_data_l_1 = {
  265. .start = 'L' - 'A',
  266. .no_banks = 1,
  267. };
  268. static const struct sunxi_gpio_soc_data soc_data_l_2 = {
  269. .start = 'L' - 'A',
  270. .no_banks = 2,
  271. };
  272. static const struct sunxi_gpio_soc_data soc_data_l_3 = {
  273. .start = 'L' - 'A',
  274. .no_banks = 3,
  275. };
  276. #define ID(_compat_, _soc_data_) \
  277. { .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
  278. static const struct udevice_id sunxi_gpio_ids[] = {
  279. ID("allwinner,sun4i-a10-pinctrl", a_all),
  280. ID("allwinner,sun5i-a10s-pinctrl", a_all),
  281. ID("allwinner,sun5i-a13-pinctrl", a_all),
  282. ID("allwinner,sun50i-h5-pinctrl", a_all),
  283. ID("allwinner,sun6i-a31-pinctrl", a_all),
  284. ID("allwinner,sun6i-a31s-pinctrl", a_all),
  285. ID("allwinner,sun7i-a20-pinctrl", a_all),
  286. ID("allwinner,sun8i-a23-pinctrl", a_all),
  287. ID("allwinner,sun8i-a33-pinctrl", a_all),
  288. ID("allwinner,sun8i-a83t-pinctrl", a_all),
  289. ID("allwinner,sun8i-h3-pinctrl", a_all),
  290. ID("allwinner,sun8i-r40-pinctrl", a_all),
  291. ID("allwinner,sun8i-v3s-pinctrl", a_all),
  292. ID("allwinner,sun9i-a80-pinctrl", a_all),
  293. ID("allwinner,sun50i-a64-pinctrl", a_all),
  294. ID("allwinner,sun50i-h6-pinctrl", a_all),
  295. ID("allwinner,sun6i-a31-r-pinctrl", l_2),
  296. ID("allwinner,sun8i-a23-r-pinctrl", l_1),
  297. ID("allwinner,sun8i-a83t-r-pinctrl", l_1),
  298. ID("allwinner,sun8i-h3-r-pinctrl", l_1),
  299. ID("allwinner,sun9i-a80-r-pinctrl", l_3),
  300. ID("allwinner,sun50i-a64-r-pinctrl", l_1),
  301. ID("allwinner,sun50i-h6-r-pinctrl", l_2),
  302. { }
  303. };
  304. U_BOOT_DRIVER(gpio_sunxi) = {
  305. .name = "gpio_sunxi",
  306. .id = UCLASS_GPIO,
  307. .ops = &gpio_sunxi_ops,
  308. .of_match = sunxi_gpio_ids,
  309. .bind = gpio_sunxi_bind,
  310. .probe = gpio_sunxi_probe,
  311. };
  312. #endif /* DM_GPIO */