gpio.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* linux/arch/arm/mach-s5p64x0/gpio.c
  2. *
  3. * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
  4. * http://www.samsung.com
  5. *
  6. * S5P64X0 - GPIOlib support
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/irq.h>
  14. #include <linux/io.h>
  15. #include <linux/gpio.h>
  16. #include <mach/map.h>
  17. #include <mach/regs-gpio.h>
  18. #include <plat/gpio-core.h>
  19. #include <plat/gpio-cfg.h>
  20. #include <plat/gpio-cfg-helpers.h>
  21. /* To be implemented S5P6450 GPIO */
  22. /*
  23. * S5P6440 GPIO bank summary:
  24. *
  25. * Bank GPIOs Style SlpCon ExtInt Group
  26. * A 6 4Bit Yes 1
  27. * B 7 4Bit Yes 1
  28. * C 8 4Bit Yes 2
  29. * F 2 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. * N 16 2Bit No IRQ_EINT
  35. * P 8 2Bit Yes 8
  36. * R 15 4Bit[2] Yes 8
  37. *
  38. * [1] BANKF pins 14,15 do not form part of the external interrupt sources
  39. * [2] BANK has two control registers, GPxCON0 and GPxCON1
  40. */
  41. static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
  42. unsigned int offset)
  43. {
  44. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  45. void __iomem *base = ourchip->base;
  46. void __iomem *regcon = base;
  47. unsigned long con;
  48. unsigned long flags;
  49. switch (offset) {
  50. case 6:
  51. offset += 1;
  52. case 0:
  53. case 1:
  54. case 2:
  55. case 3:
  56. case 4:
  57. case 5:
  58. regcon -= 4;
  59. break;
  60. default:
  61. offset -= 7;
  62. break;
  63. }
  64. s3c_gpio_lock(ourchip, flags);
  65. con = __raw_readl(regcon);
  66. con &= ~(0xf << con_4bit_shift(offset));
  67. __raw_writel(con, regcon);
  68. s3c_gpio_unlock(ourchip, flags);
  69. return 0;
  70. }
  71. static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
  72. unsigned int offset, int value)
  73. {
  74. struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
  75. void __iomem *base = ourchip->base;
  76. void __iomem *regcon = base;
  77. unsigned long con;
  78. unsigned long dat;
  79. unsigned long flags;
  80. unsigned con_offset = offset;
  81. switch (con_offset) {
  82. case 6:
  83. con_offset += 1;
  84. case 0:
  85. case 1:
  86. case 2:
  87. case 3:
  88. case 4:
  89. case 5:
  90. regcon -= 4;
  91. break;
  92. default:
  93. con_offset -= 7;
  94. break;
  95. }
  96. s3c_gpio_lock(ourchip, flags);
  97. con = __raw_readl(regcon);
  98. con &= ~(0xf << con_4bit_shift(con_offset));
  99. con |= 0x1 << con_4bit_shift(con_offset);
  100. dat = __raw_readl(base + GPIODAT_OFF);
  101. if (value)
  102. dat |= 1 << offset;
  103. else
  104. dat &= ~(1 << offset);
  105. __raw_writel(con, regcon);
  106. __raw_writel(dat, base + GPIODAT_OFF);
  107. s3c_gpio_unlock(ourchip, flags);
  108. return 0;
  109. }
  110. int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
  111. unsigned int off, unsigned int cfg)
  112. {
  113. void __iomem *reg = chip->base;
  114. unsigned int shift;
  115. unsigned long flags;
  116. u32 con;
  117. switch (off) {
  118. case 0:
  119. case 1:
  120. case 2:
  121. case 3:
  122. case 4:
  123. case 5:
  124. shift = (off & 7) * 4;
  125. reg -= 4;
  126. break;
  127. case 6:
  128. shift = ((off + 1) & 7) * 4;
  129. reg -= 4;
  130. default:
  131. shift = ((off + 1) & 7) * 4;
  132. break;
  133. }
  134. if (s3c_gpio_is_cfg_special(cfg)) {
  135. cfg &= 0xf;
  136. cfg <<= shift;
  137. }
  138. s3c_gpio_lock(chip, flags);
  139. con = __raw_readl(reg);
  140. con &= ~(0xf << shift);
  141. con |= cfg;
  142. __raw_writel(con, reg);
  143. s3c_gpio_unlock(chip, flags);
  144. return 0;
  145. }
  146. static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
  147. {
  148. .cfg_eint = 0,
  149. }, {
  150. .cfg_eint = 7,
  151. }, {
  152. .cfg_eint = 3,
  153. .set_config = s5p64x0_gpio_setcfg_4bit_rbank,
  154. }, {
  155. .cfg_eint = 0,
  156. .set_config = s3c_gpio_setcfg_s3c24xx,
  157. .get_config = s3c_gpio_getcfg_s3c24xx,
  158. }, {
  159. .cfg_eint = 2,
  160. .set_config = s3c_gpio_setcfg_s3c24xx,
  161. .get_config = s3c_gpio_getcfg_s3c24xx,
  162. }, {
  163. .cfg_eint = 3,
  164. .set_config = s3c_gpio_setcfg_s3c24xx,
  165. .get_config = s3c_gpio_getcfg_s3c24xx,
  166. },
  167. };
  168. static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
  169. {
  170. .base = S5P6440_GPA_BASE,
  171. .config = &s5p64x0_gpio_cfgs[1],
  172. .chip = {
  173. .base = S5P6440_GPA(0),
  174. .ngpio = S5P6440_GPIO_A_NR,
  175. .label = "GPA",
  176. },
  177. }, {
  178. .base = S5P6440_GPB_BASE,
  179. .config = &s5p64x0_gpio_cfgs[1],
  180. .chip = {
  181. .base = S5P6440_GPB(0),
  182. .ngpio = S5P6440_GPIO_B_NR,
  183. .label = "GPB",
  184. },
  185. }, {
  186. .base = S5P6440_GPC_BASE,
  187. .config = &s5p64x0_gpio_cfgs[1],
  188. .chip = {
  189. .base = S5P6440_GPC(0),
  190. .ngpio = S5P6440_GPIO_C_NR,
  191. .label = "GPC",
  192. },
  193. }, {
  194. .base = S5P6440_GPG_BASE,
  195. .config = &s5p64x0_gpio_cfgs[1],
  196. .chip = {
  197. .base = S5P6440_GPG(0),
  198. .ngpio = S5P6440_GPIO_G_NR,
  199. .label = "GPG",
  200. },
  201. },
  202. };
  203. static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
  204. {
  205. .base = S5P6440_GPH_BASE + 0x4,
  206. .config = &s5p64x0_gpio_cfgs[1],
  207. .chip = {
  208. .base = S5P6440_GPH(0),
  209. .ngpio = S5P6440_GPIO_H_NR,
  210. .label = "GPH",
  211. },
  212. },
  213. };
  214. static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
  215. {
  216. .base = S5P6440_GPR_BASE + 0x4,
  217. .config = &s5p64x0_gpio_cfgs[2],
  218. .chip = {
  219. .base = S5P6440_GPR(0),
  220. .ngpio = S5P6440_GPIO_R_NR,
  221. .label = "GPR",
  222. },
  223. },
  224. };
  225. static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
  226. {
  227. .base = S5P6440_GPF_BASE,
  228. .config = &s5p64x0_gpio_cfgs[5],
  229. .chip = {
  230. .base = S5P6440_GPF(0),
  231. .ngpio = S5P6440_GPIO_F_NR,
  232. .label = "GPF",
  233. },
  234. }, {
  235. .base = S5P6440_GPI_BASE,
  236. .config = &s5p64x0_gpio_cfgs[3],
  237. .chip = {
  238. .base = S5P6440_GPI(0),
  239. .ngpio = S5P6440_GPIO_I_NR,
  240. .label = "GPI",
  241. },
  242. }, {
  243. .base = S5P6440_GPJ_BASE,
  244. .config = &s5p64x0_gpio_cfgs[3],
  245. .chip = {
  246. .base = S5P6440_GPJ(0),
  247. .ngpio = S5P6440_GPIO_J_NR,
  248. .label = "GPJ",
  249. },
  250. }, {
  251. .base = S5P6440_GPN_BASE,
  252. .config = &s5p64x0_gpio_cfgs[4],
  253. .chip = {
  254. .base = S5P6440_GPN(0),
  255. .ngpio = S5P6440_GPIO_N_NR,
  256. .label = "GPN",
  257. },
  258. }, {
  259. .base = S5P6440_GPP_BASE,
  260. .config = &s5p64x0_gpio_cfgs[5],
  261. .chip = {
  262. .base = S5P6440_GPP(0),
  263. .ngpio = S5P6440_GPIO_P_NR,
  264. .label = "GPP",
  265. },
  266. },
  267. };
  268. void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
  269. {
  270. for (; nr_chips > 0; nr_chips--, chipcfg++) {
  271. if (!chipcfg->set_config)
  272. chipcfg->set_config = s3c_gpio_setcfg_s3c64xx_4bit;
  273. if (!chipcfg->get_config)
  274. chipcfg->get_config = s3c_gpio_getcfg_s3c64xx_4bit;
  275. if (!chipcfg->set_pull)
  276. chipcfg->set_pull = s3c_gpio_setpull_updown;
  277. if (!chipcfg->get_pull)
  278. chipcfg->get_pull = s3c_gpio_getpull_updown;
  279. }
  280. }
  281. static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
  282. int nr_chips)
  283. {
  284. for (; nr_chips > 0; nr_chips--, chip++) {
  285. chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
  286. chip->chip.direction_output =
  287. s5p64x0_gpiolib_rbank_4bit2_output;
  288. s3c_gpiolib_add(chip);
  289. }
  290. }
  291. static int __init s5p6440_gpiolib_init(void)
  292. {
  293. struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
  294. int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
  295. s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
  296. ARRAY_SIZE(s5p64x0_gpio_cfgs));
  297. for (; nr_chips > 0; nr_chips--, chips++)
  298. s3c_gpiolib_add(chips);
  299. samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
  300. ARRAY_SIZE(s5p6440_gpio_4bit));
  301. samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
  302. ARRAY_SIZE(s5p6440_gpio_4bit2));
  303. s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
  304. ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
  305. return 0;
  306. }
  307. arch_initcall(s5p6440_gpiolib_init);