gpiolib.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* arch/arm/plat-s3c64xx/gpiolib.c
  2. *
  3. * Copyright 2008 Openmoko, Inc.
  4. * Copyright 2008 Simtec Electronics
  5. * Ben Dooks <ben@simtec.co.uk>
  6. * http://armlinux.simtec.co.uk/
  7. *
  8. * S3C64XX - GPIOlib support
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/irq.h>
  16. #include <linux/io.h>
  17. #include <mach/map.h>
  18. #include <mach/gpio.h>
  19. #include <plat/gpio-core.h>
  20. #include <plat/regs-gpio.h>
  21. /* GPIO bank summary:
  22. *
  23. * Bank GPIOs Style SlpCon ExtInt Group
  24. * A 8 4Bit Yes 1
  25. * B 7 4Bit Yes 1
  26. * C 8 4Bit Yes 2
  27. * D 5 4Bit Yes 3
  28. * E 5 4Bit Yes None
  29. * F 16 2Bit Yes 4 [1]
  30. * G 7 4Bit Yes 5
  31. * H 10 4Bit[2] Yes 6
  32. * I 16 2Bit Yes None
  33. * J 12 2Bit Yes None
  34. * K 16 4Bit[2] No None
  35. * L 15 4Bit[2] No None
  36. * M 6 4Bit No IRQ_EINT
  37. * N 16 2Bit No IRQ_EINT
  38. * O 16 2Bit Yes 7
  39. * P 15 2Bit Yes 8
  40. * Q 9 2Bit Yes 9
  41. *
  42. * [1] BANKF pins 14,15 do not form part of the external interrupt sources
  43. * [2] BANK has two control registers, GPxCON0 and GPxCON1
  44. */
  45. #define OFF_GPCON (0x00)
  46. #define OFF_GPDAT (0x04)
  47. #define con_4bit_shift(__off) ((__off) * 4)
  48. /* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
  49. * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
  50. * following example:
  51. *
  52. * base + 0x00: Control register, 4 bits per gpio
  53. * gpio n: 4 bits starting at (4*n)
  54. * 0000 = input, 0001 = output, others mean special-function
  55. * base + 0x04: Data register, 1 bit per gpio
  56. * bit n: data bit n
  57. *
  58. * Note, since the data register is one bit per gpio and is at base + 0x4
  59. * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
  60. * the output.
  61. */
  62. static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
  63. {
  64. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  65. void __iomem *base = ourchip->base;
  66. unsigned long con;
  67. con = __raw_readl(base + OFF_GPCON);
  68. con &= ~(0xf << con_4bit_shift(offset));
  69. __raw_writel(con, base + OFF_GPCON);
  70. return 0;
  71. }
  72. static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
  73. unsigned offset, int value)
  74. {
  75. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  76. void __iomem *base = ourchip->base;
  77. unsigned long con;
  78. unsigned long dat;
  79. con = __raw_readl(base + OFF_GPCON);
  80. con &= ~(0xf << con_4bit_shift(offset));
  81. con |= 0x1 << con_4bit_shift(offset);
  82. dat = __raw_readl(base + OFF_GPDAT);
  83. if (value)
  84. dat |= 1 << offset;
  85. else
  86. dat &= ~(1 << offset);
  87. __raw_writel(dat, base + OFF_GPDAT);
  88. __raw_writel(con, base + OFF_GPCON);
  89. __raw_writel(dat, base + OFF_GPDAT);
  90. return 0;
  91. }
  92. /* The next set of routines are for the case where the GPIO configuration
  93. * registers are 4 bits per GPIO but there is more than one register (the
  94. * bank has more than 8 GPIOs.
  95. *
  96. * This case is the similar to the 4 bit case, but the registers are as
  97. * follows:
  98. *
  99. * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
  100. * gpio n: 4 bits starting at (4*n)
  101. * 0000 = input, 0001 = output, others mean special-function
  102. * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
  103. * gpio n: 4 bits starting at (4*n)
  104. * 0000 = input, 0001 = output, others mean special-function
  105. * base + 0x08: Data register, 1 bit per gpio
  106. * bit n: data bit n
  107. *
  108. * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
  109. * store the 'base + 0x4' address so that these routines see the data
  110. * register at ourchip->base + 0x04.
  111. */
  112. static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
  113. {
  114. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  115. void __iomem *base = ourchip->base;
  116. void __iomem *regcon = base;
  117. unsigned long con;
  118. if (offset > 7)
  119. offset -= 8;
  120. else
  121. regcon -= 4;
  122. con = __raw_readl(regcon);
  123. con &= ~(0xf << con_4bit_shift(offset));
  124. __raw_writel(con, regcon);
  125. return 0;
  126. }
  127. static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
  128. unsigned offset, int value)
  129. {
  130. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  131. void __iomem *base = ourchip->base;
  132. void __iomem *regcon = base;
  133. unsigned long con;
  134. unsigned long dat;
  135. if (offset > 7)
  136. offset -= 8;
  137. else
  138. regcon -= 4;
  139. con = __raw_readl(regcon);
  140. con &= ~(0xf << con_4bit_shift(offset));
  141. con |= 0x1 << con_4bit_shift(offset);
  142. dat = __raw_readl(base + OFF_GPDAT);
  143. if (value)
  144. dat |= 1 << offset;
  145. else
  146. dat &= ~(1 << offset);
  147. __raw_writel(dat, base + OFF_GPDAT);
  148. __raw_writel(con, regcon);
  149. __raw_writel(dat, base + OFF_GPDAT);
  150. return 0;
  151. }
  152. static struct s3c_gpio_chip gpio_4bit[] = {
  153. {
  154. .base = S3C64XX_GPA_BASE,
  155. .chip = {
  156. .base = S3C64XX_GPA(0),
  157. .ngpio = S3C64XX_GPIO_A_NR,
  158. .label = "GPA",
  159. },
  160. }, {
  161. .base = S3C64XX_GPB_BASE,
  162. .chip = {
  163. .base = S3C64XX_GPB(0),
  164. .ngpio = S3C64XX_GPIO_B_NR,
  165. .label = "GPB",
  166. },
  167. }, {
  168. .base = S3C64XX_GPC_BASE,
  169. .chip = {
  170. .base = S3C64XX_GPC(0),
  171. .ngpio = S3C64XX_GPIO_C_NR,
  172. .label = "GPC",
  173. },
  174. }, {
  175. .base = S3C64XX_GPD_BASE,
  176. .chip = {
  177. .base = S3C64XX_GPD(0),
  178. .ngpio = S3C64XX_GPIO_D_NR,
  179. .label = "GPD",
  180. },
  181. }, {
  182. .base = S3C64XX_GPE_BASE,
  183. .chip = {
  184. .base = S3C64XX_GPE(0),
  185. .ngpio = S3C64XX_GPIO_E_NR,
  186. .label = "GPE",
  187. },
  188. }, {
  189. .base = S3C64XX_GPG_BASE,
  190. .chip = {
  191. .base = S3C64XX_GPG(0),
  192. .ngpio = S3C64XX_GPIO_G_NR,
  193. .label = "GPG",
  194. },
  195. }, {
  196. .base = S3C64XX_GPM_BASE,
  197. .chip = {
  198. .base = S3C64XX_GPM(0),
  199. .ngpio = S3C64XX_GPIO_M_NR,
  200. .label = "GPM",
  201. },
  202. },
  203. };
  204. static struct s3c_gpio_chip gpio_4bit2[] = {
  205. {
  206. .base = S3C64XX_GPH_BASE + 0x4,
  207. .chip = {
  208. .base = S3C64XX_GPH(0),
  209. .ngpio = S3C64XX_GPIO_H_NR,
  210. .label = "GPH",
  211. },
  212. }, {
  213. .base = S3C64XX_GPK_BASE + 0x4,
  214. .chip = {
  215. .base = S3C64XX_GPK(0),
  216. .ngpio = S3C64XX_GPIO_K_NR,
  217. .label = "GPK",
  218. },
  219. }, {
  220. .base = S3C64XX_GPL_BASE + 0x4,
  221. .chip = {
  222. .base = S3C64XX_GPL(0),
  223. .ngpio = S3C64XX_GPIO_L_NR,
  224. .label = "GPL",
  225. },
  226. },
  227. };
  228. static struct s3c_gpio_chip gpio_2bit[] = {
  229. {
  230. .base = S3C64XX_GPF_BASE,
  231. .chip = {
  232. .base = S3C64XX_GPF(0),
  233. .ngpio = S3C64XX_GPIO_F_NR,
  234. .label = "GPF",
  235. },
  236. }, {
  237. .base = S3C64XX_GPI_BASE,
  238. .chip = {
  239. .base = S3C64XX_GPI(0),
  240. .ngpio = S3C64XX_GPIO_I_NR,
  241. .label = "GPI",
  242. },
  243. }, {
  244. .base = S3C64XX_GPJ_BASE,
  245. .chip = {
  246. .base = S3C64XX_GPJ(0),
  247. .ngpio = S3C64XX_GPIO_J_NR,
  248. .label = "GPJ",
  249. },
  250. }, {
  251. .base = S3C64XX_GPN_BASE,
  252. .chip = {
  253. .base = S3C64XX_GPN(0),
  254. .ngpio = S3C64XX_GPIO_N_NR,
  255. .label = "GPN",
  256. },
  257. }, {
  258. .base = S3C64XX_GPO_BASE,
  259. .chip = {
  260. .base = S3C64XX_GPO(0),
  261. .ngpio = S3C64XX_GPIO_O_NR,
  262. .label = "GPO",
  263. },
  264. }, {
  265. .base = S3C64XX_GPP_BASE,
  266. .chip = {
  267. .base = S3C64XX_GPP(0),
  268. .ngpio = S3C64XX_GPIO_P_NR,
  269. .label = "GPP",
  270. },
  271. }, {
  272. .base = S3C64XX_GPQ_BASE,
  273. .chip = {
  274. .base = S3C64XX_GPQ(0),
  275. .ngpio = S3C64XX_GPIO_Q_NR,
  276. .label = "GPQ",
  277. },
  278. },
  279. };
  280. static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
  281. {
  282. chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
  283. chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
  284. }
  285. static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
  286. {
  287. chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
  288. chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
  289. }
  290. static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
  291. int nr_chips,
  292. void (*fn)(struct s3c_gpio_chip *))
  293. {
  294. for (; nr_chips > 0; nr_chips--, chips++) {
  295. if (fn)
  296. (fn)(chips);
  297. s3c_gpiolib_add(chips);
  298. }
  299. }
  300. static __init int s3c64xx_gpiolib_init(void)
  301. {
  302. s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
  303. s3c64xx_gpiolib_add_4bit);
  304. s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
  305. s3c64xx_gpiolib_add_4bit2);
  306. s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL);
  307. return 0;
  308. }
  309. arch_initcall(s3c64xx_gpiolib_init);