sunxi_gpio.c 8.0 KB

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