From 4f2056873ff0748d413c0dc3577186f78fafa7c9 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 7 Sep 2016 13:33:47 -0700 Subject: xtensa: extract common CPU reset code into separate function platform_restart implementatations do the same thing to reset CPU. Don't duplicate that code, move it to a function and call it from platform_restart. Signed-off-by: Max Filippov --- arch/xtensa/platforms/iss/setup.c | 20 +------------------- arch/xtensa/platforms/xt2000/setup.c | 21 +-------------------- arch/xtensa/platforms/xtfpga/setup.c | 22 +--------------------- 3 files changed, 3 insertions(+), 60 deletions(-) (limited to 'arch/xtensa/platforms') diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index 391820539f0a..e29e1b41ef96 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -53,25 +53,7 @@ void platform_restart(void) { /* Flush and reset the mmu, simulate a processor reset, and * jump to the reset vector. */ - - __asm__ __volatile__("movi a2, 15\n\t" - "wsr a2, icountlevel\n\t" - "movi a2, 0\n\t" - "wsr a2, icount\n\t" -#if XCHAL_NUM_IBREAK > 0 - "wsr a2, ibreakenable\n\t" -#endif -#if XCHAL_HAVE_LOOPS - "wsr a2, lcount\n\t" -#endif - "movi a2, 0x1f\n\t" - "wsr a2, ps\n\t" - "isync\n\t" - "jx %0\n\t" - : - : "a" (XCHAL_RESET_VECTOR_VADDR) - : "a2"); - + cpu_reset(); /* control never gets here */ } diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index 5f4bd71971d6..11b91d6a3b82 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c @@ -64,26 +64,7 @@ void platform_restart(void) { /* Flush and reset the mmu, simulate a processor reset, and * jump to the reset vector. */ - - __asm__ __volatile__ ("movi a2, 15\n\t" - "wsr a2, icountlevel\n\t" - "movi a2, 0\n\t" - "wsr a2, icount\n\t" -#if XCHAL_NUM_IBREAK > 0 - "wsr a2, ibreakenable\n\t" -#endif -#if XCHAL_HAVE_LOOPS - "wsr a2, lcount\n\t" -#endif - "movi a2, 0x1f\n\t" - "wsr a2, ps\n\t" - "isync\n\t" - "jx %0\n\t" - : - : "a" (XCHAL_RESET_VECTOR_VADDR) - : "a2" - ); - + cpu_reset(); /* control never gets here */ } diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index b509d1f55ed5..f0b753f335d8 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -54,27 +54,7 @@ void platform_restart(void) { /* Flush and reset the mmu, simulate a processor reset, and * jump to the reset vector. */ - - - __asm__ __volatile__ ("movi a2, 15\n\t" - "wsr a2, icountlevel\n\t" - "movi a2, 0\n\t" - "wsr a2, icount\n\t" -#if XCHAL_NUM_IBREAK > 0 - "wsr a2, ibreakenable\n\t" -#endif -#if XCHAL_HAVE_LOOPS - "wsr a2, lcount\n\t" -#endif - "movi a2, 0x1f\n\t" - "wsr a2, ps\n\t" - "isync\n\t" - "jx %0\n\t" - : - : "a" (XCHAL_RESET_VECTOR_VADDR) - : "a2" - ); - + cpu_reset(); /* control never gets here */ } -- cgit v1.2.3-59-g8ed1b From 58c3e3ac7a1daf56523567507a096a3e4026596d Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 25 Jul 2016 10:58:10 +0300 Subject: xtensa: xtfpga: use clock provider, don't update DT Instead of querying hardcoded FPGA frequency register and then updating clock-frequency property in specificly named DT nodes in machine setup code register a clock provider that returns fixed-rate clock, configured by register specified in DT. This way we have less magic/hardcoded names and use more existing common clock framework code. Signed-off-by: Max Filippov Tested-by: Guenter Roeck --- arch/xtensa/boot/dts/xtfpga.dtsi | 11 ++++++----- arch/xtensa/platforms/xtfpga/setup.c | 33 +++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 9 deletions(-) (limited to 'arch/xtensa/platforms') diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi index cd45f9c2c448..ded56984dd23 100644 --- a/arch/xtensa/boot/dts/xtfpga.dtsi +++ b/arch/xtensa/boot/dts/xtfpga.dtsi @@ -36,11 +36,6 @@ }; clocks { - osc: main-oscillator { - #clock-cells = <0>; - compatible = "fixed-clock"; - }; - clk54: clk54 { #clock-cells = <0>; compatible = "fixed-clock"; @@ -54,6 +49,12 @@ compatible = "simple-bus"; ranges = <0x00000000 0xf0000000 0x10000000>; + osc: main-oscillator { + #clock-cells = <0>; + compatible = "cdns,xtfpga-clock"; + reg = <0x0d020004 0x4>; + }; + serial0: serial@0d050020 { device_type = "serial"; compatible = "ns16550a"; diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index f0b753f335d8..99a38a6febea 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -87,6 +89,33 @@ static void __init update_clock_frequency(struct device_node *node) of_update_property(node, newfreq); } +static void __init xtfpga_clk_setup(struct device_node *np) +{ + void __iomem *base = of_iomap(np, 0); + struct clk *clk; + u32 freq; + + if (!base) { + pr_err("%s: invalid address\n", np->name); + return; + } + + freq = __raw_readl(base); + iounmap(base); + clk = clk_register_fixed_rate(NULL, np->name, NULL, 0, freq); + + if (IS_ERR(clk)) { + pr_err("%s: clk registration failed\n", np->name); + return; + } + + if (of_clk_add_provider(np, of_clk_src_simple_get, clk)) { + pr_err("%s: clk provider registration failed\n", np->name); + return; + } +} +CLK_OF_DECLARE(xtfpga_clk, "cdns,xtfpga-clock", xtfpga_clk_setup); + #define MAC_LEN 6 static void __init update_local_mac(struct device_node *node) { @@ -117,12 +146,8 @@ static void __init update_local_mac(struct device_node *node) static int __init machine_setup(void) { - struct device_node *clock; struct device_node *eth = NULL; - for_each_node_by_name(clock, "main-oscillator") - update_clock_frequency(clock); - if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc"))) update_local_mac(eth); return 0; -- cgit v1.2.3-59-g8ed1b From 205ad548a7426fb6813760cd9917d3fc24122576 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 20 Sep 2016 11:11:08 -0700 Subject: xtensa: rearrange CCOUNT calibration DT-enabled kernel should have a CPU node connected to a clock. This clock is the CCOUNT clock. Use old platform_calibrate_ccount call as a fallback when CPU node cannot be found or has no clock and in non-DT-enabled configurations. Drop no longer needed code that updates CPU clock-frequency property in the DT; drop DT-related code from the platform_calibrate_ccount too. Move of_clk_init to the top of time_init, so that clocks are initialized before CCOUNT calibration is attempted. Signed-off-by: Max Filippov --- arch/xtensa/boot/dts/xtfpga.dtsi | 4 +--- arch/xtensa/kernel/setup.c | 2 -- arch/xtensa/kernel/time.c | 40 +++++++++++++++++++++++++++++++++++- arch/xtensa/platforms/xtfpga/setup.c | 39 +---------------------------------- 4 files changed, 41 insertions(+), 44 deletions(-) (limited to 'arch/xtensa/platforms') diff --git a/arch/xtensa/boot/dts/xtfpga.dtsi b/arch/xtensa/boot/dts/xtfpga.dtsi index ded56984dd23..91616a9d79df 100644 --- a/arch/xtensa/boot/dts/xtfpga.dtsi +++ b/arch/xtensa/boot/dts/xtfpga.dtsi @@ -19,9 +19,7 @@ cpu@0 { compatible = "cdns,xtensa-cpu"; reg = <0>; - /* Filled in by platform_setup from FPGA register - * clock-frequency = <100000000>; - */ + clocks = <&osc>; }; }; diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 7ed63688f93c..d61c8468abea 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -249,7 +248,6 @@ void __init early_init_devtree(void *params) static int __init xtensa_device_probe(void) { - of_clk_init(NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); return 0; } diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index b9ad9feadc2d..9a5bcd0381a7 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -12,6 +12,8 @@ * Chris Zankel */ +#include +#include #include #include #include @@ -134,16 +136,52 @@ void local_timer_setup(unsigned cpu) 0xf, 0xffffffff); } +#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT +#ifdef CONFIG_OF +static void __init calibrate_ccount(void) +{ + struct device_node *cpu; + struct clk *clk; + + cpu = of_find_compatible_node(NULL, NULL, "cdns,xtensa-cpu"); + if (cpu) { + clk = of_clk_get(cpu, 0); + if (!IS_ERR(clk)) { + ccount_freq = clk_get_rate(clk); + return; + } else { + pr_warn("%s: CPU input clock not found\n", + __func__); + } + } else { + pr_warn("%s: CPU node not found in the device tree\n", + __func__); + } + + platform_calibrate_ccount(); +} +#else +static inline void calibrate_ccount(void) +{ + platform_calibrate_ccount(); +} +#endif +#endif + void __init time_init(void) { + of_clk_init(NULL); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT printk("Calibrating CPU frequency "); - platform_calibrate_ccount(); + calibrate_ccount(); printk("%d.%02d MHz\n", (int)ccount_freq/1000000, (int)(ccount_freq/10000)%100); #else ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL; #endif + WARN(!ccount_freq, + "%s: CPU clock frequency is not set up correctly\n", + __func__); clocksource_register_hz(&ccount_clocksource, ccount_freq); local_timer_setup(0); setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction); diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 99a38a6febea..e236df450a7b 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -66,29 +66,6 @@ void __init platform_setup(char **cmdline) #ifdef CONFIG_OF -static void __init update_clock_frequency(struct device_node *node) -{ - struct property *newfreq; - u32 freq; - - if (!of_property_read_u32(node, "clock-frequency", &freq) && freq != 0) - return; - - newfreq = kzalloc(sizeof(*newfreq) + sizeof(u32), GFP_KERNEL); - if (!newfreq) - return; - newfreq->value = newfreq + 1; - newfreq->length = sizeof(freq); - newfreq->name = kstrdup("clock-frequency", GFP_KERNEL); - if (!newfreq->name) { - kfree(newfreq); - return; - } - - *(u32 *)newfreq->value = cpu_to_be32(*(u32 *)XTFPGA_CLKFRQ_VADDR); - of_update_property(node, newfreq); -} - static void __init xtfpga_clk_setup(struct device_node *np) { void __iomem *base = of_iomap(np, 0); @@ -172,21 +149,7 @@ void platform_heartbeat(void) void __init platform_calibrate_ccount(void) { - long clk_freq = 0; -#ifdef CONFIG_OF - struct device_node *cpu = - of_find_compatible_node(NULL, NULL, "cdns,xtensa-cpu"); - if (cpu) { - u32 freq; - update_clock_frequency(cpu); - if (!of_property_read_u32(cpu, "clock-frequency", &freq)) - clk_freq = freq; - } -#endif - if (!clk_freq) - clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR; - - ccount_freq = clk_freq; + ccount_freq = *(long *)XTFPGA_CLKFRQ_VADDR; } #endif -- cgit v1.2.3-59-g8ed1b From 70feca7199647dd548536d7e6b55a742053e6839 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 20 Sep 2016 11:29:37 -0700 Subject: xtensa: xtfpga: group platform_* functions together Group platform_* functions together and turn two separate #ifdef/#ifndef blocks into single #ifdef/#else. No functional changes. Signed-off-by: Max Filippov --- arch/xtensa/platforms/xtfpga/setup.c | 46 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 24 deletions(-) (limited to 'arch/xtensa/platforms') diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index e236df450a7b..779be723eb2b 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -64,6 +64,27 @@ void __init platform_setup(char **cmdline) { } +/* early initialization */ + +void __init platform_init(bp_tag_t *first) +{ +} + +/* Heartbeat. */ + +void platform_heartbeat(void) +{ +} + +#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT + +void __init platform_calibrate_ccount(void) +{ + ccount_freq = *(long *)XTFPGA_CLKFRQ_VADDR; +} + +#endif + #ifdef CONFIG_OF static void __init xtfpga_clk_setup(struct device_node *np) @@ -131,30 +152,7 @@ static int __init machine_setup(void) } arch_initcall(machine_setup); -#endif - -/* early initialization */ - -void __init platform_init(bp_tag_t *first) -{ -} - -/* Heartbeat. */ - -void platform_heartbeat(void) -{ -} - -#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT - -void __init platform_calibrate_ccount(void) -{ - ccount_freq = *(long *)XTFPGA_CLKFRQ_VADDR; -} - -#endif - -#ifndef CONFIG_OF +#else #include #include -- cgit v1.2.3-59-g8ed1b From feec273a2b4d98f8aa76c5d83f24053b211c8525 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 20 Sep 2016 17:26:48 -0700 Subject: xtensa: ISS: define simc_exit and use it instead of inline asm A number of ISS platform functions use inline assembly to invoke simulator exit, not all correctly. Define simc_exit(exit_code) and use it instead of inline assembly. Signed-off-by: Max Filippov --- arch/xtensa/platforms/iss/include/platform/simcall.h | 5 +++++ arch/xtensa/platforms/iss/setup.c | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'arch/xtensa/platforms') diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h index 12b15ad1e586..27d7a528b41a 100644 --- a/arch/xtensa/platforms/iss/include/platform/simcall.h +++ b/arch/xtensa/platforms/iss/include/platform/simcall.h @@ -76,6 +76,11 @@ static inline int __simc(int a, int b, int c, int d) return ret; } +static inline int simc_exit(int exit_code) +{ + return __simc(SYS_exit, exit_code, 0, 0); +} + static inline int simc_open(const char *file, int flags, int mode) { return __simc(SYS_open, (int) file, flags, mode); diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index e29e1b41ef96..379aeddcc638 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -32,6 +32,8 @@ #include #include +#include + void __init platform_init(bp_tag_t* bootparam) { @@ -41,13 +43,13 @@ void __init platform_init(bp_tag_t* bootparam) void platform_halt(void) { pr_info(" ** Called platform_halt() **\n"); - __asm__ __volatile__("movi a2, 1\nsimcall\n"); + simc_exit(0); } void platform_power_off(void) { pr_info(" ** Called platform_power_off() **\n"); - __asm__ __volatile__("movi a2, 1\nsimcall\n"); + simc_exit(0); } void platform_restart(void) { @@ -80,7 +82,7 @@ void platform_heartbeat(void) static int iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) { - __asm__ __volatile__("movi a2, -1; simcall\n"); + simc_exit(1); return NOTIFY_DONE; } -- cgit v1.2.3-59-g8ed1b From 549409b4b584604f8eb225ebbb19be74204fe789 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 20 Sep 2016 17:58:20 -0700 Subject: xtensa: ISS: allow simdisk to use high memory buffers ISS kernel by default has only low memory. But it may be configured to support high memory and started in a simulator with more than 128M of RAM. Simdisk driver in such configuration can get IO request with a high memory page. There may be no TLB entry for that page, only page table entry. However simulators don't do pagewalking, so such IO request will fail. Touch IO buffer in the buffer read/write loop so that a TLB entry is likely there when read or write simcall is invoked. Signed-off-by: Max Filippov --- arch/xtensa/platforms/iss/simdisk.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/xtensa/platforms') diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c index f58a4e6472cb..ede04cca30dd 100644 --- a/arch/xtensa/platforms/iss/simdisk.c +++ b/arch/xtensa/platforms/iss/simdisk.c @@ -86,6 +86,7 @@ static void simdisk_transfer(struct simdisk *dev, unsigned long sector, unsigned long io; simc_lseek(dev->fd, offset, SEEK_SET); + READ_ONCE(*buffer); if (write) io = simc_write(dev->fd, buffer, nbytes); else -- cgit v1.2.3-59-g8ed1b