Commit a663a71e429d7d06a7773edc4092995c5fe1171f

Authored by Russell King
Committed by Russell King

Merge git://git.marvell.com/orion into devel

Showing 20 changed files Side-by-side Diff

... ... @@ -387,6 +387,7 @@
387 387 bool "Marvell Kirkwood"
388 388 select CPU_FEROCEON
389 389 select PCI
  390 + select GENERIC_GPIO
390 391 select GENERIC_TIME
391 392 select GENERIC_CLOCKEVENTS
392 393 select PLAT_ORION
... ... @@ -429,6 +430,7 @@
429 430 bool "Marvell MV78xx0"
430 431 select CPU_FEROCEON
431 432 select PCI
  433 + select GENERIC_GPIO
432 434 select GENERIC_TIME
433 435 select GENERIC_CLOCKEVENTS
434 436 select PLAT_ORION
arch/arm/mach-kirkwood/include/mach/gpio.h
  1 +/*
  2 + * arch/asm-arm/mach-kirkwood/include/mach/gpio.h
  3 + *
  4 + * This file is licensed under the terms of the GNU General Public
  5 + * License version 2. This program is licensed "as is" without any
  6 + * warranty of any kind, whether express or implied.
  7 + */
  8 +
  9 +#ifndef __ASM_ARCH_GPIO_H
  10 +#define __ASM_ARCH_GPIO_H
  11 +
  12 +#include <mach/irqs.h>
  13 +#include <plat/gpio.h>
  14 +#include <asm-generic/gpio.h> /* cansleep wrappers */
  15 +
  16 +#define GPIO_MAX 50
  17 +#define GPIO_OFF(pin) (((pin) >> 5) ? 0x0140 : 0x0100)
  18 +#define GPIO_OUT(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x00)
  19 +#define GPIO_IO_CONF(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x04)
  20 +#define GPIO_BLINK_EN(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x08)
  21 +#define GPIO_IN_POL(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x0c)
  22 +#define GPIO_DATA_IN(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x10)
  23 +#define GPIO_EDGE_CAUSE(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x14)
  24 +#define GPIO_EDGE_MASK(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x18)
  25 +#define GPIO_LEVEL_MASK(pin) (DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x1c)
  26 +
  27 +static inline int gpio_to_irq(int pin)
  28 +{
  29 + return pin + IRQ_KIRKWOOD_GPIO_START;
  30 +}
  31 +
  32 +static inline int irq_to_gpio(int irq)
  33 +{
  34 + return irq - IRQ_KIRKWOOD_GPIO_START;
  35 +}
  36 +
  37 +
  38 +#endif
arch/arm/mach-kirkwood/include/mach/irqs.h
... ... @@ -11,8 +11,6 @@
11 11 #ifndef __ASM_ARCH_IRQS_H
12 12 #define __ASM_ARCH_IRQS_H
13 13  
14   -#include "kirkwood.h" /* need GPIO_MAX */
15   -
16 14 /*
17 15 * Low Interrupt Controller
18 16 */
... ... @@ -57,7 +55,7 @@
57 55 * KIRKWOOD General Purpose Pins
58 56 */
59 57 #define IRQ_KIRKWOOD_GPIO_START 64
60   -#define NR_GPIO_IRQS GPIO_MAX
  58 +#define NR_GPIO_IRQS 50
61 59  
62 60 #define NR_IRQS (IRQ_KIRKWOOD_GPIO_START + NR_GPIO_IRQS)
63 61  
arch/arm/mach-kirkwood/include/mach/kirkwood.h
... ... @@ -117,8 +117,5 @@
117 117 #define SATA_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x80000)
118 118  
119 119  
120   -#define GPIO_MAX 50
121   -
122   -
123 120 #endif
arch/arm/mach-kirkwood/irq.c
... ... @@ -13,11 +13,46 @@
13 13 #include <linux/irq.h>
14 14 #include <linux/io.h>
15 15 #include <plat/irq.h>
  16 +#include <asm/gpio.h>
16 17 #include "common.h"
17 18  
  19 +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
  20 +{
  21 + BUG_ON(irq < IRQ_KIRKWOOD_GPIO_LOW_0_7);
  22 + BUG_ON(irq > IRQ_KIRKWOOD_GPIO_HIGH_16_23);
  23 +
  24 + orion_gpio_irq_handler((irq - IRQ_KIRKWOOD_GPIO_LOW_0_7) << 3);
  25 +}
  26 +
18 27 void __init kirkwood_init_irq(void)
19 28 {
  29 + int i;
  30 +
20 31 orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
21 32 orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
  33 +
  34 + /*
  35 + * Mask and clear GPIO IRQ interrupts.
  36 + */
  37 + writel(0, GPIO_LEVEL_MASK(0));
  38 + writel(0, GPIO_EDGE_MASK(0));
  39 + writel(0, GPIO_EDGE_CAUSE(0));
  40 + writel(0, GPIO_LEVEL_MASK(32));
  41 + writel(0, GPIO_EDGE_MASK(32));
  42 + writel(0, GPIO_EDGE_CAUSE(32));
  43 +
  44 + for (i = IRQ_KIRKWOOD_GPIO_START; i < NR_IRQS; i++) {
  45 + set_irq_chip(i, &orion_gpio_irq_level_chip);
  46 + set_irq_handler(i, handle_level_irq);
  47 + irq_desc[i].status |= IRQ_LEVEL;
  48 + set_irq_flags(i, IRQF_VALID);
  49 + }
  50 + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler);
  51 + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler);
  52 + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler);
  53 + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler);
  54 + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler);
  55 + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler);
  56 + set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23, gpio_irq_handler);
