diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2012-09-27 12:07:25 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-09-27 12:07:25 -0400 |
commit | 35a041e77ab5faad7916b8f77fae0b34b9fa7878 (patch) | |
tree | d1ea4e68087d5d4b1c64e1aa6f5833aadfe41645 /arch/mips | |
parent | e33fd70baea1032a62b1a2a051ea4c07a1aaa402 (diff) | |
parent | c9e854cf940fbc09846c255895efceb3bc9bf095 (diff) |
Merge branch 'lantiq' of git://dev.phrozen.org/mips-next into mips-for-linux-next
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/Kconfig | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h | 4 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-lantiq/gpio.h | 5 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h | 2 | ||||
-rw-r--r-- | arch/mips/lantiq/Kconfig | 2 | ||||
-rw-r--r-- | arch/mips/lantiq/falcon/prom.c | 5 | ||||
-rw-r--r-- | arch/mips/lantiq/falcon/sysctrl.c | 1 | ||||
-rw-r--r-- | arch/mips/lantiq/irq.c | 82 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/gpio.c | 183 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/gptu.c | 214 | ||||
-rw-r--r-- | arch/mips/lantiq/xway/sysctrl.c | 3 |
13 files changed, 287 insertions, 220 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 386ff651ecaf..c0cbde6c1770 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -242,6 +242,8 @@ config LANTIQ | |||
242 | select HAVE_MACH_CLKDEV | 242 | select HAVE_MACH_CLKDEV |
243 | select CLKDEV_LOOKUP | 243 | select CLKDEV_LOOKUP |
244 | select USE_OF | 244 | select USE_OF |
245 | select PINCTRL | ||
246 | select PINCTRL_LANTIQ | ||
245 | 247 | ||
246 | config LASAT | 248 | config LASAT |
247 | bool "LASAT Networks platforms" | 249 | bool "LASAT Networks platforms" |
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h index 318f982f04ff..c6b63a409641 100644 --- a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h +++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h | |||
@@ -20,4 +20,6 @@ | |||
20 | 20 | ||
21 | #define MIPS_CPU_TIMER_IRQ 7 | 21 | #define MIPS_CPU_TIMER_IRQ 7 |
22 | 22 | ||
23 | #define MAX_IM 5 | ||
24 | |||
23 | #endif /* _FALCON_IRQ__ */ | 25 | #endif /* _FALCON_IRQ__ */ |
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h index b385252584ee..fccac3592651 100644 --- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h | |||
@@ -57,6 +57,10 @@ extern __iomem void *ltq_sys1_membase; | |||
57 | #define ltq_sys1_w32_mask(clear, set, reg) \ | 57 | #define ltq_sys1_w32_mask(clear, set, reg) \ |
58 | ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg) | 58 | ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg) |
59 | 59 | ||
60 | /* allow the gpio and pinctrl drivers to talk to eachother */ | ||
61 | extern int pinctrl_falcon_get_range_size(int id); | ||
62 | extern void pinctrl_falcon_add_gpio_range(struct pinctrl_gpio_range *range); | ||
63 | |||
60 | /* | 64 | /* |
61 | * to keep the irq code generic we need to define this to 0 as falcon | 65 | * to keep the irq code generic we need to define this to 0 as falcon |
62 | * has no EIU/EBU | 66 | * has no EIU/EBU |
diff --git a/arch/mips/include/asm/mach-lantiq/gpio.h b/arch/mips/include/asm/mach-lantiq/gpio.h index f79505b43609..9ba1caebca5f 100644 --- a/arch/mips/include/asm/mach-lantiq/gpio.h +++ b/arch/mips/include/asm/mach-lantiq/gpio.h | |||
@@ -1,10 +1,7 @@ | |||
1 | #ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H | 1 | #ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H |
2 | #define __ASM_MIPS_MACH_LANTIQ_GPIO_H | 2 | #define __ASM_MIPS_MACH_LANTIQ_GPIO_H |
3 | 3 | ||
4 | static inline int gpio_to_irq(unsigned int gpio) | 4 | #define gpio_to_irq __gpio_to_irq |
5 | { | ||
6 | return -1; | ||
7 | } | ||
8 | 5 | ||
9 | #define gpio_get_value __gpio_get_value | 6 | #define gpio_get_value __gpio_get_value |
10 | #define gpio_set_value __gpio_set_value | 7 | #define gpio_set_value __gpio_set_value |
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h index aa0b3b866f84..5eadfe582529 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h | |||
@@ -21,4 +21,6 @@ | |||
21 | 21 | ||
22 | #define MIPS_CPU_TIMER_IRQ 7 | 22 | #define MIPS_CPU_TIMER_IRQ 7 |
23 | 23 | ||
24 | #define MAX_IM 5 | ||
25 | |||
24 | #endif | 26 | #endif |
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig index 20bdf40b3efa..d84f361f1e45 100644 --- a/arch/mips/lantiq/Kconfig +++ b/arch/mips/lantiq/Kconfig | |||
@@ -2,6 +2,7 @@ if LANTIQ | |||
2 | 2 | ||
3 | config SOC_TYPE_XWAY | 3 | config SOC_TYPE_XWAY |
4 | bool | 4 | bool |
5 | select PINCTRL_XWAY | ||
5 | default n | 6 | default n |
6 | 7 | ||
7 | choice | 8 | choice |
@@ -19,6 +20,7 @@ config SOC_XWAY | |||
19 | 20 | ||
20 | config SOC_FALCON | 21 | config SOC_FALCON |
21 | bool "FALCON" | 22 | bool "FALCON" |
23 | select PINCTRL_FALCON | ||
22 | 24 | ||
23 | endchoice | 25 | endchoice |
24 | 26 | ||
diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c index c1d278f05a3a..aa9497947859 100644 --- a/arch/mips/lantiq/falcon/prom.c +++ b/arch/mips/lantiq/falcon/prom.c | |||
@@ -8,6 +8,8 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <asm/cacheflush.h> | ||
12 | #include <asm/traps.h> | ||
11 | #include <asm/io.h> | 13 | #include <asm/io.h> |
12 | 14 | ||
13 | #include <lantiq_soc.h> | 15 | #include <lantiq_soc.h> |
@@ -84,4 +86,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i) | |||
84 | unreachable(); | 86 | unreachable(); |
85 | break; | 87 | break; |
86 | } | 88 | } |
89 | |||
90 | board_nmi_handler_setup = ltq_soc_nmi_setup; | ||
91 | board_ejtag_handler_setup = ltq_soc_ejtag_setup; | ||
87 | } | 92 | } |
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c index ba0123d13d40..2d4ced332b37 100644 --- a/arch/mips/lantiq/falcon/sysctrl.c +++ b/arch/mips/lantiq/falcon/sysctrl.c | |||
@@ -171,6 +171,7 @@ static inline void clkdev_add_sys(const char *dev, unsigned int module, | |||
171 | clk->cl.con_id = NULL; | 171 | clk->cl.con_id = NULL; |
172 | clk->cl.clk = clk; | 172 | clk->cl.clk = clk; |
173 | clk->module = module; | 173 | clk->module = module; |
174 | clk->bits = bits; | ||
174 | clk->activate = sysctl_activate; | 175 | clk->activate = sysctl_activate; |
175 | clk->deactivate = sysctl_deactivate; | 176 | clk->deactivate = sysctl_deactivate; |
176 | clk->enable = sysctl_clken; | 177 | clk->enable = sysctl_clken; |
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 57c1a4e51408..f36acd1b3808 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c | |||
@@ -55,8 +55,8 @@ | |||
55 | */ | 55 | */ |
56 | #define LTQ_ICU_EBU_IRQ 22 | 56 | #define LTQ_ICU_EBU_IRQ 22 |
57 | 57 | ||
58 | #define ltq_icu_w32(x, y) ltq_w32((x), ltq_icu_membase + (y)) | 58 | #define ltq_icu_w32(m, x, y) ltq_w32((x), ltq_icu_membase[m] + (y)) |
59 | #define ltq_icu_r32(x) ltq_r32(ltq_icu_membase + (x)) | 59 | #define ltq_icu_r32(m, x) ltq_r32(ltq_icu_membase[m] + (x)) |
60 | 60 | ||
61 | #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y)) | 61 | #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y)) |
62 | #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x)) | 62 | #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x)) |
@@ -82,17 +82,18 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | static int exin_avail; | 84 | static int exin_avail; |
85 | static void __iomem *ltq_icu_membase; | 85 | static void __iomem *ltq_icu_membase[MAX_IM]; |
86 | static void __iomem *ltq_eiu_membase; | 86 | static void __iomem *ltq_eiu_membase; |
87 | static struct irq_domain *ltq_domain; | ||
87 | 88 | ||
88 | void ltq_disable_irq(struct irq_data *d) | 89 | void ltq_disable_irq(struct irq_data *d) |
89 | { | 90 | { |
90 | u32 ier = LTQ_ICU_IM0_IER; | 91 | u32 ier = LTQ_ICU_IM0_IER; |
91 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; | 92 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; |
93 | int im = offset / INT_NUM_IM_OFFSET; | ||
92 | 94 | ||
93 | ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); | ||
94 | offset %= INT_NUM_IM_OFFSET; | 95 | offset %= INT_NUM_IM_OFFSET; |
95 | ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier); | 96 | ltq_icu_w32(im, ltq_icu_r32(im, ier) & ~BIT(offset), ier); |
96 | } | 97 | } |
97 | 98 | ||
98 | void ltq_mask_and_ack_irq(struct irq_data *d) | 99 | void ltq_mask_and_ack_irq(struct irq_data *d) |
@@ -100,32 +101,31 @@ void ltq_mask_and_ack_irq(struct irq_data *d) | |||
100 | u32 ier = LTQ_ICU_IM0_IER; | 101 | u32 ier = LTQ_ICU_IM0_IER; |
101 | u32 isr = LTQ_ICU_IM0_ISR; | 102 | u32 isr = LTQ_ICU_IM0_ISR; |
102 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; | 103 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; |
104 | int im = offset / INT_NUM_IM_OFFSET; | ||
103 | 105 | ||
104 | ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); | ||
105 | isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); | ||
106 | offset %= INT_NUM_IM_OFFSET; | 106 | offset %= INT_NUM_IM_OFFSET; |
107 | ltq_icu_w32(ltq_icu_r32(ier) & ~BIT(offset), ier); | 107 | ltq_icu_w32(im, ltq_icu_r32(im, ier) & ~BIT(offset), ier); |
108 | ltq_icu_w32(BIT(offset), isr); | 108 | ltq_icu_w32(im, BIT(offset), isr); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void ltq_ack_irq(struct irq_data *d) | 111 | static void ltq_ack_irq(struct irq_data *d) |
112 | { | 112 | { |
113 | u32 isr = LTQ_ICU_IM0_ISR; | 113 | u32 isr = LTQ_ICU_IM0_ISR; |
114 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; | 114 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; |
115 | int im = offset / INT_NUM_IM_OFFSET; | ||
115 | 116 | ||
116 | isr += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); | ||
117 | offset %= INT_NUM_IM_OFFSET; | 117 | offset %= INT_NUM_IM_OFFSET; |
118 | ltq_icu_w32(BIT(offset), isr); | 118 | ltq_icu_w32(im, BIT(offset), isr); |
119 | } | 119 | } |
120 | 120 | ||
121 | void ltq_enable_irq(struct irq_data *d) | 121 | void ltq_enable_irq(struct irq_data *d) |
122 | { | 122 | { |
123 | u32 ier = LTQ_ICU_IM0_IER; | 123 | u32 ier = LTQ_ICU_IM0_IER; |
124 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; | 124 | int offset = d->hwirq - MIPS_CPU_IRQ_CASCADE; |
125 | int im = offset / INT_NUM_IM_OFFSET; | ||
125 | 126 | ||
126 | ier += LTQ_ICU_OFFSET * (offset / INT_NUM_IM_OFFSET); | ||
127 | offset %= INT_NUM_IM_OFFSET; | 127 | offset %= INT_NUM_IM_OFFSET; |
128 | ltq_icu_w32(ltq_icu_r32(ier) | BIT(offset), ier); | 128 | ltq_icu_w32(im, ltq_icu_r32(im, ier) | BIT(offset), ier); |
129 | } | 129 | } |
130 | 130 | ||
131 | static unsigned int ltq_startup_eiu_irq(struct irq_data *d) | 131 | static unsigned int ltq_startup_eiu_irq(struct irq_data *d) |
@@ -192,7 +192,7 @@ static void ltq_hw_irqdispatch(int module) | |||
192 | { | 192 | { |
193 | u32 irq; | 193 | u32 irq; |
194 | 194 | ||
195 | irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET)); | 195 | irq = ltq_icu_r32(module, LTQ_ICU_IM0_IOSR); |
196 | if (irq == 0) | 196 | if (irq == 0) |
197 | return; | 197 | return; |
198 | 198 | ||
@@ -220,10 +220,14 @@ DEFINE_HWx_IRQDISPATCH(2) | |||
220 | DEFINE_HWx_IRQDISPATCH(3) | 220 | DEFINE_HWx_IRQDISPATCH(3) |
221 | DEFINE_HWx_IRQDISPATCH(4) | 221 | DEFINE_HWx_IRQDISPATCH(4) |
222 | 222 | ||
223 | #if MIPS_CPU_TIMER_IRQ == 7 | ||
223 | static void ltq_hw5_irqdispatch(void) | 224 | static void ltq_hw5_irqdispatch(void) |
224 | { | 225 | { |
225 | do_IRQ(MIPS_CPU_TIMER_IRQ); | 226 | do_IRQ(MIPS_CPU_TIMER_IRQ); |
226 | } | 227 | } |
228 | #else | ||
229 | DEFINE_HWx_IRQDISPATCH(5) | ||
230 | #endif | ||
227 | 231 | ||
228 | #ifdef CONFIG_MIPS_MT_SMP | 232 | #ifdef CONFIG_MIPS_MT_SMP |
229 | void __init arch_init_ipiirq(int irq, struct irqaction *action) | 233 | void __init arch_init_ipiirq(int irq, struct irqaction *action) |
@@ -271,11 +275,11 @@ asmlinkage void plat_irq_dispatch(void) | |||
271 | unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; | 275 | unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; |
272 | unsigned int i; | 276 | unsigned int i; |
273 | 277 | ||
274 | if (pending & CAUSEF_IP7) { | 278 | if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) { |
275 | do_IRQ(MIPS_CPU_TIMER_IRQ); | 279 | do_IRQ(MIPS_CPU_TIMER_IRQ); |
276 | goto out; | 280 | goto out; |
277 | } else { | 281 | } else { |
278 | for (i = 0; i < 5; i++) { | 282 | for (i = 0; i < MAX_IM; i++) { |
279 | if (pending & (CAUSEF_IP2 << i)) { | 283 | if (pending & (CAUSEF_IP2 << i)) { |
280 | ltq_hw_irqdispatch(i); | 284 | ltq_hw_irqdispatch(i); |
281 | goto out; | 285 | goto out; |
@@ -293,6 +297,9 @@ static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | |||
293 | struct irq_chip *chip = <q_irq_type; | 297 | struct irq_chip *chip = <q_irq_type; |
294 | int i; | 298 | int i; |
295 | 299 | ||
300 | if (hw < MIPS_CPU_IRQ_CASCADE) | ||
301 | return 0; | ||
302 | |||
296 | for (i = 0; i < exin_avail; i++) | 303 | for (i = 0; i < exin_avail; i++) |
297 | if (hw == ltq_eiu_irq[i]) | 304 | if (hw == ltq_eiu_irq[i]) |
298 | chip = <q_eiu_type; | 305 | chip = <q_eiu_type; |
@@ -318,19 +325,23 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) | |||
318 | struct resource res; | 325 | struct resource res; |
319 | int i; | 326 | int i; |
320 | 327 | ||
321 | if (of_address_to_resource(node, 0, &res)) | 328 | for (i = 0; i < MAX_IM; i++) { |
322 | panic("Failed to get icu memory range"); | 329 | if (of_address_to_resource(node, i, &res)) |
330 | panic("Failed to get icu memory range"); | ||
323 | 331 | ||
324 | if (request_mem_region(res.start, resource_size(&res), res.name) < 0) | 332 | if (request_mem_region(res.start, resource_size(&res), |
325 | pr_err("Failed to request icu memory"); | 333 | res.name) < 0) |
334 | pr_err("Failed to request icu memory"); | ||
326 | 335 | ||
327 | ltq_icu_membase = ioremap_nocache(res.start, resource_size(&res)); | 336 | ltq_icu_membase[i] = ioremap_nocache(res.start, |
328 | if (!ltq_icu_membase) | 337 | resource_size(&res)); |
329 | panic("Failed to remap icu memory"); | 338 | if (!ltq_icu_membase[i]) |
339 | panic("Failed to remap icu memory"); | ||
340 | } | ||
330 | 341 | ||
331 | /* the external interrupts are optional and xway only */ | 342 | /* the external interrupts are optional and xway only */ |
332 | eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu"); | 343 | eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu"); |
333 | if (eiu_node && of_address_to_resource(eiu_node, 0, &res)) { | 344 | if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) { |
334 | /* find out how many external irq sources we have */ | 345 | /* find out how many external irq sources we have */ |
335 | const __be32 *count = of_get_property(node, | 346 | const __be32 *count = of_get_property(node, |
336 | "lantiq,count", NULL); | 347 | "lantiq,count", NULL); |
@@ -351,17 +362,17 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) | |||
351 | } | 362 | } |
352 | 363 | ||
353 | /* turn off all irqs by default */ | 364 | /* turn off all irqs by default */ |
354 | for (i = 0; i < 5; i++) { | 365 | for (i = 0; i < MAX_IM; i++) { |
355 | /* make sure all irqs are turned off by default */ | 366 | /* make sure all irqs are turned off by default */ |
356 | ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET)); | 367 | ltq_icu_w32(i, 0, LTQ_ICU_IM0_IER); |
357 | /* clear all possibly pending interrupts */ | 368 | /* clear all possibly pending interrupts */ |
358 | ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET)); | 369 | ltq_icu_w32(i, ~0, LTQ_ICU_IM0_ISR); |
359 | } | 370 | } |
360 | 371 | ||
361 | mips_cpu_irq_init(); | 372 | mips_cpu_irq_init(); |
362 | 373 | ||
363 | for (i = 2; i <= 6; i++) | 374 | for (i = 0; i < MAX_IM; i++) |
364 | setup_irq(i, &cascade); | 375 | setup_irq(i + 2, &cascade); |
365 | 376 | ||
366 | if (cpu_has_vint) { | 377 | if (cpu_has_vint) { |
367 | pr_info("Setting up vectored interrupts\n"); | 378 | pr_info("Setting up vectored interrupts\n"); |
@@ -373,7 +384,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) | |||
373 | set_vi_handler(7, ltq_hw5_irqdispatch); | 384 | set_vi_handler(7, ltq_hw5_irqdispatch); |
374 | } | 385 | } |
375 | 386 | ||
376 | irq_domain_add_linear(node, 6 * INT_NUM_IM_OFFSET, | 387 | ltq_domain = irq_domain_add_linear(node, |
388 | (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE, | ||
377 | &irq_domain_ops, 0); | 389 | &irq_domain_ops, 0); |
378 | 390 | ||
379 | #if defined(CONFIG_MIPS_MT_SMP) | 391 | #if defined(CONFIG_MIPS_MT_SMP) |
@@ -397,12 +409,20 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) | |||
397 | 409 | ||
398 | /* tell oprofile which irq to use */ | 410 | /* tell oprofile which irq to use */ |
399 | cp0_perfcount_irq = LTQ_PERF_IRQ; | 411 | cp0_perfcount_irq = LTQ_PERF_IRQ; |
412 | |||
413 | /* | ||
414 | * if the timer irq is not one of the mips irqs we need to | ||
415 | * create a mapping | ||
416 | */ | ||
417 | if (MIPS_CPU_TIMER_IRQ != 7) | ||
418 | irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ); | ||
419 | |||
400 | return 0; | 420 | return 0; |
401 | } | 421 | } |
402 | 422 | ||
403 | unsigned int __cpuinit get_c0_compare_int(void) | 423 | unsigned int __cpuinit get_c0_compare_int(void) |
404 | { | 424 | { |
405 | return CP0_LEGACY_COMPARE_IRQ; | 425 | return MIPS_CPU_TIMER_IRQ; |
406 | } | 426 | } |
407 | 427 | ||
408 | static struct of_device_id __initdata of_irq_ids[] = { | 428 | static struct of_device_id __initdata of_irq_ids[] = { |
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile index dc3194f6ee42..70a58c747bd0 100644 --- a/arch/mips/lantiq/xway/Makefile +++ b/arch/mips/lantiq/xway/Makefile | |||
@@ -1 +1 @@ | |||
obj-y := prom.o sysctrl.o clk.o reset.o gpio.o dma.o | obj-y := prom.o sysctrl.o clk.o reset.o dma.o gptu.o | ||
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c deleted file mode 100644 index 2ab39e93d9be..000000000000 --- a/arch/mips/lantiq/xway/gpio.c +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published | ||
4 | * by the Free Software Foundation. | ||
5 | * | ||
6 | * Copyright (C) 2010 John Crispin <blogic@openwrt.org> | ||
7 | */ | ||
8 | |||
9 | #include <linux/slab.h> | ||
10 | #include <linux/export.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/ioport.h> | ||
14 | #include <linux/io.h> | ||
15 | |||
16 | #include <lantiq_soc.h> | ||
17 | |||
18 | #define LTQ_GPIO_OUT 0x00 | ||
19 | #define LTQ_GPIO_IN 0x04 | ||
20 | #define LTQ_GPIO_DIR 0x08 | ||
21 | #define LTQ_GPIO_ALTSEL0 0x0C | ||
22 | #define LTQ_GPIO_ALTSEL1 0x10 | ||
23 | #define LTQ_GPIO_OD 0x14 | ||
24 | |||
25 | #define PINS_PER_PORT 16 | ||
26 | #define MAX_PORTS 3 | ||
27 | |||
28 | #define ltq_gpio_getbit(m, r, p) (!!(ltq_r32(m + r) & (1 << p))) | ||
29 | #define ltq_gpio_setbit(m, r, p) ltq_w32_mask(0, (1 << p), m + r) | ||
30 | #define ltq_gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r) | ||
31 | |||
32 | struct ltq_gpio { | ||
33 | void __iomem *membase; | ||
34 | struct gpio_chip chip; | ||
35 | }; | ||
36 | |||
37 | static struct ltq_gpio ltq_gpio_port[MAX_PORTS]; | ||
38 | |||
39 | int ltq_gpio_request(unsigned int pin, unsigned int alt0, | ||
40 | unsigned int alt1, unsigned int dir, const char *name) | ||
41 | { | ||
42 | int id = 0; | ||
43 | |||
44 | if (pin >= (MAX_PORTS * PINS_PER_PORT)) | ||
45 | return -EINVAL; | ||
46 | if (gpio_request(pin, name)) { | ||
47 | pr_err("failed to setup lantiq gpio: %s\n", name); | ||
48 | return -EBUSY; | ||
49 | } | ||
50 | if (dir) | ||
51 | gpio_direction_output(pin, 1); | ||
52 | else | ||
53 | gpio_direction_input(pin); | ||
54 | while (pin >= PINS_PER_PORT) { | ||
55 | pin -= PINS_PER_PORT; | ||
56 | id++; | ||
57 | } | ||
58 | if (alt0) | ||
59 | ltq_gpio_setbit(ltq_gpio_port[id].membase, | ||
60 | LTQ_GPIO_ALTSEL0, pin); | ||
61 | else | ||
62 | ltq_gpio_clearbit(ltq_gpio_port[id].membase, | ||
63 | LTQ_GPIO_ALTSEL0, pin); | ||
64 | if (alt1) | ||
65 | ltq_gpio_setbit(ltq_gpio_port[id].membase, | ||
66 | LTQ_GPIO_ALTSEL1, pin); | ||
67 | else | ||
68 | ltq_gpio_clearbit(ltq_gpio_port[id].membase, | ||
69 | LTQ_GPIO_ALTSEL1, pin); | ||
70 | return 0; | ||
71 | } | ||
72 | EXPORT_SYMBOL(ltq_gpio_request); | ||
73 | |||
74 | static void ltq_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) | ||
75 | { | ||
76 | struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip); | ||
77 | |||
78 | if (value) | ||
79 | ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset); | ||
80 | else | ||
81 | ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset); | ||
82 | } | ||
83 | |||
84 | static int ltq_gpio_get(struct gpio_chip *chip, unsigned int offset) | ||
85 | { | ||
86 | struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip); | ||
87 | |||
88 | return ltq_gpio_getbit(ltq_gpio->membase, LTQ_GPIO_IN, offset); | ||
89 | } | ||
90 | |||
91 | static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) | ||
92 | { | ||
93 | struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip); | ||
94 | |||
95 | ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset); | ||
96 | ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int ltq_gpio_direction_output(struct gpio_chip *chip, | ||
102 | unsigned int offset, int value) | ||
103 | { | ||
104 | struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip); | ||
105 | |||
106 | ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset); | ||
107 | ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset); | ||
108 | ltq_gpio_set(chip, offset, value); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset) | ||
114 | { | ||
115 | struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip); | ||
116 | |||
117 | ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset); | ||
118 | ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int ltq_gpio_probe(struct platform_device *pdev) | ||
123 | { | ||
124 | struct resource *res; | ||
125 | |||
126 | if (pdev->id >= MAX_PORTS) { | ||
127 | dev_err(&pdev->dev, "invalid gpio port %d\n", | ||
128 | pdev->id); | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
132 | if (!res) { | ||
133 | dev_err(&pdev->dev, "failed to get memory for gpio port %d\n", | ||
134 | pdev->id); | ||
135 | return -ENOENT; | ||
136 | } | ||
137 | res = devm_request_mem_region(&pdev->dev, res->start, | ||
138 | resource_size(res), dev_name(&pdev->dev)); | ||
139 | if (!res) { | ||
140 | dev_err(&pdev->dev, | ||
141 | "failed to request memory for gpio port %d\n", | ||
142 | pdev->id); | ||
143 | return -EBUSY; | ||
144 | } | ||
145 | ltq_gpio_port[pdev->id].membase = devm_ioremap_nocache(&pdev->dev, | ||
146 | res->start, resource_size(res)); | ||
147 | if (!ltq_gpio_port[pdev->id].membase) { | ||
148 | dev_err(&pdev->dev, "failed to remap memory for gpio port %d\n", | ||
149 | pdev->id); | ||
150 | return -ENOMEM; | ||
151 | } | ||
152 | ltq_gpio_port[pdev->id].chip.label = "ltq_gpio"; | ||
153 | ltq_gpio_port[pdev->id].chip.direction_input = ltq_gpio_direction_input; | ||
154 | ltq_gpio_port[pdev->id].chip.direction_output = | ||
155 | ltq_gpio_direction_output; | ||
156 | ltq_gpio_port[pdev->id].chip.get = ltq_gpio_get; | ||
157 | ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set; | ||
158 | ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req; | ||
159 | ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id; | ||
160 | ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT; | ||
161 | platform_set_drvdata(pdev, <q_gpio_port[pdev->id]); | ||
162 | return gpiochip_add(<q_gpio_port[pdev->id].chip); | ||
163 | } | ||
164 | |||
165 | static struct platform_driver | ||
166 | ltq_gpio_driver = { | ||
167 | .probe = ltq_gpio_probe, | ||
168 | .driver = { | ||
169 | .name = "ltq_gpio", | ||
170 | .owner = THIS_MODULE, | ||
171 | }, | ||
172 | }; | ||
173 | |||
174 | int __init ltq_gpio_init(void) | ||
175 | { | ||
176 | int ret = platform_driver_register(<q_gpio_driver); | ||
177 | |||
178 | if (ret) | ||
179 | pr_info("ltq_gpio : Error registering platform driver!"); | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | postcore_initcall(ltq_gpio_init); | ||
diff --git a/arch/mips/lantiq/xway/gptu.c b/arch/mips/lantiq/xway/gptu.c new file mode 100644 index 000000000000..cbb56fc022bc --- /dev/null +++ b/arch/mips/lantiq/xway/gptu.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published | ||
4 | * by the Free Software Foundation. | ||
5 | * | ||
6 | * Copyright (C) 2012 John Crispin <blogic@openwrt.org> | ||
7 | * Copyright (C) 2012 Lantiq GmbH | ||
8 | */ | ||
9 | |||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/ioport.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/of_platform.h> | ||
14 | #include <linux/of_irq.h> | ||
15 | |||
16 | #include <lantiq_soc.h> | ||
17 | #include "../clk.h" | ||
18 | |||
19 | /* the magic ID byte of the core */ | ||
20 | #define GPTU_MAGIC 0x59 | ||
21 | /* clock control register */ | ||
22 | #define GPTU_CLC 0x00 | ||
23 | /* id register */ | ||
24 | #define GPTU_ID 0x08 | ||
25 | /* interrupt node enable */ | ||
26 | #define GPTU_IRNEN 0xf4 | ||
27 | /* interrupt control register */ | ||
28 | #define GPTU_IRCR 0xf8 | ||
29 | /* interrupt capture register */ | ||
30 | #define GPTU_IRNCR 0xfc | ||
31 | /* there are 3 identical blocks of 2 timers. calculate register offsets */ | ||
32 | #define GPTU_SHIFT(x) (x % 2 ? 4 : 0) | ||
33 | #define GPTU_BASE(x) (((x >> 1) * 0x20) + 0x10) | ||
34 | /* timer control register */ | ||
35 | #define GPTU_CON(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x00) | ||
36 | /* timer auto reload register */ | ||
37 | #define GPTU_RUN(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x08) | ||
38 | /* timer manual reload register */ | ||
39 | #define GPTU_RLD(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x10) | ||
40 | /* timer count register */ | ||
41 | #define GPTU_CNT(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x18) | ||
42 | |||
43 | /* GPTU_CON(x) */ | ||
44 | #define CON_CNT BIT(2) | ||
45 | #define CON_EDGE_ANY (BIT(7) | BIT(6)) | ||
46 | #define CON_SYNC BIT(8) | ||
47 | #define CON_CLK_INT BIT(10) | ||
48 | |||
49 | /* GPTU_RUN(x) */ | ||
50 | #define RUN_SEN BIT(0) | ||
51 | #define RUN_RL BIT(2) | ||
52 | |||
53 | /* set clock to runmode */ | ||
54 | #define CLC_RMC BIT(8) | ||
55 | /* bring core out of suspend */ | ||
56 | #define CLC_SUSPEND BIT(4) | ||
57 | /* the disable bit */ | ||
58 | #define CLC_DISABLE BIT(0) | ||
59 | |||
60 | #define gptu_w32(x, y) ltq_w32((x), gptu_membase + (y)) | ||
61 | #define gptu_r32(x) ltq_r32(gptu_membase + (x)) | ||
62 | |||
63 | enum gptu_timer { | ||
64 | TIMER1A = 0, | ||
65 | TIMER1B, | ||
66 | TIMER2A, | ||
67 | TIMER2B, | ||
68 | TIMER3A, | ||
69 | TIMER3B | ||
70 | }; | ||
71 | |||
72 | static void __iomem *gptu_membase; | ||
73 | static struct resource irqres[6]; | ||
74 | |||
75 | static irqreturn_t timer_irq_handler(int irq, void *priv) | ||
76 | { | ||
77 | int timer = irq - irqres[0].start; | ||
78 | gptu_w32(1 << timer, GPTU_IRNCR); | ||
79 | return IRQ_HANDLED; | ||
80 | } | ||
81 | |||
82 | static void gptu_hwinit(void) | ||
83 | { | ||
84 | gptu_w32(0x00, GPTU_IRNEN); | ||
85 | gptu_w32(0xff, GPTU_IRNCR); | ||
86 | gptu_w32(CLC_RMC | CLC_SUSPEND, GPTU_CLC); | ||
87 | } | ||
88 | |||
89 | static void gptu_hwexit(void) | ||
90 | { | ||
91 | gptu_w32(0x00, GPTU_IRNEN); | ||
92 | gptu_w32(0xff, GPTU_IRNCR); | ||
93 | gptu_w32(CLC_DISABLE, GPTU_CLC); | ||
94 | } | ||
95 | |||
96 | static int gptu_enable(struct clk *clk) | ||
97 | { | ||
98 | int ret = request_irq(irqres[clk->bits].start, timer_irq_handler, | ||
99 | IRQF_TIMER, "gtpu", NULL); | ||
100 | if (ret) { | ||
101 | pr_err("gptu: failed to request irq\n"); | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | gptu_w32(CON_CNT | CON_EDGE_ANY | CON_SYNC | CON_CLK_INT, | ||
106 | GPTU_CON(clk->bits)); | ||
107 | gptu_w32(1, GPTU_RLD(clk->bits)); | ||
108 | gptu_w32(gptu_r32(GPTU_IRNEN) | BIT(clk->bits), GPTU_IRNEN); | ||
109 | gptu_w32(RUN_SEN | RUN_RL, GPTU_RUN(clk->bits)); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static void gptu_disable(struct clk *clk) | ||
114 | { | ||
115 | gptu_w32(0, GPTU_RUN(clk->bits)); | ||
116 | gptu_w32(0, GPTU_CON(clk->bits)); | ||
117 | gptu_w32(0, GPTU_RLD(clk->bits)); | ||
118 | gptu_w32(gptu_r32(GPTU_IRNEN) & ~BIT(clk->bits), GPTU_IRNEN); | ||
119 | free_irq(irqres[clk->bits].start, NULL); | ||
120 | } | ||
121 | |||
122 | static inline void clkdev_add_gptu(struct device *dev, const char *con, | ||
123 | unsigned int timer) | ||
124 | { | ||
125 | struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); | ||
126 | |||
127 | clk->cl.dev_id = dev_name(dev); | ||
128 | clk->cl.con_id = con; | ||
129 | clk->cl.clk = clk; | ||
130 | clk->enable = gptu_enable; | ||
131 | clk->disable = gptu_disable; | ||
132 | clk->bits = timer; | ||
133 | clkdev_add(&clk->cl); | ||
134 | } | ||
135 | |||
136 | static int __devinit gptu_probe(struct platform_device *pdev) | ||
137 | { | ||
138 | struct clk *clk; | ||
139 | struct resource *res; | ||
140 | |||
141 | if (of_irq_to_resource_table(pdev->dev.of_node, irqres, 6) != 6) { | ||
142 | dev_err(&pdev->dev, "Failed to get IRQ list\n"); | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
147 | if (!res) { | ||
148 | dev_err(&pdev->dev, "Failed to get resource\n"); | ||
149 | return -ENOMEM; | ||
150 | } | ||
151 | |||
152 | /* remap gptu register range */ | ||
153 | gptu_membase = devm_request_and_ioremap(&pdev->dev, res); | ||
154 | if (!gptu_membase) { | ||
155 | dev_err(&pdev->dev, "Failed to remap resource\n"); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | |||
159 | /* enable our clock */ | ||
160 | clk = clk_get(&pdev->dev, NULL); | ||
161 | if (IS_ERR(clk)) { | ||
162 | dev_err(&pdev->dev, "Failed to get clock\n"); | ||
163 | return -ENOENT; | ||
164 | } | ||
165 | clk_enable(clk); | ||
166 | |||
167 | /* power up the core */ | ||
168 | gptu_hwinit(); | ||
169 | |||
170 | /* the gptu has a ID register */ | ||
171 | if (((gptu_r32(GPTU_ID) >> 8) & 0xff) != GPTU_MAGIC) { | ||
172 | dev_err(&pdev->dev, "Failed to find magic\n"); | ||
173 | gptu_hwexit(); | ||
174 | return -ENAVAIL; | ||
175 | } | ||
176 | |||
177 | /* register the clocks */ | ||
178 | clkdev_add_gptu(&pdev->dev, "timer1a", TIMER1A); | ||
179 | clkdev_add_gptu(&pdev->dev, "timer1b", TIMER1B); | ||
180 | clkdev_add_gptu(&pdev->dev, "timer2a", TIMER2A); | ||
181 | clkdev_add_gptu(&pdev->dev, "timer2b", TIMER2B); | ||
182 | clkdev_add_gptu(&pdev->dev, "timer3a", TIMER3A); | ||
183 | clkdev_add_gptu(&pdev->dev, "timer3b", TIMER3B); | ||
184 | |||
185 | dev_info(&pdev->dev, "gptu: 6 timers loaded\n"); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static const struct of_device_id gptu_match[] = { | ||
191 | { .compatible = "lantiq,gptu-xway" }, | ||
192 | {}, | ||
193 | }; | ||
194 | MODULE_DEVICE_TABLE(of, dma_match); | ||
195 | |||
196 | static struct platform_driver dma_driver = { | ||
197 | .probe = gptu_probe, | ||
198 | .driver = { | ||
199 | .name = "gptu-xway", | ||
200 | .owner = THIS_MODULE, | ||
201 | .of_match_table = gptu_match, | ||
202 | }, | ||
203 | }; | ||
204 | |||
205 | int __init gptu_init(void) | ||
206 | { | ||
207 | int ret = platform_driver_register(&dma_driver); | ||
208 | |||
209 | if (ret) | ||
210 | pr_info("gptu: Error registering platform driver\n"); | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | arch_initcall(gptu_init); | ||
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index befbb760ab76..67c3a91e54e7 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c | |||
@@ -145,7 +145,8 @@ static int pci_enable(struct clk *clk) | |||
145 | { | 145 | { |
146 | unsigned int val = ltq_cgu_r32(ifccr); | 146 | unsigned int val = ltq_cgu_r32(ifccr); |
147 | /* set bus clock speed */ | 147 | /* set bus clock speed */ |
148 | if (of_machine_is_compatible("lantiq,ar9")) { | 148 | if (of_machine_is_compatible("lantiq,ar9") || |
149 | of_machine_is_compatible("lantiq,vr9")) { | ||
149 | val &= ~0x1f00000; | 150 | val &= ~0x1f00000; |
150 | if (clk->rate == CLOCK_33M) | 151 | if (clk->rate == CLOCK_33M) |
151 | val |= 0xe00000; | 152 | val |= 0xe00000; |