board-trout-gpio.c 5.9 KB

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