board-trout-gpio.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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. return TROUT_GPIO_TO_INT(offset + chip->base);
  65. }
  66. #define TROUT_GPIO_BANK(name, reg_num, base_gpio, shadow_val) \
  67. { \
  68. .chip = { \
  69. .label = name, \
  70. .direction_input = msm_gpiolib_direction_input,\
  71. .direction_output = msm_gpiolib_direction_output, \
  72. .get = msm_gpiolib_get, \
  73. .set = msm_gpiolib_set, \
  74. .to_irq = trout_gpio_to_irq, \
  75. .base = base_gpio, \
  76. .ngpio = 8, \
  77. }, \
  78. .reg = (void *) reg_num + TROUT_CPLD_BASE, \
  79. .shadow = shadow_val, \
  80. }
  81. static struct msm_gpio_chip msm_gpio_banks[] = {
  82. #if defined(CONFIG_MSM_DEBUG_UART1)
  83. /* H2W pins <-> UART1 */
  84. TROUT_GPIO_BANK("MISC2", 0x00, TROUT_GPIO_MISC2_BASE, 0x40),
  85. #else
  86. /* H2W pins <-> UART3, Bluetooth <-> UART1 */
  87. TROUT_GPIO_BANK("MISC2", 0x00, TROUT_GPIO_MISC2_BASE, 0x80),
  88. #endif
  89. /* I2C pull */
  90. TROUT_GPIO_BANK("MISC3", 0x02, TROUT_GPIO_MISC3_BASE, 0x04),
  91. TROUT_GPIO_BANK("MISC4", 0x04, TROUT_GPIO_MISC4_BASE, 0),
  92. /* mmdi 32k en */
  93. TROUT_GPIO_BANK("MISC5", 0x06, TROUT_GPIO_MISC5_BASE, 0x04),
  94. TROUT_GPIO_BANK("INT2", 0x08, TROUT_GPIO_INT2_BASE, 0),
  95. TROUT_GPIO_BANK("MISC1", 0x0a, TROUT_GPIO_MISC1_BASE, 0),
  96. TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0),
  97. };
  98. static void trout_gpio_irq_ack(struct irq_data *d)
  99. {
  100. int bank = TROUT_INT_TO_BANK(d->irq);
  101. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  102. int reg = TROUT_BANK_TO_STAT_REG(bank);
  103. /*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", d->irq);*/
  104. writeb(mask, TROUT_CPLD_BASE + reg);
  105. }
  106. static void trout_gpio_irq_mask(struct irq_data *d)
  107. {
  108. unsigned long flags;
  109. uint8_t reg_val;
  110. int bank = TROUT_INT_TO_BANK(d->irq);
  111. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  112. int reg = TROUT_BANK_TO_MASK_REG(bank);
  113. local_irq_save(flags);
  114. reg_val = trout_int_mask[bank] |= mask;
  115. /*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n",
  116. d->irq, bank, reg_val);*/
  117. writeb(reg_val, TROUT_CPLD_BASE + reg);
  118. local_irq_restore(flags);
  119. }
  120. static void trout_gpio_irq_unmask(struct irq_data *d)
  121. {
  122. unsigned long flags;
  123. uint8_t reg_val;
  124. int bank = TROUT_INT_TO_BANK(d->irq);
  125. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  126. int reg = TROUT_BANK_TO_MASK_REG(bank);
  127. local_irq_save(flags);
  128. reg_val = trout_int_mask[bank] &= ~mask;
  129. /*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n",
  130. d->irq, bank, reg_val);*/
  131. writeb(reg_val, TROUT_CPLD_BASE + reg);
  132. local_irq_restore(flags);
  133. }
  134. int trout_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
  135. {
  136. unsigned long flags;
  137. int bank = TROUT_INT_TO_BANK(d->irq);
  138. uint8_t mask = TROUT_INT_TO_MASK(d->irq);
  139. local_irq_save(flags);
  140. if(on)
  141. trout_sleep_int_mask[bank] &= ~mask;
  142. else
  143. trout_sleep_int_mask[bank] |= mask;
  144. local_irq_restore(flags);
  145. return 0;
  146. }
  147. static void trout_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
  148. {
  149. int j, m;
  150. unsigned v;
  151. int bank;
  152. int stat_reg;
  153. int int_base = TROUT_INT_START;
  154. uint8_t int_mask;
  155. for (bank = 0; bank < 2; bank++) {
  156. stat_reg = TROUT_BANK_TO_STAT_REG(bank);
  157. v = readb(TROUT_CPLD_BASE + stat_reg);
  158. int_mask = trout_int_mask[bank];
  159. if (v & int_mask) {
  160. writeb(v & int_mask, TROUT_CPLD_BASE + stat_reg);
  161. printk(KERN_ERR "trout_gpio_irq_handler: got masked "
  162. "interrupt: %d:%02x\n", bank, v & int_mask);
  163. }
  164. v &= ~int_mask;
  165. while (v) {
  166. m = v & -v;
  167. j = fls(m) - 1;
  168. /*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b"
  169. "it %d irq %d\n", bank, v, m, j, int_base + j);*/
  170. v &= ~m;
  171. generic_handle_irq(int_base + j);
  172. }
  173. int_base += TROUT_INT_BANK0_COUNT;
  174. }
  175. desc->irq_data.chip->irq_ack(&desc->irq_data);
  176. }
  177. static struct irq_chip trout_gpio_irq_chip = {
  178. .name = "troutgpio",
  179. .irq_ack = trout_gpio_irq_ack,
  180. .irq_mask = trout_gpio_irq_mask,
  181. .irq_unmask = trout_gpio_irq_unmask,
  182. .irq_set_wake = trout_gpio_irq_set_wake,
  183. };
  184. /*
  185. * Called from the processor-specific init to enable GPIO pin support.
  186. */
  187. int __init trout_init_gpio(void)
  188. {
  189. int i;
  190. for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) {
  191. irq_set_chip_and_handler(i, &trout_gpio_irq_chip,
  192. handle_edge_irq);
  193. set_irq_flags(i, IRQF_VALID);
  194. }
  195. for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++)
  196. gpiochip_add(&msm_gpio_banks[i].chip);
  197. irq_set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
  198. irq_set_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
  199. irq_set_irq_wake(MSM_GPIO_TO_INT(17), 1);
  200. return 0;
  201. }
  202. postcore_initcall(trout_init_gpio);