[linux-yocto] [PATCH 15/18] arm/mach-axxia: Same build for HW and simlation.

Charlie Paul cpaul.windriver at gmail.com
Tue Feb 18 09:26:45 PST 2014


From: Anders Berg <anders.berg at lsi.com>

Removed the config ARCH_AXXIA_SIM, that used to identify builds for simulator.
The same build can now be run on both hardware and simulation platforms, using
different DTBs.

arm/axxia: Removed some debug log messages

Signed-off-by: Anders Berg <anders.berg at lsi.com>
---
 arch/arm/Makefile                |    3 -
 arch/arm/boot/dts/axm55xx.dts    |   11 ++
 arch/arm/boot/dts/axm55xxsim.dts |   46 ++++-
 arch/arm/include/asm/spinlock.h  |    5 +-
 arch/arm/mach-axxia/Kconfig      |    3 -
 arch/arm/mach-axxia/axxia.c      |   56 +-----
 arch/arm/mach-axxia/axxia.h      |    4 +-
 arch/arm/mach-axxia/clock.c      |  181 +++++++------------
 arch/arm/mach-axxia/platsmp.c    |  178 ++++++-------------
 arch/arm/mach-axxia/wrappers.c   |   42 -----
 drivers/misc/lsi-smmon.c         |  362 +++++++++++++++++---------------------
 11 files changed, 337 insertions(+), 554 deletions(-)

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 4429c88..992f213 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -134,10 +134,7 @@ endif
 textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000
 textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
 textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
-
-ifneq ($(CONFIG_ARCH_AXXIA_SIM),y)
 textofs-$(CONFIG_ARCH_AXXIA)   := 0x00408000
-endif
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
diff --git a/arch/arm/boot/dts/axm55xx.dts b/arch/arm/boot/dts/axm55xx.dts
index f84d909..1aabe31 100644
--- a/arch/arm/boot/dts/axm55xx.dts
+++ b/arch/arm/boot/dts/axm55xx.dts
@@ -213,6 +213,17 @@
 			     <1 10 0xf08>;
 	};
 
