board-trout-gpio.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * linux/arch/arm/mach-msm/gpio.c
  3. *
  4. * Copyright (C) 2005 HP Labs
  5. * Copyright (C) 2008 Google, Inc.
  6. * Copyright (C) 2009 Pavel Machek <pavel@ucw.cz>
  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 as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/io.h>
  16. #include <linux/irq.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/gpio.h>
  19. #include "board-trout.h"
  20. static uint8_t trout_int_mask[2] = {
  21. [0] = 0xff, /* mask all interrupts */
  22. [1] = 0xff,
  23. };
  24. static uint8_t trout_sleep_int_mask[] = {
  25. [0] = 0xff,
  26. [1] = 0xff,
  27. };
  28. struct msm_gpio_chip {
  29. struct gpio_chip chip;
  30. void __iomem *reg; /* Base of register bank */
  31. u8 shadow;
  32. };
  33. #define to_msm_gpio_chip(c) container_of(c, struct msm_gpio_chip, chip)
  34. static int msm_gpiolib_get(struct gpio_chip *chip, unsigned offset)
  35. {
  36. struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
  37. unsigned mask = 1 << offset;
  38. return !!(readb(msm_gpio->reg) & mask);
  39. }
  40. static void msm_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
  41. {
  42. struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
  43. unsigned mask = 1 << offset;
  44. if (val)
  45. msm_gpio->shadow |= mask;
  46. else
  47. msm_gpio->shadow &= ~mask;
  48. writeb(msm_gpio->shadow, msm_gpio->reg);
  49. }
  50. static int msm_gpiolib_direction_input(struct gpio_chip *chip,
  51. unsigned offset)
  52. {
  53. msm_gpiolib_set(chip, offset, 0);
  54. return 0;
  55. }
  56. static int msm_gpiolib_direction_output(struct gpio_chip *chip,
  57. unsigned offset, int val)
  58. {
  59. msm_gpiolib_set(chip, offset, val);
  60. return 0;
  61. }
  62. static int trout_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  63. {
  64. struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
  65. return TROUT_GPIO_TO_INT(offset + chip->base);
  66. }
  67. #define TROUT_GPIO_BANK(name, reg_num, base_gpio, shadow_val) \
  68. { \
  69. .chip = { \
  70. .label = name, \
  71. .direction_input = msm_gpiolib_direction_input,\
  72. .direction_output = msm_gpiolib_direction_output, \
  73. .get = msm_gpiolib_get, \
  74. .set = msm_gpiolib_set, \
  75. .to_irq = trout_gpio_to_irq, \
  76. .base = base_gpio, \
  77. .ngpio = 8, \
  78. }, \
  79. .reg = (void *) reg_num + TROUT_CPLD_BASE, \
  80. .shadow = shadow_val, \
  81. }
  82. static struct msm_gpio_chip msm_gpio_banks[] = {
  83. #if defined(CONFIG_MSM_DEBUG_UART1)
  84. /* H2W pins <-> UART1 */
  85. TROUT_GPIO_BANK("MISC2", 0x00, TROUT_GPIO_MISC2_BASE, 0x40),
  86. #else
  87. /* H2W pins <-> UART3, Bluetooth <-> UART1 */
  88. TROUT_GPIO_BANK("MISC2", 0x00, TROUT_GPIO_MISC2_BASE, 0x80),
  89. #endif
  90. /* I2C pull */
  91. TROUT_GPIO_BANK("MISC3", 0x02, TROUT_GPIO_MISC3_BASE, 0x04),
  92. TROUT_GPIO_BANK("MISC4", 0x04, TROUT_GPIO_MISC4_BASE, 0),
  93. /* mmdi 32k en */
  94. TROUT_GPIO_BANK("MISC5", 0x06, TROUT_GPIO_MISC5_BASE, 0x04),
  95. TROUT_GPIO_BANK("INT2", 0x08, TROUT_GPIO_INT2_BASE, 0),
  96. TROUT_GPIO_BANK("MISC1", 0x0a, TROUT_GPIO_MISC1_BASE, 0),
  97. TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0),
  98. };
  99. static void trout_gpio_irq_ack(struct irq_data *d)
  100. {
  101. int bank = TROUT_INT_TO_BANK(d->irq);
  102. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  103. int reg = TROUT_BANK_TO_STAT_REG(bank);
  104. /*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", d->irq);*/
  105. writeb(mask, TROUT_CPLD_BASE + reg);
  106. }
  107. static void trout_gpio_irq_mask(struct irq_data *d)
  108. {
  109. unsigned long flags;
  110. uint8_t reg_val;
  111. int bank = TROUT_INT_TO_BANK(d->irq);
  112. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  113. int reg = TROUT_BANK_TO_MASK_REG(bank);
  114. local_irq_save(flags);
  115. reg_val = trout_int_mask[bank] |= mask;
  116. /*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n",
  117. d->irq, bank, reg_val);*/
  118. writeb(reg_val, TROUT_CPLD_BASE + reg);
  119. local_irq_restore(flags);
  120. }
  121. static void trout_gpio_irq_unmask(struct irq_data *d)
  122. {
  123. unsigned long flags;
  124. uint8_t reg_val;
  125. int bank = TROUT_INT_TO_BANK(d->irq);
  126. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  127. int reg = TROUT_BANK_TO_MASK_REG(bank);
  128. local_irq_save(flags);
  129. reg_val = trout_int_mask[bank] &= ~mask;
  130. /*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n",
  131. d->irq, bank, reg_val);*/
  132. writeb(reg_val, TROUT_CPLD_BASE + reg);
  133. local_irq_restore(flags);
  134. }
  135. int trout_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
  136. {
  137. unsigned long flags;
  138. int bank = TROUT_INT_TO_BANK(d->irq);
  139. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  140. local_irq_save(flags);
  141. if(on)
  142. trout_sleep_int_mask[bank] &= ~mask;
  143. else
  144. trout_sleep_int_mask[bank] |= mask;
  145. local_irq_restore(flags);
  146. return 0;
  147. }
  148. static void trout_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
  149. {
  150. int j, m;
  151. unsigned v;
  152. int bank;
  153. int stat_reg;
  154. int int_base = TROUT_INT_START;
  155. uint8_t int_mask;
  156. for (bank = 0; bank < 2; bank++) {
  157. stat_reg = TROUT_BANK_TO_STAT_REG(bank);
  158. v = readb(TROUT_CPLD_BASE + stat_reg);
  159. int_mask = trout_int_mask[bank];
  160. if (v & int_mask) {
  161. writeb(v & int_mask, TROUT_CPLD_BASE + stat_reg);
  162. printk(KERN_ERR "trout_gpio_irq_handler: got masked "
  163. "interrupt: %d:%02x\n", bank, v & int_mask);
  164. }
  165. v &= ~int_mask;
  166. while (v) {
  167. m = v & -v;
  168. j = fls(m) - 1;
  169. /*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b"
  170. "it %d irq %d\n", bank, v, m, j, int_base + j);*/
  171. v &= ~m;
  172. generic_handle_irq(int_base + j);
  173. }
  174. int_base += TROUT_INT_BANK0_COUNT;
  175. }
  176. desc->irq_data.chip->irq_ack(&desc->irq_data);
  177. }
  178. static struct irq_chip trout_gpio_irq_chip = {
  179. .name = "troutgpio",
  180. .irq_ack = trout_gpio_irq_ack,
  181. .irq_mask = trout_gpio_irq_mask,
  182. .irq_unmask = trout_gpio_irq_unmask,
  183. .irq_set_wake = trout_gpio_irq_set_wake,
  184. };
  185. /*
  186. * Called from the processor-specific init to enable GPIO pin support.
  187. */
  188. int __init trout_init_gpio(void)
  189. {
  190. int i;
  191. for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) {
  192. set_irq_chip(i, &trout_gpio_irq_chip);
  193. set_irq_handler(i, handle_edge_irq);
  194. set_irq_flags(i, IRQF_VALID);
  195. }
  196. for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++)
  197. gpiochip_add(&msm_gpio_banks[i].chip);
  198. set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
  199. set_irq_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
  200. set_irq_wake(MSM_GPIO_TO_INT(17), 1);
  201. return 0;
  202. }
  203. postcore_initcall(trout_init_gpio);