gpio.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* linux/arch/arm/mach-vt8500/gpio.c
  2. *
  3. * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
  4. *
  5. * This software is licensed under the terms of the GNU General Public
  6. * License version 2, as published by the Free Software Foundation, and
  7. * may be copied, distributed, and modified under those terms.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/gpio.h>
  16. #include <linux/init.h>
  17. #include <linux/irq.h>
  18. #include <linux/io.h>
  19. #include "devices.h"
  20. #define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
  21. #define ENABLE_REGS 0x0
  22. #define DIRECTION_REGS 0x20
  23. #define OUTVALUE_REGS 0x40
  24. #define INVALUE_REGS 0x60
  25. #define EXT_REGOFF 0x1c
  26. static void __iomem *regbase;
  27. struct vt8500_gpio_chip {
  28. struct gpio_chip chip;
  29. unsigned int shift;
  30. unsigned int regoff;
  31. };
  32. static int gpio_to_irq_map[8];
  33. static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
  34. unsigned offset)
  35. {
  36. struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
  37. unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
  38. val |= (1 << vt8500_chip->shift << offset);
  39. writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
  40. return 0;
  41. }
  42. static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
  43. unsigned offset)
  44. {
  45. struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
  46. unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
  47. val &= ~(1 << vt8500_chip->shift << offset);
  48. writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
  49. }
  50. static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
  51. unsigned offset)
  52. {
  53. struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
  54. unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
  55. val &= ~(1 << vt8500_chip->shift << offset);
  56. writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
  57. return 0;
  58. }
  59. static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
  60. unsigned offset, int value)
  61. {
  62. struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
  63. unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
  64. val |= (1 << vt8500_chip->shift << offset);
  65. writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
  66. if (value) {
  67. val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff);
  68. val |= (1 << vt8500_chip->shift << offset);
  69. writel(val, regbase + OUTVALUE_REGS + vt8500_chip->regoff);
  70. }
  71. return 0;
  72. }
  73. static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
  74. unsigned offset)
  75. {
  76. struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
  77. return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff)
  78. >> vt8500_chip->shift >> offset) & 1;
  79. }
  80. static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
  81. unsigned offset, int value)
  82. {
  83. struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
  84. unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
  85. if (value)
  86. val |= (1 << vt8500_chip->shift << offset);
  87. else
  88. val &= ~(1 << vt8500_chip->shift << offset);
  89. writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff);
  90. }
  91. #define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num) \
  92. { \
  93. .chip = { \
  94. .label = __name, \
  95. .request = vt8500_muxed_gpio_request, \
  96. .free = vt8500_muxed_gpio_free, \
  97. .direction_input = vt8500_muxed_gpio_direction_input, \
  98. .direction_output = vt8500_muxed_gpio_direction_output, \
  99. .get = vt8500_muxed_gpio_get_value, \
  100. .set = vt8500_muxed_gpio_set_value, \
  101. .can_sleep = 0, \
  102. .base = __base, \
  103. .ngpio = __num, \
  104. }, \
  105. .shift = __shift, \
  106. .regoff = __off, \
  107. }
  108. static struct vt8500_gpio_chip vt8500_muxed_gpios[] = {
  109. VT8500_GPIO_BANK("uart0", 0, 0x0, 8, 4),
  110. VT8500_GPIO_BANK("uart1", 4, 0x0, 12, 4),
  111. VT8500_GPIO_BANK("spi0", 8, 0x0, 16, 4),
  112. VT8500_GPIO_BANK("spi1", 12, 0x0, 20, 4),
  113. VT8500_GPIO_BANK("spi2", 16, 0x0, 24, 4),
  114. VT8500_GPIO_BANK("pwmout", 24, 0x0, 28, 2),
  115. VT8500_GPIO_BANK("sdmmc", 0, 0x4, 30, 11),
  116. VT8500_GPIO_BANK("ms", 16, 0x4, 41, 7),
  117. VT8500_GPIO_BANK("i2c0", 24, 0x4, 48, 2),
  118. VT8500_GPIO_BANK("i2c1", 26, 0x4, 50, 2),
  119. VT8500_GPIO_BANK("mii", 0, 0x8, 52, 20),
  120. VT8500_GPIO_BANK("see", 20, 0x8, 72, 4),
  121. VT8500_GPIO_BANK("ide", 24, 0x8, 76, 7),
  122. VT8500_GPIO_BANK("ccir", 0, 0xc, 83, 19),
  123. VT8500_GPIO_BANK("ts", 8, 0x10, 102, 11),
  124. VT8500_GPIO_BANK("lcd", 0, 0x14, 113, 23),
  125. };
  126. static int vt8500_gpio_direction_input(struct gpio_chip *chip,
  127. unsigned offset)
  128. {
  129. unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
  130. val &= ~(1 << offset);
  131. writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
  132. return 0;
  133. }
  134. static int vt8500_gpio_direction_output(struct gpio_chip *chip,
  135. unsigned offset, int value)
  136. {
  137. unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
  138. val |= (1 << offset);
  139. writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
  140. if (value) {
  141. val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
  142. val |= (1 << offset);
  143. writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
  144. }
  145. return 0;
  146. }
  147. static int vt8500_gpio_get_value(struct gpio_chip *chip,
  148. unsigned offset)
  149. {
  150. return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
  151. }
  152. static void vt8500_gpio_set_value(struct gpio_chip *chip,
  153. unsigned offset, int value)
  154. {
  155. unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
  156. if (value)
  157. val |= (1 << offset);
  158. else
  159. val &= ~(1 << offset);
  160. writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
  161. }
  162. static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  163. {
  164. if (offset > 7)
  165. return -EINVAL;
  166. return gpio_to_irq_map[offset];
  167. }
  168. static struct gpio_chip vt8500_external_gpios = {
  169. .label = "extgpio",
  170. .direction_input = vt8500_gpio_direction_input,
  171. .direction_output = vt8500_gpio_direction_output,
  172. .get = vt8500_gpio_get_value,
  173. .set = vt8500_gpio_set_value,
  174. .to_irq = vt8500_gpio_to_irq,
  175. .can_sleep = 0,
  176. .base = 0,
  177. .ngpio = 8,
  178. };
  179. void __init vt8500_gpio_init(void)
  180. {
  181. int i;
  182. for (i = 0; i < 8; i++)
  183. gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
  184. regbase = ioremap(wmt_gpio_base, SZ_64K);
  185. if (!regbase) {
  186. printk(KERN_ERR "Failed to map MMIO registers for GPIO\n");
  187. return;
  188. }
  189. gpiochip_add(&vt8500_external_gpios);
  190. for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
  191. gpiochip_add(&vt8500_muxed_gpios[i].chip);
  192. }