+	sm0 at 00220000 {
+		compatible = "lsi,smmon";
+		reg = <0 0x00220000 0 0x1000>;
+		interrupts = <0 192 4>;
+	};
+
+	sm1 at 00220000 {
+		compatible = "lsi,smmon";
+		reg = <0 0x000f0000 0 0x1000>;
+		interrupts = <0 193 4>;
+	};
 
 	gpdma at 2020140000 {
 		compatible = "lsi,dma32";
diff --git a/arch/arm/boot/dts/axm55xxsim.dts b/arch/arm/boot/dts/axm55xxsim.dts
index 6cc60ab..6e73be8 100644
--- a/arch/arm/boot/dts/axm55xxsim.dts
+++ b/arch/arm/boot/dts/axm55xxsim.dts
@@ -20,6 +20,8 @@
 
 /dts-v1/;
 
+/memreserve/ 0x00000000 0x00400000;
+
 / {
 	model = "AXM5516";
 	compatible = "arm", "lsi,axm5516-sim";
@@ -30,11 +32,9 @@
 	chosen { };
 
 	aliases {
-		serial0 = &axxia_serial0;
-		serial1 = &axxia_serial1;
-		serial2 = &axxia_serial2;
-		serial3 = &axxia_serial3;
-		timer   = &axxia_timers;
+		serial0   = &axxia_serial0;
+		timer	  = &axxia_timers;
+		ethernet0 = &axxia_net0;
 	};
 
 	cpus {
@@ -46,6 +46,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 1 {
@@ -53,6 +54,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <1>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 2 {
@@ -60,6 +62,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <2>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 3 {
@@ -67,6 +70,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <3>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 4 {
@@ -74,6 +78,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <4>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 5 {
@@ -81,6 +86,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <5>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 6 {
@@ -88,6 +94,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <6>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 7 {
@@ -95,6 +102,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <7>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 8 {
@@ -102,6 +110,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <8>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 9 {
@@ -109,6 +118,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <9>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 10 {
@@ -116,6 +126,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <10>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 11 {
@@ -123,6 +134,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <11>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 12 {
@@ -130,6 +142,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <12>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 13 {
@@ -137,6 +150,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <13>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 14 {
@@ -144,6 +158,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <14>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
 		};
 
 		cpu at 15 {
@@ -151,6 +166,24 @@
 			compatible = "arm,cortex-a15";
 			reg = <15>;
 			clock-frequency= <0>;
+			cpu-release-addr = <0x10000020>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu {
+			frequency = <1400000000>;
+		};
+
+		peripheral {
+			frequency = <400000000>;
+		};
+
+		emmc {
+			frequency = <25000000>;
 		};
 	};
 
@@ -197,7 +230,6 @@
 	};
 
 	gpdma at 2020141000 {
-		status = "disabled";
 		compatible = "lsi,dma32";
 		reg = <0x20 0x20141000 0x00 0x1000>;
 		interrupts = <0 64 4>, /* busy */
@@ -223,7 +255,7 @@
 		interrupts = <0 45 4>;
 	};
 
-	ethernet at 201100000000 {
+	axxia_net0: ethernet at 201100000000 {
 		compatible = "smsc,lan91c111";
 		device_type = "network";
 		reg = <0x20 0x11000000 0 0x10000>;
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index 38d6e27..857f7ea 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -37,7 +37,8 @@
 						\
 	"nop.w"					\
 )
-#elif CONFIG_ARCH_AXXIA || CONFIG_ARCH_AXXIA_SIM
+#elif defined(CONFIG_ARCH_AXXIA)
+/* Disable use of wfe/sev in Axxia. */
 #define SEV
 #define WFE(cond)
 #else
@@ -91,7 +92,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 	: "cc");
 
 	while (lockval.tickets.next != lockval.tickets.owner) {
-#if !CONFIG_ARCH_AXXIA && !CONFIG_ARCH_AXXIA_SIM
+#if !defined(CONFIG_ARCH_AXXIA)
 		wfe();
 #endif
 		lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
diff --git a/arch/arm/mach-axxia/Kconfig b/arch/arm/mach-axxia/Kconfig
index 92b1dd1..4a4922f 100644
--- a/arch/arm/mach-axxia/Kconfig
+++ b/arch/arm/mach-axxia/Kconfig
@@ -28,7 +28,4 @@ config ARCH_AXXIA_DT
 	  If your bootloader supports Flattened Device Tree based booting,
 	  say Y here.
 
-config ARCH_AXXIA_SIM
-	bool "Build for Simulation instead of Emulation or ASIC"
-
 endmenu
diff --git a/arch/arm/mach-axxia/axxia.c b/arch/arm/mach-axxia/axxia.c
index 55549fa..b227ca9 100644
--- a/arch/arm/mach-axxia/axxia.c
+++ b/arch/arm/mach-axxia/axxia.c
@@ -56,8 +56,8 @@
 #include "i2c.h"
 
 static const char *axxia_dt_match[] __initconst = {
-	"lsi,axm5516",		/* AXM5516 */
-	"lsi,axm5516-sim",	/* AXM5516 Simulation */
+	"lsi,axm5516",
+	"lsi,axm5516-sim",
 	NULL
 };
 
@@ -102,8 +102,11 @@ void __init axxia_dt_timer_init(void)
 	const char *path;
 	struct device_node *node;
 	void __iomem *base;
+	int is_sim;
 
-	axxia_init_clocks();
+	is_sim = of_find_compatible_node(NULL, NULL, "lsi,axm5516-sim") != NULL;
+
+	axxia_init_clocks(is_sim);
 
 #ifdef CONFIG_ARM_ARCH_TIMER
 	of_clk_init(NULL);
@@ -259,37 +262,6 @@ static struct spi_board_info spi_devs[] __initdata = {
 	}
 };
 
-#ifndef CONFIG_ARCH_AXXIA_SIM
-static int
-l3_set_pstate(void __iomem *l3ctrl, unsigned int req, unsigned int act)
-{
-	static const u8 hn_f[] = {
-		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
-	};
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(hn_f); ++i) {
-		/* set state NOL3 */
-		writel(req, l3ctrl + (hn_f[i] << 16) + 0x10);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(hn_f); ++i) {
-		unsigned long status;
-		int retries = 10000;
-
-		do {
-			status = readl(l3ctrl + (hn_f[i] << 16) + 0x18);
-			udelay(1);
-		} while ((0 < --retries) && (act != (status & 0xf)));
-
-		if (0 == retries)
-			return -ENODEV;
-	}
-
-	return 0;
-}
-#endif
-
 static int
 axxia_bus_notifier(struct notifier_block *nb, unsigned long event, void *obj)
 {
@@ -316,22 +288,6 @@ static struct notifier_block axxia_amba_nb = {
 
 void __init axxia_dt_init(void)
 {
-#ifndef CONFIG_ARCH_AXXIA_SIM
-	void __iomem *l3ctrl;
-	int rc;
-
-	/* Enable L3-cache */
-	l3ctrl = ioremap(0x2000000000ULL, SZ_4M);
-	if (l3ctrl) {
-		rc = l3_set_pstate(l3ctrl, 0x3, 0xc);
-		if (rc < 0)
-			pr_warn("axxia: Failed to intialize L3-cache\n");
-		iounmap(l3ctrl);
-	} else {
-		pr_warn("axxia: Failed to map L3-cache control regs\n");
-	}
-#endif
-
 	bus_register_notifier(&platform_bus_type, &axxia_platform_nb);
 	bus_register_notifier(&amba_bustype, &axxia_amba_nb);
 
diff --git a/arch/arm/mach-axxia/axxia.h b/arch/arm/mach-axxia/axxia.h
index be1cca6..3393d37 100644
--- a/arch/arm/mach-axxia/axxia.h
+++ b/arch/arm/mach-axxia/axxia.h
@@ -1,7 +1,7 @@
 #ifndef _AXXIA_H
 
-void axxia_init_clocks(void);
-extern void axxia_ddr_retention_init(void);
+void axxia_init_clocks(int is_sim);
+void axxia_ddr_retention_init(void);
 
 extern struct smp_operations axxia_smp_ops;
 
diff --git a/arch/arm/mach-axxia/clock.c b/arch/arm/mach-axxia/clock.c
index 63d02de..c8c28cf 100644
--- a/arch/arm/mach-axxia/clock.c
+++ b/arch/arm/mach-axxia/clock.c
@@ -17,9 +17,6 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
-#define AXXIA_CPU_CLOCK 1400000000
-#define AXXIA_SYS_CLOCK  450000000
-#define AXXIA_DDR_CLOCK 1866000000
 
 #define clk_register_clkdev(_clk, _conid, _devfmt, ...) \
 	do { \
@@ -28,143 +25,85 @@
 		clkdev_add(cl); \
 	} while (0)
 
-/*
-  ------------------------------------------------------------------------------
-  axxia_init_clocks
-
-  Clock setup for Emulation/ASIC systems.
-*/
-
-#ifdef CONFIG_ARCH_AXXIA_SIM
-void __init
-axxia_init_clocks(void)
+enum clk_ids {
+	clk_cpu,
+	clk_per,
+	clk_mmc,
+	clk_apb,
+	clk_1mhz,
+	NR_CLK_IDS
+};
+
+static struct dt_clk_lookup {
+	const char  *path;
+	const char  *name;
+	enum clk_ids id;
+	u32          default_freq;
+} dt_clks[] = {
+	{"/clocks/cpu",        "clk_cpu", clk_cpu, 1400000000 },
+	{"/clocks/peripheral", "clk_per", clk_per,  200000000 },
+	{"/clocks/emmc",       "clk_mmc", clk_mmc,  200000000 },
+};
+
+static struct clk *clk[NR_CLK_IDS];
+
+static void axxia_register_clks(void)
 {
-	struct clk *clk;
 	int i;
 
-	/* APB clock dummy */
-	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL,
-				      CLK_IS_ROOT, AXXIA_SYS_CLOCK/2);
-	clk_register_clkdev(clk, "apb_pclk", NULL);
-
-	/* CPU core clock (1400MHz) from CPU_PLL */
-	clk = clk_register_fixed_rate(NULL, "clk_cpu", NULL,
-				      CLK_IS_ROOT, AXXIA_CPU_CLOCK);
-
-	/* APB and System AXI clock from CPU_PLL */
-	clk = clk_register_fixed_rate(NULL, "clk_pclk", NULL,
-				      CLK_IS_ROOT, AXXIA_CPU_CLOCK/9);
-
-	/* DDR3 (interface 1) clock from SMEM1_PLL */
-	clk = clk_register_fixed_rate(NULL, "clk_smem1_2x", NULL,
-				      CLK_IS_ROOT, AXXIA_DDR_CLOCK);
-
-	/* AXIS slow peripheral clock from SMEM1_PLL. */
-	clk = clk_register_fixed_rate(NULL, "clk_per", NULL,
-				      CLK_IS_ROOT, 24000000);
-	/* PL011 UART0 */
-	clk_register_clkdev(clk, NULL, "2010080000.uart");
-	/* PL011 UART1 */
-	clk_register_clkdev(clk, NULL, "2010081000.uart");
-	/* PL011 UART2 */
-	clk_register_clkdev(clk, NULL, "2010082000.uart");
-	/* PL011 UART3 */
-	clk_register_clkdev(clk, NULL, "2010083000.uart");
-	/* PL022 SSP */
-	clk_register_clkdev(clk, NULL, "ssp");
+	for (i = 0; i < ARRAY_SIZE(dt_clks); ++i) {
+		struct dt_clk_lookup *c = &dt_clks[i];
+		struct device_node *np = of_find_node_by_path(c->path);
+		u32 freq;
+
+		if (!np || of_property_read_u32(np, "frequency", &freq)) {
+			pr_warn("axxia: No 'frequency' in %s\n", c->path);
+			freq = c->default_freq;
+		}
+		clk[c->id] = clk_register_fixed_rate(NULL, c->name, NULL,
+						     CLK_IS_ROOT, freq);
+	}
 
-	/* Timers 1MHz clock */
-	clk = clk_register_fixed_rate(NULL, "clk_1mhz", NULL,
-				      CLK_IS_ROOT, 1000000);
-	/* SP804 timers */
-	clk_register_clkdev(clk, NULL, "sp804");
-	for (i = 0; i < 8; i++)
-		clk_register_clkdev(clk, NULL, "axxia-timer%d", i);
+	/* APB clock dummy */
+	clk[clk_apb] = clk_register_fixed_rate(NULL, "apb_pclk", NULL,
+					       CLK_IS_ROOT, 1000000);
 
-	/* Dummy MMC clk */
-	clk = clk_register_fixed_rate(NULL, "clk_mmci", NULL,
-				      CLK_IS_ROOT, 25000000);
-	/* PL180 MMCI */
-	clk_register_clkdev(clk, NULL, "mmci");
+	clk[clk_1mhz] = clk_register_fixed_rate(NULL, "clk_1mhz", NULL,
+						CLK_IS_ROOT, 1000000);
 }
 
-#else /* !CONFIG_ARCH_AXXIA_SIM */
-
 void __init
-axxia_init_clocks(void)
+axxia_init_clocks(int is_sim)
 {
-	struct clk *clk;
 	int i;
-	struct device_node *np;
-	u32 frequency;
-
-	np = of_find_node_by_path("/clocks/cpu");
 
-	if (np) {
-		if (of_property_read_u32(np, "frequency", &frequency))
-			pr_err("%d - Error!", __LINE__);
-	}
+	pr_info("axxia: init_clocks: is_sim=%d\n", is_sim);
 
-	clk = clk_register_fixed_rate(NULL, "clk_cpu", NULL,
-				      CLK_IS_ROOT, frequency);
+	axxia_register_clks();
 
-	np = of_find_node_by_path("/clocks/peripheral");
+	/* PL011 UARTs */
+	clk_register_clkdev(clk[clk_per], NULL, "2010080000.uart");
+	clk_register_clkdev(clk[clk_per], NULL, "2010081000.uart");
+	clk_register_clkdev(clk[clk_per], NULL, "2010082000.uart");
+	clk_register_clkdev(clk[clk_per], NULL, "2010083000.uart");
 
-	if (np) {
-		if (of_property_read_u32(np, "frequency", &frequency))
-			pr_err("%d - Error!", __LINE__);
-	}
-
-	clk = clk_register_fixed_rate(NULL, "clk_per", NULL,
-				      CLK_IS_ROOT, frequency);
-
-	/* PL011 UART0 */
-	clk_register_clkdev(clk, NULL, "2010080000.uart");
-	/* PL011 UART1 */
-	clk_register_clkdev(clk, NULL, "2010081000.uart");
-	/* PL011 UART2 */
-	clk_register_clkdev(clk, NULL, "2010082000.uart");
-	/* PL011 UART3 */
-	clk_register_clkdev(clk, NULL, "2010083000.uart");
 	/* PL022 SSP */
-	clk_register_clkdev(clk, NULL, "ssp");
+	clk_register_clkdev(clk[clk_per], NULL, "ssp");
+
 	/* I2C */
-	clk_register_clkdev(clk, NULL, "2010084000.i2c");
-	clk_register_clkdev(clk, NULL, "2010085000.i2c");
-	clk_register_clkdev(clk, NULL, "2010086000.i2c");
-	clk_register_clkdev(clk, NULL, "2010087000.i2c");
+	clk_register_clkdev(clk[clk_per], NULL, "2010084000.i2c");
+	clk_register_clkdev(clk[clk_per], NULL, "2010085000.i2c");
+	clk_register_clkdev(clk[clk_per], NULL, "2010086000.i2c");
+	clk_register_clkdev(clk[clk_per], NULL, "2010087000.i2c");
+
 	/* SP804 timers */
-	clk_register_clkdev(clk, NULL, "sp804");
+	clk_register_clkdev(clk[is_sim ? clk_1mhz : clk_per], NULL, "sp804");
 	for (i = 0; i < 8; i++)
-		clk_register_clkdev(clk, NULL, "axxia-timer%d", i);
-
-	np = of_find_node_by_path("/clocks/emmc");
-
-	if (np) {
-		if (of_property_read_u32(np, "frequency", &frequency))
-			pr_err("%d - Error!", __LINE__);
-	}
-
-	clk = clk_register_fixed_rate(NULL, "clk_mmci", NULL,
-				      CLK_IS_ROOT, frequency);
+		clk_register_clkdev(clk[is_sim ? clk_1mhz : clk_per],
+				    NULL, "axxia-timer%d", i);
 
 	/* PL180 MMCI */
-	clk_register_clkdev(clk, NULL, "mmci");
-
-	/* APB clock dummy */
-	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL,
-				      CLK_IS_ROOT, AXXIA_SYS_CLOCK/2);
-	clk_register_clkdev(clk, "apb_pclk", NULL);
+	clk_register_clkdev(clk[clk_mmc], NULL, "mmci");
 
-	/* APB and System AXI clock from CPU_PLL */
-	clk = clk_register_fixed_rate(NULL, "clk_pclk", NULL,
-				      CLK_IS_ROOT, AXXIA_CPU_CLOCK/9);
-
-	/* DDR3 (interface 1) clock from SMEM1_PLL */
-	clk = clk_register_fixed_rate(NULL, "clk_smem1_2x", NULL,
-				      CLK_IS_ROOT, AXXIA_DDR_CLOCK);
-
-	return;
+	clk_register_clkdev(clk[clk_apb], "apb_pclk", NULL);
 }
-
-#endif /* CONFIG_ARCH_AXXIA_SIM */
diff --git a/arch/arm/mach-axxia/platsmp.c b/arch/arm/mach-axxia/platsmp.c
index cfd18d9..1922122 100644
--- a/arch/arm/mach-axxia/platsmp.c
+++ b/arch/arm/mach-axxia/platsmp.c
@@ -109,11 +109,7 @@ int __cpuinit axxia_boot_secondary(unsigned int cpu, struct task_struct *idle)
 	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
 	/* Wait for so long, then give up if nothing happens ... */
-#ifdef CONFIG_ARCH_AXXIA_SIM
 	timeout = jiffies + (1 * HZ);
-#else
-	timeout = jiffies + (10 * HZ);
-#endif
 	while (time_before(jiffies, timeout)) {
 		smp_rmb();
 		if (pen_release == -1)
@@ -131,160 +127,86 @@ int __cpuinit axxia_boot_secondary(unsigned int cpu, struct task_struct *idle)
 	return pen_release != -1 ? -ENOSYS : 0;
 }
 
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-static void __init axxia_smp_init_cpus(void)
+static __init struct device_node *get_cpu_node(int cpu)
 {
-	int ncores = 0;
 	struct device_node *np;
-	u32 cpu_num;
 
-	for_each_node_by_name(np, "cpu") {
-		if (++ncores > nr_cpu_ids) {
-			pr_warn("SMP: More cores (%u) in DTB than max (%u)\n",
-				ncores, nr_cpu_ids);
-			break;
-		}
-		if (!of_property_read_u32(np, "reg", &cpu_num)) {
-			if (cpu_num >= 0 && cpu_num < 16)
-				set_cpu_possible(cpu_num, true);
-			else
-				pr_warn("SMP: Invalid cpu number (%u)\n",
-					 cpu_num);
-		}
+	for_each_node_by_type(np, "cpu") {
+		u32 reg;
+		if (of_property_read_u32(np, "reg", &reg))
+			continue;
+		if (reg == cpu_logical_map(cpu))
+			return np;
 	}
+
+	return NULL;
 }
 
 static void __init axxia_smp_prepare_cpus(unsigned int max_cpus)
 {
-#ifdef CONFIG_ARCH_AXXIA_SIM
-	int i;
+	void __iomem *apb2_ser3_base;
+	int cpu_count = 0;
+	int cpu;
 
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
+	apb2_ser3_base = ioremap(APB2_SER3_PHY_ADDR, APB2_SER3_ADDR_SIZE);
+	if (WARN_ON(!apb2_ser3_base))
+		return;
 
 	/*
-	 * This is the entry point of the routine that the secondary
-	 * cores will execute once they are released from their
-	 * "holding pen".
+	 * Initialise the present map, which describes the set of CPUs actually
+	 * populated at the present time.
 	 */
-	*(u32 *)phys_to_virt(0x10000020) =
-					  virt_to_phys(axxia_secondary_startup);
-#else
-	int i;
-	int cpu_count = 0;
-	u32 phys_cpu = 0;
-	void __iomem *apb2_ser3_base;
-	unsigned long resetVal;
-	struct device_node *np;
-	unsigned long release_addr[NR_CPUS] = {0};
-	u32 release;
-
-	if (of_find_compatible_node(NULL, NULL, "lsi,axm5516")) {
-		for_each_node_by_name(np, "cpu") {
-			if (of_property_read_u32(np, "reg", &phys_cpu))
-				continue;
+	for_each_possible_cpu(cpu) {
+		struct device_node *np;
+		u32 release_phys;
+		u32 *release_virt;
 
-			if (0 == phys_cpu)
-				continue;
-
-			if (of_property_read_u32(np, "cpu-release-addr",
-						 &release))
-				continue;
-
-			release_addr[phys_cpu] = release;
-			pr_debug("%s:%d - set address for %d to 0x%08lx\n",
-				 __FILE__, __LINE__,
-				 phys_cpu, release_addr[phys_cpu]);
-		}
+		np = get_cpu_node(cpu);
+		if (!np)
+			continue;
+		if (of_property_read_u32(np, "cpu-release-addr", &release_phys))
+			continue;
 
 		/*
-		 * Initialise the present map, which describes the set of CPUs
-		 * actually populated at the present time.
+		 * Release all physical cpus when not in hyp mode since we
+		 * might want to bring them online later.
+		 *
+		 * Also we need to get the execution into kernel code (it's
+		 * currently executing in u-boot).  u-boot releases the cores
+		 * from reset in hyp mode.
 		 */
-
-		apb2_ser3_base = ioremap(APB2_SER3_PHY_ADDR,
-					 APB2_SER3_ADDR_SIZE);
-
-		for (i = 0; i < NR_CPUS; i++) {
-			/* check if this is a possible CPU and
-			 * it is within max_cpus range */
-			if ((cpu_possible(i)) &&
-				(cpu_count < max_cpus) &&
-			    (0 != release_addr[i])) {
-				set_cpu_present(cpu_count, true);
-				cpu_count++;
-			}
-
-			if (!is_hyp_mode_available()) {
-				/*
-				 * Release all physical cpus when not in hyp
-				 * mode since we might want to bring them
-				 * online later.
-				 *
-				 * Also we need to get the execution into
-				 * kernel code (it's currently executing in
-				 * u-boot).  u-boot releases the cores from
-				 * reset in hyp mode.
-				 */
-				phys_cpu = cpu_logical_map(i);
-
-				if (phys_cpu != 0) {
-					resetVal = readl(apb2_ser3_base +
-							 0x1010);
-					writel(0xab, apb2_ser3_base+0x1000);
-					resetVal &= ~(1 << phys_cpu);
-					writel(resetVal, apb2_ser3_base+0x1010);
-					udelay(1000);
-				}
+		if (!is_hyp_mode_available()) {
+			u32 phys_cpu = cpu_logical_map(cpu);
+			if (phys_cpu != 0) {
+				u32 tmp = readl(apb2_ser3_base + 0x1010);
+				writel(0xab, apb2_ser3_base+0x1000);
+				tmp &= ~(1 << phys_cpu);
+				writel(tmp, apb2_ser3_base+0x1010);
 			}
 		}
 
-		iounmap(apb2_ser3_base);
-
-		/*
-		 * This is the entry point of the routine that the secondary
-		 * cores will execute once they are released from their
-		 * "holding pen".
-		 */
-		for (i = 0; i < NR_CPUS; i++) {
-			if (release_addr[i] != 0) {
-				u32 *vrel_addr =
-					(u32 *)phys_to_virt(release_addr[i]);
-				*vrel_addr =
-					virt_to_phys(axxia_secondary_startup);
-				smp_wmb();
-				__cpuc_flush_dcache_area(vrel_addr,
-							 sizeof(u32));
-			}
+		if (cpu_count < max_cpus) {
+			set_cpu_present(cpu, true);
+			cpu_count++;
 		}
-	} else if (of_find_compatible_node(NULL, NULL, "lsi,axm5516-sim")) {
-		for (i = 0; i < max_cpus; i++)
-			set_cpu_present(i, true);
 
 		/*
 		 * This is the entry point of the routine that the secondary
 		 * cores will execute once they are released from their
 		 * "holding pen".
 		 */
-		*(u32 *)phys_to_virt(0x10000020) =
-			virt_to_phys(axxia_secondary_startup);
-		smp_wmb();
-		__cpuc_flush_dcache_area((void *)phys_to_virt(0x10000020),
-					 sizeof(u32));
+		if (release_phys != 0) {
+			release_virt = (u32 *)phys_to_virt(release_phys);
+			*release_virt = virt_to_phys(axxia_secondary_startup);
+			smp_wmb();
+			__cpuc_flush_dcache_area(release_virt, sizeof(u32));
+		}
 	}
-	return;
-#endif
+
+	iounmap(apb2_ser3_base);
 }
 
 struct smp_operations axxia_smp_ops __initdata = {
-	.smp_init_cpus		= axxia_smp_init_cpus,
 	.smp_prepare_cpus	= axxia_smp_prepare_cpus,
 	.smp_secondary_init	= axxia_secondary_init,
 	.smp_boot_secondary	= axxia_boot_secondary,
diff --git a/arch/arm/mach-axxia/wrappers.c b/arch/arm/mach-axxia/wrappers.c
index dd25901..513dd9c 100644
--- a/arch/arm/mach-axxia/wrappers.c
+++ b/arch/arm/mach-axxia/wrappers.c
@@ -28,48 +28,6 @@
 /*
   ==============================================================================
   ==============================================================================
-  MDIO
-  ==============================================================================
-  ==============================================================================
-*/
-
-/*
-  These are not wrappers, but are required when loading the RTE in simulation.
-*/
-
-#ifdef CONFIG_ARCH_AXXIA_SIM
-
-/*
-  ------------------------------------------------------------------------------
-  acp_mdio_read
-*/
-
-int
-acp_mdio_read(unsigned long address, unsigned long offset,
-	      unsigned short *value, int clause45)
-{
-	return 0;
-}
-EXPORT_SYMBOL(acp_mdio_read);
-
-/*
-  ------------------------------------------------------------------------------
-  acp_mdio_write
-*/
-
-int
-acp_mdio_write(unsigned long address, unsigned long offset,
-	       unsigned short value, int clause45)
-{
-	return 0;
-}
-EXPORT_SYMBOL(acp_mdio_write);
-
-#endif	/* CONFIG_ARCH_AXXIA_SIM */
-
-/*
-  ==============================================================================
-  ==============================================================================
   Platform Device Registration
   ==============================================================================
   ==============================================================================
diff --git a/drivers/misc/lsi-smmon.c b/drivers/misc/lsi-smmon.c
index 5ab644b..21d59b0 100644
--- a/drivers/misc/lsi-smmon.c
+++ b/drivers/misc/lsi-smmon.c
@@ -14,21 +14,18 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/ratelimit.h>
 #include <linux/slab.h>
 
 #include <mach/ncr.h>
 
-#ifndef CONFIG_ARCH_AXXIA
-#error "Only AXM55xx is Supported At Present!"
-#endif
-
 static int log = 1;
-module_param(log, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-MODULE_PARM_DESC(log, "Log each error on the console.");
+module_param(log, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(log, "Log each error to kernel log.");
 
 /*
-  AXM55xx Interrupt Status Bits
+  AXM55xx memory controller interrupt status bits:
 
   Bit [24] = The software-initiated control word write has completed.
   Bit [23] = The user-initiated DLL resync has completed.
@@ -71,229 +68,202 @@ MODULE_PARM_DESC(log, "Log each error on the console.");
 
   Of these, 1, 2, 3, 4, 5, 6, 7, 11, and 19 are of interest.
 */
+#define SM_INT_MASK (0x1f7f701)
+
+enum events {
+	EV_ILLEGAL = 0,
+	EV_MULT_ILLEGAL,
+	EV_CORR_ECC,
+	EV_MULT_CORR_ECC,
+	EV_UNCORR_ECC,
+	EV_MULT_UNCORR_ECC,
+	EV_PORT_ERROR,
+	EV_WRAP_ERROR,
+	EV_PARITY_ERROR,
+	NR_EVENTS
+};
 
-struct smmon_counts {
-	unsigned long illegal_access[2];
-	unsigned long multiple_illegal_access[2];
-	unsigned long correctable_ecc[2];
-	unsigned long multiple_correctable_ecc[2];
-	unsigned long uncorrectable_ecc[2];
-	unsigned long multiple_uncorrectable_ecc[2];
-	unsigned long port_error[2];
-	unsigned long wrap_error[2];
-	unsigned long parity_error[2];
+static const u32 event_mask[NR_EVENTS] = {
+	[EV_ILLEGAL]          = 0x00000002,
+	[EV_MULT_ILLEGAL]     = 0x00000004,
+	[EV_CORR_ECC]         = 0x00000008,
+	[EV_MULT_CORR_ECC]    = 0x00000010,
+	[EV_UNCORR_ECC]       = 0x00000020,
+	[EV_MULT_UNCORR_ECC]  = 0x00000040,
+	[EV_PORT_ERROR]       = 0x00000080,
+	[EV_WRAP_ERROR]       = 0x00000800,
+	[EV_PARITY_ERROR]     = 0x00080000,
 };
 
-static struct smmon_counts counts;
+static const struct event_logging {
+	const char *level;
+	const char *name;
+} event_logging[NR_EVENTS] = {
+	[EV_ILLEGAL]         = {KERN_ERR, "Illegal access"},
+	[EV_MULT_ILLEGAL]    = {KERN_ERR, "Illegal access"},
+	[EV_CORR_ECC]        = {KERN_NOTICE, "Correctable ECC error"},
+	[EV_MULT_CORR_ECC]   = {KERN_NOTICE, "Correctable ECC error"},
+	[EV_UNCORR_ECC]      = {KERN_CRIT, "Uncorrectable ECC error"},
+	[EV_MULT_UNCORR_ECC] = {KERN_CRIT, "Uncorrectable ECC error"},
+	[EV_PORT_ERROR]      = {KERN_CRIT, "Port error"},
+	[EV_WRAP_ERROR]      = {KERN_CRIT, "Wrap error"},
+	[EV_PARITY_ERROR]    = {KERN_CRIT, "Parity error"},
+};
 
-DEFINE_RAW_SPINLOCK(counts_lock);
+struct smmon_attr {
+	struct device_attribute attr;
+	int                     event;
+};
 
-#define SUMMARY_SIZE 512
-static char *summary;
-module_param(summary, charp, S_IRUGO);
-MODULE_PARM_DESC(summary, "A Summary of the Current Error Counts.");
+#define SMMON_ATTR(_name, _event) \
+	{ \
+		.attr = __ATTR(_name, S_IRUGO, smmon_show, NULL), \
+		.event = _event \
+	}
 
-/*
-  ------------------------------------------------------------------------------
-  update_summary
-*/
+struct sm_dev {
+	struct platform_device *pdev;
+	u32 region; /* NCR region address */
+	u32 counter[NR_EVENTS];
+};
 
-static void
-update_summary(void)
+
+static ssize_t
+smmon_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	memset(summary, 0, SUMMARY_SIZE);
-	sprintf(summary,
-		"------------ Counts for SM0/SM1 ----------\n"
-		"                   Illegal Access: %lu/%lu\n"
-		"        Multiple Illegal Accesses: %lu/%lu\n"
-		"            Correctable ECC Error: %lu/%lu\n"
-		"  Multiple Correctable ECC Errors: %lu/%lu\n"
-		"          Uncorrectable ECC Error: %lu/%lu\n"
-		"Multiple Uncorrectable ECC Errors: %lu/%lu\n"
-		"                      Port Errors: %lu/%lu\n"
-		"                      Wrap Errors: %lu/%lu\n"
-		"                    Parity Errors: %lu/%lu\n",
-		counts.illegal_access[0],
-		counts.illegal_access[1],
-		counts.multiple_illegal_access[0],
-		counts.multiple_illegal_access[1],
-		counts.correctable_ecc[0],
-		counts.correctable_ecc[1],
-		counts.multiple_correctable_ecc[0],
-		counts.multiple_correctable_ecc[1],
-		counts.uncorrectable_ecc[0],
-		counts.uncorrectable_ecc[1],
-		counts.multiple_uncorrectable_ecc[0],
-		counts.multiple_uncorrectable_ecc[1],
-		counts.port_error[0],
-		counts.port_error[1],
-		counts.wrap_error[0],
-		counts.wrap_error[1],
-		counts.parity_error[0],
-		counts.parity_error[1]);
-
-	return;
+	struct sm_dev *sm = dev_get_drvdata(dev);
+	struct smmon_attr *sma = container_of(attr, struct smmon_attr, attr);
+	return sprintf(buf, "%u", sm->counter[sma->event]);
 }
 
-/*
-  ------------------------------------------------------------------------------
-  smmon_isr
-*/
+static struct smmon_attr smmon_attr_counter[] = {
+	SMMON_ATTR(illegal_access, EV_ILLEGAL),
+	SMMON_ATTR(illegal_access_mult, EV_MULT_ILLEGAL),
+	SMMON_ATTR(correctable_ecc_error, EV_CORR_ECC),
+	SMMON_ATTR(correctable_ecc_error_mult, EV_MULT_CORR_ECC),
+	SMMON_ATTR(uncorrectable_ecc_error, EV_UNCORR_ECC),
+	SMMON_ATTR(uncorrectable_ecc_error_mult, EV_MULT_UNCORR_ECC),
+	SMMON_ATTR(port_error, EV_PORT_ERROR),
+	SMMON_ATTR(wrap_error, EV_WRAP_ERROR),
+	SMMON_ATTR(parity_error, EV_PARITY_ERROR),
+};
+
+static struct attribute *smmon_attr[] = {
+	&smmon_attr_counter[EV_ILLEGAL].attr.attr,
+	&smmon_attr_counter[EV_MULT_ILLEGAL].attr.attr,
+	&smmon_attr_counter[EV_CORR_ECC].attr.attr,
+	&smmon_attr_counter[EV_MULT_CORR_ECC].attr.attr,
+	&smmon_attr_counter[EV_UNCORR_ECC].attr.attr,
+	&smmon_attr_counter[EV_MULT_UNCORR_ECC].attr.attr,
+	&smmon_attr_counter[EV_PORT_ERROR].attr.attr,
+	&smmon_attr_counter[EV_WRAP_ERROR].attr.attr,
+	&smmon_attr_counter[EV_PARITY_ERROR].attr.attr,
+	NULL
+};
+
+static struct attribute_group smmon_attr_group = {
+	.name  = "counters",
+	.attrs = smmon_attr
+};
 
 static irqreturn_t
 smmon_isr(int interrupt, void *device)
 {
-	unsigned long status;
-	unsigned long region;
-	int rc;
-	int sm;
-
-	if ((32 + 161) == interrupt) {
-		region = NCP_REGION_ID(0x22, 0);
-		sm = 1;
-	} else if ((32 + 160) == interrupt) {
-		region = NCP_REGION_ID(0xf, 0);
-		sm = 0;
-	} else {
-		return IRQ_NONE;
-	}
-
-	rc = ncr_read(region, 0x410, 4, &status);
+	struct sm_dev *sm = device;
+	u32 status;
+	int i;
 
-	if (0 != rc) {
-		pr_err("smmon(%d): Error reading interrupt status!\n", sm);
+	if (ncr_read(sm->region, 0x410, 4, &status)) {
+		pr_err("%s: Error reading interrupt status\n",
+		       dev_name(&sm->pdev->dev));
 		return IRQ_NONE;
 	}
 
-	raw_spin_lock(&counts_lock);
-
-	if (0 != (0x00000002 & status) || 0 != (0x00000004 & status))
-		pr_err("smmon(%d): Illegal Access!\n", sm);
-
-	if (0 != (0x00000002 & status))
-		++counts.illegal_access[sm];
-
-	if (0 != (0x00000004 & status))
-		++counts.multiple_illegal_access[sm];
-
-	if ((0 != (0x00000008 & status) || 0 != (0x00000010 & status)) &&
-	    0 != log)
-		pr_notice("smmon(%d): Correctable ECC Error!\n", sm);
-
-	if (0 != (0x00000008 & status))
-		++counts.correctable_ecc[sm];
-
-	if (0 != (0x00000010 & status))
-		++counts.multiple_correctable_ecc[sm];
-
-	if ((0 != (0x00000020 & status) ||
-	     0 != (0x00000040 & status)) &&
-	    0 != log)
-		pr_crit("smmon(%d): Uncorrectable ECC Error!\n", sm);
-
-	if (0 != (0x00000020 & status))
-		++counts.uncorrectable_ecc[sm];
+	for (i = 0; i < NR_EVENTS; ++i) {
+		if ((status & event_mask[i]) != 0) {
+			++sm->counter[i];
+			if (log)
+				printk_ratelimited("%s%s: %s\n",
+						   event_logging[i].level,
+						   dev_name(&sm->pdev->dev),
+						   event_logging[i].name);
+		}
+	}
 
-	if (0 != (0x00000040 & status))
-		++counts.multiple_uncorrectable_ecc[sm];
+	/* Clear interrupt */
+	ncr_write(sm->region, 0x548, 4, &status);
 
-	if (0 != (0x00000080 & status)) {
-		++counts.port_error[sm];
+	return IRQ_HANDLED;
+}
 
-		if (0 != log)
-			pr_crit("smmon(%d): Port Error!\n", sm);
+static int
+smmon_probe(struct platform_device *pdev)
+{
+	struct sm_dev *sm;
+	struct resource *io;
+	struct resource *irq;
+	u32 mask = SM_INT_MASK;
+	int rc = 0;
+
+	sm = devm_kzalloc(&pdev->dev, sizeof(*sm), GFP_KERNEL);
+	if (!sm) {
+		rc = -ENOMEM;
+		goto out;
 	}
+	sm->pdev = pdev;
 
-	if (0 != (0x00000800 & status)) {
-		++counts.wrap_error[sm];
-
-		if (0 != log)
-			pr_crit("smmon(%d): Wrap Error!\n", sm);
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!io) {
+		rc = -EINVAL;
+		goto out;
 	}
+	sm->region = io->start;
 
-	if (0 != (0x00080000 & status)) {
-		++counts.parity_error[sm];
-
-		if (0 != log)
-			pr_crit("smmon(%d): Parity Error!\n", sm);
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		rc = -EINVAL;
+		goto out;
 	}
 
-	update_summary();
+	rc = devm_request_irq(&pdev->dev, irq->start, smmon_isr,
+			      IRQF_ONESHOT, dev_name(&pdev->dev), pdev);
+	if (rc)
+		goto out;
 
-	raw_spin_unlock(&counts_lock);
+	/* Enable memory controller interrupts */
+	ncr_write(sm->region, 0x414, 4, &mask);
 
-	ncr_write(region, 0x548, 4, &status);
+	rc = sysfs_create_group(&pdev->dev.kobj, &smmon_attr_group);
+	if (rc)
+		goto out;
 
-	return IRQ_HANDLED;
+	dev_set_drvdata(&pdev->dev, sm);
+	pr_info("%s: Memory controller monitor\n", dev_name(&pdev->dev));
+out:
+	return rc;
 }
 
-/*
-  ==============================================================================
-  ==============================================================================
-  Linux Interface
-  ==============================================================================
-  ==============================================================================
-*/
-
-/*
-  ------------------------------------------------------------------------------
-  smmon_init
-*/
-
-static int __init
-smmon_init(void)
+static int
+smmon_remove(struct platform_device *pdev)
 {
-	int rc;
-	int mask;
-
-	summary = kmalloc(SUMMARY_SIZE, GFP_KERNEL);
-
-	if (NULL == summary)
-		return -ENOMEM;
-
-	update_summary();
-
-	memset(&counts, 0, sizeof(struct smmon_counts));
-
-	/*
-	  Set the interrupt mask for each controller.
-	*/
-
-	mask = 0x1f7f701;
-	ncr_write(NCP_REGION_ID(0x22, 0), 0x414, 4, &mask);
-	ncr_write(NCP_REGION_ID(0xf, 0), 0x414, 4, &mask);
-
-	rc = request_irq(32 + 161, smmon_isr, IRQF_ONESHOT,
-			 "smmon_0", NULL);
-	rc |= request_irq(32 + 160, smmon_isr, IRQF_ONESHOT,
-			  "smmon_1", NULL);
-
-	if (0 != rc)
-		return -EBUSY;
-
-	pr_info("lsi_smmon: Monitoring System Memory\n");
-
+	sysfs_remove_group(&pdev->dev.kobj, &smmon_attr_group);
 	return 0;
 }
 
-module_init(smmon_init);
-
-/*
-  ------------------------------------------------------------------------------
-  smmon_exit
-*/
-
-static void __exit
-smmon_exit(void)
-{
-	free_irq(32 + 161, NULL);
-	free_irq(32 + 160, NULL);
-
-	kfree(summary);
-
-	pr_info("lsi_smmon: Not Monitoring System Memory\n");
+static const struct of_device_id smmon_id_table[] = {
+	{ .compatible = "lsi,smmon" },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, smmon_id_table);
+
+static struct platform_driver smmon_driver = {
+	.driver = {
+		.name = "lsi-smmon",
+		.of_match_table = smmon_id_table
+	},
+	.probe = smmon_probe,
+	.remove = smmon_remove,
+};
 
-	return;
-}
+module_platform_driver(smmon_driver);
 
-module_exit(smmon_exit);
-- 
1.7.9.5



More information about the linux-yocto mailing list