22 57 }
arch/arm/mach-mv78xx0/include/mach/gpio.h
  1 +/*
  2 + * arch/asm-arm/mach-mv78xx0/include/mach/gpio.h
  3 + *
  4 + * This file is licensed under the terms of the GNU General Public
  5 + * License version 2. This program is licensed "as is" without any
  6 + * warranty of any kind, whether express or implied.
  7 + */
  8 +
  9 +#ifndef __ASM_ARCH_GPIO_H
  10 +#define __ASM_ARCH_GPIO_H
  11 +
  12 +#include <mach/irqs.h>
  13 +#include <plat/gpio.h>
  14 +#include <asm-generic/gpio.h> /* cansleep wrappers */
  15 +
  16 +extern int mv78xx0_core_index(void);
  17 +
  18 +#define GPIO_MAX 32
  19 +#define GPIO_OUT(pin) (DEV_BUS_VIRT_BASE + 0x0100)
  20 +#define GPIO_IO_CONF(pin) (DEV_BUS_VIRT_BASE + 0x0104)
  21 +#define GPIO_BLINK_EN(pin) (DEV_BUS_VIRT_BASE + 0x0108)
  22 +#define GPIO_IN_POL(pin) (DEV_BUS_VIRT_BASE + 0x010c)
  23 +#define GPIO_DATA_IN(pin) (DEV_BUS_VIRT_BASE + 0x0110)
  24 +#define GPIO_EDGE_CAUSE(pin) (DEV_BUS_VIRT_BASE + 0x0114)
  25 +#define GPIO_MASK_OFF (mv78xx0_core_index() ? 0x18 : 0)
  26 +#define GPIO_EDGE_MASK(pin) (DEV_BUS_VIRT_BASE + 0x0118 + GPIO_MASK_OFF)
  27 +#define GPIO_LEVEL_MASK(pin) (DEV_BUS_VIRT_BASE + 0x011c + GPIO_MASK_OFF)
  28 +
  29 +static inline int gpio_to_irq(int pin)
  30 +{
  31 + return pin + IRQ_MV78XX0_GPIO_START;
  32 +}
  33 +
  34 +static inline int irq_to_gpio(int irq)
  35 +{
  36 + return irq - IRQ_MV78XX0_GPIO_START;
  37 +}
  38 +
  39 +
  40 +#endif
arch/arm/mach-mv78xx0/include/mach/irqs.h
... ... @@ -11,8 +11,6 @@
11 11 #ifndef __ASM_ARCH_IRQS_H
12 12 #define __ASM_ARCH_IRQS_H
13 13  
14   -#include "mv78xx0.h" /* need GPIO_MAX */
15   -
16 14 /*
17 15 * MV78xx0 Low Interrupt Controller
18 16 */
... ... @@ -88,7 +86,7 @@
88 86 * MV78XX0 General Purpose Pins
89 87 */
90 88 #define IRQ_MV78XX0_GPIO_START 96
91   -#define NR_GPIO_IRQS GPIO_MAX
  89 +#define NR_GPIO_IRQS 32
92 90  
93 91 #define NR_IRQS (IRQ_MV78XX0_GPIO_START + NR_GPIO_IRQS)
94 92  
arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
... ... @@ -122,8 +122,5 @@
122 122 #define SATA_PHYS_BASE (MV78XX0_REGS_PHYS_BASE | 0xa0000)
123 123  
124 124  
125   -#define GPIO_MAX 32
126   -
127   -
128 125 #endif
arch/arm/mach-mv78xx0/irq.c
... ... @@ -11,14 +11,43 @@
11 11 #include <linux/kernel.h>
12 12 #include <linux/init.h>
13 13 #include <linux/pci.h>
  14 +#include <linux/irq.h>
  15 +#include <asm/gpio.h>
14 16 #include <mach/mv78xx0.h>
15 17 #include <plat/irq.h>
16 18 #include "common.h"
17 19  
  20 +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
  21 +{
  22 + BUG_ON(irq < IRQ_MV78XX0_GPIO_0_7 || irq > IRQ_MV78XX0_GPIO_24_31);
  23 +
  24 + orion_gpio_irq_handler((irq - IRQ_MV78XX0_GPIO_0_7) << 3);
  25 +}
  26 +
18 27 void __init mv78xx0_init_irq(void)
19 28 {
  29 + int i;
  30 +
20 31 orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
21 32 orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
22 33 orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF));
  34 +
  35 + /*
  36 + * Mask and clear GPIO IRQ interrupts.
  37 + */
  38 + writel(0, GPIO_LEVEL_MASK(0));
  39 + writel(0, GPIO_EDGE_MASK(0));
  40 + writel(0, GPIO_EDGE_CAUSE(0));
  41 +
  42 + for (i = IRQ_MV78XX0_GPIO_START; i < NR_IRQS; i++) {
  43 + set_irq_chip(i, &orion_gpio_irq_level_chip);
  44 + set_irq_handler(i, handle_level_irq);
  45 + irq_desc[i].status |= IRQ_LEVEL;
  46 + set_irq_flags(i, IRQF_VALID);
  47 + }
  48 + set_irq_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler);
  49 + set_irq_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler);
  50 + set_irq_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler);
  51 + set_irq_chained_handler(IRQ_MV78XX0_GPIO_24_31, gpio_irq_handler);
23 52 }
arch/arm/mach-orion5x/Makefile
1   -obj-y += common.o addr-map.o pci.o gpio.o irq.o mpp.o
  1 +obj-y += common.o addr-map.o pci.o irq.o mpp.o
