mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-12 14:12:48 +02:00
1010 lines
27 KiB
Diff
1010 lines
27 KiB
Diff
|
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
|
||
|
|