diff options
Diffstat (limited to 'target/linux/lantiq/patches-3.3/0004-lantiq-core-support.patch')
-rw-r--r-- | target/linux/lantiq/patches-3.3/0004-lantiq-core-support.patch | 1009 |
1 files changed, 1009 insertions, 0 deletions
diff --git a/target/linux/lantiq/patches-3.3/0004-lantiq-core-support.patch b/target/linux/lantiq/patches-3.3/0004-lantiq-core-support.patch new file mode 100644 index 0000000000..d048988ebb --- /dev/null +++ b/target/linux/lantiq/patches-3.3/0004-lantiq-core-support.patch @@ -0,0 +1,1009 @@ +From 94a0ad7aea40f0143670cfb6d5794f2f4b6b1aa7 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Fri, 3 Aug 2012 09:51:32 +0200 +Subject: [PATCH 04/25] lantiq core support + +--- + arch/mips/Kconfig | 6 +- + arch/mips/lantiq/Kconfig | 10 ++ + arch/mips/lantiq/Makefile | 2 + + arch/mips/lantiq/Platform | 2 + + arch/mips/lantiq/clk.c | 136 +++++++++++---------- + arch/mips/lantiq/clk.h | 59 ++++++++- + arch/mips/lantiq/devices.c | 30 +---- + arch/mips/lantiq/devices.h | 4 + + arch/mips/lantiq/early_printk.c | 14 ++- + arch/mips/lantiq/irq.c | 262 +++++++++++++++++++++++++++++++-------- + arch/mips/lantiq/machtypes.h | 5 + + arch/mips/lantiq/prom.c | 63 ++++++++-- + arch/mips/lantiq/prom.h | 4 + + 13 files changed, 435 insertions(+), 162 deletions(-) + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index cffcae6..0e2ce5d 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -228,8 +228,11 @@ config LANTIQ + select ARCH_REQUIRE_GPIOLIB + select SWAP_IO_SPACE + select BOOT_RAW +- select HAVE_CLK ++ select HAVE_MACH_CLKDEV ++ select CLKDEV_LOOKUP ++ select HAVE_OPROFILE + select MIPS_MACHINE ++ select USB_ARCH_HAS_HCD + + config LASAT + bool "LASAT Networks platforms" +@@ -2391,6 +2394,7 @@ config PCI_DOMAINS + bool + + source "drivers/pci/Kconfig" ++source "drivers/pci/pcie/Kconfig" + + # + # ISA support is now enabled via select. Too many systems still have the one +diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig +index 3fccf21..b7ba0fe 100644 +--- a/arch/mips/lantiq/Kconfig ++++ b/arch/mips/lantiq/Kconfig +@@ -16,8 +16,18 @@ config SOC_XWAY + bool "XWAY" + select SOC_TYPE_XWAY + select HW_HAS_PCI ++ ++config SOC_FALCON ++ bool "FALCON" ++ ++config SOC_SVIP ++ bool "SVIP" ++ select MIPS_CPU_SCACHE ++ + endchoice + + source "arch/mips/lantiq/xway/Kconfig" ++source "arch/mips/lantiq/falcon/Kconfig" ++source "arch/mips/lantiq/svip/Kconfig" + + endif +diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile +index e5dae0e..db1ce50 100644 +--- a/arch/mips/lantiq/Makefile ++++ b/arch/mips/lantiq/Makefile +@@ -9,3 +9,5 @@ obj-y := irq.o setup.o clk.o prom.o devices.o + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + + obj-$(CONFIG_SOC_TYPE_XWAY) += xway/ ++obj-$(CONFIG_SOC_FALCON) += falcon/ ++obj-$(CONFIG_SOC_SVIP) += svip/ +diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform +index f3dff05..857548c 100644 +--- a/arch/mips/lantiq/Platform ++++ b/arch/mips/lantiq/Platform +@@ -6,3 +6,5 @@ platform-$(CONFIG_LANTIQ) += lantiq/ + cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq + load-$(CONFIG_LANTIQ) = 0xffffffff80002000 + cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway ++cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon ++cflags-$(CONFIG_SOC_SVIP) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/svip +diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c +index 412814f..6c95f5e 100644 +--- a/arch/mips/lantiq/clk.c ++++ b/arch/mips/lantiq/clk.c +@@ -12,6 +12,7 @@ + #include <linux/kernel.h> + #include <linux/types.h> + #include <linux/clk.h> ++#include <linux/clkdev.h> + #include <linux/err.h> + #include <linux/list.h> + +@@ -22,44 +23,32 @@ + #include <lantiq_soc.h> + + #include "clk.h" ++#include "prom.h" + +-struct clk { +- const char *name; +- unsigned long rate; +- unsigned long (*get_rate) (void); +-}; ++/* lantiq socs have 3 static clocks */ ++static struct clk cpu_clk_generic[3]; + +-static struct clk *cpu_clk; +-static int cpu_clk_cnt; ++void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io) ++{ ++ cpu_clk_generic[0].rate = cpu; ++ cpu_clk_generic[1].rate = fpi; ++ cpu_clk_generic[2].rate = io; ++} + +-/* lantiq socs have 3 static clocks */ +-static struct clk cpu_clk_generic[] = { +- { +- .name = "cpu", +- .get_rate = ltq_get_cpu_hz, +- }, { +- .name = "fpi", +- .get_rate = ltq_get_fpi_hz, +- }, { +- .name = "io", +- .get_rate = ltq_get_io_region_clock, +- }, +-}; +- +-static struct resource ltq_cgu_resource = { +- .name = "cgu", +- .start = LTQ_CGU_BASE_ADDR, +- .end = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1, +- .flags = IORESOURCE_MEM, +-}; +- +-/* remapped clock register range */ +-void __iomem *ltq_cgu_membase; +- +-void clk_init(void) ++struct clk *clk_get_cpu(void) + { +- cpu_clk = cpu_clk_generic; +- cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic); ++ return &cpu_clk_generic[0]; ++} ++ ++struct clk *clk_get_fpi(void) ++{ ++ return &cpu_clk_generic[1]; ++} ++EXPORT_SYMBOL_GPL(clk_get_fpi); ++ ++struct clk *clk_get_io(void) ++{ ++ return &cpu_clk_generic[2]; + } + + static inline int clk_good(struct clk *clk) +@@ -82,37 +71,60 @@ unsigned long clk_get_rate(struct clk *clk) + } + EXPORT_SYMBOL(clk_get_rate); + +-struct clk *clk_get(struct device *dev, const char *id) ++int clk_set_rate(struct clk *clk, unsigned long rate) + { +- int i; +- +- for (i = 0; i < cpu_clk_cnt; i++) +- if (!strcmp(id, cpu_clk[i].name)) +- return &cpu_clk[i]; +- BUG(); +- return ERR_PTR(-ENOENT); +-} +-EXPORT_SYMBOL(clk_get); ++ if (unlikely(!clk_good(clk))) ++ return 0; + +-void clk_put(struct clk *clk) +-{ +- /* not used */ ++ clk->rate = rate; ++ return 0; + } +-EXPORT_SYMBOL(clk_put); ++EXPORT_SYMBOL(clk_set_rate); + + int clk_enable(struct clk *clk) + { +- /* not used */ +- return 0; ++ if (unlikely(!clk_good(clk))) ++ return -1; ++ ++ if (clk->enable) ++ return clk->enable(clk); ++ ++ return -1; + } + EXPORT_SYMBOL(clk_enable); + + void clk_disable(struct clk *clk) + { +- /* not used */ ++ if (unlikely(!clk_good(clk))) ++ return; ++ ++ if (clk->disable) ++ clk->disable(clk); + } + EXPORT_SYMBOL(clk_disable); + ++int clk_activate(struct clk *clk) ++{ ++ if (unlikely(!clk_good(clk))) ++ return -1; ++ ++ if (clk->activate) ++ return clk->activate(clk); ++ ++ return -1; ++} ++EXPORT_SYMBOL(clk_activate); ++ ++void clk_deactivate(struct clk *clk) ++{ ++ if (unlikely(!clk_good(clk))) ++ return; ++ ++ if (clk->deactivate) ++ clk->deactivate(clk); ++} ++EXPORT_SYMBOL(clk_deactivate); ++ + static inline u32 ltq_get_counter_resolution(void) + { + u32 res; +@@ -133,21 +145,17 @@ void __init plat_time_init(void) + { + struct clk *clk; + +- if (insert_resource(&iomem_resource, <q_cgu_resource) < 0) +- panic("Failed to insert cgu memory"); +- +- if (request_mem_region(ltq_cgu_resource.start, +- resource_size(<q_cgu_resource), "cgu") < 0) +- panic("Failed to request cgu memory"); ++ ltq_soc_init(); + +- ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start, +- resource_size(<q_cgu_resource)); +- if (!ltq_cgu_membase) { +- pr_err("Failed to remap cgu memory\n"); +- unreachable(); +- } +- clk = clk_get(0, "cpu"); ++ clk = clk_get_cpu(); + mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution(); ++#ifdef CONFIG_SOC_SVIP ++ write_c0_count(0); ++ write_c0_compare(mips_hpt_frequency / HZ); ++ enable_irq(MIPS_CPU_TIMER_IRQ); ++#else + write_c0_compare(read_c0_count()); ++#endif ++ pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000); + clk_put(clk); + } +diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h +index 3328925..564ef03 100644 +--- a/arch/mips/lantiq/clk.h ++++ b/arch/mips/lantiq/clk.h +@@ -9,10 +9,61 @@ + #ifndef _LTQ_CLK_H__ + #define _LTQ_CLK_H__ + +-extern void clk_init(void); ++#include <linux/clkdev.h> + +-extern unsigned long ltq_get_cpu_hz(void); +-extern unsigned long ltq_get_fpi_hz(void); +-extern unsigned long ltq_get_io_region_clock(void); ++/* clock speeds */ ++#define CLOCK_33M 33333333 ++#define CLOCK_60M 60000000 ++#define CLOCK_62_5M 62500000 ++#define CLOCK_83M 83333333 ++#define CLOCK_83_5M 83500000 ++#define CLOCK_98_304M 98304000 ++#define CLOCK_100M 100000000 ++#define CLOCK_111M 111111111 ++#define CLOCK_125M 125000000 ++#define CLOCK_133M 133333333 ++#define CLOCK_150M 150000000 ++#define CLOCK_166M 166666666 ++#define CLOCK_167M 166666667 ++#define CLOCK_196_608M 196608000 ++#define CLOCK_200M 200000000 ++#define CLOCK_250M 250000000 ++#define CLOCK_266M 266666666 ++#define CLOCK_300M 300000000 ++#define CLOCK_333M 333333333 ++#define CLOCK_393M 393215332 ++#define CLOCK_400M 400000000 ++#define CLOCK_500M 500000000 ++#define CLOCK_600M 600000000 ++ ++struct clk { ++ struct clk_lookup cl; ++ unsigned long rate; ++ unsigned int module; ++ unsigned int bits; ++ unsigned long (*get_rate) (void); ++ int (*enable) (struct clk *clk); ++ void (*disable) (struct clk *clk); ++ int (*activate) (struct clk *clk); ++ void (*deactivate) (struct clk *clk); ++ void (*reboot) (struct clk *clk); ++}; ++ ++extern void clkdev_add_static(unsigned long cpu, unsigned long fpi, ++ unsigned long io); ++ ++extern unsigned long ltq_danube_cpu_hz(void); ++extern unsigned long ltq_danube_fpi_hz(void); ++extern unsigned long ltq_danube_io_region_clock(void); ++ ++extern unsigned long ltq_svip_cpu_hz(void); ++extern unsigned long ltq_svip_fpi_hz(void); ++extern unsigned long ltq_svip_io_region_clock(void); ++ ++extern unsigned long ltq_ar9_cpu_hz(void); ++extern unsigned long ltq_ar9_fpi_hz(void); ++ ++extern unsigned long ltq_vr9_cpu_hz(void); ++extern unsigned long ltq_vr9_fpi_hz(void); + + #endif +diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c +index de1cb2b..7193d78 100644 +--- a/arch/mips/lantiq/devices.c ++++ b/arch/mips/lantiq/devices.c +@@ -27,12 +27,8 @@ + #include "devices.h" + + /* nor flash */ +-static struct resource ltq_nor_resource = { +- .name = "nor", +- .start = LTQ_FLASH_START, +- .end = LTQ_FLASH_START + LTQ_FLASH_MAX - 1, +- .flags = IORESOURCE_MEM, +-}; ++static struct resource ltq_nor_resource = ++ MEM_RES("nor", LTQ_FLASH_START, LTQ_FLASH_MAX); + + static struct platform_device ltq_nor = { + .name = "ltq_nor", +@@ -47,12 +43,8 @@ void __init ltq_register_nor(struct physmap_flash_data *data) + } + + /* watchdog */ +-static struct resource ltq_wdt_resource = { +- .name = "watchdog", +- .start = LTQ_WDT_BASE_ADDR, +- .end = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1, +- .flags = IORESOURCE_MEM, +-}; ++static struct resource ltq_wdt_resource = ++ MEM_RES("watchdog", LTQ_WDT_BASE_ADDR, LTQ_WDT_SIZE); + + void __init ltq_register_wdt(void) + { +@@ -61,24 +53,14 @@ void __init ltq_register_wdt(void) + + /* asc ports */ + static struct resource ltq_asc0_resources[] = { +- { +- .name = "asc0", +- .start = LTQ_ASC0_BASE_ADDR, +- .end = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1, +- .flags = IORESOURCE_MEM, +- }, ++ MEM_RES("asc0", LTQ_ASC0_BASE_ADDR, LTQ_ASC_SIZE), + IRQ_RES(tx, LTQ_ASC_TIR(0)), + IRQ_RES(rx, LTQ_ASC_RIR(0)), + IRQ_RES(err, LTQ_ASC_EIR(0)), + }; + + static struct resource ltq_asc1_resources[] = { +- { +- .name = "asc1", +- .start = LTQ_ASC1_BASE_ADDR, +- .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1, +- .flags = IORESOURCE_MEM, +- }, ++ MEM_RES("asc1", LTQ_ASC1_BASE_ADDR, LTQ_ASC_SIZE), + IRQ_RES(tx, LTQ_ASC_TIR(1)), + IRQ_RES(rx, LTQ_ASC_RIR(1)), + IRQ_RES(err, LTQ_ASC_EIR(1)), +diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h +index 2947bb1..a03c23f 100644 +--- a/arch/mips/lantiq/devices.h ++++ b/arch/mips/lantiq/devices.h +@@ -14,6 +14,10 @@ + + #define IRQ_RES(resname, irq) \ + {.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ} ++#define MEM_RES(resname, adr_start, adr_size) \ ++ { .name = resname, .flags = IORESOURCE_MEM, \ ++ .start = ((adr_start) & ~KSEG1), \ ++ .end = ((adr_start + adr_size - 1) & ~KSEG1) } + + extern void ltq_register_nor(struct physmap_flash_data *data); + extern void ltq_register_wdt(void); +diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c +index 972e05f..5089075 100644 +--- a/arch/mips/lantiq/early_printk.c ++++ b/arch/mips/lantiq/early_printk.c +@@ -12,11 +12,13 @@ + #include <lantiq.h> + #include <lantiq_soc.h> + +-/* no ioremap possible at this early stage, lets use KSEG1 instead */ +-#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC1_BASE_ADDR) + #define ASC_BUF 1024 +-#define LTQ_ASC_FSTAT ((u32 *)(LTQ_ASC_BASE + 0x0048)) +-#define LTQ_ASC_TBUF ((u32 *)(LTQ_ASC_BASE + 0x0020)) ++#define LTQ_ASC_FSTAT ((u32 *)(LTQ_EARLY_ASC + 0x0048)) ++#ifdef __BIG_ENDIAN ++#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020 + 3)) ++#else ++#define LTQ_ASC_TBUF ((u32 *)(LTQ_EARLY_ASC + 0x0020)) ++#endif + #define TXMASK 0x3F00 + #define TXOFFSET 8 + +@@ -27,7 +29,7 @@ void prom_putchar(char c) + local_irq_save(flags); + do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET); + if (c == '\n') +- ltq_w32('\r', LTQ_ASC_TBUF); +- ltq_w32(c, LTQ_ASC_TBUF); ++ ltq_w8('\r', LTQ_ASC_TBUF); ++ ltq_w8(c, LTQ_ASC_TBUF); + local_irq_restore(flags); + } +diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c +index d673731..63dbb83 100644 +--- a/arch/mips/lantiq/irq.c ++++ b/arch/mips/lantiq/irq.c +@@ -9,12 +9,17 @@ + + #include <linux/interrupt.h> + #include <linux/ioport.h> ++#include <linux/sched.h> + + #include <asm/bootinfo.h> + #include <asm/irq_cpu.h> + + #include <lantiq_soc.h> + #include <irq.h> ++#ifdef CONFIG_SOC_SVIP ++#include <ebu_reg.h> ++#include <base_reg.h> ++#endif + + /* register definitions */ + #define LTQ_ICU_IM0_ISR 0x0000 +@@ -40,17 +45,28 @@ + + #define MAX_EIU 6 + ++/* the performance counter */ ++#define LTQ_PERF_IRQ (INT_NUM_IM4_IRL0 + 31) ++ + /* irqs generated by device attached to the EBU need to be acked in + * a special manner + */ + #define LTQ_ICU_EBU_IRQ 22 + +-#define ltq_icu_w32(x, y) ltq_w32((x), ltq_icu_membase + (y)) +-#define ltq_icu_r32(x) ltq_r32(ltq_icu_membase + (x)) ++#define ltq_icu_w32(x, y, m) ltq_w32((x), ltq_icu_membase[m] + (y)) ++#define ltq_icu_r32(x, m) ltq_r32(ltq_icu_membase[m] + (x)) + + #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y)) + #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x)) + ++/* our 2 ipi interrupts for VSMP */ ++#define MIPS_CPU_IPI_RESCHED_IRQ 0 ++#define MIPS_CPU_IPI_CALL_IRQ 1 ++ ++#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) ++int gic_present; ++#endif ++ + static unsigned short ltq_eiu_irq[MAX_EIU] = { + LTQ_EIU_IR0, + LTQ_EIU_IR1, +@@ -60,11 +76,78 @@ static unsigned short ltq_eiu_irq[MAX_EIU] = { + LTQ_EIU_IR5, + }; + +-static struct resource ltq_icu_resource = { +- .name = "icu", +- .start = LTQ_ICU_BASE_ADDR, +- .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1, +- .flags = IORESOURCE_MEM, ++static struct resource ltq_icu_resource[IM_NUM] = { ++{ ++ .name = "icu_im0", ++ .start = LTQ_ICU_BASE_ADDR, ++ .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_OFFSET - 1, ++ .flags = IORESOURCE_MEM, ++}, ++#if IM_NUM >= 2 ++{ ++ .name = "icu_im1", ++#ifdef LTQ_ICU_BASE_ADDR1 ++ .start = LTQ_ICU_BASE_ADDR1, ++ .end = LTQ_ICU_BASE_ADDR1 + LTQ_ICU_OFFSET - 1, ++#else ++ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 1), ++ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 2) - 1, ++#endif ++ .flags = IORESOURCE_MEM, ++}, ++#endif ++#if IM_NUM >= 3 ++{ ++ .name = "icu_im2", ++#ifdef LTQ_ICU_BASE_ADDR2 ++ .start = LTQ_ICU_BASE_ADDR2, ++ .end = LTQ_ICU_BASE_ADDR2 + LTQ_ICU_OFFSET - 1, ++#else ++ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 2), ++ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 3) - 1, ++#endif ++ .flags = IORESOURCE_MEM, ++}, ++#endif ++#if IM_NUM >= 4 ++{ ++ .name = "icu_im3", ++#ifdef LTQ_ICU_BASE_ADDR3 ++ .start = LTQ_ICU_BASE_ADDR3, ++ .end = LTQ_ICU_BASE_ADDR3 + LTQ_ICU_OFFSET - 1, ++#else ++ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 3), ++ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 4) - 1, ++#endif ++ .flags = IORESOURCE_MEM, ++}, ++#endif ++#if IM_NUM >= 5 ++{ ++ .name = "icu_im4", ++#ifdef LTQ_ICU_BASE_ADDR4 ++ .start = LTQ_ICU_BASE_ADDR4, ++ .end = LTQ_ICU_BASE_ADDR4 + LTQ_ICU_OFFSET - 1, ++#else ++ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 4), ++ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 5) - 1, ++#endif ++ .flags = IORESOURCE_MEM, ++}, ++#endif ++#if IM_NUM >= 6 ++{ ++ .name = "icu_im5", ++#ifdef LTQ_ICU_BASE_ADDR5 ++ .start = LTQ_ICU_BASE_ADDR5, ++ .end = LTQ_ICU_BASE_ADDR5 + LTQ_ICU_OFFSET - 1, ++#else ++ .start = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 5), ++ .end = LTQ_ICU_BASE_ADDR + (LTQ_ICU_OFFSET * 6) - 1, ++#endif ++ .flags = IORESOURCE_MEM, ++}, ++#endif + }; + + static struct resource ltq_eiu_resource = { +@@ -74,50 +157,53 @@ static struct resource ltq_eiu_resource = { + .flags = IORESOURCE_MEM, + }; + +-static void __iomem *ltq_icu_membase; ++static void __iomem *ltq_icu_membase[IM_NUM]; + static void __iomem *ltq_eiu_membase; + + void ltq_disable_irq(struct irq_data *d) + { +- u32 ier = LTQ_ICU_IM0_IER; + int irq_nr = d->irq - INT_NUM_IRQ0; ++ unsigned int im_nr; + +- ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); ++ im_nr = (irq_nr / INT_NUM_IM_OFFSET); + irq_nr %= INT_NUM_IM_OFFSET; +- ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier); ++ ++ ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) & ~(1 << irq_nr), ++ LTQ_ICU_IM0_IER, im_nr); + } + + void ltq_mask_and_ack_irq(struct irq_data *d) + { +- u32 ier = LTQ_ICU_IM0_IER; +- u32 isr = LTQ_ICU_IM0_ISR; + int irq_nr = d->irq - INT_NUM_IRQ0; ++ unsigned int im_nr; + +- ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); +- isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); ++ im_nr = (irq_nr / INT_NUM_IM_OFFSET); + irq_nr %= INT_NUM_IM_OFFSET; +- ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier); +- ltq_icu_w32((1 << irq_nr), isr); ++ ++ ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) & ~(1 << irq_nr), LTQ_ICU_IM0_IER, im_nr); ++ ltq_icu_w32((1 << irq_nr), LTQ_ICU_IM0_ISR, im_nr); + } + + static void ltq_ack_irq(struct irq_data *d) + { +- u32 isr = LTQ_ICU_IM0_ISR; + int irq_nr = d->irq - INT_NUM_IRQ0; ++ unsigned int im_nr; + +- isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); ++ im_nr = (irq_nr / INT_NUM_IM_OFFSET); + irq_nr %= INT_NUM_IM_OFFSET; +- ltq_icu_w32((1 << irq_nr), isr); ++ ++ ltq_icu_w32((1 << irq_nr), LTQ_ICU_IM0_ISR, im_nr); + } + + void ltq_enable_irq(struct irq_data *d) + { +- u32 ier = LTQ_ICU_IM0_IER; + int irq_nr = d->irq - INT_NUM_IRQ0; ++ unsigned int im_nr; + +- ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET); ++ im_nr = (irq_nr / INT_NUM_IM_OFFSET); + irq_nr %= INT_NUM_IM_OFFSET; +- ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier); ++ ++ ltq_icu_w32(ltq_icu_r32(LTQ_ICU_IM0_IER, im_nr) | (1 << irq_nr), LTQ_ICU_IM0_IER, im_nr); + } + + static unsigned int ltq_startup_eiu_irq(struct irq_data *d) +@@ -184,7 +270,7 @@ static void ltq_hw_irqdispatch(int module) + { + u32 irq; + +- irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET)); ++ irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR, module); + if (irq == 0) + return; + +@@ -194,10 +280,12 @@ static void ltq_hw_irqdispatch(int module) + irq = __fls(irq); + do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module)); + ++#ifndef CONFIG_SOC_SVIP + /* if this is a EBU irq, we need to ack it or get a deadlock */ +- if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0)) ++ if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) + ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10, + LTQ_EBU_PCC_ISTAT); ++#endif + } + + #define DEFINE_HWx_IRQDISPATCH(x) \ +@@ -211,21 +299,66 @@ DEFINE_HWx_IRQDISPATCH(2) + DEFINE_HWx_IRQDISPATCH(3) + DEFINE_HWx_IRQDISPATCH(4) + ++#if MIPS_CPU_TIMER_IRQ == 7 + static void ltq_hw5_irqdispatch(void) + { + do_IRQ(MIPS_CPU_TIMER_IRQ); + } ++#else ++DEFINE_HWx_IRQDISPATCH(5) ++#endif ++ ++#ifdef CONFIG_MIPS_MT_SMP ++void __init arch_init_ipiirq(int irq, struct irqaction *action) ++{ ++ setup_irq(irq, action); ++ irq_set_handler(irq, handle_percpu_irq); ++} ++ ++static void ltq_sw0_irqdispatch(void) ++{ ++ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); ++} ++ ++static void ltq_sw1_irqdispatch(void) ++{ ++ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); ++} ++static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) ++{ ++ scheduler_ipi(); ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) ++{ ++ smp_call_function_interrupt(); ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction irq_resched = { ++ .handler = ipi_resched_interrupt, ++ .flags = IRQF_PERCPU, ++ .name = "IPI_resched" ++}; ++ ++static struct irqaction irq_call = { ++ .handler = ipi_call_interrupt, ++ .flags = IRQF_PERCPU, ++ .name = "IPI_call" ++}; ++#endif + + asmlinkage void plat_irq_dispatch(void) + { + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + unsigned int i; + +- if (pending & CAUSEF_IP7) { ++ if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) { + do_IRQ(MIPS_CPU_TIMER_IRQ); + goto out; + } else { +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < IM_NUM; i++) { + if (pending & (CAUSEF_IP2 << i)) { + ltq_hw_irqdispatch(i); + goto out; +@@ -247,41 +380,45 @@ void __init arch_init_irq(void) + { + int i; + +- if (insert_resource(&iomem_resource, <q_icu_resource) < 0) +- panic("Failed to insert icu memory"); ++ for (i=0; i < IM_NUM; i++) { ++ if (insert_resource(&iomem_resource, <q_icu_resource[i]) < 0) ++ panic("Failed to insert icu memory\n"); + +- if (request_mem_region(ltq_icu_resource.start, +- resource_size(<q_icu_resource), "icu") < 0) +- panic("Failed to request icu memory"); ++ if (request_mem_region(ltq_icu_resource[i].start, ++ resource_size(<q_icu_resource[i]), "icu") < 0) ++ panic("Failed to request icu memory\n"); + +- ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start, +- resource_size(<q_icu_resource)); +- if (!ltq_icu_membase) +- panic("Failed to remap icu memory"); ++ ltq_icu_membase[i] = ioremap_nocache(ltq_icu_resource[i].start, ++ resource_size(<q_icu_resource[i])); ++ if (!ltq_icu_membase[i]) ++ panic("Failed to remap icu memory\n"); ++ } + +- if (insert_resource(&iomem_resource, <q_eiu_resource) < 0) +- panic("Failed to insert eiu memory"); ++ if (LTQ_EIU_BASE_ADDR) { ++ if (insert_resource(&iomem_resource, <q_eiu_resource) < 0) ++ panic("Failed to insert eiu memory\n"); + +- if (request_mem_region(ltq_eiu_resource.start, +- resource_size(<q_eiu_resource), "eiu") < 0) +- panic("Failed to request eiu memory"); ++ if (request_mem_region(ltq_eiu_resource.start, ++ resource_size(<q_eiu_resource), "eiu") < 0) ++ panic("Failed to request eiu memory\n"); + +- ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start, ++ ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start, + resource_size(<q_eiu_resource)); +- if (!ltq_eiu_membase) +- panic("Failed to remap eiu memory"); ++ if (!ltq_eiu_membase) ++ panic("Failed to remap eiu memory\n"); ++ } + + /* make sure all irqs are turned off by default */ +- for (i = 0; i < 5; i++) +- ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET)); +- +- /* clear all possibly pending interrupts */ +- ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET)); ++ for (i = 0; i < IM_NUM; i++) { ++ ltq_icu_w32(0, LTQ_ICU_IM0_IER, i); ++ /* clear all possibly pending interrupts */ ++ ltq_icu_w32(~0, LTQ_ICU_IM0_ISR, i); ++ } + + mips_cpu_irq_init(); + +- for (i = 2; i <= 6; i++) +- setup_irq(i, &cascade); ++ for (i = 0; i < IM_NUM; i++) ++ setup_irq(i + 2, &cascade); + + if (cpu_has_vint) { + pr_info("Setting up vectored interrupts\n"); +@@ -294,9 +431,9 @@ void __init arch_init_irq(void) + } + + for (i = INT_NUM_IRQ0; +- i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++) +- if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) || +- (i == LTQ_EIU_IR2)) ++ i <= (INT_NUM_IRQ0 + (IM_NUM * INT_NUM_IM_OFFSET)); i++) ++ if (((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) || ++ (i == LTQ_EIU_IR2)) && LTQ_EIU_BASE_ADDR) + irq_set_chip_and_handler(i, <q_eiu_type, + handle_level_irq); + /* EIU3-5 only exist on ar9 and vr9 */ +@@ -308,6 +445,17 @@ void __init arch_init_irq(void) + irq_set_chip_and_handler(i, <q_irq_type, + handle_level_irq); + ++#if defined(CONFIG_MIPS_MT_SMP) ++ if (cpu_has_vint) { ++ pr_info("Setting up IPI vectored interrupts\n"); ++ set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch); ++ set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch); ++ } ++ arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ, ++ &irq_resched); ++ arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call); ++#endif ++ + #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) + set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | + IE_IRQ3 | IE_IRQ4 | IE_IRQ5); +@@ -315,9 +463,15 @@ void __init arch_init_irq(void) + set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 | + IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); + #endif ++ ++ cp0_perfcount_irq = LTQ_PERF_IRQ; + } + + unsigned int __cpuinit get_c0_compare_int(void) + { ++#ifdef CONFIG_SOC_SVIP ++ return MIPS_CPU_TIMER_IRQ; ++#else + return CP0_LEGACY_COMPARE_IRQ; ++#endif + } +diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h +index 7e01b8c..dfc6af7 100644 +--- a/arch/mips/lantiq/machtypes.h ++++ b/arch/mips/lantiq/machtypes.h +@@ -15,6 +15,11 @@ enum lantiq_mach_type { + LTQ_MACH_GENERIC = 0, + LTQ_MACH_EASY50712, /* Danube evaluation board */ + LTQ_MACH_EASY50601, /* Amazon SE evaluation board */ ++ ++ /* FALCON */ ++ LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */ ++ LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */ ++ LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */ + }; + + #endif +diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c +index e34fcfd..00ad59c 100644 +--- a/arch/mips/lantiq/prom.c ++++ b/arch/mips/lantiq/prom.c +@@ -16,6 +16,10 @@ + #include "prom.h" + #include "clk.h" + ++/* access to the ebu needs to be locked between different drivers */ ++DEFINE_SPINLOCK(ebu_lock); ++EXPORT_SYMBOL_GPL(ebu_lock); ++ + static struct ltq_soc_info soc_info; + + unsigned int ltq_get_cpu_ver(void) +@@ -45,27 +49,68 @@ static void __init prom_init_cmdline(void) + char **argv = (char **) KSEG1ADDR(fw_arg1); + int i; + ++ arcs_cmdline[0] = '\0'; ++ + for (i = 0; i < argc; i++) { +- char *p = (char *) KSEG1ADDR(argv[i]); ++ char *p = (char *) KSEG1ADDR(argv[i]); + +- if (p && *p) { ++ if (CPHYSADDR(p) && *p) { + strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); + strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); + } + } + } + +-void __init prom_init(void) ++void __iomem *ltq_remap_resource(struct resource *res) + { +- struct clk *clk; ++ __iomem void *ret = NULL; ++ struct resource *lookup = lookup_resource(&iomem_resource, res->start); ++ ++ if (lookup && strcmp(lookup->name, res->name)) { ++ pr_err("conflicting memory range %s\n", res->name); ++ return NULL; ++ } ++ if (!lookup) { ++ if (insert_resource(&iomem_resource, res) < 0) { ++ pr_err("Failed to insert %s memory\n", res->name); ++ return NULL; ++ } ++ } ++ if (request_mem_region(res->start, ++ resource_size(res), res->name) < 0) { ++ pr_err("Failed to request %s memory\n", res->name); ++ goto err_res; ++ } + ++ ret = ioremap_nocache(res->start, resource_size(res)); ++ if (!ret) ++ goto err_mem; ++ ++ pr_debug("remap: 0x%08X-0x%08X : \"%s\"\n", ++ res->start, res->end, res->name); ++ return ret; ++ ++err_mem: ++ panic("Failed to remap %s memory\n", res->name); ++ release_mem_region(res->start, resource_size(res)); ++ ++err_res: ++ release_resource(res); ++ return NULL; ++} ++EXPORT_SYMBOL(ltq_remap_resource); ++ ++void __init prom_init(void) ++{ + ltq_soc_detect(&soc_info); +- clk_init(); +- clk = clk_get(0, "cpu"); +- snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d", +- soc_info.name, soc_info.rev); +- clk_put(clk); ++ snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s", ++ soc_info.name, soc_info.rev_type); + soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0'; + pr_info("SoC: %s\n", soc_info.sys_type); + prom_init_cmdline(); ++ ++#if defined(CONFIG_MIPS_MT_SMP) ++ if (register_vsmp_smp_ops()) ++ panic("failed to register_vsmp_smp_ops()"); ++#endif + } +diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h +index b4229d9..51dba1b 100644 +--- a/arch/mips/lantiq/prom.h ++++ b/arch/mips/lantiq/prom.h +@@ -9,17 +9,21 @@ + #ifndef _LTQ_PROM_H__ + #define _LTQ_PROM_H__ + ++#define LTQ_SYS_REV_LEN 0x10 + #define LTQ_SYS_TYPE_LEN 0x100 + + struct ltq_soc_info { + unsigned char *name; + unsigned int rev; ++ unsigned char rev_type[LTQ_SYS_REV_LEN]; ++ unsigned int srev; + unsigned int partnum; + unsigned int type; + unsigned char sys_type[LTQ_SYS_TYPE_LEN]; + }; + + extern void ltq_soc_detect(struct ltq_soc_info *i); ++extern void ltq_soc_init(void); + extern void ltq_soc_setup(void); + + #endif +-- +1.7.9.1 + |