2 2 obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
3 3 obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
4 4 obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
arch/arm/mach-orion5x/common.h
... ... @@ -51,13 +51,6 @@
51 51 struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
52 52 int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
53 53  
54   -/*
55   - * Valid GPIO pins according to MPP setup, used by machine-setup.
56   - * (/mach-orion/gpio.c).
57   - */
58   -void orion5x_gpio_set_valid(unsigned pin, int valid);
59   -void gpio_display(void); /* debug */
60   -
61 54 struct machine_desc;
62 55 struct meminfo;
63 56 struct tag;
arch/arm/mach-orion5x/gpio.c
1   -/*
2   - * arch/arm/mach-orion5x/gpio.c
3   - *
4   - * GPIO functions for Marvell Orion System On Chip
5   - *
6   - * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7   - *
8   - * This file is licensed under the terms of the GNU General Public
9   - * License version 2. This program is licensed "as is" without any
10   - * warranty of any kind, whether express or implied.
11   - */
12   -
13   -#include <linux/kernel.h>
14   -#include <linux/init.h>
15   -#include <linux/module.h>
16   -#include <linux/spinlock.h>
17   -#include <linux/bitops.h>
18   -#include <linux/io.h>
19   -#include <asm/gpio.h>
20   -#include <mach/orion5x.h>
21   -#include "common.h"
22   -
23   -static DEFINE_SPINLOCK(gpio_lock);
24   -static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
25   -static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
26   -
27   -void __init orion5x_gpio_set_valid(unsigned pin, int valid)
28   -{
29   - if (valid)
30   - __set_bit(pin, gpio_valid);
31   - else
32   - __clear_bit(pin, gpio_valid);
33   -}
34   -
35   -/*
36   - * GENERIC_GPIO primitives
37   - */
38   -int gpio_direction_input(unsigned pin)
39   -{
40   - unsigned long flags;
41   -
42   - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
43   - pr_debug("%s: invalid GPIO %d\n", __func__, pin);
44   - return -EINVAL;
45   - }
46   -
47   - spin_lock_irqsave(&gpio_lock, flags);
48   -
49   - /*
50   - * Some callers might have not used the gpio_request(),
51   - * so flag this pin as requested now.
52   - */
53   - if (!gpio_label[pin])
54   - gpio_label[pin] = "?";
55   -
56   - orion5x_setbits(GPIO_IO_CONF, 1 << pin);
57   -
58   - spin_unlock_irqrestore(&gpio_lock, flags);
59   - return 0;
60   -}
61   -EXPORT_SYMBOL(gpio_direction_input);
62   -
63   -int gpio_direction_output(unsigned pin, int value)
64   -{
65   - unsigned long flags;
66   - int mask;
67   -
68   - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
69   - pr_debug("%s: invalid GPIO %d\n", __func__, pin);
70   - return -EINVAL;
71   - }
72   -
73   - spin_lock_irqsave(&gpio_lock, flags);
74   -
75   - /*
76   - * Some callers might have not used the gpio_request(),
77   - * so flag this pin as requested now.
78   - */
79   - if (!gpio_label[pin])
80   - gpio_label[pin] = "?";
81   -
82   - mask = 1 << pin;
83   - orion5x_clrbits(GPIO_BLINK_EN, mask);
84   - if (value)
85   - orion5x_setbits(GPIO_OUT, mask);
86   - else
87   - orion5x_clrbits(GPIO_OUT, mask);
88   - orion5x_clrbits(GPIO_IO_CONF, mask);
89   -
90   - spin_unlock_irqrestore(&gpio_lock, flags);
91   - return 0;
92   -}
93   -EXPORT_SYMBOL(gpio_direction_output);
94   -
95   -int gpio_get_value(unsigned pin)
96   -{
97   - int val, mask = 1 << pin;
98   -
99   - if (readl(GPIO_IO_CONF) & mask)
100   - val = readl(GPIO_DATA_IN) ^ readl(GPIO_IN_POL);
101   - else
102   - val = readl(GPIO_OUT);
103   -
104   - return val & mask;
105   -}
106   -EXPORT_SYMBOL(gpio_get_value);
107   -
108   -void gpio_set_value(unsigned pin, int value)
109   -{
110   - unsigned long flags;
111   - int mask = 1 << pin;
112   -
113   - spin_lock_irqsave(&gpio_lock, flags);
114   -
115   - orion5x_clrbits(GPIO_BLINK_EN, mask);
116   - if (value)
117   - orion5x_setbits(GPIO_OUT, mask);
118   - else
119   - orion5x_clrbits(GPIO_OUT, mask);
120   -
121   - spin_unlock_irqrestore(&gpio_lock, flags);
122   -}
123   -EXPORT_SYMBOL(gpio_set_value);
124   -
125   -void orion5x_gpio_set_blink(unsigned pin, int blink)
126   -{
127   - unsigned long flags;
128   - int mask = 1 << pin;
129   -
130   - spin_lock_irqsave(&gpio_lock, flags);
131   -
132   - orion5x_clrbits(GPIO_OUT, mask);
133   - if (blink)
134   - orion5x_setbits(GPIO_BLINK_EN, mask);
135   - else
136   - orion5x_clrbits(GPIO_BLINK_EN, mask);
137   -
138   - spin_unlock_irqrestore(&gpio_lock, flags);
139   -}
140   -EXPORT_SYMBOL(orion5x_gpio_set_blink);
141   -
142   -int gpio_request(unsigned pin, const char *label)
143   -{
144   - int ret = 0;
145   - unsigned long flags;
146   -
147   - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
148   - pr_debug("%s: invalid GPIO %d\n", __func__, pin);
149   - return -EINVAL;
150   - }
151   -
152   - spin_lock_irqsave(&gpio_lock, flags);
153   -
154   - if (gpio_label[pin]) {
155   - pr_debug("%s: GPIO %d already used as %s\n",
156   - __func__, pin, gpio_label[pin]);
157   - ret = -EBUSY;
158   - } else
159   - gpio_label[pin] = label ? label : "?";
160   -
161   - spin_unlock_irqrestore(&gpio_lock, flags);
162   - return ret;
163   -}
164   -EXPORT_SYMBOL(gpio_request);
165   -
166   -void gpio_free(unsigned pin)
167   -{
168   - might_sleep();
169   -
170   - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
171   - pr_debug("%s: invalid GPIO %d\n", __func__, pin);
172   - return;
173   - }
174   -
175   - if (!gpio_label[pin])
176   - pr_warning("%s: GPIO %d already freed\n", __func__, pin);
177   - else
178   - gpio_label[pin] = NULL;
179   -}
180   -EXPORT_SYMBOL(gpio_free);
181   -
182   -/* Debug helper */
183   -void gpio_display(void)
184   -{
185   - int i;
186   -
187   - for (i = 0; i < GPIO_MAX; i++) {
188   - printk(KERN_DEBUG "Pin-%d: ", i);
189   -
190   - if (!test_bit(i, gpio_valid)) {
191   - printk("non-GPIO\n");
192   - } else if (!gpio_label[i]) {
193   - printk("GPIO, free\n");
194   - } else {
195   - printk("GPIO, used by %s, ", gpio_label[i]);
196   - if (readl(GPIO_IO_CONF) & (1 << i)) {
197   - printk("input, active %s, level %s, edge %s\n",
198   - ((readl(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
199   - ((readl(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
200   - ((readl(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
201   - } else {
202   - printk("output, val=%d\n", (readl(GPIO_OUT) >> i) & 1);
203   - }
204   - }
205   - }
206   -
207   - printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
208   - MPP_0_7_CTRL, readl(MPP_0_7_CTRL));
209   - printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
210   - MPP_8_15_CTRL, readl(MPP_8_15_CTRL));
211   - printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
212   - MPP_16_19_CTRL, readl(MPP_16_19_CTRL));
213   - printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
214   - MPP_DEV_CTRL, readl(MPP_DEV_CTRL));
215   - printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
216   - GPIO_OUT, readl(GPIO_OUT));
217   - printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
218   - GPIO_IO_CONF, readl(GPIO_IO_CONF));
219   - printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
220   - GPIO_BLINK_EN, readl(GPIO_BLINK_EN));
221   - printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
222   - GPIO_IN_POL, readl(GPIO_IN_POL));
223   - printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
224   - GPIO_DATA_IN, readl(GPIO_DATA_IN));
225   - printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
226   - GPIO_LEVEL_MASK, readl(GPIO_LEVEL_MASK));
227   - printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
228   - GPIO_EDGE_CAUSE, readl(GPIO_EDGE_CAUSE));
229   - printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
230   - GPIO_EDGE_MASK, readl(GPIO_EDGE_MASK));
231   -}
arch/arm/mach-orion5x/include/mach/gpio.h
... ... @@ -2,19 +2,27 @@
2 2 * arch/arm/mach-orion5x/include/mach/gpio.h
3 3 *
4 4 * This file is licensed under the terms of the GNU General Public
5   - * License version 2. This program is licensed "as is" without any
  5 + * License version 2. This program is licensed "as is" without any
