Root/target/linux/lantiq/patches-3.3/0004-lantiq-core-support.patch

1From 94a0ad7aea40f0143670cfb6d5794f2f4b6b1aa7 Mon Sep 17 00:00:00 2001
2From: John Crispin <blogic@openwrt.org>
3Date: Fri, 3 Aug 2012 09:51:32 +0200
4Subject: [PATCH 04/25] lantiq core support
5
6---
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(-)
21
22diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
23index 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
28     select SWAP_IO_SPACE
29     select BOOT_RAW
30- select HAVE_CLK
31+ select HAVE_MACH_CLKDEV
32+ select CLKDEV_LOOKUP
33+ select HAVE_OPROFILE
34     select MIPS_MACHINE
35+ select USB_ARCH_HAS_HCD
36 
37 config LASAT
38     bool "LASAT Networks platforms"
39@@ -2391,6 +2394,7 @@ config PCI_DOMAINS
40     bool
41 
42 source "drivers/pci/Kconfig"
43+source "drivers/pci/pcie/Kconfig"
44 
45 #
46 # ISA support is now enabled via select. Too many systems still have the one
47diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
48index 3fccf21..b7ba0fe 100644
49--- a/arch/mips/lantiq/Kconfig
50+++ b/arch/mips/lantiq/Kconfig
51@@ -16,8 +16,18 @@ config SOC_XWAY
52     bool "XWAY"
53     select SOC_TYPE_XWAY
54     select HW_HAS_PCI
55+
56+config SOC_FALCON
57+ bool "FALCON"
58+
59+config SOC_SVIP
60+ bool "SVIP"
61+ select MIPS_CPU_SCACHE
62+
63 endchoice
64 
65 source "arch/mips/lantiq/xway/Kconfig"
66+source "arch/mips/lantiq/falcon/Kconfig"
67+source "arch/mips/lantiq/svip/Kconfig"
68 
69 endif
70diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
71index 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
76 
77 obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
78+obj-$(CONFIG_SOC_FALCON) += falcon/
79+obj-$(CONFIG_SOC_SVIP) += svip/
80diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform
81index 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
90diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
91index 412814f..6c95f5e 100644
92--- a/arch/mips/lantiq/clk.c
93+++ b/arch/mips/lantiq/clk.c
94@@ -12,6 +12,7 @@
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>
101 
102@@ -22,44 +23,32 @@
103 #include <lantiq_soc.h>
104 
105 #include "clk.h"
106+#include "prom.h"
107 
108-struct clk {
109- const char *name;
110- unsigned long rate;
111- unsigned long (*get_rate) (void);
112-};
113+/* lantiq socs have 3 static clocks */
114+static struct clk cpu_clk_generic[3];
115 
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)
119+{
120+ cpu_clk_generic[0].rate = cpu;
121+ cpu_clk_generic[1].rate = fpi;
122+ cpu_clk_generic[2].rate = io;
123+}
124 
125-/* lantiq socs have 3 static clocks */
126-static struct clk cpu_clk_generic[] = {
127- {
128- .name = "cpu",
129- .get_rate = ltq_get_cpu_hz,
130- }, {
131- .name = "fpi",
132- .get_rate = ltq_get_fpi_hz,
133- }, {
134- .name = "io",
135- .get_rate = ltq_get_io_region_clock,
136- },
137-};
138-
139-static struct resource ltq_cgu_resource = {
140- .name = "cgu",
141- .start = LTQ_CGU_BASE_ADDR,
142- .end = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
143- .flags = IORESOURCE_MEM,
144-};
145-
146-/* remapped clock register range */
147-void __iomem *ltq_cgu_membase;
148-
149-void clk_init(void)
150+struct clk *clk_get_cpu(void)
151 {
152- cpu_clk = cpu_clk_generic;
153- cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
154+ return &cpu_clk_generic[0];
155+}
156+
157+struct clk *clk_get_fpi(void)
158+{
159+ return &cpu_clk_generic[1];
160+}
161+EXPORT_SYMBOL_GPL(clk_get_fpi);
162+
163+struct clk *clk_get_io(void)
164+{
165+ return &cpu_clk_generic[2];
166 }
167 
168 static inline int clk_good(struct clk *clk)
169@@ -82,37 +71,60 @@ unsigned long clk_get_rate(struct clk *clk)
170 }
171 EXPORT_SYMBOL(clk_get_rate);
172 
173-struct clk *clk_get(struct device *dev, const char *id)
174+int clk_set_rate(struct clk *clk, unsigned long rate)
175 {
176- int i;
177-
178- for (i = 0; i < cpu_clk_cnt; i++)
179- if (!strcmp(id, cpu_clk[i].name))
180- return &cpu_clk[i];
181- BUG();
182- return ERR_PTR(-ENOENT);
183-}
184-EXPORT_SYMBOL(clk_get);
185+ if (unlikely(!clk_good(clk)))
186+ return 0;
187 
188-void clk_put(struct clk *clk)
189-{
190- /* not used */
191+ clk->rate = rate;
192+ return 0;
193 }
194-EXPORT_SYMBOL(clk_put);
195+EXPORT_SYMBOL(clk_set_rate);
196 
197 int clk_enable(struct clk *clk)
198 {
199- /* not used */
200- return 0;
201+ if (unlikely(!clk_good(clk)))
202+ return -1;
203+
204+ if (clk->enable)
205+ return clk->enable(clk);
206+
207+ return -1;
208 }
209 EXPORT_SYMBOL(clk_enable);
210 
211 void clk_disable(struct clk *clk)
212 {
213- /* not used */
214+ if (unlikely(!clk_good(clk)))
215+ return;
216+
217+ if (clk->disable)
218+ clk->disable(clk);
219 }
220 EXPORT_SYMBOL(clk_disable);
221 
222+int clk_activate(struct clk *clk)
223+{
224+ if (unlikely(!clk_good(clk)))
225+ return -1;
226+
227+ if (clk->activate)
228+ return clk->activate(clk);
229+
230+ return -1;
231+}
232+EXPORT_SYMBOL(clk_activate);
233+
234+void clk_deactivate(struct clk *clk)
235+{
236+ if (unlikely(!clk_good(clk)))
237+ return;
238+
239+ if (clk->deactivate)
240+ clk->deactivate(clk);
241+}
242+EXPORT_SYMBOL(clk_deactivate);
243+
244 static inline u32 ltq_get_counter_resolution(void)
245 {
246     u32 res;
247@@ -133,21 +145,17 @@ void __init plat_time_init(void)
248 {
249     struct clk *clk;
250 
251- if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
252- panic("Failed to insert cgu memory");
253-
254- if (request_mem_region(ltq_cgu_resource.start,
255- resource_size(&ltq_cgu_resource), "cgu") < 0)
256- panic("Failed to request cgu memory");
257+ ltq_soc_init();
258 
259- ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
260- resource_size(&ltq_cgu_resource));
261- if (!ltq_cgu_membase) {
262- pr_err("Failed to remap cgu memory\n");
263- unreachable();
264- }
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
269+ write_c0_count(0);
270+ write_c0_compare(mips_hpt_frequency / HZ);
271+ enable_irq(MIPS_CPU_TIMER_IRQ);
272+#else
273     write_c0_compare(read_c0_count());
274+#endif
275+ pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
276     clk_put(clk);
277 }
278diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
279index 3328925..564ef03 100644
280--- a/arch/mips/lantiq/clk.h
281+++ b/arch/mips/lantiq/clk.h
282@@ -9,10 +9,61 @@
283 #ifndef _LTQ_CLK_H__
284 #define _LTQ_CLK_H__
285 
286-extern void clk_init(void);
287+#include <linux/clkdev.h>
288 
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);
292+/* clock speeds */
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
316+
317+struct clk {
318+ struct clk_lookup cl;
319+ unsigned long rate;
320+ unsigned int module;
321+ unsigned int bits;
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);
328+};
329+
330+extern void clkdev_add_static(unsigned long cpu, unsigned long fpi,
331+ unsigned long io);
332+
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);
336+
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);
340+
341+extern unsigned long ltq_ar9_cpu_hz(void);
342+extern unsigned long ltq_ar9_fpi_hz(void);
343+
344+extern unsigned long ltq_vr9_cpu_hz(void);
345+extern unsigned long ltq_vr9_fpi_hz(void);
346 
347 #endif
348diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
349index de1cb2b..7193d78 100644
350--- a/arch/mips/lantiq/devices.c
351+++ b/arch/mips/lantiq/devices.c
352@@ -27,12 +27,8 @@
353 #include "devices.h"
354 
355 /* nor flash */
356-static struct resource ltq_nor_resource = {
357- .name = "nor",
358- .start = LTQ_FLASH_START,
359- .end = LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
360- .flags = IORESOURCE_MEM,
361-};
362+static struct resource ltq_nor_resource =
363+ MEM_RES("nor", LTQ_FLASH_START, LTQ_FLASH_MAX);
364 
365 static struct platform_device ltq_nor = {
366     .name = "ltq_nor",
367@@ -47,12 +43,8 @@ void __init ltq_register_nor(struct physmap_flash_data *data)
368 }
369 
370 /* watchdog */
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,
376-};
377+static struct resource ltq_wdt_resource =
378+ MEM_RES("watchdog", LTQ_WDT_BASE_ADDR, LTQ_WDT_SIZE);
379 
380 void __init ltq_register_wdt(void)
381 {
382@@ -61,24 +53,14 @@ void __init ltq_register_wdt(void)
383 
384 /* asc ports */
385 static struct resource ltq_asc0_resources[] = {
386- {
387- .name = "asc0",
388- .start = LTQ_ASC0_BASE_ADDR,
389- .end = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
390- .flags = IORESOURCE_MEM,
391- },
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)),
396 };
397 
398 static struct resource ltq_asc1_resources[] = {
399- {
400- .name = "asc1",
401- .start = LTQ_ASC1_BASE_ADDR,
402- .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
403- .flags = IORESOURCE_MEM,
404- },
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)),
409diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
410index 2947bb1..a03c23f 100644
411--- a/arch/mips/lantiq/devices.h
412+++ b/arch/mips/lantiq/devices.h
413@@ -14,6 +14,10 @@
414 
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) }
421 
422 extern void ltq_register_nor(struct physmap_flash_data *data);
423 extern void ltq_register_wdt(void);
424diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c
425index 972e05f..5089075 100644
426--- a/arch/mips/lantiq/early_printk.c
427+++ b/arch/mips/lantiq/early_printk.c
428@@ -12,11 +12,13 @@
429 #include <lantiq.h>
430 #include <lantiq_soc.h>
431 
432-/* no ioremap possible at this early stage, lets use KSEG1 instead */
433-#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
434 #define ASC_BUF 1024
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))
438+#ifdef __BIG_ENDIAN
439+#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020 + 3))
440+#else
441+#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020))
442+#endif
443 #define TXMASK 0x3F00
444 #define TXOFFSET 8
445 
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);
449     if (c == '\n')
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);
455 }
456diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
457index d673731..63dbb83 100644
458--- a/arch/mips/lantiq/irq.c
459+++ b/arch/mips/lantiq/irq.c
460@@ -9,12 +9,17 @@
461 
462 #include <linux/interrupt.h>
463 #include <linux/ioport.h>
464+#include <linux/sched.h>
465 
466 #include <asm/bootinfo.h>
467 #include <asm/irq_cpu.h>
468 
469 #include <lantiq_soc.h>
470 #include <irq.h>
471+#ifdef CONFIG_SOC_SVIP
472+#include <ebu_reg.h>
473+#include <base_reg.h>
474+#endif
475 
476 /* register definitions */
477 #define LTQ_ICU_IM0_ISR 0x0000
478@@ -40,17 +45,28 @@
479 
480 #define MAX_EIU 6
481 
482+/* the performance counter */
483+#define LTQ_PERF_IRQ (INT_NUM_IM4_IRL0 + 31)
484+
485 /* irqs generated by device attached to the EBU need to be acked in
486  * a special manner
487  */
488 #define LTQ_ICU_EBU_IRQ 22
489 
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))
494 
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))
497 
498+/* our 2 ipi interrupts for VSMP */
499+#define MIPS_CPU_IPI_RESCHED_IRQ 0
500+#define MIPS_CPU_IPI_CALL_IRQ 1
501+
502+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
503+int gic_present;
504+#endif
505+
506 static unsigned short ltq_eiu_irq[MAX_EIU] = {
507     LTQ_EIU_IR0,
508     LTQ_EIU_IR1,
509@@ -60,11 +76,78 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = {
510     LTQ_EIU_IR5,
511 };
512 
513-static struct resource ltq_icu_resource = {
514- .name = "icu",
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] = {
519+{
520+ .name = "icu_im0",
521+ .start = LTQ_ICU_BASE_ADDR,
522+ .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_OFFSET - 1,
523+ .flags = IORESOURCE_MEM,
524+},
525+#if IM_NUM >= 2
526+{
527+ .name = "icu_im1",
528+#ifdef LTQ_ICU_BASE_ADDR1
529+ .start = LTQ_ICU_BASE_ADDR1,
530+ .end = LTQ_ICU_BASE_ADDR1 + LTQ_ICU_OFFSET - 1,
531+#else
532+ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 1),
533+ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 2) - 1,
534+#endif
535+ .flags = IORESOURCE_MEM,
536+},
537+#endif
538+#if IM_NUM >= 3
539+{
540+ .name = "icu_im2",
541+#ifdef LTQ_ICU_BASE_ADDR2
542+ .start = LTQ_ICU_BASE_ADDR2,
543+ .end = LTQ_ICU_BASE_ADDR2 + LTQ_ICU_OFFSET - 1,
544+#else
545+ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 2),
546+ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 3) - 1,
547+#endif
548+ .flags = IORESOURCE_MEM,
549+},
550+#endif
551+#if IM_NUM >= 4
552+{
553+ .name = "icu_im3",
554+#ifdef LTQ_ICU_BASE_ADDR3
555+ .start = LTQ_ICU_BASE_ADDR3,
556+ .end = LTQ_ICU_BASE_ADDR3 + LTQ_ICU_OFFSET - 1,
557+#else
558+ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 3),
559+ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 4) - 1,
560+#endif
561+ .flags = IORESOURCE_MEM,
562+},
563+#endif
564+#if IM_NUM >= 5
565+{
566+ .name = "icu_im4",
567+#ifdef LTQ_ICU_BASE_ADDR4
568+ .start = LTQ_ICU_BASE_ADDR4,
569+ .end = LTQ_ICU_BASE_ADDR4 + LTQ_ICU_OFFSET - 1,
570+#else
571+ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 4),
572+ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 5) - 1,
573+#endif
574+ .flags = IORESOURCE_MEM,
575+},
576+#endif
577+#if IM_NUM >= 6
578+{
579+ .name = "icu_im5",
580+#ifdef LTQ_ICU_BASE_ADDR5
581+ .start = LTQ_ICU_BASE_ADDR5,
582+ .end = LTQ_ICU_BASE_ADDR5 + LTQ_ICU_OFFSET - 1,
583+#else
584+ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 5),
585+ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 6) - 1,
586+#endif
587+ .flags = IORESOURCE_MEM,
588+},
589+#endif
590 };
591 
592 static struct resource ltq_eiu_resource = {
593@@ -74,50 +157,53 @@ static struct resource ltq_eiu_resource = {
594     .flags = IORESOURCE_MEM,
595 };
596 
597-static void __iomem *ltq_icu_membase;
598+static void __iomem *ltq_icu_membase[IM_NUM];
599 static void __iomem *ltq_eiu_membase;
600 
601 void ltq_disable_irq(struct irq_data *d)
602 {
603- u32 ier = LTQ_ICU_IM0_IER;
604     int irq_nr = d->irq - INT_NUM_IRQ0;
605+ unsigned int im_nr;
606 
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);
611+
612+ ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) & ~(1 << irq_nr),
613+ LTQ_ICU_IM0_IER, im_nr);
614 }
615 
616 void ltq_mask_and_ack_irq(struct irq_data *d)
617 {
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;
622 
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);
629+
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);
632 }
633 
634 static void ltq_ack_irq(struct irq_data *d)
635 {
636- u32 isr = LTQ_ICU_IM0_ISR;
637     int irq_nr = d->irq - INT_NUM_IRQ0;
638+ unsigned int im_nr;
639 
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);
644+
645+ ltq_icu_w32((1 << irq_nr), LTQ_ICU_IM0_ISR, im_nr);
646 }
647 
648 void ltq_enable_irq(struct irq_data *d)
649 {
650- u32 ier = LTQ_ICU_IM0_IER;
651     int irq_nr = d->irq - INT_NUM_IRQ0;
652+ unsigned int im_nr;
653 
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);
658+
659+ ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) | (1 << irq_nr), LTQ_ICU_IM0_IER, im_nr);
660 }
661 
662 static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
663@@ -184,7 +270,7 @@ static void ltq_hw_irqdispatch(int module)
664 {
665     u32 irq;
666 
667- irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET));
668+ irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR, module);
669     if (irq == 0)
670         return;
671 
672@@ -194,10 +280,12 @@ static void ltq_hw_irqdispatch(int module)
673     irq = __fls(irq);
674     do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
675 
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,
681             LTQ_EBU_PCC_ISTAT);
682+#endif
683 }
684 
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)
689 
690+#if MIPS_CPU_TIMER_IRQ == 7
691 static void ltq_hw5_irqdispatch(void)
692 {
693     do_IRQ(MIPS_CPU_TIMER_IRQ);
694 }
695+#else
696+DEFINE_HWx_IRQDISPATCH(5)
697+#endif
698+
699+#ifdef CONFIG_MIPS_MT_SMP
700+void __init arch_init_ipiirq(int irq, struct irqaction *action)
701+{
702+ setup_irq(irq, action);
703+ irq_set_handler(irq, handle_percpu_irq);
704+}
705+
706+static void ltq_sw0_irqdispatch(void)
707+{
708+ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
709+}
710+
711+static void ltq_sw1_irqdispatch(void)
712+{
713+ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
714+}
715+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
716+{
717+ scheduler_ipi();
718+ return IRQ_HANDLED;
719+}
720+
721+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
722+{
723+ smp_call_function_interrupt();
724+ return IRQ_HANDLED;
725+}
726+
727+static struct irqaction irq_resched = {
728+ .handler = ipi_resched_interrupt,
729+ .flags = IRQF_PERCPU,
730+ .name = "IPI_resched"
731+};
732+
733+static struct irqaction irq_call = {
734+ .handler = ipi_call_interrupt,
735+ .flags = IRQF_PERCPU,
736+ .name = "IPI_call"
737+};
738+#endif
739 
740 asmlinkage void plat_irq_dispatch(void)
741 {
742     unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
743     unsigned int i;
744 
745- if (pending & CAUSEF_IP7) {
746+ if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) {
747         do_IRQ(MIPS_CPU_TIMER_IRQ);
748         goto out;
749     } else {
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);
754                 goto out;
755@@ -247,41 +380,45 @@ void __init arch_init_irq(void)
756 {
757     int i;
758 
759- if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
760- panic("Failed to insert icu memory");
761+ for (i=0; i < IM_NUM; i++) {
762+ if (insert_resource(&iomem_resource, &ltq_icu_resource[i]) < 0)
763+ panic("Failed to insert icu memory\n");
764 
765- if (request_mem_region(ltq_icu_resource.start,
766- resource_size(&ltq_icu_resource), "icu") < 0)
767- panic("Failed to request icu memory");
768+ if (request_mem_region(ltq_icu_resource[i].start,
769+ resource_size(&ltq_icu_resource[i]), "icu") < 0)
770+ panic("Failed to request icu memory\n");
771 
772- ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
773- resource_size(&ltq_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(&ltq_icu_resource[i]));
778+ if (!ltq_icu_membase[i])
779+ panic("Failed to remap icu memory\n");
780+ }
781 
782- if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
783- panic("Failed to insert eiu memory");
784+ if (LTQ_EIU_BASE_ADDR) {
785+ if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
786+ panic("Failed to insert eiu memory\n");
787 
788- if (request_mem_region(ltq_eiu_resource.start,
789- resource_size(&ltq_eiu_resource), "eiu") < 0)
790- panic("Failed to request eiu memory");
791+ if (request_mem_region(ltq_eiu_resource.start,
792+ resource_size(&ltq_eiu_resource), "eiu") < 0)
793+ panic("Failed to request eiu memory\n");
794 
795- ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
796+ ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
797                 resource_size(&ltq_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");
802+ }
803 
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));
807-
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);
814+ }
815 
816     mips_cpu_irq_init();
817 
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);
822 
823     if (cpu_has_vint) {
824         pr_info("Setting up vectored interrupts\n");
825@@ -294,9 +431,9 @@ void __init arch_init_irq(void)
826     }
827 
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, &ltq_eiu_type,
836                 handle_level_irq);
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, &ltq_irq_type,
840                 handle_level_irq);
841 
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);
847+ }
848+ arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ,
849+ &irq_resched);
850+ arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call);
851+#endif
852+
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);
859 #endif
860+
861+ cp0_perfcount_irq = LTQ_PERF_IRQ;
862 }
863 
864 unsigned int __cpuinit get_c0_compare_int(void)
865 {
866+#ifdef CONFIG_SOC_SVIP
867+ return MIPS_CPU_TIMER_IRQ;
868+#else
869     return CP0_LEGACY_COMPARE_IRQ;
870+#endif
871 }
872diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
873index 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 */
880+
881+ /* FALCON */
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 */
885 };
886 
887 #endif
888diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
889index e34fcfd..00ad59c 100644
890--- a/arch/mips/lantiq/prom.c
891+++ b/arch/mips/lantiq/prom.c
892@@ -16,6 +16,10 @@
893 #include "prom.h"
894 #include "clk.h"
895 
896+/* access to the ebu needs to be locked between different drivers */
897+DEFINE_SPINLOCK(ebu_lock);
898+EXPORT_SYMBOL_GPL(ebu_lock);
899+
900 static struct ltq_soc_info soc_info;
901 
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);
905     int i;
906 
907+ arcs_cmdline[0] = '\0';
908+
909     for (i = 0; i < argc; i++) {
910- char *p = (char *) KSEG1ADDR(argv[i]);
911+ char *p = (char *) KSEG1ADDR(argv[i]);
912 
913- if (p && *p) {
914+ if (CPHYSADDR(p) && *p) {
915             strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
916             strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
917         }
918     }
919 }
920 
921-void __init prom_init(void)
922+void __iomem *ltq_remap_resource(struct resource *res)
923 {
924- struct clk *clk;
925+ __iomem void *ret = NULL;
926+ struct resource *lookup = lookup_resource(&iomem_resource, res->start);
927+
928+ if (lookup && strcmp(lookup->name, res->name)) {
929+ pr_err("conflicting memory range %s\n", res->name);
930+ return NULL;
931+ }
932+ if (!lookup) {
933+ if (insert_resource(&iomem_resource, res) < 0) {
934+ pr_err("Failed to insert %s memory\n", res->name);
935+ return NULL;
936+ }
937+ }
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);
941+ goto err_res;
942+ }
943 
944+ ret = ioremap_nocache(res->start, resource_size(res));
945+ if (!ret)
946+ goto err_mem;
947+
948+ pr_debug("remap: 0x%08X-0x%08X : \"%s\"\n",
949+ res->start, res->end, res->name);
950+ return ret;
951+
952+err_mem:
953+ panic("Failed to remap %s memory\n", res->name);
954+ release_mem_region(res->start, resource_size(res));
955+
956+err_res:
957+ release_resource(res);
958+ return NULL;
959+}
960+EXPORT_SYMBOL(ltq_remap_resource);
961+
962+void __init prom_init(void)
963+{
964     ltq_soc_detect(&soc_info);
965- clk_init();
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);
969- clk_put(clk);
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);
974     prom_init_cmdline();
975+
976+#if defined(CONFIG_MIPS_MT_SMP)
977+ if (register_vsmp_smp_ops())
978+ panic("failed to register_vsmp_smp_ops()");
979+#endif
980 }
981diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
982index b4229d9..51dba1b 100644
983--- a/arch/mips/lantiq/prom.h
984+++ b/arch/mips/lantiq/prom.h
985@@ -9,17 +9,21 @@
986 #ifndef _LTQ_PROM_H__
987 #define _LTQ_PROM_H__
988 
989+#define LTQ_SYS_REV_LEN 0x10
990 #define LTQ_SYS_TYPE_LEN 0x100
991 
992 struct ltq_soc_info {
993     unsigned char *name;
994     unsigned int rev;
995+ unsigned char rev_type[LTQ_SYS_REV_LEN];
996+ unsigned int srev;
997     unsigned int partnum;
998     unsigned int type;
999     unsigned char sys_type[LTQ_SYS_TYPE_LEN];
1000 };
1001 
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);
1005 
1006 #endif
1007--
10081.7.9.1
1009
1010

Archive Download this file



interactive