adi_gpio2.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /*
  2. * ADI GPIO2 Abstraction Layer
  3. * Support BF54x, BF60x and future processors.
  4. *
  5. * Copyright 2008-2013 Analog Devices Inc.
  6. *
  7. * Licensed under the GPL-2 or later
  8. */
  9. #include <common.h>
  10. #include <asm/errno.h>
  11. #include <asm/gpio.h>
  12. #include <asm/portmux.h>
  13. static struct gpio_port_t * const gpio_array[] = {
  14. (struct gpio_port_t *)PORTA_FER,
  15. (struct gpio_port_t *)PORTB_FER,
  16. (struct gpio_port_t *)PORTC_FER,
  17. (struct gpio_port_t *)PORTD_FER,
  18. (struct gpio_port_t *)PORTE_FER,
  19. (struct gpio_port_t *)PORTF_FER,
  20. (struct gpio_port_t *)PORTG_FER,
  21. #if defined(CONFIG_BF54x)
  22. (struct gpio_port_t *)PORTH_FER,
  23. (struct gpio_port_t *)PORTI_FER,
  24. (struct gpio_port_t *)PORTJ_FER,
  25. #endif
  26. };
  27. #define RESOURCE_LABEL_SIZE 16
  28. static struct str_ident {
  29. char name[RESOURCE_LABEL_SIZE];
  30. } str_ident[MAX_RESOURCES];
  31. static void gpio_error(unsigned gpio)
  32. {
  33. printf("adi_gpio2: GPIO %d wasn't requested!\n", gpio);
  34. }
  35. static void set_label(unsigned short ident, const char *label)
  36. {
  37. if (label) {
  38. strncpy(str_ident[ident].name, label,
  39. RESOURCE_LABEL_SIZE);
  40. str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
  41. }
  42. }
  43. static char *get_label(unsigned short ident)
  44. {
  45. return *str_ident[ident].name ? str_ident[ident].name : "UNKNOWN";
  46. }
  47. static int cmp_label(unsigned short ident, const char *label)
  48. {
  49. if (label == NULL)
  50. printf("adi_gpio2: please provide none-null label\n");
  51. if (label)
  52. return strcmp(str_ident[ident].name, label);
  53. else
  54. return -EINVAL;
  55. }
  56. #define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]
  57. #define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
  58. #define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))
  59. #define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))
  60. #define DECLARE_RESERVED_MAP(m, c) unsigned short reserved_##m##_map[c]
  61. static DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
  62. static DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES));
  63. inline int check_gpio(unsigned gpio)
  64. {
  65. #if defined(CONFIG_BF54x)
  66. if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 ||
  67. gpio == GPIO_PH14 || gpio == GPIO_PH15 ||
  68. gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
  69. return -EINVAL;
  70. #endif
  71. if (gpio >= MAX_GPIOS)
  72. return -EINVAL;
  73. return 0;
  74. }
  75. static void port_setup(unsigned gpio, unsigned short usage)
  76. {
  77. #if defined(CONFIG_BF54x)
  78. if (usage == GPIO_USAGE)
  79. gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
  80. else
  81. gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
  82. #else
  83. if (usage == GPIO_USAGE)
  84. gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio);
  85. else
  86. gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio);
  87. #endif
  88. SSYNC();
  89. }
  90. inline void portmux_setup(unsigned short per)
  91. {
  92. u32 pmux;
  93. u16 ident = P_IDENT(per);
  94. u16 function = P_FUNCT2MUX(per);
  95. pmux = gpio_array[gpio_bank(ident)]->port_mux;
  96. pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
  97. pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
  98. gpio_array[gpio_bank(ident)]->port_mux = pmux;
  99. }
  100. inline u16 get_portmux(unsigned short per)
  101. {
  102. u32 pmux;
  103. u16 ident = P_IDENT(per);
  104. pmux = gpio_array[gpio_bank(ident)]->port_mux;
  105. return pmux >> (2 * gpio_sub_n(ident)) & 0x3;
  106. }
  107. unsigned short get_gpio_dir(unsigned gpio)
  108. {
  109. return 0x01 &
  110. (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio));
  111. }
  112. /***********************************************************
  113. *
  114. * FUNCTIONS: Peripheral Resource Allocation
  115. * and PortMux Setup
  116. *
  117. * INPUTS/OUTPUTS:
  118. * per Peripheral Identifier
  119. * label String
  120. *
  121. * DESCRIPTION: Peripheral Resource Allocation and Setup API
  122. **************************************************************/
  123. int peripheral_request(unsigned short per, const char *label)
  124. {
  125. unsigned short ident = P_IDENT(per);
  126. /*
  127. * Don't cares are pins with only one dedicated function
  128. */
  129. if (per & P_DONTCARE)
  130. return 0;
  131. if (!(per & P_DEFINED))
  132. return -ENODEV;
  133. BUG_ON(ident >= MAX_RESOURCES);
  134. /* If a pin can be muxed as either GPIO or peripheral, make
  135. * sure it is not already a GPIO pin when we request it.
  136. */
  137. if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
  138. printf("%s: Peripheral %d is already reserved as GPIO by %s!\n",
  139. __func__, ident, get_label(ident));
  140. return -EBUSY;
  141. }
  142. if (unlikely(is_reserved(peri, ident, 1))) {
  143. /*
  144. * Pin functions like AMC address strobes my
  145. * be requested and used by several drivers
  146. */
  147. if (!((per & P_MAYSHARE) &&
  148. get_portmux(per) == P_FUNCT2MUX(per))) {
  149. /*
  150. * Allow that the identical pin function can
  151. * be requested from the same driver twice
  152. */
  153. if (cmp_label(ident, label) == 0)
  154. goto anyway;
  155. printf("%s: Peripheral %d function %d is already "
  156. "reserved by %s!\n", __func__, ident,
  157. P_FUNCT2MUX(per), get_label(ident));
  158. return -EBUSY;
  159. }
  160. }
  161. anyway:
  162. reserve(peri, ident);
  163. portmux_setup(per);
  164. port_setup(ident, PERIPHERAL_USAGE);
  165. set_label(ident, label);
  166. return 0;
  167. }
  168. int peripheral_request_list(const unsigned short per[], const char *label)
  169. {
  170. u16 cnt;
  171. int ret;
  172. for (cnt = 0; per[cnt] != 0; cnt++) {
  173. ret = peripheral_request(per[cnt], label);
  174. if (ret < 0) {
  175. for (; cnt > 0; cnt--)
  176. peripheral_free(per[cnt - 1]);
  177. return ret;
  178. }
  179. }
  180. return 0;
  181. }
  182. void peripheral_free(unsigned short per)
  183. {
  184. unsigned short ident = P_IDENT(per);
  185. if (per & P_DONTCARE)
  186. return;
  187. if (!(per & P_DEFINED))
  188. return;
  189. if (unlikely(!is_reserved(peri, ident, 0)))
  190. return;
  191. if (!(per & P_MAYSHARE))
  192. port_setup(ident, GPIO_USAGE);
  193. unreserve(peri, ident);
  194. set_label(ident, "free");
  195. }
  196. void peripheral_free_list(const unsigned short per[])
  197. {
  198. u16 cnt;
  199. for (cnt = 0; per[cnt] != 0; cnt++)
  200. peripheral_free(per[cnt]);
  201. }
  202. /***********************************************************
  203. *
  204. * FUNCTIONS: GPIO Driver
  205. *
  206. * INPUTS/OUTPUTS:
  207. * gpio PIO Number between 0 and MAX_GPIOS
  208. * label String
  209. *
  210. * DESCRIPTION: GPIO Driver API
  211. **************************************************************/
  212. int gpio_request(unsigned gpio, const char *label)
  213. {
  214. if (check_gpio(gpio) < 0)
  215. return -EINVAL;
  216. /*
  217. * Allow that the identical GPIO can
  218. * be requested from the same driver twice
  219. * Do nothing and return -
  220. */
  221. if (cmp_label(gpio, label) == 0)
  222. return 0;
  223. if (unlikely(is_reserved(gpio, gpio, 1))) {
  224. printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
  225. gpio, get_label(gpio));
  226. return -EBUSY;
  227. }
  228. if (unlikely(is_reserved(peri, gpio, 1))) {
  229. printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
  230. "by %s!\n", gpio, get_label(gpio));
  231. return -EBUSY;
  232. }
  233. reserve(gpio, gpio);
  234. set_label(gpio, label);
  235. port_setup(gpio, GPIO_USAGE);
  236. return 0;
  237. }
  238. int gpio_free(unsigned gpio)
  239. {
  240. if (check_gpio(gpio) < 0)
  241. return -1;
  242. if (unlikely(!is_reserved(gpio, gpio, 0))) {
  243. gpio_error(gpio);
  244. return -1;
  245. }
  246. unreserve(gpio, gpio);
  247. set_label(gpio, "free");
  248. return 0;
  249. }
  250. #ifdef ADI_SPECIAL_GPIO_BANKS
  251. static DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
  252. int special_gpio_request(unsigned gpio, const char *label)
  253. {
  254. /*
  255. * Allow that the identical GPIO can
  256. * be requested from the same driver twice
  257. * Do nothing and return -
  258. */
  259. if (cmp_label(gpio, label) == 0)
  260. return 0;
  261. if (unlikely(is_reserved(special_gpio, gpio, 1))) {
  262. printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
  263. gpio, get_label(gpio));
  264. return -EBUSY;
  265. }
  266. if (unlikely(is_reserved(peri, gpio, 1))) {
  267. printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
  268. "by %s!\n", gpio, get_label(gpio));
  269. return -EBUSY;
  270. }
  271. reserve(special_gpio, gpio);
  272. reserve(peri, gpio);
  273. set_label(gpio, label);
  274. port_setup(gpio, GPIO_USAGE);
  275. return 0;
  276. }
  277. void special_gpio_free(unsigned gpio)
  278. {
  279. if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
  280. gpio_error(gpio);
  281. return;
  282. }
  283. unreserve(special_gpio, gpio);
  284. unreserve(peri, gpio);
  285. set_label(gpio, "free");
  286. }
  287. #endif
  288. static inline void __gpio_direction_input(unsigned gpio)
  289. {
  290. gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
  291. #if defined(CONFIG_BF54x)
  292. gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
  293. #else
  294. gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio);
  295. #endif
  296. }
  297. int gpio_direction_input(unsigned gpio)
  298. {
  299. unsigned long flags;
  300. if (!is_reserved(gpio, gpio, 0)) {
  301. gpio_error(gpio);
  302. return -EINVAL;
  303. }
  304. local_irq_save(flags);
  305. __gpio_direction_input(gpio);
  306. local_irq_restore(flags);
  307. return 0;
  308. }
  309. int gpio_set_value(unsigned gpio, int arg)
  310. {
  311. if (arg)
  312. gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
  313. else
  314. gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
  315. return 0;
  316. }
  317. int gpio_direction_output(unsigned gpio, int value)
  318. {
  319. unsigned long flags;
  320. if (!is_reserved(gpio, gpio, 0)) {
  321. gpio_error(gpio);
  322. return -EINVAL;
  323. }
  324. local_irq_save(flags);
  325. #if defined(CONFIG_BF54x)
  326. gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
  327. #else
  328. gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio);
  329. #endif
  330. gpio_set_value(gpio, value);
  331. gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
  332. local_irq_restore(flags);
  333. return 0;
  334. }
  335. int gpio_get_value(unsigned gpio)
  336. {
  337. return 1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
  338. }
  339. void gpio_labels(void)
  340. {
  341. int c, gpio;
  342. for (c = 0; c < MAX_RESOURCES; c++) {
  343. gpio = is_reserved(gpio, c, 1);
  344. if (!check_gpio(c) && gpio)
  345. printf("GPIO_%d:\t%s\tGPIO %s\n", c, get_label(c),
  346. get_gpio_dir(c) ? "OUTPUT" : "INPUT");
  347. else if (is_reserved(peri, c, 1))
  348. printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c));
  349. else
  350. continue;
  351. }
  352. }