6 6 * warranty of any kind, whether express or implied.
7 7 */
8 8  
9   -extern int gpio_request(unsigned pin, const char *label);
10   -extern void gpio_free(unsigned pin);
11   -extern int gpio_direction_input(unsigned pin);
12   -extern int gpio_direction_output(unsigned pin, int value);
13   -extern int gpio_get_value(unsigned pin);
14   -extern void gpio_set_value(unsigned pin, int value);
15   -extern void orion5x_gpio_set_blink(unsigned pin, int blink);
16   -extern void gpio_display(void); /* debug */
  9 +#ifndef __ASM_ARCH_GPIO_H
  10 +#define __ASM_ARCH_GPIO_H
17 11  
  12 +#include <mach/irqs.h>
  13 +#include <plat/gpio.h>
  14 +#include <asm-generic/gpio.h> /* cansleep wrappers */
  15 +
  16 +#define GPIO_MAX 32
  17 +#define GPIO_OUT(pin) ORION5X_DEV_BUS_REG(0x100)
  18 +#define GPIO_IO_CONF(pin) ORION5X_DEV_BUS_REG(0x104)
  19 +#define GPIO_BLINK_EN(pin) ORION5X_DEV_BUS_REG(0x108)
  20 +#define GPIO_IN_POL(pin) ORION5X_DEV_BUS_REG(0x10c)
  21 +#define GPIO_DATA_IN(pin) ORION5X_DEV_BUS_REG(0x110)
  22 +#define GPIO_EDGE_CAUSE(pin) ORION5X_DEV_BUS_REG(0x114)
  23 +#define GPIO_EDGE_MASK(pin) ORION5X_DEV_BUS_REG(0x118)
  24 +#define GPIO_LEVEL_MASK(pin) ORION5X_DEV_BUS_REG(0x11c)
  25 +
18 26 static inline int gpio_to_irq(int pin)
19 27 {
20 28 return pin + IRQ_ORION5X_GPIO_START;
... ... @@ -25,5 +33,6 @@
25 33 return irq - IRQ_ORION5X_GPIO_START;
26 34 }
27 35  
28   -#include <asm-generic/gpio.h> /* cansleep wrappers */
  36 +
  37 +#endif
arch/arm/mach-orion5x/include/mach/irqs.h
... ... @@ -13,8 +13,6 @@
13 13 #ifndef __ASM_ARCH_IRQS_H
14 14 #define __ASM_ARCH_IRQS_H
15 15  
16   -#include "orion5x.h" /* need GPIO_MAX */
17   -
18 16 /*
19 17 * Orion Main Interrupt Controller
20 18 */
... ... @@ -54,7 +52,7 @@
54 52 * Orion General Purpose Pins
55 53 */
56 54 #define IRQ_ORION5X_GPIO_START 32
57   -#define NR_GPIO_IRQS GPIO_MAX
  55 +#define NR_GPIO_IRQS 32
58 56  
59 57 #define NR_IRQS (IRQ_ORION5X_GPIO_START + NR_GPIO_IRQS)
60 58  
arch/arm/mach-orion5x/include/mach/orion5x.h
... ... @@ -134,14 +134,6 @@
134 134 #define MPP_16_19_CTRL ORION5X_DEV_BUS_REG(0x050)
135 135 #define MPP_DEV_CTRL ORION5X_DEV_BUS_REG(0x008)
136 136 #define MPP_RESET_SAMPLE ORION5X_DEV_BUS_REG(0x010)
137   -#define GPIO_OUT ORION5X_DEV_BUS_REG(0x100)
138   -#define GPIO_IO_CONF ORION5X_DEV_BUS_REG(0x104)
139   -#define GPIO_BLINK_EN ORION5X_DEV_BUS_REG(0x108)
140   -#define GPIO_IN_POL ORION5X_DEV_BUS_REG(0x10c)
141   -#define GPIO_DATA_IN ORION5X_DEV_BUS_REG(0x110)
142   -#define GPIO_EDGE_CAUSE ORION5X_DEV_BUS_REG(0x114)
143   -#define GPIO_EDGE_MASK ORION5X_DEV_BUS_REG(0x118)
144   -#define GPIO_LEVEL_MASK ORION5X_DEV_BUS_REG(0x11c)
145 137 #define DEV_BANK_0_PARAM ORION5X_DEV_BUS_REG(0x45c)
146 138 #define DEV_BANK_1_PARAM ORION5X_DEV_BUS_REG(0x460)
147 139 #define DEV_BANK_2_PARAM ORION5X_DEV_BUS_REG(0x464)
... ... @@ -149,7 +141,6 @@
149 141 #define DEV_BUS_CTRL ORION5X_DEV_BUS_REG(0x4c0)
150 142 #define DEV_BUS_INT_CAUSE ORION5X_DEV_BUS_REG(0x4d0)
151 143 #define DEV_BUS_INT_MASK ORION5X_DEV_BUS_REG(0x4d4)
152   -#define GPIO_MAX 32
153 144  
154 145 /***************************************************************************
155 146 * Orion CPU Bridge Registers
arch/arm/mach-orion5x/irq.c
... ... @@ -19,194 +19,39 @@
19 19 #include <plat/irq.h>
20 20 #include "common.h"
21 21  
22   -/*****************************************************************************
23   - * Orion GPIO IRQ
24   - *
25   - * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
26   - * value of the line or the opposite value.
27   - *
28   - * Level IRQ handlers: DATA_IN is used directly as cause register.
29   - * Interrupt are masked by LEVEL_MASK registers.
30   - * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
31   - * Interrupt are masked by EDGE_MASK registers.
32   - * Both-edge handlers: Similar to regular Edge handlers, but also swaps
33   - * the polarity to catch the next line transaction.
34   - * This is a race condition that might not perfectly
35   - * work on some use cases.
36   - *
37   - * Every eight GPIO lines are grouped (OR'ed) before going up to main
38   - * cause register.
39   - *
40   - * EDGE cause mask
41   - * data-in /--------| |-----| |----\
42   - * -----| |----- ---- to main cause reg
43   - * X \----------------| |----/
44   - * polarity LEVEL mask
45   - *
46   - ****************************************************************************/
47   -static void orion5x_gpio_irq_ack(u32 irq)
  22 +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
