Root/target/linux/lantiq/patches-2.6.39/0001-MIPS-Lantiq-Add-initial-support-for-Lantiq-SoCs.patch

1From 9e0235e97ea2617beaacaa16ab5f0b9e75f4680e Mon Sep 17 00:00:00 2001
2From: John Crispin <blogic@openwrt.org>
3Date: Wed, 30 Mar 2011 09:27:47 +0200
4Subject: [PATCH 01/13] MIPS: Lantiq: Add initial support for Lantiq SoCs
5
6Add initial support for Mips based SoCs made by Lantiq. This series will add
7support for the XWAY family.
8
9The series allows booting a minimal system using a initramfs or NOR. Missing
10drivers and support for Amazon and GPON family will be provided in a later
11series.
12
13[Ralf: Remove some cargo cult programming and fixed formatting.]
14
15Signed-off-by: John Crispin <blogic@openwrt.org>
16Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
17Signed-off-by: David Daney <ddaney@caviumnetworks.com>
18Cc: linux-mips@linux-mips.org
19Patchwork: https://patchwork.linux-mips.org/patch/2252/
20Patchwork: https://patchwork.linux-mips.org/patch/2371/
21Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
22---
23 arch/mips/Kbuild.platforms | 1 +
24 arch/mips/Kconfig | 17 ++
25 arch/mips/include/asm/mach-lantiq/lantiq.h | 63 ++++++
26 arch/mips/include/asm/mach-lantiq/war.h | 24 ++
27 arch/mips/lantiq/Makefile | 9 +
28 arch/mips/lantiq/Platform | 7 +
29 arch/mips/lantiq/clk.c | 140 ++++++++++++
30 arch/mips/lantiq/clk.h | 18 ++
31 arch/mips/lantiq/early_printk.c | 33 +++
32 arch/mips/lantiq/irq.c | 326 ++++++++++++++++++++++++++++
33 arch/mips/lantiq/prom.c | 71 ++++++
34 arch/mips/lantiq/prom.h | 24 ++
35 arch/mips/lantiq/setup.c | 41 ++++
36 13 files changed, 774 insertions(+), 0 deletions(-)
37 create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq.h
38 create mode 100644 arch/mips/include/asm/mach-lantiq/war.h
39 create mode 100644 arch/mips/lantiq/Makefile
40 create mode 100644 arch/mips/lantiq/Platform
41 create mode 100644 arch/mips/lantiq/clk.c
42 create mode 100644 arch/mips/lantiq/clk.h
43 create mode 100644 arch/mips/lantiq/early_printk.c
44 create mode 100644 arch/mips/lantiq/irq.c
45 create mode 100644 arch/mips/lantiq/prom.c
46 create mode 100644 arch/mips/lantiq/prom.h
47 create mode 100644 arch/mips/lantiq/setup.c
48
49--- a/arch/mips/Kconfig
50+++ b/arch/mips/Kconfig
51@@ -212,6 +212,23 @@ config MACH_JZ4740
52     select HAVE_PWM
53     select HAVE_CLK
54 
55+config LANTIQ
56+ bool "Lantiq based platforms"
57+ select DMA_NONCOHERENT
58+ select IRQ_CPU
59+ select CEVT_R4K
60+ select CSRC_R4K
61+ select SYS_HAS_CPU_MIPS32_R1
62+ select SYS_HAS_CPU_MIPS32_R2
63+ select SYS_SUPPORTS_BIG_ENDIAN
64+ select SYS_SUPPORTS_32BIT_KERNEL
65+ select SYS_SUPPORTS_MULTITHREADING
66+ select SYS_HAS_EARLY_PRINTK
67+ select ARCH_REQUIRE_GPIOLIB
68+ select SWAP_IO_SPACE
69+ select BOOT_RAW
70+ select HAVE_CLK
71+
72 config LASAT
73     bool "LASAT Networks platforms"
74     select CEVT_R4K
75--- /dev/null
76+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
77@@ -0,0 +1,63 @@
78+/*
79+ * This program is free software; you can redistribute it and/or modify it
80+ * under the terms of the GNU General Public License version 2 as published
81+ * by the Free Software Foundation.
82+ *
83+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
84+ */
85+#ifndef _LANTIQ_H__
86+#define _LANTIQ_H__
87+
88+#include <linux/irq.h>
89+
90+/* generic reg access functions */
91+#define ltq_r32(reg) __raw_readl(reg)
92+#define ltq_w32(val, reg) __raw_writel(val, reg)
93+#define ltq_w32_mask(clear, set, reg) \
94+ ltq_w32((ltq_r32(reg) & ~(clear)) | (set), reg)
95+#define ltq_r8(reg) __raw_readb(reg)
96+#define ltq_w8(val, reg) __raw_writeb(val, reg)
97+
98+/* register access macros for EBU and CGU */
99+#define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y))
100+#define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x))
101+#define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y))
102+#define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x))
103+
104+extern __iomem void *ltq_ebu_membase;
105+extern __iomem void *ltq_cgu_membase;
106+
107+extern unsigned int ltq_get_cpu_ver(void);
108+extern unsigned int ltq_get_soc_type(void);
109+
110+/* clock speeds */
111+#define CLOCK_60M 60000000
112+#define CLOCK_83M 83333333
113+#define CLOCK_111M 111111111
114+#define CLOCK_133M 133333333
115+#define CLOCK_167M 166666667
116+#define CLOCK_200M 200000000
117+#define CLOCK_266M 266666666
118+#define CLOCK_333M 333333333
119+#define CLOCK_400M 400000000
120+
121+/* spinlock all ebu i/o */
122+extern spinlock_t ebu_lock;
123+
124+/* some irq helpers */
125+extern void ltq_disable_irq(struct irq_data *d);
126+extern void ltq_mask_and_ack_irq(struct irq_data *d);
127+extern void ltq_enable_irq(struct irq_data *d);
128+
129+/* find out what caused the last cpu reset */
130+extern int ltq_reset_cause(void);
131+#define LTQ_RST_CAUSE_WDTRST 0x20
132+
133+#define IOPORT_RESOURCE_START 0x10000000
134+#define IOPORT_RESOURCE_END 0xffffffff
135+#define IOMEM_RESOURCE_START 0x10000000
136+#define IOMEM_RESOURCE_END 0xffffffff
137+#define LTQ_FLASH_START 0x10000000
138+#define LTQ_FLASH_MAX 0x04000000
139+
140+#endif
141--- /dev/null
142+++ b/arch/mips/include/asm/mach-lantiq/war.h
143@@ -0,0 +1,24 @@
144+/*
145+ * This file is subject to the terms and conditions of the GNU General Public
146+ * License. See the file "COPYING" in the main directory of this archive
147+ * for more details.
148+ *
149+ */
150+#ifndef __ASM_MIPS_MACH_LANTIQ_WAR_H
151+#define __ASM_MIPS_MACH_LANTIQ_WAR_H
152+
153+#define R4600_V1_INDEX_ICACHEOP_WAR 0
154+#define R4600_V1_HIT_CACHEOP_WAR 0
155+#define R4600_V2_HIT_CACHEOP_WAR 0
156+#define R5432_CP0_INTERRUPT_WAR 0
157+#define BCM1250_M3_WAR 0
158+#define SIBYTE_1956_WAR 0
159+#define MIPS4K_ICACHE_REFILL_WAR 0
160+#define MIPS_CACHE_SYNC_WAR 0
161+#define TX49XX_ICACHE_INDEX_INV_WAR 0
162+#define RM9000_CDEX_SMP_WAR 0
163+#define ICACHE_REFILLS_WORKAROUND_WAR 0
164+#define R10000_LLSC_WAR 0
165+#define MIPS34K_MISSED_ITLB_WAR 0
166+
167+#endif
168--- /dev/null
169+++ b/arch/mips/lantiq/Makefile
170@@ -0,0 +1,9 @@
171+# Copyright (C) 2010 John Crispin <blogic@openwrt.org>
172+#
173+# This program is free software; you can redistribute it and/or modify it
174+# under the terms of the GNU General Public License version 2 as published
175+# by the Free Software Foundation.
176+
177+obj-y := irq.o setup.o clk.o prom.o
178+
179+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
180--- /dev/null
181+++ b/arch/mips/lantiq/Platform
182@@ -0,0 +1,7 @@
183+#
184+# Lantiq
185+#
186+
187+platform-$(CONFIG_LANTIQ) += lantiq/
188+cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
189+load-$(CONFIG_LANTIQ) = 0xffffffff80002000
190--- /dev/null
191+++ b/arch/mips/lantiq/clk.c
192@@ -0,0 +1,144 @@
193+/*
194+ * This program is free software; you can redistribute it and/or modify it
195+ * under the terms of the GNU General Public License version 2 as published
196+ * by the Free Software Foundation.
197+ *
198+ * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
199+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
200+ */
201+#include <linux/io.h>
202+#include <linux/module.h>
203+#include <linux/init.h>
204+#include <linux/kernel.h>
205+#include <linux/types.h>
206+#include <linux/clk.h>
207+#include <linux/err.h>
208+#include <linux/list.h>
209+
210+#include <asm/time.h>
211+#include <asm/irq.h>
212+#include <asm/div64.h>
213+
214+#include <lantiq_soc.h>
215+
216+#include "clk.h"
217+
218+struct clk {
219+ const char *name;
220+ unsigned long rate;
221+ unsigned long (*get_rate) (void);
222+};
223+
224+static struct clk *cpu_clk;
225+static int cpu_clk_cnt;
226+
227+/* lantiq socs have 3 static clocks */
228+static struct clk cpu_clk_generic[] = {
229+ {
230+ .name = "cpu",
231+ .get_rate = ltq_get_cpu_hz,
232+ }, {
233+ .name = "fpi",
234+ .get_rate = ltq_get_fpi_hz,
235+ }, {
236+ .name = "io",
237+ .get_rate = ltq_get_io_region_clock,
238+ },
239+};
240+
241+#ifdef CONFIG_SOC_TYPE_XWAY
242+static struct resource ltq_cgu_resource = {
243+ .name = "cgu",
244+ .start = LTQ_CGU_BASE_ADDR,
245+ .end = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
246+ .flags = IORESOURCE_MEM,
247+};
248+
249+/* remapped clock register range */
250+void __iomem *ltq_cgu_membase;
251+#endif
252+
253+void clk_init(void)
254+{
255+ cpu_clk = cpu_clk_generic;
256+ cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
257+}
258+
259+static inline int clk_good(struct clk *clk)
260+{
261+ return clk && !IS_ERR(clk);
262+}
263+
264+unsigned long clk_get_rate(struct clk *clk)
265+{
266+ if (unlikely(!clk_good(clk)))
267+ return 0;
268+
269+ if (clk->rate != 0)
270+ return clk->rate;
271+
272+ if (clk->get_rate != NULL)
273+ return clk->get_rate();
274+
275+ return 0;
276+}
277+EXPORT_SYMBOL(clk_get_rate);
278+
279+struct clk *clk_get(struct device *dev, const char *id)
280+{
281+ int i;
282+
283+ for (i = 0; i < cpu_clk_cnt; i++)
284+ if (!strcmp(id, cpu_clk[i].name))
285+ return &cpu_clk[i];
286+ BUG();
287+ return ERR_PTR(-ENOENT);
288+}
289+EXPORT_SYMBOL(clk_get);
290+
291+void clk_put(struct clk *clk)
292+{
293+ /* not used */
294+}
295+EXPORT_SYMBOL(clk_put);
296+
297+static inline u32 ltq_get_counter_resolution(void)
298+{
299+ u32 res;
300+
301+ __asm__ __volatile__(
302+ ".set push\n"
303+ ".set mips32r2\n"
304+ "rdhwr %0, $3\n"
305+ ".set pop\n"
306+ : "=&r" (res)
307+ : /* no input */
308+ : "memory");
309+
310+ return res;
311+}
312+
313+void __init plat_time_init(void)
314+{
315+ struct clk *clk;
316+
317+#ifdef CONFIG_SOC_TYPE_XWAY
318+ if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
319+ panic("Failed to insert cgu memory\n");
320+
321+ if (request_mem_region(ltq_cgu_resource.start,
322+ resource_size(&ltq_cgu_resource), "cgu") < 0)
323+ panic("Failed to request cgu memory\n");
324+
325+ ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
326+ resource_size(&ltq_cgu_resource));
327+ if (!ltq_cgu_membase) {
328+ pr_err("Failed to remap cgu memory\n");
329+ unreachable();
330+ }
331+#endif
332+ clk = clk_get(0, "cpu");
333+ mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
334+ write_c0_compare(read_c0_count());
335+ clk_put(clk);
336+}
337--- /dev/null
338+++ b/arch/mips/lantiq/clk.h
339@@ -0,0 +1,18 @@
340+/*
341+ * This program is free software; you can redistribute it and/or modify it
342+ * under the terms of the GNU General Public License version 2 as published
343+ * by the Free Software Foundation.
344+ *
345+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
346+ */
347+
348+#ifndef _LTQ_CLK_H__
349+#define _LTQ_CLK_H__
350+
351+extern void clk_init(void);
352+
353+extern unsigned long ltq_get_cpu_hz(void);
354+extern unsigned long ltq_get_fpi_hz(void);
355+extern unsigned long ltq_get_io_region_clock(void);
356+
357+#endif
358--- /dev/null
359+++ b/arch/mips/lantiq/early_printk.c
360@@ -0,0 +1,37 @@
361+/*
362+ * This program is free software; you can redistribute it and/or modify it
363+ * under the terms of the GNU General Public License version 2 as published
364+ * by the Free Software Foundation.
365+ *
366+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
367+ */
368+
369+#include <linux/init.h>
370+#include <linux/cpu.h>
371+
372+#include <lantiq.h>
373+#include <lantiq_soc.h>
374+
375+/* no ioremap possible at this early stage, lets use KSEG1 instead */
376+#ifdef CONFIG_SOC_FALCON
377+#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC0_BASE_ADDR)
378+#else
379+#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
380+#endif
381+#define ASC_BUF 1024
382+#define LTQ_ASC_FSTAT ((u32 *)(LTQ_ASC_BASE + 0x0048))
383+#define LTQ_ASC_TBUF ((u32 *)(LTQ_ASC_BASE + 0x0020))
384+#define TXMASK 0x3F00
385+#define TXOFFSET 8
386+
387+void prom_putchar(char c)
388+{
389+ unsigned long flags;
390+
391+ local_irq_save(flags);
392+ do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
393+ if (c == '\n')
394+ ltq_w32('\r', LTQ_ASC_TBUF);
395+ ltq_w32(c, LTQ_ASC_TBUF);
396+ local_irq_restore(flags);
397+}
398--- /dev/null
399+++ b/arch/mips/lantiq/irq.c
400@@ -0,0 +1,339 @@
401+/*
402+ * This program is free software; you can redistribute it and/or modify it
403+ * under the terms of the GNU General Public License version 2 as published
404+ * by the Free Software Foundation.
405+ *
406+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
407+ * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
408+ */
409+
410+#include <linux/interrupt.h>
411+#include <linux/ioport.h>
412+#include <linux/module.h>
413+
414+#include <asm/bootinfo.h>
415+#include <asm/irq_cpu.h>
416+
417+#include <lantiq_soc.h>
418+#include <irq.h>
419+
420+/* register definitions */
421+#define LTQ_ICU_IM0_ISR 0x0000
422+#define LTQ_ICU_IM0_IER 0x0008
423+#define LTQ_ICU_IM0_IOSR 0x0010
424+#define LTQ_ICU_IM0_IRSR 0x0018
425+#define LTQ_ICU_IM0_IMR 0x0020
426+#define LTQ_ICU_IM1_ISR 0x0028
427+#define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
428+
429+#ifdef CONFIG_SOC_TYPE_XWAY
430+
431+#define LTQ_EIU_EXIN_C 0x0000
432+#define LTQ_EIU_EXIN_INIC 0x0004
433+#define LTQ_EIU_EXIN_INEN 0x000C
434+
435+/* irq numbers used by the external interrupt unit (EIU) */
436+#define LTQ_EIU_IR0 (INT_NUM_IM4_IRL0 + 30)
437+#define LTQ_EIU_IR1 (INT_NUM_IM3_IRL0 + 31)
438+#define LTQ_EIU_IR2 (INT_NUM_IM1_IRL0 + 26)
439+#define LTQ_EIU_IR3 INT_NUM_IM1_IRL0
440+#define LTQ_EIU_IR4 (INT_NUM_IM1_IRL0 + 1)
441+#define LTQ_EIU_IR5 (INT_NUM_IM1_IRL0 + 2)
442+#define LTQ_EIU_IR6 (INT_NUM_IM2_IRL0 + 30)
443+
444+#define MAX_EIU 6
445+
446+/* irqs generated by device attached to the EBU need to be acked in
447+ * a special manner
448+ */
449+#define LTQ_ICU_EBU_IRQ 22
450+
451+#define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y))
452+#define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x))
453+
454+static unsigned short ltq_eiu_irq[MAX_EIU] = {
455+ LTQ_EIU_IR0,
456+ LTQ_EIU_IR1,
457+ LTQ_EIU_IR2,
458+ LTQ_EIU_IR3,
459+ LTQ_EIU_IR4,
460+ LTQ_EIU_IR5,
461+};
462+
463+static void __iomem *ltq_eiu_membase;
464+
465+static struct resource ltq_eiu_resource = {
466+ .name = "eiu",
467+ .start = LTQ_EIU_BASE_ADDR,
468+ .end = LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
469+ .flags = IORESOURCE_MEM,
470+};
471+
472+#endif
473+
474+static struct resource ltq_icu_resource = {
475+ .name = "icu",
476+ .start = LTQ_ICU_BASE_ADDR,
477+ .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
478+ .flags = IORESOURCE_MEM,
479+};
480+
481+#define ltq_icu_w32(x, y) ltq_w32((x), ltq_icu_membase + (y))
482+#define ltq_icu_r32(x) ltq_r32(ltq_icu_membase + (x))
483+
484+static void __iomem *ltq_icu_membase;
485+
486+
487+void ltq_disable_irq(struct irq_data *d)
488+{
489+ u32 ier = LTQ_ICU_IM0_IER;
490+ int irq_nr = d->irq - INT_NUM_IRQ0;
491+
492+ ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
493+ irq_nr %= INT_NUM_IM_OFFSET;
494+ ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
495+}
496+
497+void ltq_mask_and_ack_irq(struct irq_data *d)
498+{
499+ u32 ier = LTQ_ICU_IM0_IER;
500+ u32 isr = LTQ_ICU_IM0_ISR;
501+ int irq_nr = d->irq - INT_NUM_IRQ0;
502+
503+ ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
504+ isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
505+ irq_nr %= INT_NUM_IM_OFFSET;
506+ ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
507+ ltq_icu_w32((1 << irq_nr), isr);
508+}
509+EXPORT_SYMBOL(ltq_mask_and_ack_irq);
510+
511+static void ltq_ack_irq(struct irq_data *d)
512+{
513+ u32 isr = LTQ_ICU_IM0_ISR;
514+ int irq_nr = d->irq - INT_NUM_IRQ0;
515+
516+ isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
517+ irq_nr %= INT_NUM_IM_OFFSET;
518+ ltq_icu_w32((1 << irq_nr), isr);
519+}
520+
521+void ltq_enable_irq(struct irq_data *d)
522+{
523+ u32 ier = LTQ_ICU_IM0_IER;
524+ int irq_nr = d->irq - INT_NUM_IRQ0;
525+
526+ ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
527+ irq_nr %= INT_NUM_IM_OFFSET;
528+ ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier);
529+}
530+
531+#ifdef CONFIG_SOC_TYPE_XWAY
532+static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
533+{
534+ int i;
535+ int irq_nr = d->irq - INT_NUM_IRQ0;
536+
537+ ltq_enable_irq(d);
538+ for (i = 0; i < MAX_EIU; i++) {
539+ if (irq_nr == ltq_eiu_irq[i]) {
540+ /* low level - we should really handle set_type */
541+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
542+ (0x6 << (i * 4)), LTQ_EIU_EXIN_C);
543+ /* clear all pending */
544+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~(1 << i),
545+ LTQ_EIU_EXIN_INIC);
546+ /* enable */
547+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | (1 << i),
548+ LTQ_EIU_EXIN_INEN);
549+ break;
550+ }
551+ }
552+
553+ return 0;
554+}
555+
556+static void ltq_shutdown_eiu_irq(struct irq_data *d)
557+{
558+ int i;
559+ int irq_nr = d->irq - INT_NUM_IRQ0;
560+
561+ ltq_disable_irq(d);
562+ for (i = 0; i < MAX_EIU; i++) {
563+ if (irq_nr == ltq_eiu_irq[i]) {
564+ /* disable */
565+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i),
566+ LTQ_EIU_EXIN_INEN);
567+ break;
568+ }
569+ }
570+}
571+#endif
572+
573+static struct irq_chip ltq_irq_type = {
574+ "icu",
575+ .irq_enable = ltq_enable_irq,
576+ .irq_disable = ltq_disable_irq,
577+ .irq_unmask = ltq_enable_irq,
578+ .irq_ack = ltq_ack_irq,
579+ .irq_mask = ltq_disable_irq,
580+ .irq_mask_ack = ltq_mask_and_ack_irq,
581+};
582+
583+#ifdef CONFIG_SOC_TYPE_XWAY
584+static struct irq_chip ltq_eiu_type = {
585+ "eiu",
586+ .irq_startup = ltq_startup_eiu_irq,
587+ .irq_shutdown = ltq_shutdown_eiu_irq,
588+ .irq_enable = ltq_enable_irq,
589+ .irq_disable = ltq_disable_irq,
590+ .irq_unmask = ltq_enable_irq,
591+ .irq_ack = ltq_ack_irq,
592+ .irq_mask = ltq_disable_irq,
593+ .irq_mask_ack = ltq_mask_and_ack_irq,
594+};
595+#endif
596+
597+static void ltq_hw_irqdispatch(int module)
598+{
599+ u32 irq;
600+
601+ irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET));
602+ if (irq == 0)
603+ return;
604+
605+ /* silicon bug causes only the msb set to 1 to be valid. all
606+ * other bits might be bogus
607+ */
608+ irq = __fls(irq);
609+ do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
610+
611+#ifdef CONFIG_SOC_TYPE_XWAY
612+ /* if this is a EBU irq, we need to ack it or get a deadlock */
613+ if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
614+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
615+ LTQ_EBU_PCC_ISTAT);
616+#endif
617+}
618+
619+#define DEFINE_HWx_IRQDISPATCH(x) \
620+ static void ltq_hw ## x ## _irqdispatch(void) \
621+ { \
622+ ltq_hw_irqdispatch(x); \
623+ }
624+DEFINE_HWx_IRQDISPATCH(0)
625+DEFINE_HWx_IRQDISPATCH(1)
626+DEFINE_HWx_IRQDISPATCH(2)
627+DEFINE_HWx_IRQDISPATCH(3)
628+DEFINE_HWx_IRQDISPATCH(4)
629+
630+static void ltq_hw5_irqdispatch(void)
631+{
632+ do_IRQ(MIPS_CPU_TIMER_IRQ);
633+}
634+
635+asmlinkage void plat_irq_dispatch(void)
636+{
637+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
638+ unsigned int i;
639+
640+ if (pending & CAUSEF_IP7) {
641+ do_IRQ(MIPS_CPU_TIMER_IRQ);
642+ goto out;
643+ } else {
644+ for (i = 0; i < 5; i++) {
645+ if (pending & (CAUSEF_IP2 << i)) {
646+ ltq_hw_irqdispatch(i);
647+ goto out;
648+ }
649+ }
650+ }
651+ pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
652+
653+out:
654+ return;
655+}
656+
657+static struct irqaction cascade = {
658+ .handler = no_action,
659+ .flags = IRQF_DISABLED,
660+ .name = "cascade",
661+};
662+
663+void __init arch_init_irq(void)
664+{
665+ int i;
666+
667+ if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
668+ panic("Failed to insert icu memory\n");
669+
670+ if (request_mem_region(ltq_icu_resource.start,
671+ resource_size(&ltq_icu_resource), "icu") < 0)
672+ panic("Failed to request icu memory\n");
673+
674+ ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
675+ resource_size(&ltq_icu_resource));
676+ if (!ltq_icu_membase)
677+ panic("Failed to remap icu memory\n");
678+
679+#ifdef CONFIG_SOC_TYPE_XWAY
680+ if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
681+ panic("Failed to insert eiu memory\n");
682+
683+ if (request_mem_region(ltq_eiu_resource.start,
684+ resource_size(&ltq_eiu_resource), "eiu") < 0)
685+ panic("Failed to request eiu memory\n");
686+
687+ ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
688+ resource_size(&ltq_eiu_resource));
689+ if (!ltq_eiu_membase)
690+ panic("Failed to remap eiu memory\n");
691+#endif
692+ /* make sure all irqs are turned off by default */
693+ for (i = 0; i < 5; i++)
694+ ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET));
695+
696+ /* clear all possibly pending interrupts */
697+ ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
698+
699+ mips_cpu_irq_init();
700+
701+ for (i = 2; i <= 6; i++)
702+ setup_irq(i, &cascade);
703+
704+ if (cpu_has_vint) {
705+ pr_info("Setting up vectored interrupts\n");
706+ set_vi_handler(2, ltq_hw0_irqdispatch);
707+ set_vi_handler(3, ltq_hw1_irqdispatch);
708+ set_vi_handler(4, ltq_hw2_irqdispatch);
709+ set_vi_handler(5, ltq_hw3_irqdispatch);
710+ set_vi_handler(6, ltq_hw4_irqdispatch);
711+ set_vi_handler(7, ltq_hw5_irqdispatch);
712+ }
713+
714+ for (i = INT_NUM_IRQ0;
715+ i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
716+#ifdef CONFIG_SOC_TYPE_XWAY
717+ if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) || (i == LTQ_EIU_IR2))
718+ irq_set_chip_and_handler(i, &ltq_eiu_type, handle_level_irq);
719+ /* EIU3-5 only exist on ar9 and vr9 */
720+ else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
721+ (i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
722+ irq_set_chip_and_handler(i, &ltq_eiu_type, handle_level_irq);
723+ else
724+#endif
725+ irq_set_chip_and_handler(i, &ltq_irq_type, handle_level_irq);
726+
727+#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
728+ set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
729+ IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
730+#else
731+ set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
732+ IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
733+#endif
734+}
735+
736+unsigned int __cpuinit get_c0_compare_int(void)
737+{
738+ return CP0_LEGACY_COMPARE_IRQ;
739+}
740--- /dev/null
741+++ b/arch/mips/lantiq/prom.c
742@@ -0,0 +1,71 @@
743+/*
744+ * This program is free software; you can redistribute it and/or modify it
745+ * under the terms of the GNU General Public License version 2 as published
746+ * by the Free Software Foundation.
747+ *
748+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
749+ */
750+
751+#include <linux/module.h>
752+#include <linux/clk.h>
753+#include <asm/bootinfo.h>
754+#include <asm/time.h>
755+
756+#include <lantiq.h>
757+
758+#include "prom.h"
759+#include "clk.h"
760+
761+static struct ltq_soc_info soc_info;
762+
763+unsigned int ltq_get_cpu_ver(void)
764+{
765+ return soc_info.rev;
766+}
767+EXPORT_SYMBOL(ltq_get_cpu_ver);
768+
769+unsigned int ltq_get_soc_type(void)
770+{
771+ return soc_info.type;
772+}
773+EXPORT_SYMBOL(ltq_get_soc_type);
774+
775+const char *get_system_type(void)
776+{
777+ return soc_info.sys_type;
778+}
779+
780+void prom_free_prom_memory(void)
781+{
782+}
783+
784+static void __init prom_init_cmdline(void)
785+{
786+ int argc = fw_arg0;
787+ char **argv = (char **) KSEG1ADDR(fw_arg1);
788+ int i;
789+
790+ for (i = 0; i < argc; i++) {
791+ char *p = (char *) KSEG1ADDR(argv[i]);
792+
793+ if (p && *p) {
794+ strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
795+ strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
796+ }
797+ }
798+}
799+
800+void __init prom_init(void)
801+{
802+ struct clk *clk;
803+
804+ ltq_soc_detect(&soc_info);
805+ clk_init();
806+ clk = clk_get(0, "cpu");
807+ snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
808+ soc_info.name, soc_info.rev);
809+ clk_put(clk);
810+ soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
811+ pr_info("SoC: %s\n", soc_info.sys_type);
812+ prom_init_cmdline();
813+}
814--- /dev/null
815+++ b/arch/mips/lantiq/prom.h
816@@ -0,0 +1,24 @@
817+/*
818+ * This program is free software; you can redistribute it and/or modify it
819+ * under the terms of the GNU General Public License version 2 as published
820+ * by the Free Software Foundation.
821+ *
822+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
823+ */
824+
825+#ifndef _LTQ_PROM_H__
826+#define _LTQ_PROM_H__
827+
828+#define LTQ_SYS_TYPE_LEN 0x100
829+
830+struct ltq_soc_info {
831+ unsigned char *name;
832+ unsigned int rev;
833+ unsigned int partnum;
834+ unsigned int type;
835+ unsigned char sys_type[LTQ_SYS_TYPE_LEN];
836+};
837+
838+extern void ltq_soc_detect(struct ltq_soc_info *i);
839+
840+#endif
841--- /dev/null
842+++ b/arch/mips/lantiq/setup.c
843@@ -0,0 +1,41 @@
844+/*
845+ * This program is free software; you can redistribute it and/or modify it
846+ * under the terms of the GNU General Public License version 2 as published
847+ * by the Free Software Foundation.
848+ *
849+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
850+ */
851+
852+#include <linux/kernel.h>
853+#include <linux/module.h>
854+#include <linux/io.h>
855+#include <linux/ioport.h>
856+#include <asm/bootinfo.h>
857+
858+#include <lantiq_soc.h>
859+
860+void __init plat_mem_setup(void)
861+{
862+ /* assume 16M as default incase uboot fails to pass proper ramsize */
863+ unsigned long memsize = 16;
864+ char **envp = (char **) KSEG1ADDR(fw_arg2);
865+
866+ ioport_resource.start = IOPORT_RESOURCE_START;
867+ ioport_resource.end = IOPORT_RESOURCE_END;
868+ iomem_resource.start = IOMEM_RESOURCE_START;
869+ iomem_resource.end = IOMEM_RESOURCE_END;
870+
871+ set_io_port_base((unsigned long) KSEG1);
872+
873+ while (*envp) {
874+ char *e = (char *)KSEG1ADDR(*envp);
875+ if (!strncmp(e, "memsize=", 8)) {
876+ e += 8;
877+ if (strict_strtoul(e, 0, &memsize))
878+ pr_warn("bad memsize specified\n");
879+ }
880+ envp++;
881+ }
882+ memsize *= 1024 * 1024;
883+ add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
884+}
885--- a/arch/mips/Kbuild.platforms
886+++ b/arch/mips/Kbuild.platforms
887@@ -11,6 +11,7 @@ platforms += dec
888 platforms += emma
889 platforms += jazz
890 platforms += jz4740
891+platforms += lantiq
892 platforms += lasat
893 platforms += loongson
894 platforms += mipssim
895

Archive Download this file



interactive