gpio-config.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /* linux/arch/arm/plat-s3c/gpio-config.c
  2. *
  3. * Copyright 2008 Openmoko, Inc.
  4. * Copyright 2008-2010 Simtec Electronics
  5. * Ben Dooks <ben@simtec.co.uk>
  6. * http://armlinux.simtec.co.uk/
  7. *
  8. * S3C series GPIO configuration core
  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/module.h>
  16. #include <linux/gpio.h>
  17. #include <linux/io.h>
  18. #include <plat/gpio-core.h>
  19. #include <plat/gpio-cfg.h>
  20. #include <plat/gpio-cfg-helpers.h>
  21. int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
  22. {
  23. struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
  24. unsigned long flags;
  25. int offset;
  26. int ret;
  27. if (!chip)
  28. return -EINVAL;
  29. offset = pin - chip->chip.base;
  30. s3c_gpio_lock(chip, flags);
  31. ret = s3c_gpio_do_setcfg(chip, offset, config);
  32. s3c_gpio_unlock(chip, flags);
  33. return ret;
  34. }
  35. EXPORT_SYMBOL(s3c_gpio_cfgpin);
  36. int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
  37. unsigned int cfg)
  38. {
  39. int ret;
  40. for (; nr > 0; nr--, start++) {
  41. ret = s3c_gpio_cfgpin(start, cfg);
  42. if (ret != 0)
  43. return ret;
  44. }
  45. return 0;
  46. }
  47. EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
  48. unsigned s3c_gpio_getcfg(unsigned int pin)
  49. {
  50. struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
  51. unsigned long flags;
  52. unsigned ret = 0;
  53. int offset;
  54. if (chip) {
  55. offset = pin - chip->chip.base;
  56. s3c_gpio_lock(chip, flags);
  57. ret = s3c_gpio_do_getcfg(chip, offset);
  58. s3c_gpio_unlock(chip, flags);
  59. }
  60. return ret;
  61. }
  62. EXPORT_SYMBOL(s3c_gpio_getcfg);
  63. int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
  64. {
  65. struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
  66. unsigned long flags;
  67. int offset, ret;
  68. if (!chip)
  69. return -EINVAL;
  70. offset = pin - chip->chip.base;
  71. s3c_gpio_lock(chip, flags);
  72. ret = s3c_gpio_do_setpull(chip, offset, pull);
  73. s3c_gpio_unlock(chip, flags);
  74. return ret;
  75. }
  76. EXPORT_SYMBOL(s3c_gpio_setpull);
  77. #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
  78. int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
  79. unsigned int off, unsigned int cfg)
  80. {
  81. void __iomem *reg = chip->base;
  82. unsigned int shift = off;
  83. u32 con;
  84. if (s3c_gpio_is_cfg_special(cfg)) {
  85. cfg &= 0xf;
  86. /* Map output to 0, and SFN2 to 1 */
  87. cfg -= 1;
  88. if (cfg > 1)
  89. return -EINVAL;
  90. cfg <<= shift;
  91. }
  92. con = __raw_readl(reg);
  93. con &= ~(0x1 << shift);
  94. con |= cfg;
  95. __raw_writel(con, reg);
  96. return 0;
  97. }
  98. unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
  99. unsigned int off)
  100. {
  101. u32 con;
  102. con = __raw_readl(chip->base);
  103. con >>= off;
  104. con &= 1;
  105. con++;
  106. return S3C_GPIO_SFN(con);
  107. }
  108. int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
  109. unsigned int off, unsigned int cfg)
  110. {
  111. void __iomem *reg = chip->base;
  112. unsigned int shift = off * 2;
  113. u32 con;
  114. if (s3c_gpio_is_cfg_special(cfg)) {
  115. cfg &= 0xf;
  116. if (cfg > 3)
  117. return -EINVAL;
  118. cfg <<= shift;
  119. }
  120. con = __raw_readl(reg);
  121. con &= ~(0x3 << shift);
  122. con |= cfg;
  123. __raw_writel(con, reg);
  124. return 0;
  125. }
  126. unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
  127. unsigned int off)
  128. {
  129. u32 con;
  130. con = __raw_readl(chip->base);
  131. con >>= off * 2;
  132. con &= 3;
  133. /* this conversion works for IN and OUT as well as special mode */
  134. return S3C_GPIO_SPECIAL(con);
  135. }
  136. #endif
  137. #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
  138. int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
  139. unsigned int off, unsigned int cfg)
  140. {
  141. void __iomem *reg = chip->base;
  142. unsigned int shift = (off & 7) * 4;
  143. u32 con;
  144. if (off < 8 && chip->chip.ngpio > 8)
  145. reg -= 4;
  146. if (s3c_gpio_is_cfg_special(cfg)) {
  147. cfg &= 0xf;
  148. cfg <<= shift;
  149. }
  150. con = __raw_readl(reg);
  151. con &= ~(0xf << shift);
  152. con |= cfg;
  153. __raw_writel(con, reg);
  154. return 0;
  155. }
  156. unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
  157. unsigned int off)
  158. {
  159. void __iomem *reg = chip->base;
  160. unsigned int shift = (off & 7) * 4;
  161. u32 con;
  162. if (off < 8 && chip->chip.ngpio > 8)
  163. reg -= 4;
  164. con = __raw_readl(reg);
  165. con >>= shift;
  166. con &= 0xf;
  167. /* this conversion works for IN and OUT as well as special mode */
  168. return S3C_GPIO_SPECIAL(con);
  169. }
  170. #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
  171. #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
  172. int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
  173. unsigned int off, s3c_gpio_pull_t pull)
  174. {
  175. void __iomem *reg = chip->base + 0x08;
  176. int shift = off * 2;
  177. u32 pup;
  178. pup = __raw_readl(reg);
  179. pup &= ~(3 << shift);
  180. pup |= pull << shift;
  181. __raw_writel(pup, reg);
  182. return 0;
  183. }
  184. s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
  185. unsigned int off)
  186. {
  187. void __iomem *reg = chip->base + 0x08;
  188. int shift = off * 2;
  189. u32 pup = __raw_readl(reg);
  190. pup >>= shift;
  191. pup &= 0x3;
  192. return (__force s3c_gpio_pull_t)pup;
  193. }
  194. #endif
  195. #ifdef CONFIG_S3C_GPIO_PULL_UP
  196. int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
  197. unsigned int off, s3c_gpio_pull_t pull)
  198. {
  199. void __iomem *reg = chip->base + 0x08;
  200. u32 pup = __raw_readl(reg);
  201. pup = __raw_readl(reg);
  202. if (pup == S3C_GPIO_PULL_UP)
  203. pup &= ~(1 << off);
  204. else if (pup == S3C_GPIO_PULL_NONE)
  205. pup |= (1 << off);
  206. else
  207. return -EINVAL;
  208. __raw_writel(pup, reg);
  209. return 0;
  210. }
  211. s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
  212. unsigned int off)
  213. {
  214. void __iomem *reg = chip->base + 0x08;
  215. u32 pup = __raw_readl(reg);
  216. pup &= (1 << off);
  217. return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP;
  218. }
  219. #endif /* CONFIG_S3C_GPIO_PULL_UP */
  220. #ifdef CONFIG_S5P_GPIO_DRVSTR
  221. s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
  222. {
  223. struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
  224. unsigned int off;
  225. void __iomem *reg;
  226. int shift;
  227. u32 drvstr;
  228. if (!chip)
  229. return -EINVAL;
  230. off = pin - chip->chip.base;
  231. shift = off * 2;
  232. reg = chip->base + 0x0C;
  233. drvstr = __raw_readl(reg);
  234. drvstr = drvstr >> shift;
  235. drvstr &= 0x3;
  236. return (__force s5p_gpio_drvstr_t)drvstr;
  237. }
  238. EXPORT_SYMBOL(s5p_gpio_get_drvstr);
  239. int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
  240. {
  241. struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
  242. unsigned int off;
  243. void __iomem *reg;
  244. int shift;
  245. u32 tmp;
  246. if (!chip)
  247. return -EINVAL;
  248. off = pin - chip->chip.base;
  249. shift = off * 2;
  250. reg = chip->base + 0x0C;
  251. tmp = __raw_readl(reg);
  252. tmp &= ~(0x3 << shift);
  253. tmp |= drvstr << shift;
  254. __raw_writel(tmp, reg);
  255. return 0;
  256. }
  257. EXPORT_SYMBOL(s5p_gpio_set_drvstr);
  258. #endif /* CONFIG_S5P_GPIO_DRVSTR */