48 23 {
49   - int pin = irq_to_gpio(irq);
50   - if (irq_desc[irq].status & IRQ_LEVEL)
51   - /*
52   - * Mask bit for level interrupt
53   - */
54   - orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
55   - else
56   - /*
57   - * Clear casue bit for egde interrupt
58   - */
59   - orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
60   -}
61   -
62   -static void orion5x_gpio_irq_mask(u32 irq)
63   -{
64   - int pin = irq_to_gpio(irq);
65   - if (irq_desc[irq].status & IRQ_LEVEL)
66   - orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
67   - else
68   - orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
69   -}
70   -
71   -static void orion5x_gpio_irq_unmask(u32 irq)
72   -{
73   - int pin = irq_to_gpio(irq);
74   - if (irq_desc[irq].status & IRQ_LEVEL)
75   - orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
76   - else
77   - orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
78   -}
79   -
80   -static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
81   -{
82   - int pin = irq_to_gpio(irq);
83   - struct irq_desc *desc;
84   -
85   - if ((readl(GPIO_IO_CONF) & (1 << pin)) == 0) {
86   - printk(KERN_ERR "orion5x_gpio_set_irq_type failed "
87   - "(irq %d, pin %d).\n", irq, pin);
88   - return -EINVAL;
89   - }
90   -
91   - desc = irq_desc + irq;
92   -
93   - switch (type) {
94   - case IRQ_TYPE_LEVEL_HIGH:
95   - desc->handle_irq = handle_level_irq;
96   - desc->status |= IRQ_LEVEL;
97   - orion5x_clrbits(GPIO_IN_POL, (1 << pin));
98   - break;
99   - case IRQ_TYPE_LEVEL_LOW:
100   - desc->handle_irq = handle_level_irq;
101   - desc->status |= IRQ_LEVEL;
102   - orion5x_setbits(GPIO_IN_POL, (1 << pin));
103   - break;
104   - case IRQ_TYPE_EDGE_RISING:
105   - desc->handle_irq = handle_edge_irq;
106   - desc->status &= ~IRQ_LEVEL;
107   - orion5x_clrbits(GPIO_IN_POL, (1 << pin));
108   - break;
109   - case IRQ_TYPE_EDGE_FALLING:
110   - desc->handle_irq = handle_edge_irq;
111   - desc->status &= ~IRQ_LEVEL;
112   - orion5x_setbits(GPIO_IN_POL, (1 << pin));
113   - break;
114   - case IRQ_TYPE_EDGE_BOTH:
115   - desc->handle_irq = handle_edge_irq;
116   - desc->status &= ~IRQ_LEVEL;
117   - /*
118   - * set initial polarity based on current input level
119   - */
120   - if ((readl(GPIO_IN_POL) ^ readl(GPIO_DATA_IN))
121   - & (1 << pin))
122   - orion5x_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
123   - else
124   - orion5x_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
125   -
126   - break;
127   - default:
128   - printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
129   - return -EINVAL;
130   - }
131   -
132   - desc->status &= ~IRQ_TYPE_SENSE_MASK;
133   - desc->status |= type & IRQ_TYPE_SENSE_MASK;
134   -
135   - return 0;
136   -}
137   -
138   -static struct irq_chip orion5x_gpio_irq_chip = {
139   - .name = "Orion-IRQ-GPIO",
140   - .ack = orion5x_gpio_irq_ack,
141   - .mask = orion5x_gpio_irq_mask,
142   - .unmask = orion5x_gpio_irq_unmask,
143   - .set_type = orion5x_gpio_set_irq_type,
144   -};
145   -
146   -static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
147   -{
148   - u32 cause, offs, pin;
149   -
150 24 BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31);
151   - offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8;
152   - cause = (readl(GPIO_DATA_IN) & readl(GPIO_LEVEL_MASK)) |
153   - (readl(GPIO_EDGE_CAUSE) & readl(GPIO_EDGE_MASK));
154 25  
155   - for (pin = offs; pin < offs + 8; pin++) {
156   - if (cause & (1 << pin)) {
157   - irq = gpio_to_irq(pin);
158   - desc = irq_desc + irq;
159   - if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
160   - /* Swap polarity (race with GPIO line) */
161   - u32 polarity = readl(GPIO_IN_POL);
162   - polarity ^= 1 << pin;
163   - writel(polarity, GPIO_IN_POL);
164   - }
165   - generic_handle_irq(irq);
166   - }
167   - }
  26 + orion_gpio_irq_handler((irq - IRQ_ORION5X_GPIO_0_7) << 3);
168 27 }
169 28  
170   -static void __init orion5x_init_gpio_irq(void)
  29 +void __init orion5x_init_irq(void)
171 30 {
172 31 int i;
173   - struct irq_desc *desc;
174 32  
  33 + orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
  34 +
175 35 /*
176 36 * Mask and clear GPIO IRQ interrupts
177 37 */
178   - writel(0x0, GPIO_LEVEL_MASK);
179   - writel(0x0, GPIO_EDGE_MASK);
180   - writel(0x0, GPIO_EDGE_CAUSE);
  38 + writel(0x0, GPIO_LEVEL_MASK(0));
  39 + writel(0x0, GPIO_EDGE_MASK(0));
  40 + writel(0x0, GPIO_EDGE_CAUSE(0));
181 41  
182 42 /*
183 43 * Register chained level handlers for GPIO IRQs by default.
184 44 * User can use set_type() if he wants to use edge types handlers.
185 45 */
186 46 for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
187   - set_irq_chip(i, &orion5x_gpio_irq_chip);
  47 + set_irq_chip(i, &orion_gpio_irq_level_chip);
188 48 set_irq_handler(i, handle_level_irq);
189   - desc = irq_desc + i;
190   - desc->status |= IRQ_LEVEL;
  49 + irq_desc[i].status |= IRQ_LEVEL;
191 50 set_irq_flags(i, IRQF_VALID);
192 51 }
193   - set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler);
194   - set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler);
195   - set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler);
196   - set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler);
197   -}
198   -
199   -/*****************************************************************************
200   - * Orion Main IRQ
201   - ****************************************************************************/
202   -static void __init orion5x_init_main_irq(void)
203   -{
204   - orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
205   -}
206   -
207   -void __init orion5x_init_irq(void)
208   -{
209   - orion5x_init_main_irq();
210   - orion5x_init_gpio_irq();
  52 + set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler);
  53 + set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
  54 + set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
  55 + set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler);
211 56 }
arch/arm/mach-orion5x/mpp.c
... ... @@ -12,6 +12,7 @@
12 12 #include <linux/init.h>
13 13 #include <linux/mbus.h>
14 14 #include <linux/io.h>
  15 +#include <asm/gpio.h>
15 16 #include <mach/hardware.h>
16 17 #include "common.h"
17 18 #include "mpp.h"
... ... @@ -152,7 +153,10 @@
152 153 *reg &= ~(0xf << shift);
153 154 *reg |= (num_type & 0xf) << shift;
154 155  
155   - orion5x_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO));
  156 + if (mode->type == MPP_UNUSED && (mode->mpp < 16 || is_5182()))
  157 + orion_gpio_set_unused(mode->mpp);
  158 +
  159 + orion_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO));
156 160  
157 161 mode++;
158 162 }
arch/arm/plat-orion/Makefile
... ... @@ -6,4 +6,6 @@
6 6 obj-m :=
7 7 obj-n :=
8 8 obj- :=
  9 +
  10 +obj-$(CONFIG_GENERIC_GPIO) += gpio.o
arch/arm/plat-orion/gpio.c
  1 +/*
  2 + * arch/arm/plat-orion/gpio.c
  3 + *
  4 + * Marvell Orion SoC GPIO handling.
  5 + *
  6 + * This file is licensed under the terms of the GNU General Public
  7 + * License version 2. This program is licensed "as is" without any
  8 + * warranty of any kind, whether express or implied.
  9 + */
  10 +
  11 +#include <linux/kernel.h>
  12 +#include <linux/init.h>
  13 +#include <linux/irq.h>
  14 +#include <linux/module.h>
  15 +#include <linux/spinlock.h>
  16 +#include <linux/bitops.h>
  17 +#include <linux/io.h>
  18 +#include <asm/gpio.h>
  19 +
  20 +static DEFINE_SPINLOCK(gpio_lock);
  21 +static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
  22 +static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
  23 +
  24 +static inline void __set_direction(unsigned pin, int input)
  25 +{
  26 + u32 u;
  27 +
  28 + u = readl(GPIO_IO_CONF(pin));
  29 + if (input)
  30 + u |= 1 << (pin & 31);
  31 + else
  32 + u &= ~(1 << (pin & 31));
  33 + writel(u, GPIO_IO_CONF(pin));
  34 +}
  35 +
  36 +static void __set_level(unsigned pin, int high)
  37 +{
  38 + u32 u;
  39 +
  40 + u = readl(GPIO_OUT(pin));
  41 + if (high)
  42 + u |= 1 << (pin & 31);
  43 + else
  44 + u &= ~(1 << (pin & 31));
  45 + writel(u, GPIO_OUT(pin));
  46 +}
  47 +
  48 +
  49 +/*
  50 + * GENERIC_GPIO primitives.
  51 + */
  52 +int gpio_direction_input(unsigned pin)
  53 +{
  54 + unsigned long flags;
  55 +
  56 + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
  57 + pr_debug("%s: invalid GPIO %d\n", __func__, pin);
  58 + return -EINVAL;
  59 + }
  60 +
  61 + spin_lock_irqsave(&gpio_lock, flags);
  62 +
  63 + /*
  64 + * Some callers might not have used gpio_request(),
  65 + * so flag this pin as requested now.
  66 + */
  67 + if (gpio_label[pin] == NULL)
  68 + gpio_label[pin] = "?";
  69 +
  70 + /*
  71 + * Configure GPIO direction.
  72 + */
  73 + __set_direction(pin, 1);
  74 +
  75 + spin_unlock_irqrestore(&gpio_lock, flags);
  76 +
  77 + return 0;
  78 +}
  79 +EXPORT_SYMBOL(gpio_direction_input);
  80 +
  81 +int gpio_direction_output(unsigned pin, int value)
  82 +{
  83 + unsigned long flags;
  84 + u32 u;
  85 +
  86 + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
  87 + pr_debug("%s: invalid GPIO %d\n", __func__, pin);
  88 + return -EINVAL;
  89 + }
  90 +
  91 + spin_lock_irqsave(&gpio_lock, flags);
  92 +
  93 + /*
  94 + * Some callers might not have used gpio_request(),
  95 + * so flag this pin as requested now.
  96 + */
  97 + if (gpio_label[pin] == NULL)
  98 + gpio_label[pin] = "?";
  99 +
  100 + /*
  101 + * Disable blinking.
  102 + */
  103 + u = readl(GPIO_BLINK_EN(pin));
  104 + u &= ~(1 << (pin & 31));
  105 + writel(u, GPIO_BLINK_EN(pin));
  106 +
  107 + /*
  108 + * Configure GPIO output value.
  109 + */
  110 + __set_level(pin, value);
  111 +
  112 + /*
  113 + * Configure GPIO direction.
  114 + */
  115 + __set_direction(pin, 0);
  116 +
  117 + spin_unlock_irqrestore(&gpio_lock, flags);
  118 +
  119 + return 0;
  120 +}
  121 +EXPORT_SYMBOL(gpio_direction_output);
  122 +
  123 +int gpio_get_value(unsigned pin)
  124 +{
  125 + int val;
  126 +
  127 + if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
  128 + val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
  129 + else
  130 + val = readl(GPIO_OUT(pin));
  131 +
  132 + return (val >> (pin & 31)) & 1;
  133 +}
  134 +EXPORT_SYMBOL(gpio_get_value);
  135 +
  136 +void gpio_set_value(unsigned pin, int value)
  137 +{
  138 + unsigned long flags;
  139 + u32 u;
  140 +
  141 + spin_lock_irqsave(&gpio_lock, flags);
  142 +
  143 + /*
  144 + * Disable blinking.
  145 + */
  146 + u = readl(GPIO_BLINK_EN(pin));
  147 + u &= ~(1 << (pin & 31));
  148 + writel(u, GPIO_BLINK_EN(pin));
  149 +
  150 + /*
  151 + * Configure GPIO output value.
  152 + */
  153 + __set_level(pin, value);
  154 +
  155 + spin_unlock_irqrestore(&gpio_lock, flags);
  156 +}
  157 +EXPORT_SYMBOL(gpio_set_value);
  158 +
  159 +int gpio_request(unsigned pin, const char *label)
  160 +{
  161 + unsigned long flags;
  162 + int ret;
  163 +
  164 + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
  165 + pr_debug("%s: invalid GPIO %d\n", __func__, pin);
  166 + return -EINVAL;
  167 + }
  168 +
  169 + spin_lock_irqsave(&gpio_lock, flags);
  170 + if (gpio_label[pin] == NULL) {
  171 + gpio_label[pin] = label ? label : "?";
  172 + ret = 0;
  173 + } else {
  174 + pr_debug("%s: GPIO %d already used as %s\n",
  175 + __func__, pin, gpio_label[pin]);
  176 + ret = -EBUSY;
  177 + }
  178 + spin_unlock_irqrestore(&gpio_lock, flags);
  179 +
  180 + return ret;
  181 +}
  182 +EXPORT_SYMBOL(gpio_request);
  183 +
  184 +void gpio_free(unsigned pin)
  185 +{
  186 + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
  187 + pr_debug("%s: invalid GPIO %d\n", __func__, pin);
  188 + return;
  189 + }
  190 +
  191 + if (gpio_label[pin] == NULL)
  192 + pr_warning("%s: GPIO %d already freed\n", __func__, pin);
  193 + else
  194 + gpio_label[pin] = NULL;
  195 +}
  196 +EXPORT_SYMBOL(gpio_free);
  197 +
  198 +
  199 +/*
  200 + * Orion-specific GPIO API extensions.
  201 + */
  202 +void __init orion_gpio_set_unused(unsigned pin)
  203 +{
  204 + /*
  205 + * Configure as output, drive low.
  206 + */
  207 + __set_level(pin, 0);
  208 + __set_direction(pin, 0);
  209 +}
  210 +
  211 +void __init orion_gpio_set_valid(unsigned pin, int valid)
  212 +{
  213 + if (valid)
  214 + __set_bit(pin, gpio_valid);
  215 + else
  216 + __clear_bit(pin, gpio_valid);
  217 +}
  218 +
  219 +void orion_gpio_set_blink(unsigned pin, int blink)
  220 +{
  221 + unsigned long flags;
  222 + u32 u;
  223 +
  224 + spin_lock_irqsave(&gpio_lock, flags);
  225 +
  226 + /*
  227 + * Set output value to zero.
  228 + */
  229 + __set_level(pin, 0);
  230 +
  231 + u = readl(GPIO_BLINK_EN(pin));
  232 + if (blink)
  233 + u |= 1 << (pin & 31);
  234 + else
  235 + u &= ~(1 << (pin & 31));
  236 + writel(u, GPIO_BLINK_EN(pin));
  237 +
  238 + spin_unlock_irqrestore(&gpio_lock, flags);
  239 +}
  240 +EXPORT_SYMBOL(orion_gpio_set_blink);
  241 +
  242 +
  243 +/*****************************************************************************
  244 + * Orion GPIO IRQ
  245 + *
  246 + * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same
  247 + * value of the line or the opposite value.
  248 + *
  249 + * Level IRQ handlers: DATA_IN is used directly as cause register.
  250 + * Interrupt are masked by LEVEL_MASK registers.
  251 + * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
  252 + * Interrupt are masked by EDGE_MASK registers.
  253 + * Both-edge handlers: Similar to regular Edge handlers, but also swaps
  254 + * the polarity to catch the next line transaction.
  255 + * This is a race condition that might not perfectly
  256 + * work on some use cases.
  257 + *
  258 + * Every eight GPIO lines are grouped (OR'ed) before going up to main
  259 + * cause register.
  260 + *
  261 + * EDGE cause mask
  262 + * data-in /--------| |-----| |----\
  263 + * -----| |----- ---- to main cause reg
  264 + * X \----------------| |----/
  265 + * polarity LEVEL mask
  266 + *
  267 + ****************************************************************************/
  268 +static void gpio_irq_edge_ack(u32 irq)
  269 +{
  270 + int pin = irq_to_gpio(irq);
  271 +
  272 + writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
  273 +}
  274 +
  275 +static void gpio_irq_edge_mask(u32 irq)
  276 +{
  277 + int pin = irq_to_gpio(irq);
  278 + u32 u;
  279 +
  280 + u = readl(GPIO_EDGE_MASK(pin));
  281 + u &= ~(1 << (pin & 31));
  282 + writel(u, GPIO_EDGE_MASK(pin));
  283 +}
  284 +
  285 +static void gpio_irq_edge_unmask(u32 irq)
  286 +{
  287 + int pin = irq_to_gpio(irq);
  288 + u32 u;
  289 +
  290 + u = readl(GPIO_EDGE_MASK(pin));
  291 + u |= 1 << (pin & 31);
  292 + writel(u, GPIO_EDGE_MASK(pin));
  293 +}
  294 +
  295 +static void gpio_irq_level_mask(u32 irq)
  296 +{
  297 + int pin = irq_to_gpio(irq);
  298 + u32 u;
  299 +
  300 + u = readl(GPIO_LEVEL_MASK(pin));
  301 + u &= ~(1 << (pin & 31));
  302 + writel(u, GPIO_LEVEL_MASK(pin));
  303 +}
  304 +
  305 +static void gpio_irq_level_unmask(u32 irq)
  306 +{
  307 + int pin = irq_to_gpio(irq);
  308 + u32 u;
  309 +
  310 + u = readl(GPIO_LEVEL_MASK(pin));
  311 + u |= 1 << (pin & 31);
  312 + writel(u, GPIO_LEVEL_MASK(pin));
  313 +}
  314 +
  315 +static int gpio_irq_set_type(u32 irq, u32 type)
  316 +{
  317 + int pin = irq_to_gpio(irq);
  318 + struct irq_desc *desc;
  319 + u32 u;
  320 +
  321 + u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31));
  322 + if (!u) {
  323 + printk(KERN_ERR "orion gpio_irq_set_type failed "
  324 + "(irq %d, pin %d).\n", irq, pin);
  325 + return -EINVAL;
  326 + }
  327 +
  328 + desc = irq_desc + irq;
  329 +
  330 + /*
  331 + * Set edge/level type.
  332 + */
  333 + if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
  334 + desc->chip = &orion_gpio_irq_edge_chip;
  335 + } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
  336 + desc->chip = &orion_gpio_irq_level_chip;
  337 + } else {
  338 + printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
  339 + return -EINVAL;
  340 + }
  341 +
  342 + /*
  343 + * Configure interrupt polarity.
  344 + */
  345 + if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) {
  346 + u = readl(GPIO_IN_POL(pin));
  347 + u &= ~(1 << (pin & 31));
  348 + writel(u, GPIO_IN_POL(pin));
  349 + } else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) {
  350 + u = readl(GPIO_IN_POL(pin));
  351 + u |= 1 << (pin & 31);
  352 + writel(u, GPIO_IN_POL(pin));
  353 + } else if (type == IRQ_TYPE_EDGE_BOTH) {
  354 + u32 v;
  355 +
  356 + v = readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin));
  357 +
  358 + /*
  359 + * set initial polarity based on current input level
  360 + */
  361 + u = readl(GPIO_IN_POL(pin));
  362 + if (v & (1 << (pin & 31)))
  363 + u |= 1 << (pin & 31); /* falling */
  364 + else
  365 + u &= ~(1 << (pin & 31)); /* rising */
  366 + writel(u, GPIO_IN_POL(pin));
  367 + }
  368 +
  369 + desc->status = (desc->status & ~IRQ_TYPE_SENSE_MASK) | type;
  370 +
  371 + return 0;
  372 +}
  373 +
  374 +struct irq_chip orion_gpio_irq_edge_chip = {
  375 + .name = "orion_gpio_irq_edge",
  376 + .ack = gpio_irq_edge_ack,
  377 + .mask = gpio_irq_edge_mask,
  378 + .unmask = gpio_irq_edge_unmask,
  379 + .set_type = gpio_irq_set_type,
  380 +};
  381 +
  382 +struct irq_chip orion_gpio_irq_level_chip = {
  383 + .name = "orion_gpio_irq_level",
  384 + .mask = gpio_irq_level_mask,
  385 + .mask_ack = gpio_irq_level_mask,
  386 + .unmask = gpio_irq_level_unmask,
  387 + .set_type = gpio_irq_set_type,
  388 +};
  389 +
  390 +void orion_gpio_irq_handler(int pinoff)
  391 +{
  392 + u32 cause;
  393 + int pin;
  394 +
  395 + cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff));
  396 + cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff));
  397 +
  398 + for (pin = pinoff; pin < pinoff + 8; pin++) {
  399 + int irq = gpio_to_irq(pin);
  400 + struct irq_desc *desc = irq_desc + irq;
  401 +
  402 + if (!(cause & (1 << (pin & 31))))
  403 + continue;
  404 +
  405 + if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
  406 + /* Swap polarity (race with GPIO line) */
  407 + u32 polarity;
  408 +
  409 + polarity = readl(GPIO_IN_POL(pin));
  410 + polarity ^= 1 << (pin & 31);
  411 + writel(polarity, GPIO_IN_POL(pin));
  412 + }
  413 + desc_handle_irq(irq, desc);
  414 + }
  415 +}
