adi_gpio2.c 8.7 KB

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