brcm2708: update against latest rpi-3.10.y branch
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0154-gpio-support-low-and-high-level-interrupts.patch
1 From c334aa8da6e17555823ebf05bdb429ff224e99b3 Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Thu, 9 Jan 2014 16:05:20 +0000
4 Subject: [PATCH 154/174] gpio: support low and high level interrupts
5
6 ---
7  arch/arm/mach-bcm2708/bcm2708_gpio.c | 52 +++++++++++++++++++++++++-----------
8  1 file changed, 37 insertions(+), 15 deletions(-)
9
10 --- a/arch/arm/mach-bcm2708/bcm2708_gpio.c
11 +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c
12 @@ -58,6 +58,8 @@ struct bcm2708_gpio {
13         struct gpio_chip gc;
14         unsigned long rising;
15         unsigned long falling;
16 +       unsigned long high;
17 +       unsigned long low;
18  };
19  
20  static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
21 @@ -145,20 +147,22 @@ static int bcm2708_gpio_irq_set_type(str
22         unsigned irq = d->irq;
23         struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
24  
25 -       if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
26 +       gpio->rising  &= ~(1 << __bcm2708_irq_to_gpio(irq));
27 +       gpio->falling &= ~(1 << __bcm2708_irq_to_gpio(irq));
28 +       gpio->high    &= ~(1 << __bcm2708_irq_to_gpio(irq));
29 +       gpio->low     &= ~(1 << __bcm2708_irq_to_gpio(irq));
30 +
31 +       if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
32                 return -EINVAL;
33  
34 -       if (type & IRQ_TYPE_EDGE_RISING) {
35 +       if (type & IRQ_TYPE_EDGE_RISING)
36                 gpio->rising |= (1 << __bcm2708_irq_to_gpio(irq));
37 -       } else {
38 -               gpio->rising &= ~(1 << __bcm2708_irq_to_gpio(irq));
39 -       }
40 -
41 -       if (type & IRQ_TYPE_EDGE_FALLING) {
42 +       if (type & IRQ_TYPE_EDGE_FALLING)
43                 gpio->falling |= (1 << __bcm2708_irq_to_gpio(irq));
44 -       } else {
45 -               gpio->falling &= ~(1 << __bcm2708_irq_to_gpio(irq));
46 -       }
47 +       if (type & IRQ_TYPE_LEVEL_HIGH)
48 +               gpio->high |= (1 << __bcm2708_irq_to_gpio(irq));
49 +       if (type & IRQ_TYPE_LEVEL_LOW)
50 +               gpio->low |= (1 << __bcm2708_irq_to_gpio(irq));
51         return 0;
52  }
53  
54 @@ -168,13 +172,17 @@ static void bcm2708_gpio_irq_mask(struct
55         struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
56         unsigned gn = __bcm2708_irq_to_gpio(irq);
57         unsigned gb = gn / 32;
58 -       unsigned long rising = readl(gpio->base + GPIOREN(gb));
59 +       unsigned long rising  = readl(gpio->base + GPIOREN(gb));
60         unsigned long falling = readl(gpio->base + GPIOFEN(gb));
61 +       unsigned long high    = readl(gpio->base + GPIOHEN(gb));
62 +       unsigned long low     = readl(gpio->base + GPIOLEN(gb));
63  
64         gn = gn % 32;
65  
66 -       writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
67 +       writel(rising  & ~(1 << gn), gpio->base + GPIOREN(gb));
68         writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
69 +       writel(high    & ~(1 << gn), gpio->base + GPIOHEN(gb));
70 +       writel(low     & ~(1 << gn), gpio->base + GPIOLEN(gb));
71  }
72  
73  static void bcm2708_gpio_irq_unmask(struct irq_data *d)
74 @@ -183,24 +191,38 @@ static void bcm2708_gpio_irq_unmask(stru
75         struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
76         unsigned gn = __bcm2708_irq_to_gpio(irq);
77         unsigned gb = gn / 32;
78 -       unsigned long rising = readl(gpio->base + GPIOREN(gb));
79 +       unsigned long rising  = readl(gpio->base + GPIOREN(gb));
80         unsigned long falling = readl(gpio->base + GPIOFEN(gb));
81 +       unsigned long high    = readl(gpio->base + GPIOHEN(gb));
82 +       unsigned long low     = readl(gpio->base + GPIOLEN(gb));
83  
84         gn = gn % 32;
85  
86         writel(1 << gn, gpio->base + GPIOEDS(gb));
87  
88         if (gpio->rising & (1 << gn)) {
89 -               writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
90 +               writel(rising |  (1 << gn), gpio->base + GPIOREN(gb));
91         } else {
92                 writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
93         }
94  
95         if (gpio->falling & (1 << gn)) {
96 -               writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
97 +               writel(falling |  (1 << gn), gpio->base + GPIOFEN(gb));
98         } else {
99                 writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
100         }
101 +
102 +       if (gpio->high & (1 << gn)) {
103 +               writel(high |  (1 << gn), gpio->base + GPIOHEN(gb));
104 +       } else {
105 +               writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
106 +       }
107 +
108 +       if (gpio->low & (1 << gn)) {
109 +               writel(low |  (1 << gn), gpio->base + GPIOLEN(gb));
110 +       } else {
111 +               writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
112 +       }
113  }
114  
115  static struct irq_chip bcm2708_irqchip = {