db8500_gpio.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code.
  3. * The purpose is that GPIO config found in kernel should work by simply
  4. * copy-paste it to U-Boot.
  5. *
  6. * Original Linux authors:
  7. * Copyright (C) 2008,2009 STMicroelectronics
  8. * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
  9. * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
  10. *
  11. * Ported to U-Boot by:
  12. * Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com>
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License version 2 as
  16. * published by the Free Software Foundation.
  17. */
  18. #include <common.h>
  19. #include <asm/io.h>
  20. #include <asm/arch/db8500_gpio.h>
  21. #include <asm/arch/db8500_pincfg.h>
  22. #include <linux/compiler.h>
  23. #define IO_ADDR(x) (void *) (x)
  24. /*
  25. * The GPIO module in the db8500 Systems-on-Chip is an
  26. * AMBA device, managing 32 pins and alternate functions. The logic block
  27. * is currently only used in the db8500.
  28. */
  29. #define GPIO_TOTAL_PINS 268
  30. #define GPIO_PINS_PER_BLOCK 32
  31. #define GPIO_BLOCKS_COUNT (GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK + 1)
  32. #define GPIO_BLOCK(pin) (((pin + GPIO_PINS_PER_BLOCK) >> 5) - 1)
  33. #define GPIO_PIN_WITHIN_BLOCK(pin) ((pin)%(GPIO_PINS_PER_BLOCK))
  34. /* Register in the logic block */
  35. #define DB8500_GPIO_DAT 0x00
  36. #define DB8500_GPIO_DATS 0x04
  37. #define DB8500_GPIO_DATC 0x08
  38. #define DB8500_GPIO_PDIS 0x0c
  39. #define DB8500_GPIO_DIR 0x10
  40. #define DB8500_GPIO_DIRS 0x14
  41. #define DB8500_GPIO_DIRC 0x18
  42. #define DB8500_GPIO_SLPC 0x1c
  43. #define DB8500_GPIO_AFSLA 0x20
  44. #define DB8500_GPIO_AFSLB 0x24
  45. #define DB8500_GPIO_RIMSC 0x40
  46. #define DB8500_GPIO_FIMSC 0x44
  47. #define DB8500_GPIO_IS 0x48
  48. #define DB8500_GPIO_IC 0x4c
  49. #define DB8500_GPIO_RWIMSC 0x50
  50. #define DB8500_GPIO_FWIMSC 0x54
  51. #define DB8500_GPIO_WKS 0x58
  52. static void __iomem *get_gpio_addr(unsigned gpio)
  53. {
  54. /* Our list of GPIO chips */
  55. static void __iomem *gpio_addrs[GPIO_BLOCKS_COUNT] = {
  56. IO_ADDR(CFG_GPIO_0_BASE),
  57. IO_ADDR(CFG_GPIO_1_BASE),
  58. IO_ADDR(CFG_GPIO_2_BASE),
  59. IO_ADDR(CFG_GPIO_3_BASE),
  60. IO_ADDR(CFG_GPIO_4_BASE),
  61. IO_ADDR(CFG_GPIO_5_BASE),
  62. IO_ADDR(CFG_GPIO_6_BASE),
  63. IO_ADDR(CFG_GPIO_7_BASE),
  64. IO_ADDR(CFG_GPIO_8_BASE)
  65. };
  66. return gpio_addrs[GPIO_BLOCK(gpio)];
  67. }
  68. static unsigned get_gpio_offset(unsigned gpio)
  69. {
  70. return GPIO_PIN_WITHIN_BLOCK(gpio);
  71. }
  72. /* Can only be called from config_pin. Don't configure alt-mode directly */
  73. static void gpio_set_mode(unsigned gpio, enum db8500_gpio_alt mode)
  74. {
  75. void __iomem *addr = get_gpio_addr(gpio);
  76. unsigned offset = get_gpio_offset(gpio);
  77. u32 bit = 1 << offset;
  78. u32 afunc, bfunc;
  79. afunc = readl(addr + DB8500_GPIO_AFSLA) & ~bit;
  80. bfunc = readl(addr + DB8500_GPIO_AFSLB) & ~bit;
  81. if (mode & DB8500_GPIO_ALT_A)
  82. afunc |= bit;
  83. if (mode & DB8500_GPIO_ALT_B)
  84. bfunc |= bit;
  85. writel(afunc, addr + DB8500_GPIO_AFSLA);
  86. writel(bfunc, addr + DB8500_GPIO_AFSLB);
  87. }
  88. /**
  89. * db8500_gpio_set_pull() - enable/disable pull up/down on a gpio
  90. * @gpio: pin number
  91. * @pull: one of DB8500_GPIO_PULL_DOWN, DB8500_GPIO_PULL_UP,
  92. * and DB8500_GPIO_PULL_NONE
  93. *
  94. * Enables/disables pull up/down on a specified pin. This only takes effect if
  95. * the pin is configured as an input (either explicitly or by the alternate
  96. * function).
  97. *
  98. * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
  99. * configured as an input. Otherwise, due to the way the controller registers
  100. * work, this function will change the value output on the pin.
  101. */
  102. void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull)
  103. {
  104. void __iomem *addr = get_gpio_addr(gpio);
  105. unsigned offset = get_gpio_offset(gpio);
  106. u32 bit = 1 << offset;
  107. u32 pdis;
  108. pdis = readl(addr + DB8500_GPIO_PDIS);
  109. if (pull == DB8500_GPIO_PULL_NONE)
  110. pdis |= bit;
  111. else
  112. pdis &= ~bit;
  113. writel(pdis, addr + DB8500_GPIO_PDIS);
  114. if (pull == DB8500_GPIO_PULL_UP)
  115. writel(bit, addr + DB8500_GPIO_DATS);
  116. else if (pull == DB8500_GPIO_PULL_DOWN)
  117. writel(bit, addr + DB8500_GPIO_DATC);
  118. }
  119. void db8500_gpio_make_input(unsigned gpio)
  120. {
  121. void __iomem *addr = get_gpio_addr(gpio);
  122. unsigned offset = get_gpio_offset(gpio);
  123. writel(1 << offset, addr + DB8500_GPIO_DIRC);
  124. }
  125. int db8500_gpio_get_input(unsigned gpio)
  126. {
  127. void __iomem *addr = get_gpio_addr(gpio);
  128. unsigned offset = get_gpio_offset(gpio);
  129. u32 bit = 1 << offset;
  130. printf("db8500_gpio_get_input gpio=%u addr=%p offset=%u bit=%#x\n",
  131. gpio, addr, offset, bit);
  132. return (readl(addr + DB8500_GPIO_DAT) & bit) != 0;
  133. }
  134. void db8500_gpio_make_output(unsigned gpio, int val)
  135. {
  136. void __iomem *addr = get_gpio_addr(gpio);
  137. unsigned offset = get_gpio_offset(gpio);
  138. writel(1 << offset, addr + DB8500_GPIO_DIRS);
  139. db8500_gpio_set_output(gpio, val);
  140. }
  141. void db8500_gpio_set_output(unsigned gpio, int val)
  142. {
  143. void __iomem *addr = get_gpio_addr(gpio);
  144. unsigned offset = get_gpio_offset(gpio);
  145. if (val)
  146. writel(1 << offset, addr + DB8500_GPIO_DATS);
  147. else
  148. writel(1 << offset, addr + DB8500_GPIO_DATC);
  149. }
  150. /**
  151. * config_pin - configure a pin's mux attributes
  152. * @cfg: pin configuration
  153. *
  154. * Configures a pin's mode (alternate function or GPIO), its pull up status,
  155. * and its sleep mode based on the specified configuration. The @cfg is
  156. * usually one of the SoC specific macros defined in mach/<soc>-pins.h. These
  157. * are constructed using, and can be further enhanced with, the macros in
  158. * plat/pincfg.h.
  159. *
  160. * If a pin's mode is set to GPIO, it is configured as an input to avoid
  161. * side-effects. The gpio can be manipulated later using standard GPIO API
  162. * calls.
  163. */
  164. static void config_pin(unsigned long cfg)
  165. {
  166. int pin = PIN_NUM(cfg);
  167. int pull = PIN_PULL(cfg);
  168. int af = PIN_ALT(cfg);
  169. int output = PIN_DIR(cfg);
  170. int val = PIN_VAL(cfg);
  171. if (output)
  172. db8500_gpio_make_output(pin, val);
  173. else {
  174. db8500_gpio_make_input(pin);
  175. db8500_gpio_set_pull(pin, pull);
  176. }
  177. gpio_set_mode(pin, af);
  178. }
  179. /**
  180. * db8500_config_pins - configure several pins at once
  181. * @cfgs: array of pin configurations
  182. * @num: number of elments in the array
  183. *
  184. * Configures several pins using config_pin(). Refer to that function for
  185. * further information.
  186. */
  187. void db8500_gpio_config_pins(unsigned long *cfgs, size_t num)
  188. {
  189. size_t i;
  190. for (i = 0; i < num; i++)
  191. config_pin(cfgs[i]);
  192. }