cns3xxx: merge gpio patches
[openwrt.git] / target / linux / lantiq / patches-3.3 / 0004-lantiq-core-support.patch
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
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
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
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
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
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
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
76  
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
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  }
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
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
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
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)),
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
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);
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
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  }
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
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  }
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 */
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
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
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  }
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
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 -- 
1008 1.7.9.1
1009