gpiolib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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 <mach/gpio-core.h>
  20. #include <plat/gpio-cfg.h>
  21. #include <plat/gpio-cfg-helpers.h>
  22. #include <plat/regs-gpio.h>
  23. /* GPIO bank summary:
  24. *
  25. * Bank GPIOs Style SlpCon ExtInt Group
  26. * A 8 4Bit Yes 1
  27. * B 7 4Bit Yes 1
  28. * C 8 4Bit Yes 2
  29. * D 5 4Bit Yes 3
  30. * E 5 4Bit Yes None
  31. * F 16 2Bit Yes 4 [1]
  32. * G 7 4Bit Yes 5
  33. * H 10 4Bit[2] Yes 6
  34. * I 16 2Bit Yes None
  35. * J 12 2Bit Yes None
  36. * K 16 4Bit[2] No None
  37. * L 15 4Bit[2] No None
  38. * M 6 4Bit No IRQ_EINT
  39. * N 16 2Bit No IRQ_EINT
  40. * O 16 2Bit Yes 7
  41. * P 15 2Bit Yes 8
  42. * Q 9 2Bit Yes 9
  43. *
  44. * [1] BANKF pins 14,15 do not form part of the external interrupt sources
  45. * [2] BANK has two control registers, GPxCON0 and GPxCON1
  46. */
  47. #define OFF_GPCON (0x00)
  48. #define OFF_GPDAT (0x04)
  49. #define con_4bit_shift(__off) ((__off) * 4)
  50. #if 1
  51. #define gpio_dbg(x...) do { } while(0)
  52. #else
  53. #define gpio_dbg(x...) printk(KERN_DEBUG x)
  54. #endif
  55. /* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
  56. * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
  57. * following example:
  58. *
  59. * base + 0x00: Control register, 4 bits per gpio
  60. * gpio n: 4 bits starting at (4*n)
  61. * 0000 = input, 0001 = output, others mean special-function
  62. * base + 0x04: Data register, 1 bit per gpio
  63. * bit n: data bit n
  64. *
  65. * Note, since the data register is one bit per gpio and is at base + 0x4
  66. * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
  67. * the output.
  68. */
  69. static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
  70. {
  71. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  72. void __iomem *base = ourchip->base;
  73. unsigned long con;
  74. con = __raw_readl(base + OFF_GPCON);
  75. con &= ~(0xf << con_4bit_shift(offset));
  76. __raw_writel(con, base + OFF_GPCON);
  77. gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
  78. return 0;
  79. }
  80. static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
  81. unsigned offset, int value)
  82. {
  83. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  84. void __iomem *base = ourchip->base;
  85. unsigned long con;
  86. unsigned long dat;
  87. con = __raw_readl(base + OFF_GPCON);
  88. con &= ~(0xf << con_4bit_shift(offset));
  89. con |= 0x1 << con_4bit_shift(offset);
  90. dat = __raw_readl(base + OFF_GPDAT);
  91. if (value)
  92. dat |= 1 << offset;
  93. else
  94. dat &= ~(1 << offset);
  95. __raw_writel(dat, base + OFF_GPDAT);
  96. __raw_writel(con, base + OFF_GPCON);
  97. __raw_writel(dat, base + OFF_GPDAT);
  98. gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
  99. return 0;
  100. }
  101. /* The next set of routines are for the case where the GPIO configuration
  102. * registers are 4 bits per GPIO but there is more than one register (the
  103. * bank has more than 8 GPIOs.
  104. *
  105. * This case is the similar to the 4 bit case, but the registers are as
  106. * follows:
  107. *
  108. * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
  109. * gpio n: 4 bits starting at (4*n)
  110. * 0000 = input, 0001 = output, others mean special-function
  111. * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
  112. * gpio n: 4 bits starting at (4*n)
  113. * 0000 = input, 0001 = output, others mean special-function
  114. * base + 0x08: Data register, 1 bit per gpio
  115. * bit n: data bit n
  116. *
  117. * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
  118. * store the 'base + 0x4' address so that these routines see the data
  119. * register at ourchip->base + 0x04.
  120. */
  121. static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
  122. {
  123. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  124. void __iomem *base = ourchip->base;
  125. void __iomem *regcon = base;
  126. unsigned long con;
  127. if (offset > 7)
  128. offset -= 8;
  129. else
  130. regcon -= 4;
  131. con = __raw_readl(regcon);
  132. con &= ~(0xf << con_4bit_shift(offset));
  133. __raw_writel(con, regcon);
  134. gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
  135. return 0;
  136. }
  137. static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
  138. unsigned offset, int value)
  139. {
  140. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  141. void __iomem *base = ourchip->base;
  142. void __iomem *regcon = base;
  143. unsigned long con;
  144. unsigned long dat;
  145. if (offset > 7)
  146. offset -= 8;
  147. else
  148. regcon -= 4;
  149. con = __raw_readl(regcon);
  150. con &= ~(0xf << con_4bit_shift(offset));
  151. con |= 0x1 << con_4bit_shift(offset);
  152. dat = __raw_readl(base + OFF_GPDAT);
  153. if (value)
  154. dat |= 1 << offset;
  155. else
  156. dat &= ~(1 << offset);
  157. __raw_writel(dat, base + OFF_GPDAT);
  158. __raw_writel(con, regcon);
  159. __raw_writel(dat, base + OFF_GPDAT);
  160. gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
  161. return 0;
  162. }
  163. static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
  164. .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
  165. .set_pull = s3c_gpio_setpull_updown,
  166. .get_pull = s3c_gpio_getpull_updown,
  167. };
  168. static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
  169. .cfg_eint = 7,
  170. .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
  171. .set_pull = s3c_gpio_setpull_updown,
  172. .get_pull = s3c_gpio_getpull_updown,
  173. };
  174. static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
  175. .cfg_eint = 3,
  176. .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
  177. .set_pull = s3c_gpio_setpull_updown,
  178. .get_pull = s3c_gpio_getpull_updown,
  179. };
  180. int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
  181. {
  182. return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
  183. }
  184. static struct s3c_gpio_chip gpio_4bit[] = {
  185. {
  186. .base = S3C64XX_GPA_BASE,
  187. .config = &gpio_4bit_cfg_eint0111,
  188. .chip = {
  189. .base = S3C64XX_GPA(0),
  190. .ngpio = S3C64XX_GPIO_A_NR,
  191. .label = "GPA",
  192. },
  193. }, {
  194. .base = S3C64XX_GPB_BASE,
  195. .config = &gpio_4bit_cfg_eint0111,
  196. .chip = {
  197. .base = S3C64XX_GPB(0),
  198. .ngpio = S3C64XX_GPIO_B_NR,
  199. .label = "GPB",
  200. },
  201. }, {
  202. .base = S3C64XX_GPC_BASE,
  203. .config = &gpio_4bit_cfg_eint0111,
  204. .chip = {
  205. .base = S3C64XX_GPC(0),
  206. .ngpio = S3C64XX_GPIO_C_NR,
  207. .label = "GPC",
  208. },
  209. }, {
  210. .base = S3C64XX_GPD_BASE,
  211. .config = &gpio_4bit_cfg_eint0111,
  212. .chip = {
  213. .base = S3C64XX_GPD(0),
  214. .ngpio = S3C64XX_GPIO_D_NR,
  215. .label = "GPD",
  216. },
  217. }, {
  218. .base = S3C64XX_GPE_BASE,
  219. .config = &gpio_4bit_cfg_noint,
  220. .chip = {
  221. .base = S3C64XX_GPE(0),
  222. .ngpio = S3C64XX_GPIO_E_NR,
  223. .label = "GPE",
  224. },
  225. }, {
  226. .base = S3C64XX_GPG_BASE,
  227. .config = &gpio_4bit_cfg_eint0111,
  228. .chip = {
  229. .base = S3C64XX_GPG(0),
  230. .ngpio = S3C64XX_GPIO_G_NR,
  231. .label = "GPG",
  232. },
  233. }, {
  234. .base = S3C64XX_GPM_BASE,
  235. .config = &gpio_4bit_cfg_eint0011,
  236. .chip = {
  237. .base = S3C64XX_GPM(0),
  238. .ngpio = S3C64XX_GPIO_M_NR,
  239. .label = "GPM",
  240. .to_irq = s3c64xx_gpio2int_gpm,
  241. },
  242. },
  243. };
  244. int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
  245. {
  246. return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
  247. }
  248. static struct s3c_gpio_chip gpio_4bit2[] = {
  249. {
  250. .base = S3C64XX_GPH_BASE + 0x4,
  251. .config = &gpio_4bit_cfg_eint0111,
  252. .chip = {
  253. .base = S3C64XX_GPH(0),
  254. .ngpio = S3C64XX_GPIO_H_NR,
  255. .label = "GPH",
  256. },
  257. }, {
  258. .base = S3C64XX_GPK_BASE + 0x4,
  259. .config = &gpio_4bit_cfg_noint,
  260. .chip = {
  261. .base = S3C64XX_GPK(0),
  262. .ngpio = S3C64XX_GPIO_K_NR,
  263. .label = "GPK",
  264. },
  265. }, {
  266. .base = S3C64XX_GPL_BASE + 0x4,
  267. .config = &gpio_4bit_cfg_eint0011,
  268. .chip = {
  269. .base = S3C64XX_GPL(0),
  270. .ngpio = S3C64XX_GPIO_L_NR,
  271. .label = "GPL",
  272. .to_irq = s3c64xx_gpio2int_gpl,
  273. },
  274. },
  275. };
  276. static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
  277. .set_config = s3c_gpio_setcfg_s3c24xx,
  278. .set_pull = s3c_gpio_setpull_updown,
  279. .get_pull = s3c_gpio_getpull_updown,
  280. };
  281. static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
  282. .cfg_eint = 2,
  283. .set_config = s3c_gpio_setcfg_s3c24xx,
  284. .set_pull = s3c_gpio_setpull_updown,
  285. .get_pull = s3c_gpio_getpull_updown,
  286. };
  287. static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
  288. .cfg_eint = 3,
  289. .set_config = s3c_gpio_setcfg_s3c24xx,
  290. .set_pull = s3c_gpio_setpull_updown,
  291. .get_pull = s3c_gpio_getpull_updown,
  292. };
  293. int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
  294. {
  295. return IRQ_EINT(0) + pin;
  296. }
  297. static struct s3c_gpio_chip gpio_2bit[] = {
  298. {
  299. .base = S3C64XX_GPF_BASE,
  300. .config = &gpio_2bit_cfg_eint11,
  301. .chip = {
  302. .base = S3C64XX_GPF(0),
  303. .ngpio = S3C64XX_GPIO_F_NR,
  304. .label = "GPF",
  305. },
  306. }, {
  307. .base = S3C64XX_GPI_BASE,
  308. .config = &gpio_2bit_cfg_noint,
  309. .chip = {
  310. .base = S3C64XX_GPI(0),
  311. .ngpio = S3C64XX_GPIO_I_NR,
  312. .label = "GPI",
  313. },
  314. }, {
  315. .base = S3C64XX_GPJ_BASE,
  316. .config = &gpio_2bit_cfg_noint,
  317. .chip = {
  318. .base = S3C64XX_GPJ(0),
  319. .ngpio = S3C64XX_GPIO_J_NR,
  320. .label = "GPJ",
  321. },
  322. }, {
  323. .base = S3C64XX_GPN_BASE,
  324. .config = &gpio_2bit_cfg_eint10,
  325. .chip = {
  326. .base = S3C64XX_GPN(0),
  327. .ngpio = S3C64XX_GPIO_N_NR,
  328. .label = "GPN",
  329. .to_irq = s3c64xx_gpio2int_gpn,
  330. },
  331. }, {
  332. .base = S3C64XX_GPO_BASE,
  333. .config = &gpio_2bit_cfg_eint11,
  334. .chip = {
  335. .base = S3C64XX_GPO(0),
  336. .ngpio = S3C64XX_GPIO_O_NR,
  337. .label = "GPO",
  338. },
  339. }, {
  340. .base = S3C64XX_GPP_BASE,
  341. .config = &gpio_2bit_cfg_eint11,
  342. .chip = {
  343. .base = S3C64XX_GPP(0),
  344. .ngpio = S3C64XX_GPIO_P_NR,
  345. .label = "GPP",
  346. },
  347. }, {
  348. .base = S3C64XX_GPQ_BASE,
  349. .config = &gpio_2bit_cfg_eint11,
  350. .chip = {
  351. .base = S3C64XX_GPQ(0),
  352. .ngpio = S3C64XX_GPIO_Q_NR,
  353. .label = "GPQ",
  354. },
  355. },
  356. };
  357. static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
  358. {
  359. chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
  360. chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
  361. chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
  362. }
  363. static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
  364. {
  365. chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
  366. chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
  367. chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
  368. }
  369. static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
  370. {
  371. chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
  372. }
  373. static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
  374. int nr_chips,
  375. void (*fn)(struct s3c_gpio_chip *))
  376. {
  377. for (; nr_chips > 0; nr_chips--, chips++) {
  378. if (fn)
  379. (fn)(chips);
  380. s3c_gpiolib_add(chips);
  381. }
  382. }
  383. static __init int s3c64xx_gpiolib_init(void)
  384. {
  385. s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
  386. s3c64xx_gpiolib_add_4bit);
  387. s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
  388. s3c64xx_gpiolib_add_4bit2);
  389. s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
  390. s3c64xx_gpiolib_add_2bit);
  391. return 0;
  392. }
  393. core_initcall(s3c64xx_gpiolib_init);