633-MIPS-ath79-add-gpio-irq-support.patch 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. --- a/arch/mips/ath79/gpio.c
  2. +++ b/arch/mips/ath79/gpio.c
  3. @@ -20,9 +20,14 @@
  4. #include <linux/io.h>
  5. #include <linux/ioport.h>
  6. #include <linux/gpio.h>
  7. +#include <linux/irq.h>
  8. +#include <linux/interrupt.h>
  9. +
  10. +#include <linux/of.h>
  11. #include <asm/mach-ath79/ar71xx_regs.h>
  12. #include <asm/mach-ath79/ath79.h>
  13. +#include <asm/mach-ath79/irq.h>
  14. #include "common.h"
  15. void __iomem *ath79_gpio_base;
  16. @@ -31,6 +36,13 @@ EXPORT_SYMBOL_GPL(ath79_gpio_base);
  17. static unsigned long ath79_gpio_count;
  18. static DEFINE_SPINLOCK(ath79_gpio_lock);
  19. +/*
  20. + * gpio_both_edge is a bitmask of which gpio pins need to have
  21. + * the detect priority flipped from the interrupt handler to
  22. + * emulate IRQ_TYPE_EDGE_BOTH.
  23. + */
  24. +static unsigned long gpio_both_edge = 0;
  25. +
  26. static void __ath79_gpio_set_value(unsigned gpio, int value)
  27. {
  28. void __iomem *base = ath79_gpio_base;
  29. @@ -233,6 +245,132 @@ void __init ath79_gpio_output_select(uns
  30. spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  31. }
  32. +static int ath79_gpio_irq_type(struct irq_data *d, unsigned type)
  33. +{
  34. + int offset = d->irq - ATH79_GPIO_IRQ_BASE;
  35. + void __iomem *base = ath79_gpio_base;
  36. + unsigned long flags;
  37. + unsigned long int_type;
  38. + unsigned long int_polarity;
  39. + unsigned long bit = (1 << offset);
  40. +
  41. + spin_lock_irqsave(&ath79_gpio_lock, flags);
  42. +
  43. + int_type = __raw_readl(base + AR71XX_GPIO_REG_INT_TYPE);
  44. + int_polarity = __raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY);
  45. +
  46. + gpio_both_edge &= ~bit;
  47. +
  48. + switch (type) {
  49. + case IRQ_TYPE_EDGE_RISING:
  50. + int_type &= ~bit;
  51. + int_polarity |= bit;
  52. + break;
  53. +
  54. + case IRQ_TYPE_EDGE_FALLING:
  55. + int_type &= ~bit;
  56. + int_polarity &= ~bit;
  57. + break;
  58. +
  59. + case IRQ_TYPE_LEVEL_HIGH:
  60. + int_type |= bit;
  61. + int_polarity |= bit;
  62. + break;
  63. +
  64. + case IRQ_TYPE_LEVEL_LOW:
  65. + int_type |= bit;
  66. + int_polarity &= ~bit;
  67. + break;
  68. +
  69. + case IRQ_TYPE_EDGE_BOTH:
  70. + int_type |= bit;
  71. + /* set polarity based on current value */
  72. + if (gpio_get_value(offset)) {
  73. + int_polarity &= ~bit;
  74. + } else {
  75. + int_polarity |= bit;
  76. + }
  77. + /* flip this gpio in the interrupt handler */
  78. + gpio_both_edge |= bit;
  79. + break;
  80. +
  81. + default:
  82. + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  83. + return -EINVAL;
  84. + }
  85. +
  86. + __raw_writel(int_type, base + AR71XX_GPIO_REG_INT_TYPE);
  87. + __raw_writel(int_polarity, base + AR71XX_GPIO_REG_INT_POLARITY);
  88. +
  89. + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_MODE) | (1 << offset),
  90. + base + AR71XX_GPIO_REG_INT_MODE);
  91. +
  92. + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
  93. + base + AR71XX_GPIO_REG_INT_ENABLE);
  94. +
  95. + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
  96. + return 0;
  97. +}
  98. +
  99. +static void ath79_gpio_irq_enable(struct irq_data *d)
  100. +{
  101. + int offset = d->irq - ATH79_GPIO_IRQ_BASE;
  102. + void __iomem *base = ath79_gpio_base;
  103. +
  104. + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) | (1 << offset),
  105. + base + AR71XX_GPIO_REG_INT_ENABLE);
  106. +}
  107. +
  108. +static void ath79_gpio_irq_disable(struct irq_data *d)
  109. +{
  110. + int offset = d->irq - ATH79_GPIO_IRQ_BASE;
  111. + void __iomem *base = ath79_gpio_base;
  112. +
  113. + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
  114. + base + AR71XX_GPIO_REG_INT_ENABLE);
  115. +}
  116. +
  117. +static struct irq_chip ath79_gpio_irqchip = {
  118. + .name = "GPIO",
  119. + .irq_enable = ath79_gpio_irq_enable,
  120. + .irq_disable = ath79_gpio_irq_disable,
  121. + .irq_set_type = ath79_gpio_irq_type,
  122. +};
  123. +
  124. +static irqreturn_t ath79_gpio_irq(int irq, void *dev)
  125. +{
  126. + void __iomem *base = ath79_gpio_base;
  127. + unsigned long stat = __raw_readl(base + AR71XX_GPIO_REG_INT_PENDING);
  128. + int bit_num;
  129. +
  130. + for_each_set_bit(bit_num, &stat, sizeof(stat) * BITS_PER_BYTE) {
  131. + unsigned long bit = BIT(bit_num);
  132. +
  133. + if (bit & gpio_both_edge) {
  134. + __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY) ^ bit,
  135. + base + AR71XX_GPIO_REG_INT_POLARITY);
  136. + }
  137. +
  138. + generic_handle_irq(ATH79_GPIO_IRQ(bit_num));
  139. + }
  140. +
  141. + return IRQ_HANDLED;
  142. +}
  143. +
  144. +static int __init ath79_gpio_irq_init(struct gpio_chip *chip)
  145. +{
  146. + int irq;
  147. + int irq_base = ATH79_GPIO_IRQ_BASE;
  148. +
  149. + for (irq = irq_base; irq < irq_base + chip->ngpio; irq++) {
  150. + irq_set_chip_data(irq, chip);
  151. + irq_set_chip_and_handler(irq, &ath79_gpio_irqchip, handle_simple_irq);
  152. + irq_set_noprobe(irq);
  153. + }
  154. +
  155. + return 0;
  156. +}
  157. +
  158. void __init ath79_gpio_init(void)
  159. {
  160. int err;
  161. @@ -269,6 +407,10 @@ void __init ath79_gpio_init(void)
  162. err = gpiochip_add(&ath79_gpio_chip);
  163. if (err)
  164. panic("cannot add AR71xx GPIO chip, error=%d", err);
  165. +
  166. + ath79_gpio_irq_init(&ath79_gpio_chip);
  167. +
  168. + request_irq(ATH79_MISC_IRQ(2), ath79_gpio_irq, 0, "ath79-gpio", NULL);
  169. }
  170. int gpio_get_value(unsigned gpio)
  171. @@ -291,14 +433,22 @@ EXPORT_SYMBOL(gpio_set_value);
  172. int gpio_to_irq(unsigned gpio)
  173. {
  174. - /* FIXME */
  175. - return -EINVAL;
  176. + if (gpio > ath79_gpio_count) {
  177. + return -EINVAL;
  178. + }
  179. +
  180. + return ATH79_GPIO_IRQ_BASE + gpio;
  181. }
  182. EXPORT_SYMBOL(gpio_to_irq);
  183. int irq_to_gpio(unsigned irq)
  184. {
  185. - /* FIXME */
  186. - return -EINVAL;
  187. + unsigned gpio = irq - ATH79_GPIO_IRQ_BASE;
  188. +
  189. + if (gpio > ath79_gpio_count) {
  190. + return -EINVAL;
  191. + }
  192. +
  193. + return gpio;
  194. }
  195. EXPORT_SYMBOL(irq_to_gpio);
  196. --- a/arch/mips/include/asm/mach-ath79/irq.h
  197. +++ b/arch/mips/include/asm/mach-ath79/irq.h
  198. @@ -10,7 +10,7 @@
  199. #define __ASM_MACH_ATH79_IRQ_H
  200. #define MIPS_CPU_IRQ_BASE 0
  201. -#define NR_IRQS 51
  202. +#define NR_IRQS 83
  203. #define ATH79_CPU_IRQ(_x) (MIPS_CPU_IRQ_BASE + (_x))
  204. @@ -30,6 +30,10 @@
  205. #define ATH79_IP3_IRQ_COUNT 3
  206. #define ATH79_IP3_IRQ(_x) (ATH79_IP3_IRQ_BASE + (_x))
  207. +#define ATH79_GPIO_IRQ_BASE (ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT)
  208. +#define ATH79_GPIO_IRQ_COUNT 32
  209. +#define ATH79_GPIO_IRQ(_x) (ATH79_GPIO_IRQ_BASE + (_x))
  210. +
  211. #include_next <irq.h>
  212. #endif /* __ASM_MACH_ATH79_IRQ_H */