From: Anders Berg <anders.b...@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.b...@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@00220000 { + compatible = "lsi,smmon"; + reg = <0 0x00220000 0 0x1000>; + interrupts = <0 192 4>; + }; + + sm1@00220000 { + compatible = "lsi,smmon"; + reg = <0 0x000f0000 0 0x1000>; + interrupts = <0 193 4>; + }; gpdma@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@1 { @@ -53,6 +54,7 @@ compatible = "arm,cortex-a15"; reg = <1>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@2 { @@ -60,6 +62,7 @@ compatible = "arm,cortex-a15"; reg = <2>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@3 { @@ -67,6 +70,7 @@ compatible = "arm,cortex-a15"; reg = <3>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@4 { @@ -74,6 +78,7 @@ compatible = "arm,cortex-a15"; reg = <4>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@5 { @@ -81,6 +86,7 @@ compatible = "arm,cortex-a15"; reg = <5>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@6 { @@ -88,6 +94,7 @@ compatible = "arm,cortex-a15"; reg = <6>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@7 { @@ -95,6 +102,7 @@ compatible = "arm,cortex-a15"; reg = <7>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@8 { @@ -102,6 +110,7 @@ compatible = "arm,cortex-a15"; reg = <8>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@9 { @@ -109,6 +118,7 @@ compatible = "arm,cortex-a15"; reg = <9>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@10 { @@ -116,6 +126,7 @@ compatible = "arm,cortex-a15"; reg = <10>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@11 { @@ -123,6 +134,7 @@ compatible = "arm,cortex-a15"; reg = <11>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@12 { @@ -130,6 +142,7 @@ compatible = "arm,cortex-a15"; reg = <12>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@13 { @@ -137,6 +150,7 @@ compatible = "arm,cortex-a15"; reg = <13>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@14 { @@ -144,6 +158,7 @@ compatible = "arm,cortex-a15"; reg = <14>; clock-frequency= <0>; + cpu-release-addr = <0x10000020>; }; cpu@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@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@201100000000 { + axxia_net0: ethernet@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 _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto