diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-03-02 08:22:28 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-03-02 08:22:28 -0500 |
commit | 48b3b08e00012382cb52099e509b529305ae0a00 (patch) | |
tree | 0b5ff03c195707e3e545731121bc4537a3b42ac4 /arch/arm/mach-at91 | |
parent | 6e1d521b9d1201214ec4a67a7e4360232be5f963 (diff) | |
parent | f75622f4679479d352d2fa83e0d84c6c13cfcb5f (diff) |
Merge branch 'at91-3.4-cleanup2+DT' of git://github.com/at91linux/linux-at91 into next/dt
* 'at91-3.4-cleanup2+DT' of git://github.com/at91linux/linux-at91: (22 commits)
ARM: at91: at91sam9x5cm/dt: add leds support
ARM: at91: usb_a9g20/dt: add gpio-keys support
ARM: at91: at91sam9m10g45ek/dt: add gpio-keys support
ARM: at91: at91sam9m10g45ek/dt: add leds support
ARM: at91: usb_a9g20/dt: add leds support
ARM: at91/pio: add new PIO3 features
ARM: at91: add sam9_smc.o to at91sam9x5 build
ARM: at91/tc/clocksource: Add 32 bit variant to Timer Counter
ARM: at91/tc: add device tree support to atmel_tclib
ARM: at91/tclib: take iomem size from resource
ARM: at91/pit: add traces in case of error
ARM: at91: pit add DT support
ARM: at91: AIC and GPIO IRQ device tree initialization
ARM: at91/board-dt: remove AIC irq domain from board file
ARM: at91/gpio: remove the static specification of gpio_chip.base
ARM: at91/gpio: add .to_irq gpio_chip handler
ARM: at91/gpio: non-DT builds do not have gpio_chip.of_node field
ARM: at91/gpio: add irqdomain and DT support
ARM: at91/gpio: change comments and one variable name
ARM/USB: at91/ohci-at91: remove the use of irq_to_gpio
...
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r-- | arch/arm/mach-at91/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9260.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9260_devices.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam926x_time.c | 68 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9g45.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9g45_devices.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9x5.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-dt.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-snapper9260.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-at91/generic.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-at91/gpio.c | 625 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at91_pio.h | 25 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/gpio.h | 17 | ||||
-rw-r--r-- | arch/arm/mach-at91/irq.c | 132 |
14 files changed, 810 insertions, 143 deletions
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 1b6518518d99..8512e53bed93 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -20,7 +20,7 @@ obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_d | |||
20 | obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o | 20 | obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o |
21 | obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o | 21 | obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o |
22 | obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o | 22 | obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o |
23 | obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o at91sam926x_time.o | 23 | obj-$(CONFIG_ARCH_AT91SAM9X5) += at91sam9x5.o at91sam926x_time.o sam9_smc.o |
24 | obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o | 24 | obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o |
25 | 25 | ||
26 | # AT91RM9200 board-specific support | 26 | # AT91RM9200 board-specific support |
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 4ade265be805..14b5a9c9a514 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c | |||
@@ -209,6 +209,13 @@ static struct clk_lookup periph_clocks_lookups[] = { | |||
209 | CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk), | 209 | CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk), |
210 | CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk), | 210 | CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk), |
211 | CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk), | 211 | CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk), |
212 | /* more tc lookup table for DT entries */ | ||
213 | CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk), | ||
214 | CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk), | ||
215 | CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk), | ||
216 | CLKDEV_CON_DEV_ID("t0_clk", "fffdc000.timer", &tc3_clk), | ||
217 | CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk), | ||
218 | CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk), | ||
212 | /* fake hclk clock */ | 219 | /* fake hclk clock */ |
213 | CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), | 220 | CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), |
214 | CLKDEV_CON_ID("pioA", &pioA_clk), | 221 | CLKDEV_CON_ID("pioA", &pioA_clk), |
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 40f6aeaea043..7e5651ee9f85 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c | |||
@@ -642,7 +642,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) | |||
642 | static struct resource tcb0_resources[] = { | 642 | static struct resource tcb0_resources[] = { |
643 | [0] = { | 643 | [0] = { |
644 | .start = AT91SAM9260_BASE_TCB0, | 644 | .start = AT91SAM9260_BASE_TCB0, |
645 | .end = AT91SAM9260_BASE_TCB0 + SZ_16K - 1, | 645 | .end = AT91SAM9260_BASE_TCB0 + SZ_256 - 1, |
646 | .flags = IORESOURCE_MEM, | 646 | .flags = IORESOURCE_MEM, |
647 | }, | 647 | }, |
648 | [1] = { | 648 | [1] = { |
@@ -672,7 +672,7 @@ static struct platform_device at91sam9260_tcb0_device = { | |||
672 | static struct resource tcb1_resources[] = { | 672 | static struct resource tcb1_resources[] = { |
673 | [0] = { | 673 | [0] = { |
674 | .start = AT91SAM9260_BASE_TCB1, | 674 | .start = AT91SAM9260_BASE_TCB1, |
675 | .end = AT91SAM9260_BASE_TCB1 + SZ_16K - 1, | 675 | .end = AT91SAM9260_BASE_TCB1 + SZ_256 - 1, |
676 | .flags = IORESOURCE_MEM, | 676 | .flags = IORESOURCE_MEM, |
677 | }, | 677 | }, |
678 | [1] = { | 678 | [1] = { |
@@ -699,8 +699,25 @@ static struct platform_device at91sam9260_tcb1_device = { | |||
699 | .num_resources = ARRAY_SIZE(tcb1_resources), | 699 | .num_resources = ARRAY_SIZE(tcb1_resources), |
700 | }; | 700 | }; |
701 | 701 | ||
702 | #if defined(CONFIG_OF) | ||
703 | static struct of_device_id tcb_ids[] = { | ||
704 | { .compatible = "atmel,at91rm9200-tcb" }, | ||
705 | { /*sentinel*/ } | ||
706 | }; | ||
707 | #endif | ||
708 | |||
702 | static void __init at91_add_device_tc(void) | 709 | static void __init at91_add_device_tc(void) |
703 | { | 710 | { |
711 | #if defined(CONFIG_OF) | ||
712 | struct device_node *np; | ||
713 | |||
714 | np = of_find_matching_node(NULL, tcb_ids); | ||
715 | if (np) { | ||
716 | of_node_put(np); | ||
717 | return; | ||
718 | } | ||
719 | #endif | ||
720 | |||
704 | platform_device_register(&at91sam9260_tcb0_device); | 721 | platform_device_register(&at91sam9260_tcb0_device); |
705 | platform_device_register(&at91sam9260_tcb1_device); | 722 | platform_device_register(&at91sam9260_tcb1_device); |
706 | } | 723 | } |
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index d89ead740a99..a94758b42737 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c | |||
@@ -14,6 +14,9 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_address.h> | ||
19 | #include <linux/of_irq.h> | ||
17 | 20 | ||
18 | #include <asm/mach/time.h> | 21 | #include <asm/mach/time.h> |
19 | 22 | ||
@@ -133,7 +136,8 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) | |||
133 | static struct irqaction at91sam926x_pit_irq = { | 136 | static struct irqaction at91sam926x_pit_irq = { |
134 | .name = "at91_tick", | 137 | .name = "at91_tick", |
135 | .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 138 | .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, |
136 | .handler = at91sam926x_pit_interrupt | 139 | .handler = at91sam926x_pit_interrupt, |
140 | .irq = AT91_ID_SYS, | ||
137 | }; | 141 | }; |
138 | 142 | ||
139 | static void at91sam926x_pit_reset(void) | 143 | static void at91sam926x_pit_reset(void) |
@@ -149,6 +153,51 @@ static void at91sam926x_pit_reset(void) | |||
149 | pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); | 153 | pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); |
150 | } | 154 | } |
151 | 155 | ||
156 | #ifdef CONFIG_OF | ||
157 | static struct of_device_id pit_timer_ids[] = { | ||
158 | { .compatible = "atmel,at91sam9260-pit" }, | ||
159 | { /* sentinel */ } | ||
160 | }; | ||
161 | |||
162 | static int __init of_at91sam926x_pit_init(void) | ||
163 | { | ||
164 | struct device_node *np; | ||
165 | int ret; | ||
166 | |||
167 | np = of_find_matching_node(NULL, pit_timer_ids); | ||
168 | if (!np) | ||
169 | goto err; | ||
170 | |||
171 | pit_base_addr = of_iomap(np, 0); | ||
172 | if (!pit_base_addr) | ||
173 | goto node_err; | ||
174 | |||
175 | /* Get the interrupts property */ | ||
176 | ret = irq_of_parse_and_map(np, 0); | ||
177 | if (!ret) { | ||
178 | pr_crit("AT91: PIT: Unable to get IRQ from DT\n"); | ||
179 | goto ioremap_err; | ||
180 | } | ||
181 | at91sam926x_pit_irq.irq = ret; | ||
182 | |||
183 | of_node_put(np); | ||
184 | |||
185 | return 0; | ||
186 | |||
187 | ioremap_err: | ||
188 | iounmap(pit_base_addr); | ||
189 | node_err: | ||
190 | of_node_put(np); | ||
191 | err: | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | #else | ||
195 | static int __init of_at91sam926x_pit_init(void) | ||
196 | { | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | #endif | ||
200 | |||
152 | /* | 201 | /* |
153 | * Set up both clocksource and clockevent support. | 202 | * Set up both clocksource and clockevent support. |
154 | */ | 203 | */ |
@@ -156,6 +205,10 @@ static void __init at91sam926x_pit_init(void) | |||
156 | { | 205 | { |
157 | unsigned long pit_rate; | 206 | unsigned long pit_rate; |
158 | unsigned bits; | 207 | unsigned bits; |
208 | int ret; | ||
209 | |||
210 | /* For device tree enabled device: initialize here */ | ||
211 | of_at91sam926x_pit_init(); | ||
159 | 212 | ||
160 | /* | 213 | /* |
161 | * Use our actual MCK to figure out how many MCK/16 ticks per | 214 | * Use our actual MCK to figure out how many MCK/16 ticks per |
@@ -177,7 +230,9 @@ static void __init at91sam926x_pit_init(void) | |||
177 | clocksource_register_hz(&pit_clk, pit_rate); | 230 | clocksource_register_hz(&pit_clk, pit_rate); |
178 | 231 | ||
179 | /* Set up irq handler */ | 232 | /* Set up irq handler */ |
180 | setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq); | 233 | ret = setup_irq(at91sam926x_pit_irq.irq, &at91sam926x_pit_irq); |
234 | if (ret) | ||
235 | pr_crit("AT91: PIT: Unable to setup IRQ\n"); | ||
181 | 236 | ||
182 | /* Set up and register clockevents */ | 237 | /* Set up and register clockevents */ |
183 | pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift); | 238 | pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift); |
@@ -193,6 +248,15 @@ static void at91sam926x_pit_suspend(void) | |||
193 | 248 | ||
194 | void __init at91sam926x_ioremap_pit(u32 addr) | 249 | void __init at91sam926x_ioremap_pit(u32 addr) |
195 | { | 250 | { |
251 | #if defined(CONFIG_OF) | ||
252 | struct device_node *np = | ||
253 | of_find_matching_node(NULL, pit_timer_ids); | ||
254 | |||
255 | if (np) { | ||
256 | of_node_put(np); | ||
257 | return; | ||
258 | } | ||
259 | #endif | ||
196 | pit_base_addr = ioremap(addr, 16); | 260 | pit_base_addr = ioremap(addr, 16); |
197 | 261 | ||
198 | if (!pit_base_addr) | 262 | if (!pit_base_addr) |
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index a41622ea61b8..0014573dfe17 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c | |||
@@ -229,6 +229,9 @@ static struct clk_lookup periph_clocks_lookups[] = { | |||
229 | CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk), | 229 | CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk), |
230 | CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk), | 230 | CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk), |
231 | CLKDEV_CON_DEV_ID("usart", "fff98000.serial", &usart3_clk), | 231 | CLKDEV_CON_DEV_ID("usart", "fff98000.serial", &usart3_clk), |
232 | /* more tc lookup table for DT entries */ | ||
233 | CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb0_clk), | ||
234 | CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk), | ||
232 | /* fake hclk clock */ | 235 | /* fake hclk clock */ |
233 | CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk), | 236 | CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk), |
234 | CLKDEV_CON_ID("pioA", &pioA_clk), | 237 | CLKDEV_CON_ID("pioA", &pioA_clk), |
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 410829532aab..4320b2096789 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c | |||
@@ -1052,7 +1052,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {} | |||
1052 | static struct resource tcb0_resources[] = { | 1052 | static struct resource tcb0_resources[] = { |
1053 | [0] = { | 1053 | [0] = { |
1054 | .start = AT91SAM9G45_BASE_TCB0, | 1054 | .start = AT91SAM9G45_BASE_TCB0, |
1055 | .end = AT91SAM9G45_BASE_TCB0 + SZ_16K - 1, | 1055 | .end = AT91SAM9G45_BASE_TCB0 + SZ_256 - 1, |
1056 | .flags = IORESOURCE_MEM, | 1056 | .flags = IORESOURCE_MEM, |
1057 | }, | 1057 | }, |
1058 | [1] = { | 1058 | [1] = { |
@@ -1073,7 +1073,7 @@ static struct platform_device at91sam9g45_tcb0_device = { | |||
1073 | static struct resource tcb1_resources[] = { | 1073 | static struct resource tcb1_resources[] = { |
1074 | [0] = { | 1074 | [0] = { |
1075 | .start = AT91SAM9G45_BASE_TCB1, | 1075 | .start = AT91SAM9G45_BASE_TCB1, |
1076 | .end = AT91SAM9G45_BASE_TCB1 + SZ_16K - 1, | 1076 | .end = AT91SAM9G45_BASE_TCB1 + SZ_256 - 1, |
1077 | .flags = IORESOURCE_MEM, | 1077 | .flags = IORESOURCE_MEM, |
1078 | }, | 1078 | }, |
1079 | [1] = { | 1079 | [1] = { |
@@ -1090,8 +1090,25 @@ static struct platform_device at91sam9g45_tcb1_device = { | |||
1090 | .num_resources = ARRAY_SIZE(tcb1_resources), | 1090 | .num_resources = ARRAY_SIZE(tcb1_resources), |
1091 | }; | 1091 | }; |
1092 | 1092 | ||
1093 | #if defined(CONFIG_OF) | ||
1094 | static struct of_device_id tcb_ids[] = { | ||
1095 | { .compatible = "atmel,at91rm9200-tcb" }, | ||
1096 | { /*sentinel*/ } | ||
1097 | }; | ||
1098 | #endif | ||
1099 | |||
1093 | static void __init at91_add_device_tc(void) | 1100 | static void __init at91_add_device_tc(void) |
1094 | { | 1101 | { |
1102 | #if defined(CONFIG_OF) | ||
1103 | struct device_node *np; | ||
1104 | |||
1105 | np = of_find_matching_node(NULL, tcb_ids); | ||
1106 | if (np) { | ||
1107 | of_node_put(np); | ||
1108 | return; | ||
1109 | } | ||
1110 | #endif | ||
1111 | |||
1095 | platform_device_register(&at91sam9g45_tcb0_device); | 1112 | platform_device_register(&at91sam9g45_tcb0_device); |
1096 | platform_device_register(&at91sam9g45_tcb1_device); | 1113 | platform_device_register(&at91sam9g45_tcb1_device); |
1097 | } | 1114 | } |
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index d17d4262665b..a34d96afa746 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c | |||
@@ -301,8 +301,6 @@ static void __init at91sam9x5_map_io(void) | |||
301 | 301 | ||
302 | static void __init at91sam9x5_ioremap_registers(void) | 302 | static void __init at91sam9x5_ioremap_registers(void) |
303 | { | 303 | { |
304 | if (of_at91sam926x_pit_init() < 0) | ||
305 | panic("Impossible to find PIT\n"); | ||
306 | at91_ioremap_ramc(0, AT91SAM9X5_BASE_DDRSDRC0, 512); | 304 | at91_ioremap_ramc(0, AT91SAM9X5_BASE_DDRSDRC0, 512); |
307 | } | 305 | } |
308 | 306 | ||
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index 08c8ad8609b7..583b72472ad9 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
18 | #include <linux/irqdomain.h> | 18 | #include <linux/of.h> |
19 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
20 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
21 | 21 | ||
@@ -82,15 +82,17 @@ static void __init ek_add_device_nand(void) | |||
82 | at91_add_device_nand(&ek_nand_data); | 82 | at91_add_device_nand(&ek_nand_data); |
83 | } | 83 | } |
84 | 84 | ||
85 | static const struct of_device_id aic_of_match[] __initconst = { | 85 | static const struct of_device_id irq_of_match[] __initconst = { |
86 | { .compatible = "atmel,at91rm9200-aic", }, | 86 | |
87 | {}, | 87 | { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, |
88 | { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup }, | ||
89 | { .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup }, | ||
90 | { /*sentinel*/ } | ||
88 | }; | 91 | }; |
89 | 92 | ||
90 | static void __init at91_dt_init_irq(void) | 93 | static void __init at91_dt_init_irq(void) |
91 | { | 94 | { |
92 | irq_domain_generate_simple(aic_of_match, 0xfffff000, 0); | 95 | of_irq_init(irq_of_match); |
93 | at91_init_irq_default(); | ||
94 | } | 96 | } |
95 | 97 | ||
96 | static void __init at91_dt_device_init(void) | 98 | static void __init at91_dt_device_init(void) |
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c index 4770db08e5a6..3c2e3fcc310c 100644 --- a/arch/arm/mach-at91/board-snapper9260.c +++ b/arch/arm/mach-at91/board-snapper9260.c | |||
@@ -145,11 +145,11 @@ static struct i2c_board_info __initdata snapper9260_i2c_devices[] = { | |||
145 | /* Audio codec */ | 145 | /* Audio codec */ |
146 | I2C_BOARD_INFO("tlv320aic23", 0x1a), | 146 | I2C_BOARD_INFO("tlv320aic23", 0x1a), |
147 | }, | 147 | }, |
148 | { | 148 | }; |
149 | |||
150 | static struct i2c_board_info __initdata snapper9260_i2c_isl1208 = { | ||
149 | /* RTC */ | 151 | /* RTC */ |
150 | I2C_BOARD_INFO("isl1208", 0x6f), | 152 | I2C_BOARD_INFO("isl1208", 0x6f), |
151 | .irq = gpio_to_irq(AT91_PIN_PA31), | ||
152 | }, | ||
153 | }; | 153 | }; |
154 | 154 | ||
155 | static void __init snapper9260_add_device_nand(void) | 155 | static void __init snapper9260_add_device_nand(void) |
@@ -163,6 +163,10 @@ static void __init snapper9260_board_init(void) | |||
163 | { | 163 | { |
164 | at91_add_device_i2c(snapper9260_i2c_devices, | 164 | at91_add_device_i2c(snapper9260_i2c_devices, |
165 | ARRAY_SIZE(snapper9260_i2c_devices)); | 165 | ARRAY_SIZE(snapper9260_i2c_devices)); |
166 | |||
167 | snapper9260_i2c_isl1208.irq = gpio_to_irq(AT91_PIN_PA31); | ||
168 | i2c_register_board_info(0, &snapper9260_i2c_isl1208, 1); | ||
169 | |||
166 | at91_add_device_serial(); | 170 | at91_add_device_serial(); |
167 | at91_add_device_usbh(&snapper9260_usbh_data); | 171 | at91_add_device_usbh(&snapper9260_usbh_data); |
168 | at91_add_device_udc(&snapper9260_udc_data); | 172 | at91_add_device_udc(&snapper9260_udc_data); |
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 4cad85e57470..459f01a4a546 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/clkdev.h> | 11 | #include <linux/clkdev.h> |
12 | #include <linux/of.h> | ||
12 | 13 | ||
13 | /* Map io */ | 14 | /* Map io */ |
14 | extern void __init at91_map_io(void); | 15 | extern void __init at91_map_io(void); |
@@ -25,6 +26,9 @@ extern void __init at91_init_irq_default(void); | |||
25 | extern void __init at91_init_interrupts(unsigned int priority[]); | 26 | extern void __init at91_init_interrupts(unsigned int priority[]); |
26 | extern void __init at91x40_init_interrupts(unsigned int priority[]); | 27 | extern void __init at91x40_init_interrupts(unsigned int priority[]); |
27 | extern void __init at91_aic_init(unsigned int priority[]); | 28 | extern void __init at91_aic_init(unsigned int priority[]); |
29 | extern int __init at91_aic_of_init(struct device_node *node, | ||
30 | struct device_node *parent); | ||
31 | |||
28 | 32 | ||
29 | /* Timer */ | 33 | /* Timer */ |
30 | struct sys_timer; | 34 | struct sys_timer; |
@@ -84,5 +88,7 @@ struct at91_gpio_bank { | |||
84 | }; | 88 | }; |
85 | extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks); | 89 | extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks); |
86 | extern void __init at91_gpio_irq_setup(void); | 90 | extern void __init at91_gpio_irq_setup(void); |
91 | extern int __init at91_gpio_of_irq_setup(struct device_node *node, | ||
92 | struct device_node *parent); | ||
87 | 93 | ||
88 | extern int at91_extern_irq; | 94 | extern int at91_extern_irq; |
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index 74d6783eeabb..325837a264c9 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/device.h> | ||
14 | #include <linux/gpio.h> | 15 | #include <linux/gpio.h> |
15 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
16 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
@@ -20,6 +21,10 @@ | |||
20 | #include <linux/list.h> | 21 | #include <linux/list.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/irqdomain.h> | ||
25 | #include <linux/of_address.h> | ||
26 | #include <linux/of_irq.h> | ||
27 | #include <linux/of_gpio.h> | ||
23 | 28 | ||
24 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
25 | #include <mach/at91_pio.h> | 30 | #include <mach/at91_pio.h> |
@@ -29,9 +34,12 @@ | |||
29 | struct at91_gpio_chip { | 34 | struct at91_gpio_chip { |
30 | struct gpio_chip chip; | 35 | struct gpio_chip chip; |
31 | struct at91_gpio_chip *next; /* Bank sharing same clock */ | 36 | struct at91_gpio_chip *next; /* Bank sharing same clock */ |
32 | int id; /* ID of register bank */ | 37 | int pioc_hwirq; /* PIO bank interrupt identifier on AIC */ |
33 | void __iomem *regbase; /* Base of register bank */ | 38 | int pioc_virq; /* PIO bank Linux virtual interrupt */ |
39 | int pioc_idx; /* PIO bank index */ | ||
40 | void __iomem *regbase; /* PIO bank virtual address */ | ||
34 | struct clk *clock; /* associated clock */ | 41 | struct clk *clock; /* associated clock */ |
42 | struct irq_domain *domain; /* associated irq domain */ | ||
35 | }; | 43 | }; |
36 | 44 | ||
37 | #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip) | 45 | #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip) |
@@ -43,8 +51,9 @@ static int at91_gpiolib_direction_output(struct gpio_chip *chip, | |||
43 | unsigned offset, int val); | 51 | unsigned offset, int val); |
44 | static int at91_gpiolib_direction_input(struct gpio_chip *chip, | 52 | static int at91_gpiolib_direction_input(struct gpio_chip *chip, |
45 | unsigned offset); | 53 | unsigned offset); |
54 | static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset); | ||
46 | 55 | ||
47 | #define AT91_GPIO_CHIP(name, base_gpio, nr_gpio) \ | 56 | #define AT91_GPIO_CHIP(name, nr_gpio) \ |
48 | { \ | 57 | { \ |
49 | .chip = { \ | 58 | .chip = { \ |
50 | .label = name, \ | 59 | .label = name, \ |
@@ -53,20 +62,28 @@ static int at91_gpiolib_direction_input(struct gpio_chip *chip, | |||
53 | .get = at91_gpiolib_get, \ | 62 | .get = at91_gpiolib_get, \ |
54 | .set = at91_gpiolib_set, \ | 63 | .set = at91_gpiolib_set, \ |
55 | .dbg_show = at91_gpiolib_dbg_show, \ | 64 | .dbg_show = at91_gpiolib_dbg_show, \ |
56 | .base = base_gpio, \ | 65 | .to_irq = at91_gpiolib_to_irq, \ |
57 | .ngpio = nr_gpio, \ | 66 | .ngpio = nr_gpio, \ |
58 | }, \ | 67 | }, \ |
59 | } | 68 | } |
60 | 69 | ||
61 | static struct at91_gpio_chip gpio_chip[] = { | 70 | static struct at91_gpio_chip gpio_chip[] = { |
62 | AT91_GPIO_CHIP("pioA", 0x00, 32), | 71 | AT91_GPIO_CHIP("pioA", 32), |
63 | AT91_GPIO_CHIP("pioB", 0x20, 32), | 72 | AT91_GPIO_CHIP("pioB", 32), |
64 | AT91_GPIO_CHIP("pioC", 0x40, 32), | 73 | AT91_GPIO_CHIP("pioC", 32), |
65 | AT91_GPIO_CHIP("pioD", 0x60, 32), | 74 | AT91_GPIO_CHIP("pioD", 32), |
66 | AT91_GPIO_CHIP("pioE", 0x80, 32), | 75 | AT91_GPIO_CHIP("pioE", 32), |
67 | }; | 76 | }; |
68 | 77 | ||
69 | static int gpio_banks; | 78 | static int gpio_banks; |
79 | static unsigned long at91_gpio_caps; | ||
80 | |||
81 | /* All PIO controllers support PIO3 features */ | ||
82 | #define AT91_GPIO_CAP_PIO3 (1 << 0) | ||
83 | |||
84 | #define has_pio3() (at91_gpio_caps & AT91_GPIO_CAP_PIO3) | ||
85 | |||
86 | /*--------------------------------------------------------------------------*/ | ||
70 | 87 | ||
71 | static inline void __iomem *pin_to_controller(unsigned pin) | 88 | static inline void __iomem *pin_to_controller(unsigned pin) |
72 | { | 89 | { |
@@ -83,6 +100,25 @@ static inline unsigned pin_to_mask(unsigned pin) | |||
83 | } | 100 | } |
84 | 101 | ||
85 | 102 | ||
103 | static char peripheral_function(void __iomem *pio, unsigned mask) | ||
104 | { | ||
105 | char ret = 'X'; | ||
106 | u8 select; | ||
107 | |||
108 | if (pio) { | ||
109 | if (has_pio3()) { | ||
110 | select = !!(__raw_readl(pio + PIO_ABCDSR1) & mask); | ||
111 | select |= (!!(__raw_readl(pio + PIO_ABCDSR2) & mask) << 1); | ||
112 | ret = 'A' + select; | ||
113 | } else { | ||
114 | ret = __raw_readl(pio + PIO_ABSR) & mask ? | ||
115 | 'B' : 'A'; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
86 | /*--------------------------------------------------------------------------*/ | 122 | /*--------------------------------------------------------------------------*/ |
87 | 123 | ||
88 | /* Not all hardware capabilities are exposed through these calls; they | 124 | /* Not all hardware capabilities are exposed through these calls; they |
@@ -130,7 +166,14 @@ int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup) | |||
130 | 166 | ||
131 | __raw_writel(mask, pio + PIO_IDR); | 167 | __raw_writel(mask, pio + PIO_IDR); |
132 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | 168 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); |
133 | __raw_writel(mask, pio + PIO_ASR); | 169 | if (has_pio3()) { |
170 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, | ||
171 | pio + PIO_ABCDSR1); | ||
172 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask, | ||
173 | pio + PIO_ABCDSR2); | ||
174 | } else { | ||
175 | __raw_writel(mask, pio + PIO_ASR); | ||
176 | } | ||
134 | __raw_writel(mask, pio + PIO_PDR); | 177 | __raw_writel(mask, pio + PIO_PDR); |
135 | return 0; | 178 | return 0; |
136 | } | 179 | } |
@@ -150,7 +193,14 @@ int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup) | |||
150 | 193 | ||
151 | __raw_writel(mask, pio + PIO_IDR); | 194 | __raw_writel(mask, pio + PIO_IDR); |
152 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | 195 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); |
153 | __raw_writel(mask, pio + PIO_BSR); | 196 | if (has_pio3()) { |
197 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, | ||
198 | pio + PIO_ABCDSR1); | ||
199 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask, | ||
200 | pio + PIO_ABCDSR2); | ||
201 | } else { | ||
202 | __raw_writel(mask, pio + PIO_BSR); | ||
203 | } | ||
154 | __raw_writel(mask, pio + PIO_PDR); | 204 | __raw_writel(mask, pio + PIO_PDR); |
155 | return 0; | 205 | return 0; |
156 | } | 206 | } |
@@ -158,8 +208,50 @@ EXPORT_SYMBOL(at91_set_B_periph); | |||
158 | 208 | ||
159 | 209 | ||
160 | /* | 210 | /* |
161 | * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and | 211 | * mux the pin to the "C" internal peripheral role. |
162 | * configure it for an input. | 212 | */ |
213 | int __init_or_module at91_set_C_periph(unsigned pin, int use_pullup) | ||
214 | { | ||
215 | void __iomem *pio = pin_to_controller(pin); | ||
216 | unsigned mask = pin_to_mask(pin); | ||
217 | |||
218 | if (!pio || !has_pio3()) | ||
219 | return -EINVAL; | ||
220 | |||
221 | __raw_writel(mask, pio + PIO_IDR); | ||
222 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | ||
223 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1); | ||
224 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2); | ||
225 | __raw_writel(mask, pio + PIO_PDR); | ||
226 | return 0; | ||
227 | } | ||
228 | EXPORT_SYMBOL(at91_set_C_periph); | ||
229 | |||
230 | |||
231 | /* | ||
232 | * mux the pin to the "D" internal peripheral role. | ||
233 | */ | ||
234 | int __init_or_module at91_set_D_periph(unsigned pin, int use_pullup) | ||
235 | { | ||
236 | void __iomem *pio = pin_to_controller(pin); | ||
237 | unsigned mask = pin_to_mask(pin); | ||
238 | |||
239 | if (!pio || !has_pio3()) | ||
240 | return -EINVAL; | ||
241 | |||
242 | __raw_writel(mask, pio + PIO_IDR); | ||
243 | __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR)); | ||
244 | __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1); | ||
245 | __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2); | ||
246 | __raw_writel(mask, pio + PIO_PDR); | ||
247 | return 0; | ||
248 | } | ||
249 | EXPORT_SYMBOL(at91_set_D_periph); | ||
250 | |||
251 | |||
252 | /* | ||
253 | * mux the pin to the gpio controller (instead of "A", "B", "C" | ||
254 | * or "D" peripheral), and configure it for an input. | ||
163 | */ | 255 | */ |
164 | int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup) | 256 | int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup) |
165 | { | 257 | { |
@@ -179,8 +271,8 @@ EXPORT_SYMBOL(at91_set_gpio_input); | |||
179 | 271 | ||
180 | 272 | ||
181 | /* | 273 | /* |
182 | * mux the pin to the gpio controller (instead of "A" or "B" peripheral), | 274 | * mux the pin to the gpio controller (instead of "A", "B", "C" |
183 | * and configure it for an output. | 275 | * or "D" peripheral), and configure it for an output. |
184 | */ | 276 | */ |
185 | int __init_or_module at91_set_gpio_output(unsigned pin, int value) | 277 | int __init_or_module at91_set_gpio_output(unsigned pin, int value) |
186 | { | 278 | { |
@@ -210,12 +302,37 @@ int __init_or_module at91_set_deglitch(unsigned pin, int is_on) | |||
210 | 302 | ||
211 | if (!pio) | 303 | if (!pio) |
212 | return -EINVAL; | 304 | return -EINVAL; |
305 | |||
306 | if (has_pio3() && is_on) | ||
307 | __raw_writel(mask, pio + PIO_IFSCDR); | ||
213 | __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); | 308 | __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR)); |
214 | return 0; | 309 | return 0; |
215 | } | 310 | } |
216 | EXPORT_SYMBOL(at91_set_deglitch); | 311 | EXPORT_SYMBOL(at91_set_deglitch); |
217 | 312 | ||
218 | /* | 313 | /* |
314 | * enable/disable the debounce filter; | ||
315 | */ | ||
316 | int __init_or_module at91_set_debounce(unsigned pin, int is_on, int div) | ||
317 | { | ||
318 | void __iomem *pio = pin_to_controller(pin); | ||
319 | unsigned mask = pin_to_mask(pin); | ||
320 | |||
321 | if (!pio || !has_pio3()) | ||
322 | return -EINVAL; | ||
323 | |||
324 | if (is_on) { | ||
325 | __raw_writel(mask, pio + PIO_IFSCER); | ||
326 | __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR); | ||
327 | __raw_writel(mask, pio + PIO_IFER); | ||
328 | } else { | ||
329 | __raw_writel(mask, pio + PIO_IFDR); | ||
330 | } | ||
331 | return 0; | ||
332 | } | ||
333 | EXPORT_SYMBOL(at91_set_debounce); | ||
334 | |||
335 | /* | ||
219 | * enable/disable the multi-driver; This is only valid for output and | 336 | * enable/disable the multi-driver; This is only valid for output and |
220 | * allows the output pin to run as an open collector output. | 337 | * allows the output pin to run as an open collector output. |
221 | */ | 338 | */ |
@@ -233,6 +350,41 @@ int __init_or_module at91_set_multi_drive(unsigned pin, int is_on) | |||
233 | EXPORT_SYMBOL(at91_set_multi_drive); | 350 | EXPORT_SYMBOL(at91_set_multi_drive); |
234 | 351 | ||
235 | /* | 352 | /* |
353 | * enable/disable the pull-down. | ||
354 | * If pull-up already enabled while calling the function, we disable it. | ||
355 | */ | ||
356 | int __init_or_module at91_set_pulldown(unsigned pin, int is_on) | ||
357 | { | ||
358 | void __iomem *pio = pin_to_controller(pin); | ||
359 | unsigned mask = pin_to_mask(pin); | ||
360 | |||
361 | if (!pio || !has_pio3()) | ||
362 | return -EINVAL; | ||
363 | |||
364 | /* Disable pull-up anyway */ | ||
365 | __raw_writel(mask, pio + PIO_PUDR); | ||
366 | __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR)); | ||
367 | return 0; | ||
368 | } | ||
369 | EXPORT_SYMBOL(at91_set_pulldown); | ||
370 | |||
371 | /* | ||
372 | * disable Schmitt trigger | ||
373 | */ | ||
374 | int __init_or_module at91_disable_schmitt_trig(unsigned pin) | ||
375 | { | ||
376 | void __iomem *pio = pin_to_controller(pin); | ||
377 | unsigned mask = pin_to_mask(pin); | ||
378 | |||
379 | if (!pio || !has_pio3()) | ||
380 | return -EINVAL; | ||
381 | |||
382 | __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT); | ||
383 | return 0; | ||
384 | } | ||
385 | EXPORT_SYMBOL(at91_disable_schmitt_trig); | ||
386 | |||
387 | /* | ||
236 | * assuming the pin is muxed as a gpio output, set its value. | 388 | * assuming the pin is muxed as a gpio output, set its value. |
237 | */ | 389 | */ |
238 | int at91_set_gpio_value(unsigned pin, int value) | 390 | int at91_set_gpio_value(unsigned pin, int value) |
@@ -273,9 +425,9 @@ static u32 backups[MAX_GPIO_BANKS]; | |||
273 | 425 | ||
274 | static int gpio_irq_set_wake(struct irq_data *d, unsigned state) | 426 | static int gpio_irq_set_wake(struct irq_data *d, unsigned state) |
275 | { | 427 | { |
276 | unsigned pin = irq_to_gpio(d->irq); | 428 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); |
277 | unsigned mask = pin_to_mask(pin); | 429 | unsigned mask = 1 << d->hwirq; |
278 | unsigned bank = pin / 32; | 430 | unsigned bank = at91_gpio->pioc_idx; |
279 | 431 | ||
280 | if (unlikely(bank >= MAX_GPIO_BANKS)) | 432 | if (unlikely(bank >= MAX_GPIO_BANKS)) |
281 | return -EINVAL; | 433 | return -EINVAL; |
@@ -285,7 +437,7 @@ static int gpio_irq_set_wake(struct irq_data *d, unsigned state) | |||
285 | else | 437 | else |
286 | wakeups[bank] &= ~mask; | 438 | wakeups[bank] &= ~mask; |
287 | 439 | ||
288 | irq_set_irq_wake(gpio_chip[bank].id, state); | 440 | irq_set_irq_wake(at91_gpio->pioc_virq, state); |
289 | 441 | ||
290 | return 0; | 442 | return 0; |
291 | } | 443 | } |
@@ -301,9 +453,10 @@ void at91_gpio_suspend(void) | |||
301 | __raw_writel(backups[i], pio + PIO_IDR); | 453 | __raw_writel(backups[i], pio + PIO_IDR); |
302 | __raw_writel(wakeups[i], pio + PIO_IER); | 454 | __raw_writel(wakeups[i], pio + PIO_IER); |
303 | 455 | ||
304 | if (!wakeups[i]) | 456 | if (!wakeups[i]) { |
457 | clk_unprepare(gpio_chip[i].clock); | ||
305 | clk_disable(gpio_chip[i].clock); | 458 | clk_disable(gpio_chip[i].clock); |
306 | else { | 459 | } else { |
307 | #ifdef CONFIG_PM_DEBUG | 460 | #ifdef CONFIG_PM_DEBUG |
308 | printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]); | 461 | printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]); |
309 | #endif | 462 | #endif |
@@ -318,8 +471,10 @@ void at91_gpio_resume(void) | |||
318 | for (i = 0; i < gpio_banks; i++) { | 471 | for (i = 0; i < gpio_banks; i++) { |
319 | void __iomem *pio = gpio_chip[i].regbase; | 472 | void __iomem *pio = gpio_chip[i].regbase; |
320 | 473 | ||
321 | if (!wakeups[i]) | 474 | if (!wakeups[i]) { |
322 | clk_enable(gpio_chip[i].clock); | 475 | if (clk_prepare(gpio_chip[i].clock) == 0) |
476 | clk_enable(gpio_chip[i].clock); | ||
477 | } | ||
323 | 478 | ||
324 | __raw_writel(wakeups[i], pio + PIO_IDR); | 479 | __raw_writel(wakeups[i], pio + PIO_IDR); |
325 | __raw_writel(backups[i], pio + PIO_IER); | 480 | __raw_writel(backups[i], pio + PIO_IER); |
@@ -335,7 +490,10 @@ void at91_gpio_resume(void) | |||
335 | * To use any AT91_PIN_* as an externally triggered IRQ, first call | 490 | * To use any AT91_PIN_* as an externally triggered IRQ, first call |
336 | * at91_set_gpio_input() then maybe enable its glitch filter. | 491 | * at91_set_gpio_input() then maybe enable its glitch filter. |
337 | * Then just request_irq() with the pin ID; it works like any ARM IRQ | 492 | * Then just request_irq() with the pin ID; it works like any ARM IRQ |
338 | * handler, though it always triggers on rising and falling edges. | 493 | * handler. |
494 | * First implementation always triggers on rising and falling edges | ||
495 | * whereas the newer PIO3 can be additionally configured to trigger on | ||
496 | * level, edge with any polarity. | ||
339 | * | 497 | * |
340 | * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after | 498 | * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after |
341 | * configuring them with at91_set_a_periph() or at91_set_b_periph(). | 499 | * configuring them with at91_set_a_periph() or at91_set_b_periph(). |
@@ -344,9 +502,9 @@ void at91_gpio_resume(void) | |||
344 | 502 | ||
345 | static void gpio_irq_mask(struct irq_data *d) | 503 | static void gpio_irq_mask(struct irq_data *d) |
346 | { | 504 | { |
347 | unsigned pin = irq_to_gpio(d->irq); | 505 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); |
348 | void __iomem *pio = pin_to_controller(pin); | 506 | void __iomem *pio = at91_gpio->regbase; |
349 | unsigned mask = pin_to_mask(pin); | 507 | unsigned mask = 1 << d->hwirq; |
350 | 508 | ||
351 | if (pio) | 509 | if (pio) |
352 | __raw_writel(mask, pio + PIO_IDR); | 510 | __raw_writel(mask, pio + PIO_IDR); |
@@ -354,9 +512,9 @@ static void gpio_irq_mask(struct irq_data *d) | |||
354 | 512 | ||
355 | static void gpio_irq_unmask(struct irq_data *d) | 513 | static void gpio_irq_unmask(struct irq_data *d) |
356 | { | 514 | { |
357 | unsigned pin = irq_to_gpio(d->irq); | 515 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); |
358 | void __iomem *pio = pin_to_controller(pin); | 516 | void __iomem *pio = at91_gpio->regbase; |
359 | unsigned mask = pin_to_mask(pin); | 517 | unsigned mask = 1 << d->hwirq; |
360 | 518 | ||
361 | if (pio) | 519 | if (pio) |
362 | __raw_writel(mask, pio + PIO_IER); | 520 | __raw_writel(mask, pio + PIO_IER); |
@@ -373,23 +531,66 @@ static int gpio_irq_type(struct irq_data *d, unsigned type) | |||
373 | } | 531 | } |
374 | } | 532 | } |
375 | 533 | ||
534 | /* Alternate irq type for PIO3 support */ | ||
535 | static int alt_gpio_irq_type(struct irq_data *d, unsigned type) | ||
536 | { | ||
537 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); | ||
538 | void __iomem *pio = at91_gpio->regbase; | ||
539 | unsigned mask = 1 << d->hwirq; | ||
540 | |||
541 | switch (type) { | ||
542 | case IRQ_TYPE_EDGE_RISING: | ||
543 | __raw_writel(mask, pio + PIO_ESR); | ||
544 | __raw_writel(mask, pio + PIO_REHLSR); | ||
545 | break; | ||
546 | case IRQ_TYPE_EDGE_FALLING: | ||
547 | __raw_writel(mask, pio + PIO_ESR); | ||
548 | __raw_writel(mask, pio + PIO_FELLSR); | ||
549 | break; | ||
550 | case IRQ_TYPE_LEVEL_LOW: | ||
551 | __raw_writel(mask, pio + PIO_LSR); | ||
552 | __raw_writel(mask, pio + PIO_FELLSR); | ||
553 | break; | ||
554 | case IRQ_TYPE_LEVEL_HIGH: | ||
555 | __raw_writel(mask, pio + PIO_LSR); | ||
556 | __raw_writel(mask, pio + PIO_REHLSR); | ||
557 | break; | ||
558 | case IRQ_TYPE_EDGE_BOTH: | ||
559 | /* | ||
560 | * disable additional interrupt modes: | ||
561 | * fall back to default behavior | ||
562 | */ | ||
563 | __raw_writel(mask, pio + PIO_AIMDR); | ||
564 | return 0; | ||
565 | case IRQ_TYPE_NONE: | ||
566 | default: | ||
567 | pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq)); | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | |||
571 | /* enable additional interrupt modes */ | ||
572 | __raw_writel(mask, pio + PIO_AIMER); | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
376 | static struct irq_chip gpio_irqchip = { | 577 | static struct irq_chip gpio_irqchip = { |
377 | .name = "GPIO", | 578 | .name = "GPIO", |
378 | .irq_disable = gpio_irq_mask, | 579 | .irq_disable = gpio_irq_mask, |
379 | .irq_mask = gpio_irq_mask, | 580 | .irq_mask = gpio_irq_mask, |
380 | .irq_unmask = gpio_irq_unmask, | 581 | .irq_unmask = gpio_irq_unmask, |
381 | .irq_set_type = gpio_irq_type, | 582 | /* .irq_set_type is set dynamically */ |
382 | .irq_set_wake = gpio_irq_set_wake, | 583 | .irq_set_wake = gpio_irq_set_wake, |
383 | }; | 584 | }; |
384 | 585 | ||
385 | static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) | 586 | static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) |
386 | { | 587 | { |
387 | unsigned irq_pin; | ||
388 | struct irq_data *idata = irq_desc_get_irq_data(desc); | 588 | struct irq_data *idata = irq_desc_get_irq_data(desc); |
389 | struct irq_chip *chip = irq_data_get_irq_chip(idata); | 589 | struct irq_chip *chip = irq_data_get_irq_chip(idata); |
390 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); | 590 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata); |
391 | void __iomem *pio = at91_gpio->regbase; | 591 | void __iomem *pio = at91_gpio->regbase; |
392 | u32 isr; | 592 | unsigned long isr; |
593 | int n; | ||
393 | 594 | ||
394 | /* temporarily mask (level sensitive) parent IRQ */ | 595 | /* temporarily mask (level sensitive) parent IRQ */ |
395 | chip->irq_ack(idata); | 596 | chip->irq_ack(idata); |
@@ -407,13 +608,10 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
407 | continue; | 608 | continue; |
408 | } | 609 | } |
409 | 610 | ||
410 | irq_pin = gpio_to_irq(at91_gpio->chip.base); | 611 | n = find_first_bit(&isr, BITS_PER_LONG); |
411 | 612 | while (n < BITS_PER_LONG) { | |
412 | while (isr) { | 613 | generic_handle_irq(irq_find_mapping(at91_gpio->domain, n)); |
413 | if (isr & 1) | 614 | n = find_next_bit(&isr, BITS_PER_LONG, n + 1); |
414 | generic_handle_irq(irq_pin); | ||
415 | irq_pin++; | ||
416 | isr >>= 1; | ||
417 | } | 615 | } |
418 | } | 616 | } |
419 | chip->irq_unmask(idata); | 617 | chip->irq_unmask(idata); |
@@ -424,6 +622,33 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
424 | 622 | ||
425 | #ifdef CONFIG_DEBUG_FS | 623 | #ifdef CONFIG_DEBUG_FS |
426 | 624 | ||
625 | static void gpio_printf(struct seq_file *s, void __iomem *pio, unsigned mask) | ||
626 | { | ||
627 | char *trigger = NULL; | ||
628 | char *polarity = NULL; | ||
629 | |||
630 | if (__raw_readl(pio + PIO_IMR) & mask) { | ||
631 | if (!has_pio3() || !(__raw_readl(pio + PIO_AIMMR) & mask )) { | ||
632 | trigger = "edge"; | ||
633 | polarity = "both"; | ||
634 | } else { | ||
635 | if (__raw_readl(pio + PIO_ELSR) & mask) { | ||
636 | trigger = "level"; | ||
637 | polarity = __raw_readl(pio + PIO_FRLHSR) & mask ? | ||
638 | "high" : "low"; | ||
639 | } else { | ||
640 | trigger = "edge"; | ||
641 | polarity = __raw_readl(pio + PIO_FRLHSR) & mask ? | ||
642 | "rising" : "falling"; | ||
643 | } | ||
644 | } | ||
645 | seq_printf(s, "IRQ:%s-%s\t", trigger, polarity); | ||
646 | } else { | ||
647 | seq_printf(s, "GPIO:%s\t\t", | ||
648 | __raw_readl(pio + PIO_PDSR) & mask ? "1" : "0"); | ||
649 | } | ||
650 | } | ||
651 | |||
427 | static int at91_gpio_show(struct seq_file *s, void *unused) | 652 | static int at91_gpio_show(struct seq_file *s, void *unused) |
428 | { | 653 | { |
429 | int bank, j; | 654 | int bank, j; |
@@ -431,7 +656,7 @@ static int at91_gpio_show(struct seq_file *s, void *unused) | |||
431 | /* print heading */ | 656 | /* print heading */ |
432 | seq_printf(s, "Pin\t"); | 657 | seq_printf(s, "Pin\t"); |
433 | for (bank = 0; bank < gpio_banks; bank++) { | 658 | for (bank = 0; bank < gpio_banks; bank++) { |
434 | seq_printf(s, "PIO%c\t", 'A' + bank); | 659 | seq_printf(s, "PIO%c\t\t", 'A' + bank); |
435 | }; | 660 | }; |
436 | seq_printf(s, "\n\n"); | 661 | seq_printf(s, "\n\n"); |
437 | 662 | ||
@@ -445,11 +670,10 @@ static int at91_gpio_show(struct seq_file *s, void *unused) | |||
445 | unsigned mask = pin_to_mask(pin); | 670 | unsigned mask = pin_to_mask(pin); |
446 | 671 | ||
447 | if (__raw_readl(pio + PIO_PSR) & mask) | 672 | if (__raw_readl(pio + PIO_PSR) & mask) |
448 | seq_printf(s, "GPIO:%s", __raw_readl(pio + PIO_PDSR) & mask ? "1" : "0"); | 673 | gpio_printf(s, pio, mask); |
449 | else | 674 | else |
450 | seq_printf(s, "%s", __raw_readl(pio + PIO_ABSR) & mask ? "B" : "A"); | 675 | seq_printf(s, "%c\t\t", |
451 | 676 | peripheral_function(pio, mask)); | |
452 | seq_printf(s, "\t"); | ||
453 | } | 677 | } |
454 | 678 | ||
455 | seq_printf(s, "\n"); | 679 | seq_printf(s, "\n"); |
@@ -488,46 +712,152 @@ postcore_initcall(at91_gpio_debugfs_init); | |||
488 | */ | 712 | */ |
489 | static struct lock_class_key gpio_lock_class; | 713 | static struct lock_class_key gpio_lock_class; |
490 | 714 | ||
715 | #if defined(CONFIG_OF) | ||
716 | static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq, | ||
717 | irq_hw_number_t hw) | ||
718 | { | ||
719 | struct at91_gpio_chip *at91_gpio = h->host_data; | ||
720 | |||
721 | irq_set_lockdep_class(virq, &gpio_lock_class); | ||
722 | |||
723 | /* | ||
724 | * Can use the "simple" and not "edge" handler since it's | ||
725 | * shorter, and the AIC handles interrupts sanely. | ||
726 | */ | ||
727 | irq_set_chip_and_handler(virq, &gpio_irqchip, | ||
728 | handle_simple_irq); | ||
729 | set_irq_flags(virq, IRQF_VALID); | ||
730 | irq_set_chip_data(virq, at91_gpio); | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static struct irq_domain_ops at91_gpio_ops = { | ||
736 | .map = at91_gpio_irq_map, | ||
737 | .xlate = irq_domain_xlate_twocell, | ||
738 | }; | ||
739 | |||
740 | int __init at91_gpio_of_irq_setup(struct device_node *node, | ||
741 | struct device_node *parent) | ||
742 | { | ||
743 | struct at91_gpio_chip *prev = NULL; | ||
744 | int alias_idx = of_alias_get_id(node, "gpio"); | ||
745 | struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx]; | ||
746 | |||
747 | /* Setup proper .irq_set_type function */ | ||
748 | if (has_pio3()) | ||
749 | gpio_irqchip.irq_set_type = alt_gpio_irq_type; | ||
750 | else | ||
751 | gpio_irqchip.irq_set_type = gpio_irq_type; | ||
752 | |||
753 | /* Disable irqs of this PIO controller */ | ||
754 | __raw_writel(~0, at91_gpio->regbase + PIO_IDR); | ||
755 | |||
756 | /* Setup irq domain */ | ||
757 | at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio, | ||
758 | &at91_gpio_ops, at91_gpio); | ||
759 | if (!at91_gpio->domain) | ||
760 | panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n", | ||
761 | at91_gpio->pioc_idx); | ||
762 | |||
763 | /* Setup chained handler */ | ||
764 | if (at91_gpio->pioc_idx) | ||
765 | prev = &gpio_chip[at91_gpio->pioc_idx - 1]; | ||
766 | |||
767 | /* The toplevel handler handles one bank of GPIOs, except | ||
768 | * on some SoC it can handles up to three... | ||
769 | * We only set up the handler for the first of the list. | ||
770 | */ | ||
771 | if (prev && prev->next == at91_gpio) | ||
772 | return 0; | ||
773 | |||
774 | at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent), | ||
775 | at91_gpio->pioc_hwirq); | ||
776 | irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio); | ||
777 | irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler); | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | #else | ||
782 | int __init at91_gpio_of_irq_setup(struct device_node *node, | ||
783 | struct device_node *parent) | ||
784 | { | ||
785 | return -EINVAL; | ||
786 | } | ||
787 | #endif | ||
788 | |||
789 | /* | ||
790 | * irqdomain initialization: pile up irqdomains on top of AIC range | ||
791 | */ | ||
792 | static void __init at91_gpio_irqdomain(struct at91_gpio_chip *at91_gpio) | ||
793 | { | ||
794 | int irq_base; | ||
795 | |||
796 | irq_base = irq_alloc_descs(-1, 0, at91_gpio->chip.ngpio, 0); | ||
797 | if (irq_base < 0) | ||
798 | panic("at91_gpio.%d: error %d: couldn't allocate IRQ numbers.\n", | ||
799 | at91_gpio->pioc_idx, irq_base); | ||
800 | at91_gpio->domain = irq_domain_add_legacy(NULL, at91_gpio->chip.ngpio, | ||
801 | irq_base, 0, | ||
802 | &irq_domain_simple_ops, NULL); | ||
803 | if (!at91_gpio->domain) | ||
804 | panic("at91_gpio.%d: couldn't allocate irq domain.\n", | ||
805 | at91_gpio->pioc_idx); | ||
806 | } | ||
807 | |||
491 | /* | 808 | /* |
492 | * Called from the processor-specific init to enable GPIO interrupt support. | 809 | * Called from the processor-specific init to enable GPIO interrupt support. |
493 | */ | 810 | */ |
494 | void __init at91_gpio_irq_setup(void) | 811 | void __init at91_gpio_irq_setup(void) |
495 | { | 812 | { |
496 | unsigned pioc, irq = gpio_to_irq(0); | 813 | unsigned pioc; |
814 | int gpio_irqnbr = 0; | ||
497 | struct at91_gpio_chip *this, *prev; | 815 | struct at91_gpio_chip *this, *prev; |
498 | 816 | ||
817 | /* Setup proper .irq_set_type function */ | ||
818 | if (has_pio3()) | ||
819 | gpio_irqchip.irq_set_type = alt_gpio_irq_type; | ||
820 | else | ||
821 | gpio_irqchip.irq_set_type = gpio_irq_type; | ||
822 | |||
499 | for (pioc = 0, this = gpio_chip, prev = NULL; | 823 | for (pioc = 0, this = gpio_chip, prev = NULL; |
500 | pioc++ < gpio_banks; | 824 | pioc++ < gpio_banks; |
501 | prev = this, this++) { | 825 | prev = this, this++) { |
502 | unsigned id = this->id; | 826 | int offset; |
503 | unsigned i; | ||
504 | 827 | ||
505 | __raw_writel(~0, this->regbase + PIO_IDR); | 828 | __raw_writel(~0, this->regbase + PIO_IDR); |
506 | 829 | ||
507 | for (i = 0, irq = gpio_to_irq(this->chip.base); i < 32; | 830 | /* setup irq domain for this GPIO controller */ |
508 | i++, irq++) { | 831 | at91_gpio_irqdomain(this); |
509 | irq_set_lockdep_class(irq, &gpio_lock_class); | 832 | |
833 | for (offset = 0; offset < this->chip.ngpio; offset++) { | ||
834 | unsigned int virq = irq_find_mapping(this->domain, offset); | ||
835 | irq_set_lockdep_class(virq, &gpio_lock_class); | ||
510 | 836 | ||
511 | /* | 837 | /* |
512 | * Can use the "simple" and not "edge" handler since it's | 838 | * Can use the "simple" and not "edge" handler since it's |
513 | * shorter, and the AIC handles interrupts sanely. | 839 | * shorter, and the AIC handles interrupts sanely. |
514 | */ | 840 | */ |
515 | irq_set_chip_and_handler(irq, &gpio_irqchip, | 841 | irq_set_chip_and_handler(virq, &gpio_irqchip, |
516 | handle_simple_irq); | 842 | handle_simple_irq); |
517 | set_irq_flags(irq, IRQF_VALID); | 843 | set_irq_flags(virq, IRQF_VALID); |
844 | irq_set_chip_data(virq, this); | ||
845 | |||
846 | gpio_irqnbr++; | ||
518 | } | 847 | } |
519 | 848 | ||
520 | /* The toplevel handler handles one bank of GPIOs, except | 849 | /* The toplevel handler handles one bank of GPIOs, except |
521 | * AT91SAM9263_ID_PIOCDE handles three... PIOC is first in | 850 | * on some SoC it can handles up to three... |
522 | * the list, so we only set up that handler. | 851 | * We only set up the handler for the first of the list. |
523 | */ | 852 | */ |
524 | if (prev && prev->next == this) | 853 | if (prev && prev->next == this) |
525 | continue; | 854 | continue; |
526 | 855 | ||
527 | irq_set_chip_data(id, this); | 856 | this->pioc_virq = irq_create_mapping(NULL, this->pioc_hwirq); |
528 | irq_set_chained_handler(id, gpio_irq_handler); | 857 | irq_set_chip_data(this->pioc_virq, this); |
858 | irq_set_chained_handler(this->pioc_virq, gpio_irq_handler); | ||
529 | } | 859 | } |
530 | pr_info("AT91: %d gpio irqs in %d banks\n", irq - gpio_to_irq(0), gpio_banks); | 860 | pr_info("AT91: %d gpio irqs in %d banks\n", gpio_irqnbr, gpio_banks); |
531 | } | 861 | } |
532 | 862 | ||
533 | /* gpiolib support */ | 863 | /* gpiolib support */ |
@@ -593,48 +923,175 @@ static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
593 | at91_get_gpio_value(pin) ? | 923 | at91_get_gpio_value(pin) ? |
594 | "set" : "clear"); | 924 | "set" : "clear"); |
595 | else | 925 | else |
596 | seq_printf(s, "[periph %s]\n", | 926 | seq_printf(s, "[periph %c]\n", |
597 | __raw_readl(pio + PIO_ABSR) & | 927 | peripheral_function(pio, mask)); |
598 | mask ? "B" : "A"); | ||
599 | } | 928 | } |
600 | } | 929 | } |
601 | } | 930 | } |
602 | 931 | ||
932 | static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset) | ||
933 | { | ||
934 | struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); | ||
935 | int virq; | ||
936 | |||
937 | if (offset < chip->ngpio) | ||
938 | virq = irq_create_mapping(at91_gpio->domain, offset); | ||
939 | else | ||
940 | virq = -ENXIO; | ||
941 | |||
942 | dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n", | ||
943 | chip->label, offset + chip->base, virq); | ||
944 | return virq; | ||
945 | } | ||
946 | |||
947 | static int __init at91_gpio_setup_clk(int idx) | ||
948 | { | ||
949 | struct at91_gpio_chip *at91_gpio = &gpio_chip[idx]; | ||
950 | |||
951 | /* retreive PIO controller's clock */ | ||
952 | at91_gpio->clock = clk_get_sys(NULL, at91_gpio->chip.label); | ||
953 | if (IS_ERR(at91_gpio->clock)) { | ||
954 | pr_err("at91_gpio.%d, failed to get clock, ignoring.\n", idx); | ||
955 | goto err; | ||
956 | } | ||
957 | |||
958 | if (clk_prepare(at91_gpio->clock)) | ||
959 | goto clk_prep_err; | ||
960 | |||
961 | /* enable PIO controller's clock */ | ||
962 | if (clk_enable(at91_gpio->clock)) { | ||
963 | pr_err("at91_gpio.%d, failed to enable clock, ignoring.\n", idx); | ||
964 | goto clk_err; | ||
965 | } | ||
966 | |||
967 | return 0; | ||
968 | |||
969 | clk_err: | ||
970 | clk_unprepare(at91_gpio->clock); | ||
971 | clk_prep_err: | ||
972 | clk_put(at91_gpio->clock); | ||
973 | err: | ||
974 | return -EINVAL; | ||
975 | } | ||
976 | |||
977 | #ifdef CONFIG_OF_GPIO | ||
978 | static void __init of_at91_gpio_init_one(struct device_node *np) | ||
979 | { | ||
980 | int alias_idx; | ||
981 | struct at91_gpio_chip *at91_gpio; | ||
982 | |||
983 | if (!np) | ||
984 | return; | ||
985 | |||
986 | alias_idx = of_alias_get_id(np, "gpio"); | ||
987 | if (alias_idx >= MAX_GPIO_BANKS) { | ||
988 | pr_err("at91_gpio, failed alias idx(%d) > MAX_GPIO_BANKS(%d), ignoring.\n", | ||
989 | alias_idx, MAX_GPIO_BANKS); | ||
990 | return; | ||
991 | } | ||
992 | |||
993 | at91_gpio = &gpio_chip[alias_idx]; | ||
994 | at91_gpio->chip.base = alias_idx * at91_gpio->chip.ngpio; | ||
995 | |||
996 | at91_gpio->regbase = of_iomap(np, 0); | ||
997 | if (!at91_gpio->regbase) { | ||
998 | pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", | ||
999 | alias_idx); | ||
1000 | return; | ||
1001 | } | ||
1002 | |||
1003 | /* Get the interrupts property */ | ||
1004 | if (of_property_read_u32(np, "interrupts", &at91_gpio->pioc_hwirq)) { | ||
1005 | pr_err("at91_gpio.%d, failed to get interrupts property, ignoring.\n", | ||
1006 | alias_idx); | ||
1007 | goto ioremap_err; | ||
1008 | } | ||
1009 | |||
1010 | /* Get capabilities from compatibility property */ | ||
1011 | if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio")) | ||
1012 | at91_gpio_caps |= AT91_GPIO_CAP_PIO3; | ||
1013 | |||
1014 | /* Setup clock */ | ||
1015 | if (at91_gpio_setup_clk(alias_idx)) | ||
1016 | goto ioremap_err; | ||
1017 | |||
1018 | at91_gpio->chip.of_node = np; | ||
1019 | gpio_banks = max(gpio_banks, alias_idx + 1); | ||
1020 | at91_gpio->pioc_idx = alias_idx; | ||
1021 | return; | ||
1022 | |||
1023 | ioremap_err: | ||
1024 | iounmap(at91_gpio->regbase); | ||
1025 | } | ||
1026 | |||
1027 | static int __init of_at91_gpio_init(void) | ||
1028 | { | ||
1029 | struct device_node *np = NULL; | ||
1030 | |||
1031 | /* | ||
1032 | * This isn't ideal, but it gets things hooked up until this | ||
1033 | * driver is converted into a platform_device | ||
1034 | */ | ||
1035 | for_each_compatible_node(np, NULL, "atmel,at91rm9200-gpio") | ||
1036 | of_at91_gpio_init_one(np); | ||
1037 | |||
1038 | return gpio_banks > 0 ? 0 : -EINVAL; | ||
1039 | } | ||
1040 | #else | ||
1041 | static int __init of_at91_gpio_init(void) | ||
1042 | { | ||
1043 | return -EINVAL; | ||
1044 | } | ||
1045 | #endif | ||
1046 | |||
1047 | static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq) | ||
1048 | { | ||
1049 | struct at91_gpio_chip *at91_gpio = &gpio_chip[idx]; | ||
1050 | |||
1051 | at91_gpio->chip.base = idx * at91_gpio->chip.ngpio; | ||
1052 | at91_gpio->pioc_hwirq = pioc_hwirq; | ||
1053 | at91_gpio->pioc_idx = idx; | ||
1054 | |||
1055 | at91_gpio->regbase = ioremap(regbase, 512); | ||
1056 | if (!at91_gpio->regbase) { | ||
1057 | pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", idx); | ||
1058 | return; | ||
1059 | } | ||
1060 | |||
1061 | if (at91_gpio_setup_clk(idx)) | ||
1062 | goto ioremap_err; | ||
1063 | |||
1064 | gpio_banks = max(gpio_banks, idx + 1); | ||
1065 | return; | ||
1066 | |||
1067 | ioremap_err: | ||
1068 | iounmap(at91_gpio->regbase); | ||
1069 | } | ||
1070 | |||
603 | /* | 1071 | /* |
604 | * Called from the processor-specific init to enable GPIO pin support. | 1072 | * Called from the processor-specific init to enable GPIO pin support. |
605 | */ | 1073 | */ |
606 | void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) | 1074 | void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) |
607 | { | 1075 | { |
608 | unsigned i; | 1076 | unsigned i; |
609 | struct at91_gpio_chip *at91_gpio, *last = NULL; | 1077 | struct at91_gpio_chip *at91_gpio, *last = NULL; |
610 | 1078 | ||
611 | BUG_ON(nr_banks > MAX_GPIO_BANKS); | 1079 | BUG_ON(nr_banks > MAX_GPIO_BANKS); |
612 | 1080 | ||
613 | gpio_banks = nr_banks; | 1081 | if (of_at91_gpio_init() < 0) { |
1082 | /* No GPIO controller found in device tree */ | ||
1083 | for (i = 0; i < nr_banks; i++) | ||
1084 | at91_gpio_init_one(i, data[i].regbase, data[i].id); | ||
1085 | } | ||
614 | 1086 | ||
615 | for (i = 0; i < nr_banks; i++) { | 1087 | for (i = 0; i < gpio_banks; i++) { |
616 | at91_gpio = &gpio_chip[i]; | 1088 | at91_gpio = &gpio_chip[i]; |
617 | 1089 | ||
618 | at91_gpio->id = data[i].id; | 1090 | /* |
619 | at91_gpio->chip.base = i * 32; | 1091 | * GPIO controller are grouped on some SoC: |
620 | 1092 | * PIOC, PIOD and PIOE can share the same IRQ line | |
621 | at91_gpio->regbase = ioremap(data[i].regbase, 512); | 1093 | */ |
622 | if (!at91_gpio->regbase) { | 1094 | if (last && last->pioc_hwirq == at91_gpio->pioc_hwirq) |
623 | pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", i); | ||
624 | continue; | ||
625 | } | ||
626 | |||
627 | at91_gpio->clock = clk_get_sys(NULL, at91_gpio->chip.label); | ||
628 | if (!at91_gpio->clock) { | ||
629 | pr_err("at91_gpio.%d, failed to get clock, ignoring.\n", i); | ||
630 | continue; | ||
631 | } | ||
632 | |||
633 | /* enable PIO controller's clock */ | ||
634 | clk_enable(at91_gpio->clock); | ||
635 | |||
636 | /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */ | ||
637 | if (last && last->id == at91_gpio->id) | ||
638 | last->next = at91_gpio; | 1095 | last->next = at91_gpio; |
639 | last = at91_gpio; | 1096 | last = at91_gpio; |
640 | 1097 | ||
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h index c6a31bf8a5c6..732b11c37f1a 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h | |||
@@ -40,10 +40,35 @@ | |||
40 | #define PIO_PUER 0x64 /* Pull-up Enable Register */ | 40 | #define PIO_PUER 0x64 /* Pull-up Enable Register */ |
41 | #define PIO_PUSR 0x68 /* Pull-up Status Register */ | 41 | #define PIO_PUSR 0x68 /* Pull-up Status Register */ |
42 | #define PIO_ASR 0x70 /* Peripheral A Select Register */ | 42 | #define PIO_ASR 0x70 /* Peripheral A Select Register */ |
43 | #define PIO_ABCDSR1 0x70 /* Peripheral ABCD Select Register 1 [some sam9 only] */ | ||
43 | #define PIO_BSR 0x74 /* Peripheral B Select Register */ | 44 | #define PIO_BSR 0x74 /* Peripheral B Select Register */ |
45 | #define PIO_ABCDSR2 0x74 /* Peripheral ABCD Select Register 2 [some sam9 only] */ | ||
44 | #define PIO_ABSR 0x78 /* AB Status Register */ | 46 | #define PIO_ABSR 0x78 /* AB Status Register */ |
47 | #define PIO_IFSCDR 0x80 /* Input Filter Slow Clock Disable Register */ | ||
48 | #define PIO_IFSCER 0x84 /* Input Filter Slow Clock Enable Register */ | ||
49 | #define PIO_IFSCSR 0x88 /* Input Filter Slow Clock Status Register */ | ||
50 | #define PIO_SCDR 0x8c /* Slow Clock Divider Debouncing Register */ | ||
51 | #define PIO_SCDR_DIV (0x3fff << 0) /* Slow Clock Divider Mask */ | ||
52 | #define PIO_PPDDR 0x90 /* Pad Pull-down Disable Register */ | ||
53 | #define PIO_PPDER 0x94 /* Pad Pull-down Enable Register */ | ||
54 | #define PIO_PPDSR 0x98 /* Pad Pull-down Status Register */ | ||
45 | #define PIO_OWER 0xa0 /* Output Write Enable Register */ | 55 | #define PIO_OWER 0xa0 /* Output Write Enable Register */ |
46 | #define PIO_OWDR 0xa4 /* Output Write Disable Register */ | 56 | #define PIO_OWDR 0xa4 /* Output Write Disable Register */ |
47 | #define PIO_OWSR 0xa8 /* Output Write Status Register */ | 57 | #define PIO_OWSR 0xa8 /* Output Write Status Register */ |
58 | #define PIO_AIMER 0xb0 /* Additional Interrupt Modes Enable Register */ | ||
59 | #define PIO_AIMDR 0xb4 /* Additional Interrupt Modes Disable Register */ | ||
60 | #define PIO_AIMMR 0xb8 /* Additional Interrupt Modes Mask Register */ | ||
61 | #define PIO_ESR 0xc0 /* Edge Select Register */ | ||
62 | #define PIO_LSR 0xc4 /* Level Select Register */ | ||
63 | #define PIO_ELSR 0xc8 /* Edge/Level Status Register */ | ||
64 | #define PIO_FELLSR 0xd0 /* Falling Edge/Low Level Select Register */ | ||
65 | #define PIO_REHLSR 0xd4 /* Rising Edge/ High Level Select Register */ | ||
66 | #define PIO_FRLHSR 0xd8 /* Fall/Rise - Low/High Status Register */ | ||
67 | #define PIO_SCHMITT 0x100 /* Schmitt Trigger Register */ | ||
68 | |||
69 | #define ABCDSR_PERIPH_A 0x0 | ||
70 | #define ABCDSR_PERIPH_B 0x1 | ||
71 | #define ABCDSR_PERIPH_C 0x2 | ||
72 | #define ABCDSR_PERIPH_D 0x3 | ||
48 | 73 | ||
49 | #endif | 74 | #endif |
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index e3fd225121c7..eed465ab0dd7 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h | |||
@@ -191,10 +191,15 @@ | |||
191 | extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup); | 191 | extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup); |
192 | extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup); | 192 | extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup); |
193 | extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup); | 193 | extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup); |
194 | extern int __init_or_module at91_set_C_periph(unsigned pin, int use_pullup); | ||
195 | extern int __init_or_module at91_set_D_periph(unsigned pin, int use_pullup); | ||
194 | extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup); | 196 | extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup); |
195 | extern int __init_or_module at91_set_gpio_output(unsigned pin, int value); | 197 | extern int __init_or_module at91_set_gpio_output(unsigned pin, int value); |
196 | extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on); | 198 | extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on); |
199 | extern int __init_or_module at91_set_debounce(unsigned pin, int is_on, int div); | ||
197 | extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on); | 200 | extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on); |
201 | extern int __init_or_module at91_set_pulldown(unsigned pin, int is_on); | ||
202 | extern int __init_or_module at91_disable_schmitt_trig(unsigned pin); | ||
198 | 203 | ||
199 | /* callable at any time */ | 204 | /* callable at any time */ |
200 | extern int at91_set_gpio_value(unsigned pin, int value); | 205 | extern int at91_set_gpio_value(unsigned pin, int value); |
@@ -204,18 +209,6 @@ extern int at91_get_gpio_value(unsigned pin); | |||
204 | extern void at91_gpio_suspend(void); | 209 | extern void at91_gpio_suspend(void); |
205 | extern void at91_gpio_resume(void); | 210 | extern void at91_gpio_resume(void); |
206 | 211 | ||
207 | /*-------------------------------------------------------------------------*/ | ||
208 | |||
209 | /* wrappers for "new style" GPIO calls. the old AT91-specific ones should | ||
210 | * eventually be removed (along with this errno.h inclusion), and the | ||
211 | * gpio request/free calls should probably be implemented. | ||
212 | */ | ||
213 | |||
214 | #include <asm/errno.h> | ||
215 | |||
216 | #define gpio_to_irq(gpio) (gpio + NR_AIC_IRQS) | ||
217 | #define irq_to_gpio(irq) (irq - NR_AIC_IRQS) | ||
218 | |||
219 | #endif /* __ASSEMBLY__ */ | 212 | #endif /* __ASSEMBLY__ */ |
220 | 213 | ||
221 | #endif | 214 | #endif |
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c index be6b639ecd7b..cfcfcbe36269 100644 --- a/arch/arm/mach-at91/irq.c +++ b/arch/arm/mach-at91/irq.c | |||
@@ -24,6 +24,12 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/irq.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_address.h> | ||
30 | #include <linux/of_irq.h> | ||
31 | #include <linux/irqdomain.h> | ||
32 | #include <linux/err.h> | ||
27 | 33 | ||
28 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
29 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
@@ -34,22 +40,24 @@ | |||
34 | #include <asm/mach/map.h> | 40 | #include <asm/mach/map.h> |
35 | 41 | ||
36 | void __iomem *at91_aic_base; | 42 | void __iomem *at91_aic_base; |
43 | static struct irq_domain *at91_aic_domain; | ||
44 | static struct device_node *at91_aic_np; | ||
37 | 45 | ||
38 | static void at91_aic_mask_irq(struct irq_data *d) | 46 | static void at91_aic_mask_irq(struct irq_data *d) |
39 | { | 47 | { |
40 | /* Disable interrupt on AIC */ | 48 | /* Disable interrupt on AIC */ |
41 | at91_aic_write(AT91_AIC_IDCR, 1 << d->irq); | 49 | at91_aic_write(AT91_AIC_IDCR, 1 << d->hwirq); |
42 | } | 50 | } |
43 | 51 | ||
44 | static void at91_aic_unmask_irq(struct irq_data *d) | 52 | static void at91_aic_unmask_irq(struct irq_data *d) |
45 | { | 53 | { |
46 | /* Enable interrupt on AIC */ | 54 | /* Enable interrupt on AIC */ |
47 | at91_aic_write(AT91_AIC_IECR, 1 << d->irq); | 55 | at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq); |
48 | } | 56 | } |
49 | 57 | ||
50 | unsigned int at91_extern_irq; | 58 | unsigned int at91_extern_irq; |
51 | 59 | ||
52 | #define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq) | 60 | #define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq) |
53 | 61 | ||
54 | static int at91_aic_set_type(struct irq_data *d, unsigned type) | 62 | static int at91_aic_set_type(struct irq_data *d, unsigned type) |
55 | { | 63 | { |
@@ -63,13 +71,13 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type) | |||
63 | srctype = AT91_AIC_SRCTYPE_RISING; | 71 | srctype = AT91_AIC_SRCTYPE_RISING; |
64 | break; | 72 | break; |
65 | case IRQ_TYPE_LEVEL_LOW: | 73 | case IRQ_TYPE_LEVEL_LOW: |
66 | if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq)) /* only supported on external interrupts */ | 74 | if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */ |
67 | srctype = AT91_AIC_SRCTYPE_LOW; | 75 | srctype = AT91_AIC_SRCTYPE_LOW; |
68 | else | 76 | else |
69 | return -EINVAL; | 77 | return -EINVAL; |
70 | break; | 78 | break; |
71 | case IRQ_TYPE_EDGE_FALLING: | 79 | case IRQ_TYPE_EDGE_FALLING: |
72 | if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq)) /* only supported on external interrupts */ | 80 | if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq)) /* only supported on external interrupts */ |
73 | srctype = AT91_AIC_SRCTYPE_FALLING; | 81 | srctype = AT91_AIC_SRCTYPE_FALLING; |
74 | else | 82 | else |
75 | return -EINVAL; | 83 | return -EINVAL; |
@@ -78,8 +86,8 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type) | |||
78 | return -EINVAL; | 86 | return -EINVAL; |
79 | } | 87 | } |
80 | 88 | ||
81 | smr = at91_aic_read(AT91_AIC_SMR(d->irq)) & ~AT91_AIC_SRCTYPE; | 89 | smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE; |
82 | at91_aic_write(AT91_AIC_SMR(d->irq), smr | srctype); | 90 | at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype); |
83 | return 0; | 91 | return 0; |
84 | } | 92 | } |
85 | 93 | ||
@@ -90,13 +98,13 @@ static u32 backups; | |||
90 | 98 | ||
91 | static int at91_aic_set_wake(struct irq_data *d, unsigned value) | 99 | static int at91_aic_set_wake(struct irq_data *d, unsigned value) |
92 | { | 100 | { |
93 | if (unlikely(d->irq >= 32)) | 101 | if (unlikely(d->hwirq >= NR_AIC_IRQS)) |
94 | return -EINVAL; | 102 | return -EINVAL; |
95 | 103 | ||
96 | if (value) | 104 | if (value) |
97 | wakeups |= (1 << d->irq); | 105 | wakeups |= (1 << d->hwirq); |
98 | else | 106 | else |
99 | wakeups &= ~(1 << d->irq); | 107 | wakeups &= ~(1 << d->hwirq); |
100 | 108 | ||
101 | return 0; | 109 | return 0; |
102 | } | 110 | } |
@@ -127,46 +135,112 @@ static struct irq_chip at91_aic_chip = { | |||
127 | .irq_set_wake = at91_aic_set_wake, | 135 | .irq_set_wake = at91_aic_set_wake, |
128 | }; | 136 | }; |
129 | 137 | ||
138 | static void __init at91_aic_hw_init(unsigned int spu_vector) | ||
139 | { | ||
140 | int i; | ||
141 | |||
142 | /* | ||
143 | * Perform 8 End Of Interrupt Command to make sure AIC | ||
144 | * will not Lock out nIRQ | ||
145 | */ | ||
146 | for (i = 0; i < 8; i++) | ||
147 | at91_aic_write(AT91_AIC_EOICR, 0); | ||
148 | |||
149 | /* | ||
150 | * Spurious Interrupt ID in Spurious Vector Register. | ||
151 | * When there is no current interrupt, the IRQ Vector Register | ||
152 | * reads the value stored in AIC_SPU | ||
153 | */ | ||
154 | at91_aic_write(AT91_AIC_SPU, spu_vector); | ||
155 | |||
156 | /* No debugging in AIC: Debug (Protect) Control Register */ | ||
157 | at91_aic_write(AT91_AIC_DCR, 0); | ||
158 | |||
159 | /* Disable and clear all interrupts initially */ | ||
160 | at91_aic_write(AT91_AIC_IDCR, 0xFFFFFFFF); | ||
161 | at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF); | ||
162 | } | ||
163 | |||
164 | #if defined(CONFIG_OF) | ||
165 | static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq, | ||
166 | irq_hw_number_t hw) | ||
167 | { | ||
168 | /* Put virq number in Source Vector Register */ | ||
169 | at91_aic_write(AT91_AIC_SVR(hw), virq); | ||
170 | |||
171 | /* Active Low interrupt, without priority */ | ||
172 | at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW); | ||
173 | |||
174 | irq_set_chip_and_handler(virq, &at91_aic_chip, handle_level_irq); | ||
175 | set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct irq_domain_ops at91_aic_irq_ops = { | ||
181 | .map = at91_aic_irq_map, | ||
182 | .xlate = irq_domain_xlate_twocell, | ||
183 | }; | ||
184 | |||
185 | int __init at91_aic_of_init(struct device_node *node, | ||
186 | struct device_node *parent) | ||
187 | { | ||
188 | at91_aic_base = of_iomap(node, 0); | ||
189 | at91_aic_np = node; | ||
190 | |||
191 | at91_aic_domain = irq_domain_add_linear(at91_aic_np, NR_AIC_IRQS, | ||
192 | &at91_aic_irq_ops, NULL); | ||
193 | if (!at91_aic_domain) | ||
194 | panic("Unable to add AIC irq domain (DT)\n"); | ||
195 | |||
196 | irq_set_default_host(at91_aic_domain); | ||
197 | |||
198 | at91_aic_hw_init(NR_AIC_IRQS); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | #endif | ||
203 | |||
130 | /* | 204 | /* |
131 | * Initialize the AIC interrupt controller. | 205 | * Initialize the AIC interrupt controller. |
132 | */ | 206 | */ |
133 | void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) | 207 | void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) |
134 | { | 208 | { |
135 | unsigned int i; | 209 | unsigned int i; |
210 | int irq_base; | ||
136 | 211 | ||
137 | at91_aic_base = ioremap(AT91_AIC, 512); | 212 | at91_aic_base = ioremap(AT91_AIC, 512); |
138 | |||
139 | if (!at91_aic_base) | 213 | if (!at91_aic_base) |
140 | panic("Impossible to ioremap AT91_AIC\n"); | 214 | panic("Unable to ioremap AIC registers\n"); |
215 | |||
216 | /* Add irq domain for AIC */ | ||
217 | irq_base = irq_alloc_descs(-1, 0, NR_AIC_IRQS, 0); | ||
218 | if (irq_base < 0) { | ||
219 | WARN(1, "Cannot allocate irq_descs, assuming pre-allocated\n"); | ||
220 | irq_base = 0; | ||
221 | } | ||
222 | at91_aic_domain = irq_domain_add_legacy(at91_aic_np, NR_AIC_IRQS, | ||
223 | irq_base, 0, | ||
224 | &irq_domain_simple_ops, NULL); | ||
225 | |||
226 | if (!at91_aic_domain) | ||
227 | panic("Unable to add AIC irq domain\n"); | ||
228 | |||
229 | irq_set_default_host(at91_aic_domain); | ||
141 | 230 | ||
142 | /* | 231 | /* |
143 | * The IVR is used by macro get_irqnr_and_base to read and verify. | 232 | * The IVR is used by macro get_irqnr_and_base to read and verify. |
144 | * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred. | 233 | * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred. |
145 | */ | 234 | */ |
146 | for (i = 0; i < NR_AIC_IRQS; i++) { | 235 | for (i = 0; i < NR_AIC_IRQS; i++) { |
147 | /* Put irq number in Source Vector Register: */ | 236 | /* Put hardware irq number in Source Vector Register: */ |
148 | at91_aic_write(AT91_AIC_SVR(i), i); | 237 | at91_aic_write(AT91_AIC_SVR(i), i); |
149 | /* Active Low interrupt, with the specified priority */ | 238 | /* Active Low interrupt, with the specified priority */ |
150 | at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); | 239 | at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); |
151 | 240 | ||
152 | irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq); | 241 | irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq); |
153 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); | 242 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); |
154 | |||
155 | /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */ | ||
156 | if (i < 8) | ||
157 | at91_aic_write(AT91_AIC_EOICR, 0); | ||
158 | } | 243 | } |
159 | 244 | ||
160 | /* | 245 | at91_aic_hw_init(NR_AIC_IRQS); |
161 | * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS | ||
162 | * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU | ||
163 | */ | ||
164 | at91_aic_write(AT91_AIC_SPU, NR_AIC_IRQS); | ||
165 | |||
166 | /* No debugging in AIC: Debug (Protect) Control Register */ | ||
167 | at91_aic_write(AT91_AIC_DCR, 0); | ||
168 | |||
169 | /* Disable and clear all interrupts initially */ | ||
170 | at91_aic_write(AT91_AIC_IDCR, 0xFFFFFFFF); | ||
171 | at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF); | ||
172 | } | 246 | } |