[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", ®))
+ 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