1 From 94a0ad7aea40f0143670cfb6d5794f2f4b6b1aa7 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Fri, 3 Aug 2012 09:51:32 +0200
4 Subject: [PATCH 04/25] lantiq core support
7 arch/mips/Kconfig | 6 +-
8 arch/mips/lantiq/Kconfig | 10 ++
9 arch/mips/lantiq/Makefile | 2 +
10 arch/mips/lantiq/Platform | 2 +
11 arch/mips/lantiq/clk.c | 136 +++++++++++----------
12 arch/mips/lantiq/clk.h | 59 ++++++++-
13 arch/mips/lantiq/devices.c | 30 +----
14 arch/mips/lantiq/devices.h | 4 +
15 arch/mips/lantiq/early_printk.c | 14 ++-
16 arch/mips/lantiq/irq.c | 262 +++++++++++++++++++++++++++++++--------
17 arch/mips/lantiq/machtypes.h | 5 +
18 arch/mips/lantiq/prom.c | 63 ++++++++--
19 arch/mips/lantiq/prom.h | 4 +
20 13 files changed, 435 insertions(+), 162 deletions(-)
22 diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
23 index cffcae6..0e2ce5d 100644
24 --- a/arch/mips/Kconfig
25 +++ b/arch/mips/Kconfig
26 @@ -228,8 +228,11 @@ config LANTIQ
27 select ARCH_REQUIRE_GPIOLIB
31 + select HAVE_MACH_CLKDEV
32 + select CLKDEV_LOOKUP
33 + select HAVE_OPROFILE
35 + select USB_ARCH_HAS_HCD
38 bool "LASAT Networks platforms"
39 @@ -2391,6 +2394,7 @@ config PCI_DOMAINS
42 source "drivers/pci/Kconfig"
43 +source "drivers/pci/pcie/Kconfig"
46 # ISA support is now enabled via select. Too many systems still have the one
47 diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
48 index 3fccf21..b7ba0fe 100644
49 --- a/arch/mips/lantiq/Kconfig
50 +++ b/arch/mips/lantiq/Kconfig
51 @@ -16,8 +16,18 @@ config SOC_XWAY
61 + select MIPS_CPU_SCACHE
65 source "arch/mips/lantiq/xway/Kconfig"
66 +source "arch/mips/lantiq/falcon/Kconfig"
67 +source "arch/mips/lantiq/svip/Kconfig"
70 diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
71 index e5dae0e..db1ce50 100644
72 --- a/arch/mips/lantiq/Makefile
73 +++ b/arch/mips/lantiq/Makefile
74 @@ -9,3 +9,5 @@ obj-y := irq.o setup.o clk.o prom.o devices.o
75 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
77 obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
78 +obj-$(CONFIG_SOC_FALCON) += falcon/
79 +obj-$(CONFIG_SOC_SVIP) += svip/
80 diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform
81 index f3dff05..857548c 100644
82 --- a/arch/mips/lantiq/Platform
83 +++ b/arch/mips/lantiq/Platform
84 @@ -6,3 +6,5 @@ platform-$(CONFIG_LANTIQ) += lantiq/
85 cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
86 load-$(CONFIG_LANTIQ) = 0xffffffff80002000
87 cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
88 +cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
89 +cflags-$(CONFIG_SOC_SVIP) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/svip
90 diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
91 index 412814f..6c95f5e 100644
92 --- a/arch/mips/lantiq/clk.c
93 +++ b/arch/mips/lantiq/clk.c
95 #include <linux/kernel.h>
96 #include <linux/types.h>
97 #include <linux/clk.h>
98 +#include <linux/clkdev.h>
99 #include <linux/err.h>
100 #include <linux/list.h>
103 #include <lantiq_soc.h>
110 - unsigned long rate;
111 - unsigned long (*get_rate) (void);
113 +/* lantiq socs have 3 static clocks */
114 +static struct clk cpu_clk_generic[3];
116 -static struct clk *cpu_clk;
117 -static int cpu_clk_cnt;
118 +void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io)
120 + cpu_clk_generic[0].rate = cpu;
121 + cpu_clk_generic[1].rate = fpi;
122 + cpu_clk_generic[2].rate = io;
125 -/* lantiq socs have 3 static clocks */
126 -static struct clk cpu_clk_generic[] = {
129 - .get_rate = ltq_get_cpu_hz,
132 - .get_rate = ltq_get_fpi_hz,
135 - .get_rate = ltq_get_io_region_clock,
139 -static struct resource ltq_cgu_resource = {
141 - .start = LTQ_CGU_BASE_ADDR,
142 - .end = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
143 - .flags = IORESOURCE_MEM,
146 -/* remapped clock register range */
147 -void __iomem *ltq_cgu_membase;
150 +struct clk *clk_get_cpu(void)
152 - cpu_clk = cpu_clk_generic;
153 - cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
154 + return &cpu_clk_generic[0];
157 +struct clk *clk_get_fpi(void)
159 + return &cpu_clk_generic[1];
161 +EXPORT_SYMBOL_GPL(clk_get_fpi);
163 +struct clk *clk_get_io(void)
165 + return &cpu_clk_generic[2];
168 static inline int clk_good(struct clk *clk)
169 @@ -82,37 +71,60 @@ unsigned long clk_get_rate(struct clk *clk)
171 EXPORT_SYMBOL(clk_get_rate);
173 -struct clk *clk_get(struct device *dev, const char *id)
174 +int clk_set_rate(struct clk *clk, unsigned long rate)
178 - for (i = 0; i < cpu_clk_cnt; i++)
179 - if (!strcmp(id, cpu_clk[i].name))
180 - return &cpu_clk[i];
182 - return ERR_PTR(-ENOENT);
184 -EXPORT_SYMBOL(clk_get);
185 + if (unlikely(!clk_good(clk)))
188 -void clk_put(struct clk *clk)
194 -EXPORT_SYMBOL(clk_put);
195 +EXPORT_SYMBOL(clk_set_rate);
197 int clk_enable(struct clk *clk)
201 + if (unlikely(!clk_good(clk)))
205 + return clk->enable(clk);
209 EXPORT_SYMBOL(clk_enable);
211 void clk_disable(struct clk *clk)
214 + if (unlikely(!clk_good(clk)))
220 EXPORT_SYMBOL(clk_disable);
222 +int clk_activate(struct clk *clk)
224 + if (unlikely(!clk_good(clk)))
228 + return clk->activate(clk);
232 +EXPORT_SYMBOL(clk_activate);
234 +void clk_deactivate(struct clk *clk)
236 + if (unlikely(!clk_good(clk)))
239 + if (clk->deactivate)
240 + clk->deactivate(clk);
242 +EXPORT_SYMBOL(clk_deactivate);
244 static inline u32 ltq_get_counter_resolution(void)
247 @@ -133,21 +145,17 @@ void __init plat_time_init(void)
251 - if (insert_resource(&iomem_resource, <q_cgu_resource) < 0)
252 - panic("Failed to insert cgu memory");
254 - if (request_mem_region(ltq_cgu_resource.start,
255 - resource_size(<q_cgu_resource), "cgu") < 0)
256 - panic("Failed to request cgu memory");
259 - ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
260 - resource_size(<q_cgu_resource));
261 - if (!ltq_cgu_membase) {
262 - pr_err("Failed to remap cgu memory\n");
265 - clk = clk_get(0, "cpu");
266 + clk = clk_get_cpu();
267 mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
268 +#ifdef CONFIG_SOC_SVIP
270 + write_c0_compare(mips_hpt_frequency / HZ);
271 + enable_irq(MIPS_CPU_TIMER_IRQ);
273 write_c0_compare(read_c0_count());
275 + pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
278 diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
279 index 3328925..564ef03 100644
280 --- a/arch/mips/lantiq/clk.h
281 +++ b/arch/mips/lantiq/clk.h
286 -extern void clk_init(void);
287 +#include <linux/clkdev.h>
289 -extern unsigned long ltq_get_cpu_hz(void);
290 -extern unsigned long ltq_get_fpi_hz(void);
291 -extern unsigned long ltq_get_io_region_clock(void);
293 +#define CLOCK_33M 33333333
294 +#define CLOCK_60M 60000000
295 +#define CLOCK_62_5M 62500000
296 +#define CLOCK_83M 83333333
297 +#define CLOCK_83_5M 83500000
298 +#define CLOCK_98_304M 98304000
299 +#define CLOCK_100M 100000000
300 +#define CLOCK_111M 111111111
301 +#define CLOCK_125M 125000000
302 +#define CLOCK_133M 133333333
303 +#define CLOCK_150M 150000000
304 +#define CLOCK_166M 166666666
305 +#define CLOCK_167M 166666667
306 +#define CLOCK_196_608M 196608000
307 +#define CLOCK_200M 200000000
308 +#define CLOCK_250M 250000000
309 +#define CLOCK_266M 266666666
310 +#define CLOCK_300M 300000000
311 +#define CLOCK_333M 333333333
312 +#define CLOCK_393M 393215332
313 +#define CLOCK_400M 400000000
314 +#define CLOCK_500M 500000000
315 +#define CLOCK_600M 600000000
318 + struct clk_lookup cl;
319 + unsigned long rate;
320 + unsigned int module;
322 + unsigned long (*get_rate) (void);
323 + int (*enable) (struct clk *clk);
324 + void (*disable) (struct clk *clk);
325 + int (*activate) (struct clk *clk);
326 + void (*deactivate) (struct clk *clk);
327 + void (*reboot) (struct clk *clk);
330 +extern void clkdev_add_static(unsigned long cpu, unsigned long fpi,
333 +extern unsigned long ltq_danube_cpu_hz(void);
334 +extern unsigned long ltq_danube_fpi_hz(void);
335 +extern unsigned long ltq_danube_io_region_clock(void);
337 +extern unsigned long ltq_svip_cpu_hz(void);
338 +extern unsigned long ltq_svip_fpi_hz(void);
339 +extern unsigned long ltq_svip_io_region_clock(void);
341 +extern unsigned long ltq_ar9_cpu_hz(void);
342 +extern unsigned long ltq_ar9_fpi_hz(void);
344 +extern unsigned long ltq_vr9_cpu_hz(void);
345 +extern unsigned long ltq_vr9_fpi_hz(void);
348 diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
349 index de1cb2b..7193d78 100644
350 --- a/arch/mips/lantiq/devices.c
351 +++ b/arch/mips/lantiq/devices.c
356 -static struct resource ltq_nor_resource = {
358 - .start = LTQ_FLASH_START,
359 - .end = LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
360 - .flags = IORESOURCE_MEM,
362 +static struct resource ltq_nor_resource =
363 + MEM_RES("nor", LTQ_FLASH_START, LTQ_FLASH_MAX);
365 static struct platform_device ltq_nor = {
367 @@ -47,12 +43,8 @@ void __init ltq_register_nor(struct physmap_flash_data *data)
371 -static struct resource ltq_wdt_resource = {
372 - .name = "watchdog",
373 - .start = LTQ_WDT_BASE_ADDR,
374 - .end = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1,
375 - .flags = IORESOURCE_MEM,
377 +static struct resource ltq_wdt_resource =
378 + MEM_RES("watchdog", LTQ_WDT_BASE_ADDR, LTQ_WDT_SIZE);
380 void __init ltq_register_wdt(void)
382 @@ -61,24 +53,14 @@ void __init ltq_register_wdt(void)
385 static struct resource ltq_asc0_resources[] = {
388 - .start = LTQ_ASC0_BASE_ADDR,
389 - .end = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
390 - .flags = IORESOURCE_MEM,
392 + MEM_RES("asc0", LTQ_ASC0_BASE_ADDR, LTQ_ASC_SIZE),
393 IRQ_RES(tx, LTQ_ASC_TIR(0)),
394 IRQ_RES(rx, LTQ_ASC_RIR(0)),
395 IRQ_RES(err, LTQ_ASC_EIR(0)),
398 static struct resource ltq_asc1_resources[] = {
401 - .start = LTQ_ASC1_BASE_ADDR,
402 - .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
403 - .flags = IORESOURCE_MEM,
405 + MEM_RES("asc1", LTQ_ASC1_BASE_ADDR, LTQ_ASC_SIZE),
406 IRQ_RES(tx, LTQ_ASC_TIR(1)),
407 IRQ_RES(rx, LTQ_ASC_RIR(1)),
408 IRQ_RES(err, LTQ_ASC_EIR(1)),
409 diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
410 index 2947bb1..a03c23f 100644
411 --- a/arch/mips/lantiq/devices.h
412 +++ b/arch/mips/lantiq/devices.h
415 #define IRQ_RES(resname, irq) \
416 {.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ}
417 +#define MEM_RES(resname, adr_start, adr_size) \
418 + { .name = resname, .flags = IORESOURCE_MEM, \
419 + .start = ((adr_start) & ~KSEG1), \
420 + .end = ((adr_start + adr_size - 1) & ~KSEG1) }
422 extern void ltq_register_nor(struct physmap_flash_data *data);
423 extern void ltq_register_wdt(void);
424 diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c
425 index 972e05f..5089075 100644
426 --- a/arch/mips/lantiq/early_printk.c
427 +++ b/arch/mips/lantiq/early_printk.c
430 #include <lantiq_soc.h>
432 -/* no ioremap possible at this early stage, lets use KSEG1 instead */
433 -#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
435 -#define LTQ_ASC_FSTAT ((u32 *)(LTQ_ASC_BASE + 0x0048))
436 -#define LTQ_ASC_TBUF ((u32 *)(LTQ_ASC_BASE + 0x0020))
437 +#define LTQ_ASC_FSTAT ((u32 *)(LTQ_EARLY_ASC + 0x0048))
439 +#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020 + 3))
441 +#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020))
443 #define TXMASK 0x3F00
446 @@ -27,7 +29,7 @@ void prom_putchar(char c)
447 local_irq_save(flags);
448 do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
450 - ltq_w32('\r', LTQ_ASC_TBUF);
451 - ltq_w32(c, LTQ_ASC_TBUF);
452 + ltq_w8('\r', LTQ_ASC_TBUF);
453 + ltq_w8(c, LTQ_ASC_TBUF);
454 local_irq_restore(flags);
456 diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
457 index d673731..63dbb83 100644
458 --- a/arch/mips/lantiq/irq.c
459 +++ b/arch/mips/lantiq/irq.c
462 #include <linux/interrupt.h>
463 #include <linux/ioport.h>
464 +#include <linux/sched.h>
466 #include <asm/bootinfo.h>
467 #include <asm/irq_cpu.h>
469 #include <lantiq_soc.h>
471 +#ifdef CONFIG_SOC_SVIP
472 +#include <ebu_reg.h>
473 +#include <base_reg.h>
476 /* register definitions */
477 #define LTQ_ICU_IM0_ISR 0x0000
482 +/* the performance counter */
483 +#define LTQ_PERF_IRQ (INT_NUM_IM4_IRL0 + 31)
485 /* irqs generated by device attached to the EBU need to be acked in
488 #define LTQ_ICU_EBU_IRQ 22
490 -#define ltq_icu_w32(x, y) ltq_w32((x), ltq_icu_membase + (y))
491 -#define ltq_icu_r32(x) ltq_r32(ltq_icu_membase + (x))
492 +#define ltq_icu_w32(x, y, m) ltq_w32((x), ltq_icu_membase[m] + (y))
493 +#define ltq_icu_r32(x, m) ltq_r32(ltq_icu_membase[m] + (x))
495 #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y))
496 #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x))
498 +/* our 2 ipi interrupts for VSMP */
499 +#define MIPS_CPU_IPI_RESCHED_IRQ 0
500 +#define MIPS_CPU_IPI_CALL_IRQ 1
502 +#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
506 static unsigned short ltq_eiu_irq[MAX_EIU] = {
509 @@ -60,11 +76,78 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
513 -static struct resource ltq_icu_resource = {
515 - .start = LTQ_ICU_BASE_ADDR,
516 - .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
517 - .flags = IORESOURCE_MEM,
518 +static struct resource ltq_icu_resource[IM_NUM] = {
521 + .start = LTQ_ICU_BASE_ADDR,
522 + .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_OFFSET - 1,
523 + .flags = IORESOURCE_MEM,
528 +#ifdef LTQ_ICU_BASE_ADDR1
529 + .start = LTQ_ICU_BASE_ADDR1,
530 + .end = LTQ_ICU_BASE_ADDR1 + LTQ_ICU_OFFSET - 1,
532 + .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 1),
533 + .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 2) - 1,
535 + .flags = IORESOURCE_MEM,
541 +#ifdef LTQ_ICU_BASE_ADDR2
542 + .start = LTQ_ICU_BASE_ADDR2,
543 + .end = LTQ_ICU_BASE_ADDR2 + LTQ_ICU_OFFSET - 1,
545 + .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 2),
546 + .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 3) - 1,
548 + .flags = IORESOURCE_MEM,
554 +#ifdef LTQ_ICU_BASE_ADDR3
555 + .start = LTQ_ICU_BASE_ADDR3,
556 + .end = LTQ_ICU_BASE_ADDR3 + LTQ_ICU_OFFSET - 1,
558 + .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 3),
559 + .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 4) - 1,
561 + .flags = IORESOURCE_MEM,
567 +#ifdef LTQ_ICU_BASE_ADDR4
568 + .start = LTQ_ICU_BASE_ADDR4,
569 + .end = LTQ_ICU_BASE_ADDR4 + LTQ_ICU_OFFSET - 1,
571 + .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 4),
572 + .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 5) - 1,
574 + .flags = IORESOURCE_MEM,
580 +#ifdef LTQ_ICU_BASE_ADDR5
581 + .start = LTQ_ICU_BASE_ADDR5,
582 + .end = LTQ_ICU_BASE_ADDR5 + LTQ_ICU_OFFSET - 1,
584 + .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 5),
585 + .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 6) - 1,
587 + .flags = IORESOURCE_MEM,
592 static struct resource ltq_eiu_resource = {
593 @@ -74,50 +157,53 @@ static struct resource ltq_eiu_resource = {
594 .flags = IORESOURCE_MEM,
597 -static void __iomem *ltq_icu_membase;
598 +static void __iomem *ltq_icu_membase[IM_NUM];
599 static void __iomem *ltq_eiu_membase;
601 void ltq_disable_irq(struct irq_data *d)
603 - u32 ier = LTQ_ICU_IM0_IER;
604 int irq_nr = d->irq - INT_NUM_IRQ0;
605 + unsigned int im_nr;
607 - ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
608 + im_nr = (irq_nr / INT_NUM_IM_OFFSET);
609 irq_nr %= INT_NUM_IM_OFFSET;
610 - ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
612 + ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) & ~(1 << irq_nr),
613 + LTQ_ICU_IM0_IER, im_nr);
616 void ltq_mask_and_ack_irq(struct irq_data *d)
618 - u32 ier = LTQ_ICU_IM0_IER;
619 - u32 isr = LTQ_ICU_IM0_ISR;
620 int irq_nr = d->irq - INT_NUM_IRQ0;
621 + unsigned int im_nr;
623 - ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
624 - isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
625 + im_nr = (irq_nr / INT_NUM_IM_OFFSET);
626 irq_nr %= INT_NUM_IM_OFFSET;
627 - ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
628 - ltq_icu_w32((1 << irq_nr), isr);
630 + ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) & ~(1 << irq_nr), LTQ_ICU_IM0_IER, im_nr);
631 + ltq_icu_w32((1 << irq_nr), LTQ_ICU_IM0_ISR, im_nr);
634 static void ltq_ack_irq(struct irq_data *d)
636 - u32 isr = LTQ_ICU_IM0_ISR;
637 int irq_nr = d->irq - INT_NUM_IRQ0;
638 + unsigned int im_nr;
640 - isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
641 + im_nr = (irq_nr / INT_NUM_IM_OFFSET);
642 irq_nr %= INT_NUM_IM_OFFSET;
643 - ltq_icu_w32((1 << irq_nr), isr);
645 + ltq_icu_w32((1 << irq_nr), LTQ_ICU_IM0_ISR, im_nr);
648 void ltq_enable_irq(struct irq_data *d)
650 - u32 ier = LTQ_ICU_IM0_IER;
651 int irq_nr = d->irq - INT_NUM_IRQ0;
652 + unsigned int im_nr;
654 - ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
655 + im_nr = (irq_nr / INT_NUM_IM_OFFSET);
656 irq_nr %= INT_NUM_IM_OFFSET;
657 - ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier);
659 + ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) | (1 << irq_nr), LTQ_ICU_IM0_IER, im_nr);
662 static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
663 @@ -184,7 +270,7 @@ static void ltq_hw_irqdispatch(int module)
667 - irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET));
668 + irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR, module);
672 @@ -194,10 +280,12 @@ static void ltq_hw_irqdispatch(int module)
674 do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
676 +#ifndef CONFIG_SOC_SVIP
677 /* if this is a EBU irq, we need to ack it or get a deadlock */
678 - if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
679 + if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
680 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
685 #define DEFINE_HWx_IRQDISPATCH(x) \
686 @@ -211,21 +299,66 @@ DEFINE_HWx_IRQDISPATCH(2)
687 DEFINE_HWx_IRQDISPATCH(3)
688 DEFINE_HWx_IRQDISPATCH(4)
690 +#if MIPS_CPU_TIMER_IRQ == 7
691 static void ltq_hw5_irqdispatch(void)
693 do_IRQ(MIPS_CPU_TIMER_IRQ);
696 +DEFINE_HWx_IRQDISPATCH(5)
699 +#ifdef CONFIG_MIPS_MT_SMP
700 +void __init arch_init_ipiirq(int irq, struct irqaction *action)
702 + setup_irq(irq, action);
703 + irq_set_handler(irq, handle_percpu_irq);
706 +static void ltq_sw0_irqdispatch(void)
708 + do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
711 +static void ltq_sw1_irqdispatch(void)
713 + do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
715 +static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
718 + return IRQ_HANDLED;
721 +static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
723 + smp_call_function_interrupt();
724 + return IRQ_HANDLED;
727 +static struct irqaction irq_resched = {
728 + .handler = ipi_resched_interrupt,
729 + .flags = IRQF_PERCPU,
730 + .name = "IPI_resched"
733 +static struct irqaction irq_call = {
734 + .handler = ipi_call_interrupt,
735 + .flags = IRQF_PERCPU,
740 asmlinkage void plat_irq_dispatch(void)
742 unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
745 - if (pending & CAUSEF_IP7) {
746 + if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) {
747 do_IRQ(MIPS_CPU_TIMER_IRQ);
750 - for (i = 0; i < 5; i++) {
751 + for (i = 0; i < IM_NUM; i++) {
752 if (pending & (CAUSEF_IP2 << i)) {
753 ltq_hw_irqdispatch(i);
755 @@ -247,41 +380,45 @@ void __init arch_init_irq(void)
759 - if (insert_resource(&iomem_resource, <q_icu_resource) < 0)
760 - panic("Failed to insert icu memory");
761 + for (i=0; i < IM_NUM; i++) {
762 + if (insert_resource(&iomem_resource, <q_icu_resource[i]) < 0)
763 + panic("Failed to insert icu memory\n");
765 - if (request_mem_region(ltq_icu_resource.start,
766 - resource_size(<q_icu_resource), "icu") < 0)
767 - panic("Failed to request icu memory");
768 + if (request_mem_region(ltq_icu_resource[i].start,
769 + resource_size(<q_icu_resource[i]), "icu") < 0)
770 + panic("Failed to request icu memory\n");
772 - ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
773 - resource_size(<q_icu_resource));
774 - if (!ltq_icu_membase)
775 - panic("Failed to remap icu memory");
776 + ltq_icu_membase[i] = ioremap_nocache(ltq_icu_resource[i].start,
777 + resource_size(<q_icu_resource[i]));
778 + if (!ltq_icu_membase[i])
779 + panic("Failed to remap icu memory\n");
782 - if (insert_resource(&iomem_resource, <q_eiu_resource) < 0)
783 - panic("Failed to insert eiu memory");
784 + if (LTQ_EIU_BASE_ADDR) {
785 + if (insert_resource(&iomem_resource, <q_eiu_resource) < 0)
786 + panic("Failed to insert eiu memory\n");
788 - if (request_mem_region(ltq_eiu_resource.start,
789 - resource_size(<q_eiu_resource), "eiu") < 0)
790 - panic("Failed to request eiu memory");
791 + if (request_mem_region(ltq_eiu_resource.start,
792 + resource_size(<q_eiu_resource), "eiu") < 0)
793 + panic("Failed to request eiu memory\n");
795 - ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
796 + ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
797 resource_size(<q_eiu_resource));
798 - if (!ltq_eiu_membase)
799 - panic("Failed to remap eiu memory");
800 + if (!ltq_eiu_membase)
801 + panic("Failed to remap eiu memory\n");
804 /* make sure all irqs are turned off by default */
805 - for (i = 0; i < 5; i++)
806 - ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET));
808 - /* clear all possibly pending interrupts */
809 - ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
810 + for (i = 0; i < IM_NUM; i++) {
811 + ltq_icu_w32(0, LTQ_ICU_IM0_IER, i);
812 + /* clear all possibly pending interrupts */
813 + ltq_icu_w32(~0, LTQ_ICU_IM0_ISR, i);
818 - for (i = 2; i <= 6; i++)
819 - setup_irq(i, &cascade);
820 + for (i = 0; i < IM_NUM; i++)
821 + setup_irq(i + 2, &cascade);
824 pr_info("Setting up vectored interrupts\n");
825 @@ -294,9 +431,9 @@ void __init arch_init_irq(void)
828 for (i = INT_NUM_IRQ0;
829 - i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
830 - if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
831 - (i == LTQ_EIU_IR2))
832 + i <= (INT_NUM_IRQ0 + (IM_NUM * INT_NUM_IM_OFFSET)); i++)
833 + if (((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
834 + (i == LTQ_EIU_IR2)) && LTQ_EIU_BASE_ADDR)
835 irq_set_chip_and_handler(i, <q_eiu_type,
837 /* EIU3-5 only exist on ar9 and vr9 */
838 @@ -308,6 +445,17 @@ void __init arch_init_irq(void)
839 irq_set_chip_and_handler(i, <q_irq_type,
842 +#if defined(CONFIG_MIPS_MT_SMP)
843 + if (cpu_has_vint) {
844 + pr_info("Setting up IPI vectored interrupts\n");
845 + set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch);
846 + set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch);
848 + arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ,
850 + arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call);
853 #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
854 set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
855 IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
856 @@ -315,9 +463,15 @@ void __init arch_init_irq(void)
857 set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
858 IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
861 + cp0_perfcount_irq = LTQ_PERF_IRQ;
864 unsigned int __cpuinit get_c0_compare_int(void)
866 +#ifdef CONFIG_SOC_SVIP
867 + return MIPS_CPU_TIMER_IRQ;
869 return CP0_LEGACY_COMPARE_IRQ;
872 diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
873 index 7e01b8c..dfc6af7 100644
874 --- a/arch/mips/lantiq/machtypes.h
875 +++ b/arch/mips/lantiq/machtypes.h
876 @@ -15,6 +15,11 @@ enum lantiq_mach_type {
877 LTQ_MACH_GENERIC = 0,
878 LTQ_MACH_EASY50712, /* Danube evaluation board */
879 LTQ_MACH_EASY50601, /* Amazon SE evaluation board */
882 + LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
883 + LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
884 + LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */
888 diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
889 index e34fcfd..00ad59c 100644
890 --- a/arch/mips/lantiq/prom.c
891 +++ b/arch/mips/lantiq/prom.c
896 +/* access to the ebu needs to be locked between different drivers */
897 +DEFINE_SPINLOCK(ebu_lock);
898 +EXPORT_SYMBOL_GPL(ebu_lock);
900 static struct ltq_soc_info soc_info;
902 unsigned int ltq_get_cpu_ver(void)
903 @@ -45,27 +49,68 @@ static void __init prom_init_cmdline(void)
904 char **argv = (char **) KSEG1ADDR(fw_arg1);
907 + arcs_cmdline[0] = '\0';
909 for (i = 0; i < argc; i++) {
910 - char *p = (char *) KSEG1ADDR(argv[i]);
911 + char *p = (char *) KSEG1ADDR(argv[i]);
914 + if (CPHYSADDR(p) && *p) {
915 strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
916 strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
921 -void __init prom_init(void)
922 +void __iomem *ltq_remap_resource(struct resource *res)
925 + __iomem void *ret = NULL;
926 + struct resource *lookup = lookup_resource(&iomem_resource, res->start);
928 + if (lookup && strcmp(lookup->name, res->name)) {
929 + pr_err("conflicting memory range %s\n", res->name);
933 + if (insert_resource(&iomem_resource, res) < 0) {
934 + pr_err("Failed to insert %s memory\n", res->name);
938 + if (request_mem_region(res->start,
939 + resource_size(res), res->name) < 0) {
940 + pr_err("Failed to request %s memory\n", res->name);
944 + ret = ioremap_nocache(res->start, resource_size(res));
948 + pr_debug("remap: 0x%08X-0x%08X : \"%s\"\n",
949 + res->start, res->end, res->name);
953 + panic("Failed to remap %s memory\n", res->name);
954 + release_mem_region(res->start, resource_size(res));
957 + release_resource(res);
960 +EXPORT_SYMBOL(ltq_remap_resource);
962 +void __init prom_init(void)
964 ltq_soc_detect(&soc_info);
966 - clk = clk_get(0, "cpu");
967 - snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
968 - soc_info.name, soc_info.rev);
970 + snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
971 + soc_info.name, soc_info.rev_type);
972 soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
973 pr_info("SoC: %s\n", soc_info.sys_type);
976 +#if defined(CONFIG_MIPS_MT_SMP)
977 + if (register_vsmp_smp_ops())
978 + panic("failed to register_vsmp_smp_ops()");
981 diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
982 index b4229d9..51dba1b 100644
983 --- a/arch/mips/lantiq/prom.h
984 +++ b/arch/mips/lantiq/prom.h
986 #ifndef _LTQ_PROM_H__
987 #define _LTQ_PROM_H__
989 +#define LTQ_SYS_REV_LEN 0x10
990 #define LTQ_SYS_TYPE_LEN 0x100
992 struct ltq_soc_info {
995 + unsigned char rev_type[LTQ_SYS_REV_LEN];
997 unsigned int partnum;
999 unsigned char sys_type[LTQ_SYS_TYPE_LEN];
1002 extern void ltq_soc_detect(struct ltq_soc_info *i);
1003 +extern void ltq_soc_init(void);
1004 extern void ltq_soc_setup(void);