omap_gpio.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * Copyright (c) 2009 Wind River Systems, Inc.
  3. * Tom Rix <Tom.Rix@windriver.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0
  6. *
  7. * This work is derived from the linux 2.6.27 kernel source
  8. * To fetch, use the kernel repository
  9. * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
  10. * Use the v2.6.27 tag.
  11. *
  12. * Below is the original's header including its copyright
  13. *
  14. * linux/arch/arm/plat-omap/gpio.c
  15. *
  16. * Support functions for OMAP GPIO
  17. *
  18. * Copyright (C) 2003-2005 Nokia Corporation
  19. * Written by Juha Yrjölä <juha.yrjola@nokia.com>
  20. */
  21. #include <common.h>
  22. #include <dm.h>
  23. #include <asm/gpio.h>
  24. #include <asm/io.h>
  25. #include <asm/errno.h>
  26. #define OMAP_GPIO_DIR_OUT 0
  27. #define OMAP_GPIO_DIR_IN 1
  28. #ifdef CONFIG_DM_GPIO
  29. #define GPIO_NAME_SIZE 20
  30. #define GPIO_PER_BANK 32
  31. struct gpio_bank {
  32. char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
  33. /* TODO(sjg@chromium.org): Can we use a struct here? */
  34. void *base; /* address of registers in physical memory */
  35. enum gpio_method method;
  36. };
  37. #endif
  38. static inline int get_gpio_index(int gpio)
  39. {
  40. return gpio & 0x1f;
  41. }
  42. int gpio_is_valid(int gpio)
  43. {
  44. return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
  45. }
  46. static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
  47. int is_input)
  48. {
  49. void *reg = bank->base;
  50. u32 l;
  51. switch (bank->method) {
  52. case METHOD_GPIO_24XX:
  53. reg += OMAP_GPIO_OE;
  54. break;
  55. default:
  56. return;
  57. }
  58. l = __raw_readl(reg);
  59. if (is_input)
  60. l |= 1 << gpio;
  61. else
  62. l &= ~(1 << gpio);
  63. __raw_writel(l, reg);
  64. }
  65. /**
  66. * Get the direction of the GPIO by reading the GPIO_OE register
  67. * corresponding to the specified bank.
  68. */
  69. static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
  70. {
  71. void *reg = bank->base;
  72. u32 v;
  73. switch (bank->method) {
  74. case METHOD_GPIO_24XX:
  75. reg += OMAP_GPIO_OE;
  76. break;
  77. default:
  78. return -1;
  79. }
  80. v = __raw_readl(reg);
  81. if (v & (1 << gpio))
  82. return OMAP_GPIO_DIR_IN;
  83. else
  84. return OMAP_GPIO_DIR_OUT;
  85. }
  86. static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
  87. int enable)
  88. {
  89. void *reg = bank->base;
  90. u32 l = 0;
  91. switch (bank->method) {
  92. case METHOD_GPIO_24XX:
  93. if (enable)
  94. reg += OMAP_GPIO_SETDATAOUT;
  95. else
  96. reg += OMAP_GPIO_CLEARDATAOUT;
  97. l = 1 << gpio;
  98. break;
  99. default:
  100. printf("omap3-gpio unknown bank method %s %d\n",
  101. __FILE__, __LINE__);
  102. return;
  103. }
  104. __raw_writel(l, reg);
  105. }
  106. static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
  107. {
  108. void *reg = bank->base;
  109. int input;
  110. switch (bank->method) {
  111. case METHOD_GPIO_24XX:
  112. input = _get_gpio_direction(bank, gpio);
  113. switch (input) {
  114. case OMAP_GPIO_DIR_IN:
  115. reg += OMAP_GPIO_DATAIN;
  116. break;
  117. case OMAP_GPIO_DIR_OUT:
  118. reg += OMAP_GPIO_DATAOUT;
  119. break;
  120. default:
  121. return -1;
  122. }
  123. break;
  124. default:
  125. return -1;
  126. }
  127. return (__raw_readl(reg) & (1 << gpio)) != 0;
  128. }
  129. #ifndef CONFIG_DM_GPIO
  130. static inline const struct gpio_bank *get_gpio_bank(int gpio)
  131. {
  132. return &omap_gpio_bank[gpio >> 5];
  133. }
  134. static int check_gpio(int gpio)
  135. {
  136. if (!gpio_is_valid(gpio)) {
  137. printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
  138. return -1;
  139. }
  140. return 0;
  141. }
  142. /**
  143. * Set value of the specified gpio
  144. */
  145. int gpio_set_value(unsigned gpio, int value)
  146. {
  147. const struct gpio_bank *bank;
  148. if (check_gpio(gpio) < 0)
  149. return -1;
  150. bank = get_gpio_bank(gpio);
  151. _set_gpio_dataout(bank, get_gpio_index(gpio), value);
  152. return 0;
  153. }
  154. /**
  155. * Get value of the specified gpio
  156. */
  157. int gpio_get_value(unsigned gpio)
  158. {
  159. const struct gpio_bank *bank;
  160. if (check_gpio(gpio) < 0)
  161. return -1;
  162. bank = get_gpio_bank(gpio);
  163. return _get_gpio_value(bank, get_gpio_index(gpio));
  164. }
  165. /**
  166. * Set gpio direction as input
  167. */
  168. int gpio_direction_input(unsigned gpio)
  169. {
  170. const struct gpio_bank *bank;
  171. if (check_gpio(gpio) < 0)
  172. return -1;
  173. bank = get_gpio_bank(gpio);
  174. _set_gpio_direction(bank, get_gpio_index(gpio), 1);
  175. return 0;
  176. }
  177. /**
  178. * Set gpio direction as output
  179. */
  180. int gpio_direction_output(unsigned gpio, int value)
  181. {
  182. const struct gpio_bank *bank;
  183. if (check_gpio(gpio) < 0)
  184. return -1;
  185. bank = get_gpio_bank(gpio);
  186. _set_gpio_dataout(bank, get_gpio_index(gpio), value);
  187. _set_gpio_direction(bank, get_gpio_index(gpio), 0);
  188. return 0;
  189. }
  190. /**
  191. * Request a gpio before using it.
  192. *
  193. * NOTE: Argument 'label' is unused.
  194. */
  195. int gpio_request(unsigned gpio, const char *label)
  196. {
  197. if (check_gpio(gpio) < 0)
  198. return -1;
  199. return 0;
  200. }
  201. /**
  202. * Reset and free the gpio after using it.
  203. */
  204. int gpio_free(unsigned gpio)
  205. {
  206. return 0;
  207. }
  208. #else /* new driver model interface CONFIG_DM_GPIO */
  209. /**
  210. * gpio_is_requested() - check if a GPIO has been requested
  211. *
  212. * @bank: Bank to check
  213. * @offset: GPIO offset within bank to check
  214. * @return true if marked as requested, false if not
  215. */
  216. static inline bool gpio_is_requested(struct gpio_bank *bank, int offset)
  217. {
  218. return *bank->label[offset] != '\0';
  219. }
  220. static int omap_gpio_is_output(struct gpio_bank *bank, int offset)
  221. {
  222. return _get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT;
  223. }
  224. static int check_requested(struct udevice *dev, unsigned offset,
  225. const char *func)
  226. {
  227. struct gpio_bank *bank = dev_get_priv(dev);
  228. struct gpio_dev_priv *uc_priv = dev->uclass_priv;
  229. if (!gpio_is_requested(bank, offset)) {
  230. printf("omap_gpio: %s: error: gpio %s%d not requested\n",
  231. func, uc_priv->bank_name, offset);
  232. return -EPERM;
  233. }
  234. return 0;
  235. }
  236. /* set GPIO pin 'gpio' as an input */
  237. static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
  238. {
  239. struct gpio_bank *bank = dev_get_priv(dev);
  240. int ret;
  241. ret = check_requested(dev, offset, __func__);
  242. if (ret)
  243. return ret;
  244. /* Configure GPIO direction as input. */
  245. _set_gpio_direction(bank, offset, 1);
  246. return 0;
  247. }
  248. /* set GPIO pin 'gpio' as an output, with polarity 'value' */
  249. static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
  250. int value)
  251. {
  252. struct gpio_bank *bank = dev_get_priv(dev);
  253. int ret;
  254. ret = check_requested(dev, offset, __func__);
  255. if (ret)
  256. return ret;
  257. _set_gpio_dataout(bank, offset, value);
  258. _set_gpio_direction(bank, offset, 0);
  259. return 0;
  260. }
  261. /* read GPIO IN value of pin 'gpio' */
  262. static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
  263. {
  264. struct gpio_bank *bank = dev_get_priv(dev);
  265. int ret;
  266. ret = check_requested(dev, offset, __func__);
  267. if (ret)
  268. return ret;
  269. return _get_gpio_value(bank, offset);
  270. }
  271. /* write GPIO OUT value to pin 'gpio' */
  272. static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
  273. int value)
  274. {
  275. struct gpio_bank *bank = dev_get_priv(dev);
  276. int ret;
  277. ret = check_requested(dev, offset, __func__);
  278. if (ret)
  279. return ret;
  280. _set_gpio_dataout(bank, offset, value);
  281. return 0;
  282. }
  283. static int omap_gpio_get_state(struct udevice *dev, unsigned int offset,
  284. char *buf, int bufsize)
  285. {
  286. struct gpio_dev_priv *uc_priv = dev->uclass_priv;
  287. struct gpio_bank *bank = dev_get_priv(dev);
  288. const char *label;
  289. bool requested;
  290. bool is_output;
  291. int size;
  292. label = bank->label[offset];
  293. is_output = omap_gpio_is_output(bank->base, offset);
  294. size = snprintf(buf, bufsize, "%s%d: ",
  295. uc_priv->bank_name ? uc_priv->bank_name : "", offset);
  296. buf += size;
  297. bufsize -= size;
  298. requested = gpio_is_requested(bank, offset);
  299. snprintf(buf, bufsize, "%s: %d [%c]%s%s",
  300. is_output ? "out" : " in",
  301. _get_gpio_value(bank, offset),
  302. requested ? 'x' : ' ',
  303. requested ? " " : "",
  304. label);
  305. return 0;
  306. }
  307. static int omap_gpio_request(struct udevice *dev, unsigned offset,
  308. const char *label)
  309. {
  310. struct gpio_bank *bank = dev_get_priv(dev);
  311. if (gpio_is_requested(bank, offset))
  312. return -EBUSY;
  313. strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
  314. bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
  315. return 0;
  316. }
  317. static int omap_gpio_free(struct udevice *dev, unsigned offset)
  318. {
  319. struct gpio_bank *bank = dev_get_priv(dev);
  320. int ret;
  321. ret = check_requested(dev, offset, __func__);
  322. if (ret)
  323. return ret;
  324. bank->label[offset][0] = '\0';
  325. return 0;
  326. }
  327. static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
  328. {
  329. struct gpio_bank *bank = dev_get_priv(dev);
  330. if (!gpio_is_requested(bank, offset))
  331. return GPIOF_UNUSED;
  332. /* GPIOF_FUNC is not implemented yet */
  333. if (_get_gpio_direction(bank->base, offset))
  334. return GPIOF_OUTPUT;
  335. else
  336. return GPIOF_INPUT;
  337. }
  338. static const struct dm_gpio_ops gpio_omap_ops = {
  339. .request = omap_gpio_request,
  340. .free = omap_gpio_free,
  341. .direction_input = omap_gpio_direction_input,
  342. .direction_output = omap_gpio_direction_output,
  343. .get_value = omap_gpio_get_value,
  344. .set_value = omap_gpio_set_value,
  345. .get_function = omap_gpio_get_function,
  346. .get_state = omap_gpio_get_state,
  347. };
  348. static int omap_gpio_probe(struct udevice *dev)
  349. {
  350. struct gpio_bank *bank = dev_get_priv(dev);
  351. struct omap_gpio_platdata *plat = dev_get_platdata(dev);
  352. struct gpio_dev_priv *uc_priv = dev->uclass_priv;
  353. char name[18], *str;
  354. sprintf(name, "GPIO%d_", plat->bank_index);
  355. str = strdup(name);
  356. if (!str)
  357. return -ENOMEM;
  358. uc_priv->bank_name = str;
  359. uc_priv->gpio_count = GPIO_PER_BANK;
  360. bank->base = (void *)plat->base;
  361. bank->method = plat->method;
  362. return 0;
  363. }
  364. U_BOOT_DRIVER(gpio_omap) = {
  365. .name = "gpio_omap",
  366. .id = UCLASS_GPIO,
  367. .ops = &gpio_omap_ops,
  368. .probe = omap_gpio_probe,
  369. .priv_auto_alloc_size = sizeof(struct gpio_bank),
  370. };
  371. #endif /* CONFIG_DM_GPIO */