gpiolib.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* linux/arch/arm/plat-s3c24xx/gpiolib.c
  2. *
  3. * Copyright (c) 2008 Simtec Electronics
  4. * http://armlinux.simtec.co.uk/
  5. * Ben Dooks <ben@simtec.co.uk>
  6. *
  7. * S3C24XX GPIOlib support
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/init.h>
  15. #include <linux/module.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/ioport.h>
  18. #include <linux/io.h>
  19. #include <linux/gpio.h>
  20. #include <mach/hardware.h>
  21. #include <asm/irq.h>
  22. #include <mach/regs-gpio.h>
  23. struct s3c24xx_gpio_chip {
  24. struct gpio_chip chip;
  25. void __iomem *base;
  26. };
  27. static inline struct s3c24xx_gpio_chip *to_s3c_chip(struct gpio_chip *gpc)
  28. {
  29. return container_of(gpc, struct s3c24xx_gpio_chip, chip);
  30. }
  31. /* these routines are exported for use by other parts of the platform
  32. * and system support, but are not intended to be used directly by the
  33. * drivers themsevles.
  34. */
  35. static int s3c24xx_gpiolib_input(struct gpio_chip *chip, unsigned offset)
  36. {
  37. struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
  38. void __iomem *base = ourchip->base;
  39. unsigned long flags;
  40. unsigned long con;
  41. local_irq_save(flags);
  42. con = __raw_readl(base + 0x00);
  43. con &= ~(3 << (offset * 2));
  44. con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2);
  45. __raw_writel(con, base + 0x00);
  46. local_irq_restore(flags);
  47. return 0;
  48. }
  49. static int s3c24xx_gpiolib_output(struct gpio_chip *chip,
  50. unsigned offset, int value)
  51. {
  52. struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
  53. void __iomem *base = ourchip->base;
  54. unsigned long flags;
  55. unsigned long dat;
  56. unsigned long con;
  57. local_irq_save(flags);
  58. dat = __raw_readl(base + 0x04);
  59. dat &= ~(1 << offset);
  60. if (value)
  61. dat |= 1 << offset;
  62. __raw_writel(dat, base + 0x04);
  63. con = __raw_readl(base + 0x00);
  64. con &= ~(3 << (offset * 2));
  65. con |= (S3C2410_GPIO_OUTPUT & 0xf) << (offset * 2);
  66. __raw_writel(con, base + 0x00);
  67. __raw_writel(dat, base + 0x04);
  68. local_irq_restore(flags);
  69. return 0;
  70. }
  71. static void s3c24xx_gpiolib_set(struct gpio_chip *chip,
  72. unsigned offset, int value)
  73. {
  74. struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
  75. void __iomem *base = ourchip->base;
  76. unsigned long flags;
  77. unsigned long dat;
  78. local_irq_save(flags);
  79. dat = __raw_readl(base + 0x04);
  80. dat &= ~(1 << offset);
  81. if (value)
  82. dat |= 1 << offset;
  83. __raw_writel(dat, base + 0x04);
  84. local_irq_restore(flags);
  85. }
  86. static int s3c24xx_gpiolib_get(struct gpio_chip *chip, unsigned offset)
  87. {
  88. struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
  89. unsigned long val;
  90. val = __raw_readl(ourchip->base + 0x04);
  91. val >>= offset;
  92. val &= 1;
  93. return val;
  94. }
  95. static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
  96. {
  97. return -EINVAL;
  98. }
  99. static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
  100. unsigned offset, int value)
  101. {
  102. struct s3c24xx_gpio_chip *ourchip = to_s3c_chip(chip);
  103. void __iomem *base = ourchip->base;
  104. unsigned long flags;
  105. unsigned long dat;
  106. unsigned long con;
  107. local_irq_save(flags);
  108. con = __raw_readl(base + 0x00);
  109. dat = __raw_readl(base + 0x04);
  110. dat &= ~(1 << offset);
  111. if (value)
  112. dat |= 1 << offset;
  113. __raw_writel(dat, base + 0x04);
  114. con &= ~(1 << offset);
  115. __raw_writel(con, base + 0x00);
  116. __raw_writel(dat, base + 0x04);
  117. local_irq_restore(flags);
  118. return 0;
  119. }
  120. static struct s3c24xx_gpio_chip gpios[] = {
  121. [0] = {
  122. .base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
  123. .chip = {
  124. .base = S3C2410_GPA0,
  125. .owner = THIS_MODULE,
  126. .label = "GPIOA",
  127. .ngpio = 24,
  128. .direction_input = s3c24xx_gpiolib_banka_input,
  129. .direction_output = s3c24xx_gpiolib_banka_output,
  130. },
  131. },
  132. [1] = {
  133. .base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
  134. .chip = {
  135. .base = S3C2410_GPB0,
  136. .owner = THIS_MODULE,
  137. .label = "GPIOB",
  138. .ngpio = 16,
  139. },
  140. },
  141. [2] = {
  142. .base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
  143. .chip = {
  144. .base = S3C2410_GPC0,
  145. .owner = THIS_MODULE,
  146. .label = "GPIOC",
  147. .ngpio = 16,
  148. },
  149. },
  150. [3] = {
  151. .base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
  152. .chip = {
  153. .base = S3C2410_GPD0,
  154. .owner = THIS_MODULE,
  155. .label = "GPIOD",
  156. .ngpio = 16,
  157. },
  158. },
  159. [4] = {
  160. .base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
  161. .chip = {
  162. .base = S3C2410_GPE0,
  163. .label = "GPIOE",
  164. .owner = THIS_MODULE,
  165. .ngpio = 16,
  166. },
  167. },
  168. [5] = {
  169. .base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
  170. .chip = {
  171. .base = S3C2410_GPF0,
  172. .owner = THIS_MODULE,
  173. .label = "GPIOF",
  174. .ngpio = 8,
  175. },
  176. },
  177. [6] = {
  178. .base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
  179. .chip = {
  180. .base = S3C2410_GPG0,
  181. .owner = THIS_MODULE,
  182. .label = "GPIOG",
  183. .ngpio = 10,
  184. },
  185. },
  186. };
  187. static __init void s3c24xx_gpiolib_add(struct s3c24xx_gpio_chip *chip)
  188. {
  189. struct gpio_chip *gc = &chip->chip;
  190. BUG_ON(!chip->base);
  191. BUG_ON(!gc->label);
  192. BUG_ON(!gc->ngpio);
  193. if (!gc->direction_input)
  194. gc->direction_input = s3c24xx_gpiolib_input;
  195. if (!gc->direction_output)
  196. gc->direction_output = s3c24xx_gpiolib_output;
  197. if (!gc->set)
  198. gc->set = s3c24xx_gpiolib_set;
  199. if (!gc->get)
  200. gc->get = s3c24xx_gpiolib_get;
  201. /* gpiochip_add() prints own failure message on error. */
  202. gpiochip_add(gc);
  203. }
  204. static __init int s3c24xx_gpiolib_init(void)
  205. {
  206. struct s3c24xx_gpio_chip *chip = gpios;
  207. int gpn;
  208. for (gpn = 0; gpn < ARRAY_SIZE(gpios); gpn++, chip++)
  209. s3c24xx_gpiolib_add(chip);
  210. return 0;
  211. }
  212. arch_initcall(s3c24xx_gpiolib_init);