arch/arm/plat-orion/include/plat/gpio.h
  1 +/*
  2 + * arch/arm/plat-orion/include/plat/gpio.h
  3 + *
  4 + * Marvell Orion SoC GPIO handling.
  5 + *
  6 + * This file is licensed under the terms of the GNU General Public
  7 + * License version 2. This program is licensed "as is" without any
  8 + * warranty of any kind, whether express or implied.
  9 + */
  10 +
  11 +#ifndef __PLAT_GPIO_H
  12 +#define __PLAT_GPIO_H
  13 +
  14 +/*
  15 + * GENERIC_GPIO primitives.
  16 + */
  17 +int gpio_request(unsigned pin, const char *label);
  18 +void gpio_free(unsigned pin);
  19 +int gpio_direction_input(unsigned pin);
  20 +int gpio_direction_output(unsigned pin, int value);
  21 +int gpio_get_value(unsigned pin);
  22 +void gpio_set_value(unsigned pin, int value);
  23 +
  24 +/*
  25 + * Orion-specific GPIO API extensions.
  26 + */
  27 +void orion_gpio_set_unused(unsigned pin);
  28 +void orion_gpio_set_valid(unsigned pin, int valid);
  29 +void orion_gpio_set_blink(unsigned pin, int blink);
  30 +
  31 +/*
  32 + * GPIO interrupt handling.
  33 + */
  34 +extern struct irq_chip orion_gpio_irq_edge_chip;
  35 +extern struct irq_chip orion_gpio_irq_level_chip;
  36 +void orion_gpio_irq_handler(int irqoff);
  37 +
  38 +
  39 +#endif