diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 03:44:48 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 03:44:48 +0300 |
commit | d8ea757b25ec82687c497fc90aa83f9bcea24b5b (patch) | |
tree | 4789c4d89f1ec77dcb27b855e2f479c3afd511cb /arch/xtensa/kernel | |
parent | 41844e36206be90cd4d962ea49b0abc3612a99d0 (diff) | |
parent | a4c6be5ad1d0c7af0c5421b68a00b6406b28a325 (diff) | |
download | linux-d8ea757b25ec82687c497fc90aa83f9bcea24b5b.tar.xz |
Merge tag 'xtensa-20161005' of git://github.com/jcmvbkbc/linux-xtensa
Pull Xtensa updates from Max Filippov:
"Updates for the xtensa architecture. It is a combined set of patches
for 4.8 that never got to the mainline and new patches for 4.9.
- add new kernel memory layouts for MMUv3 cores: with 256MB and 512MB
KSEG size, starting at physical address other than 0
- make kernel load address configurable
- clean up kernel memory layout macros
- drop sysmem early allocator and switch to memblock
- enable kmemleak and memory reservation from the device tree
- wire up new syscalls: userfaultfd, membarrier, mlock2,
copy_file_range, preadv2 and pwritev2
- add new platform: Cadence Configurable System Platform (CSP) and
new core variant for it: xt_lnx
- rearrange CCOUNT calibration code, make most of it generic
- improve machine reset code (XTFPGA now reboots reliably with MMUv3
cores)
- provide default memmap command line option for configurations
without device tree support
- ISS fixes: simdisk is now capable of using highmem pages, panic
correctly terminates simulator"
* tag 'xtensa-20161005' of git://github.com/jcmvbkbc/linux-xtensa: (24 commits)
xtensa: disable MMU initialization option on MMUv2 cores
xtensa: add default memmap and mmio32native options to defconfigs
xtensa: add default memmap option to common_defconfig
xtensa: add default memmap option to iss_defconfig
xtensa: ISS: allow simdisk to use high memory buffers
xtensa: ISS: define simc_exit and use it instead of inline asm
xtensa: xtfpga: group platform_* functions together
xtensa: rearrange CCOUNT calibration
xtensa: xtfpga: use clock provider, don't update DT
xtensa: Tweak xuartps UART driver Rx watermark for Cadence CSP config.
xtensa: initialize MMU before jumping to reset vector
xtensa: fix icountlevel setting in cpu_reset
xtensa: extract common CPU reset code into separate function
xtensa: Added Cadence CSP kernel configuration for Xtensa
xtensa: fix default kernel load address
xtensa: wire up new syscalls
xtensa: support reserved-memory DT node
xtensa: drop sysmem and switch to memblock
xtensa: minimize use of PLATFORM_DEFAULT_MEM_{ADDR,SIZE}
xtensa: cleanup MMU setup and kernel layout macros
...
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r-- | arch/xtensa/kernel/entry.S | 5 | ||||
-rw-r--r-- | arch/xtensa/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/xtensa/kernel/setup.c | 188 | ||||
-rw-r--r-- | arch/xtensa/kernel/time.c | 40 | ||||
-rw-r--r-- | arch/xtensa/kernel/vmlinux.lds.S | 4 |
5 files changed, 194 insertions, 45 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index fe8f7e7efb9d..fa04d9d368a7 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1632,10 +1632,11 @@ ENTRY(fast_second_level_miss) * The messy computation for 'pteval' above really simplifies * into the following: * - * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY + * pteval = ((pmdval - PAGE_OFFSET + PHYS_OFFSET) & PAGE_MASK) + * | PAGE_DIRECTORY */ - movi a1, (-PAGE_OFFSET) & 0xffffffff + movi a1, (PHYS_OFFSET - PAGE_OFFSET) & 0xffffffff add a0, a0, a1 # pmdval - PAGE_OFFSET extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK xor a0, a0, a1 diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index bc4f4bf05099..23ce62e60435 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S @@ -113,7 +113,7 @@ ENTRY(_startup) movi a0, 0 #if XCHAL_HAVE_VECBASE - movi a2, VECBASE_RESET_VADDR + movi a2, VECBASE_VADDR wsr a2, vecbase #endif diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 143251ede897..88a044af7504 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -7,6 +7,7 @@ * * Copyright (C) 1995 Linus Torvalds * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. * * Chris Zankel <chris@zankel.net> * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> @@ -22,7 +23,6 @@ #include <linux/bootmem.h> #include <linux/kernel.h> #include <linux/percpu.h> -#include <linux/clk-provider.h> #include <linux/cpu.h> #include <linux/of.h> #include <linux/of_fdt.h> @@ -114,7 +114,7 @@ static int __init parse_tag_mem(const bp_tag_t *tag) if (mi->type != MEMORY_TYPE_CONVENTIONAL) return -1; - return add_sysmem_bank(mi->start, mi->end); + return memblock_add(mi->start, mi->end - mi->start); } __tagtable(BP_TAG_MEMORY, parse_tag_mem); @@ -188,7 +188,6 @@ static int __init parse_bootparam(const bp_tag_t* tag) } #ifdef CONFIG_OF -bool __initdata dt_memory_scan = false; #if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR; @@ -228,11 +227,8 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname, void __init early_init_dt_add_memory_arch(u64 base, u64 size) { - if (!dt_memory_scan) - return; - size &= PAGE_MASK; - add_sysmem_bank(base, base + size); + memblock_add(base, size); } void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) @@ -242,9 +238,6 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) void __init early_init_devtree(void *params) { - if (sysmem.nr_banks == 0) - dt_memory_scan = true; - early_init_dt_scan(params); of_scan_flat_dt(xtensa_dt_io_area, NULL); @@ -252,14 +245,6 @@ void __init early_init_devtree(void *params) strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); } -static int __init xtensa_device_probe(void) -{ - of_clk_init(NULL); - return 0; -} - -device_initcall(xtensa_device_probe); - #endif /* CONFIG_OF */ /* @@ -277,12 +262,6 @@ void __init init_arch(bp_tag_t *bp_start) early_init_devtree(dtb_start); #endif - if (sysmem.nr_banks == 0) { - add_sysmem_bank(PLATFORM_DEFAULT_MEM_START, - PLATFORM_DEFAULT_MEM_START + - PLATFORM_DEFAULT_MEM_SIZE); - } - #ifdef CONFIG_CMDLINE_BOOL if (!command_line[0]) strlcpy(command_line, default_command_line, COMMAND_LINE_SIZE); @@ -452,6 +431,10 @@ static int __init check_s32c1i(void) early_initcall(check_s32c1i); #endif /* CONFIG_S32C1I_SELFTEST */ +static inline int mem_reserve(unsigned long start, unsigned long end) +{ + return memblock_reserve(start, end - start); +} void __init setup_arch(char **cmdline_p) { @@ -463,54 +446,54 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start < initrd_end) { initrd_is_mapped = mem_reserve(__pa(initrd_start), - __pa(initrd_end), 0) == 0; + __pa(initrd_end)) == 0; initrd_below_start_ok = 1; } else { initrd_start = 0; } #endif - mem_reserve(__pa(&_stext),__pa(&_end), 1); + mem_reserve(__pa(&_stext), __pa(&_end)); mem_reserve(__pa(&_WindowVectors_text_start), - __pa(&_WindowVectors_text_end), 0); + __pa(&_WindowVectors_text_end)); mem_reserve(__pa(&_DebugInterruptVector_literal_start), - __pa(&_DebugInterruptVector_text_end), 0); + __pa(&_DebugInterruptVector_text_end)); mem_reserve(__pa(&_KernelExceptionVector_literal_start), - __pa(&_KernelExceptionVector_text_end), 0); + __pa(&_KernelExceptionVector_text_end)); mem_reserve(__pa(&_UserExceptionVector_literal_start), - __pa(&_UserExceptionVector_text_end), 0); + __pa(&_UserExceptionVector_text_end)); mem_reserve(__pa(&_DoubleExceptionVector_literal_start), - __pa(&_DoubleExceptionVector_text_end), 0); + __pa(&_DoubleExceptionVector_text_end)); #if XCHAL_EXCM_LEVEL >= 2 mem_reserve(__pa(&_Level2InterruptVector_text_start), - __pa(&_Level2InterruptVector_text_end), 0); + __pa(&_Level2InterruptVector_text_end)); #endif #if XCHAL_EXCM_LEVEL >= 3 mem_reserve(__pa(&_Level3InterruptVector_text_start), - __pa(&_Level3InterruptVector_text_end), 0); + __pa(&_Level3InterruptVector_text_end)); #endif #if XCHAL_EXCM_LEVEL >= 4 mem_reserve(__pa(&_Level4InterruptVector_text_start), - __pa(&_Level4InterruptVector_text_end), 0); + __pa(&_Level4InterruptVector_text_end)); #endif #if XCHAL_EXCM_LEVEL >= 5 mem_reserve(__pa(&_Level5InterruptVector_text_start), - __pa(&_Level5InterruptVector_text_end), 0); + __pa(&_Level5InterruptVector_text_end)); #endif #if XCHAL_EXCM_LEVEL >= 6 mem_reserve(__pa(&_Level6InterruptVector_text_start), - __pa(&_Level6InterruptVector_text_end), 0); + __pa(&_Level6InterruptVector_text_end)); #endif #ifdef CONFIG_SMP mem_reserve(__pa(&_SecondaryResetVector_text_start), - __pa(&_SecondaryResetVector_text_end), 0); + __pa(&_SecondaryResetVector_text_end)); #endif parse_early_param(); bootmem_init(); @@ -555,6 +538,137 @@ static int __init topology_init(void) } subsys_initcall(topology_init); +void cpu_reset(void) +{ +#if XCHAL_HAVE_PTP_MMU + local_irq_disable(); + /* + * We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must + * be flushed. + * Way 4 is not currently used by linux. + * Ways 5 and 6 shall not be touched on MMUv2 as they are hardwired. + * Way 5 shall be flushed and way 6 shall be set to identity mapping + * on MMUv3. + */ + local_flush_tlb_all(); + invalidate_page_directory(); +#if XCHAL_HAVE_SPANNING_WAY + /* MMU v3 */ + { + unsigned long vaddr = (unsigned long)cpu_reset; + unsigned long paddr = __pa(vaddr); + unsigned long tmpaddr = vaddr + SZ_512M; + unsigned long tmp0, tmp1, tmp2, tmp3; + + /* + * Find a place for the temporary mapping. It must not be + * in the same 512MB region with vaddr or paddr, otherwise + * there may be multihit exception either on entry to the + * temporary mapping, or on entry to the identity mapping. + * (512MB is the biggest page size supported by TLB.) + */ + while (((tmpaddr ^ paddr) & -SZ_512M) == 0) + tmpaddr += SZ_512M; + + /* Invalidate mapping in the selected temporary area */ + if (itlb_probe(tmpaddr) & 0x8) + invalidate_itlb_entry(itlb_probe(tmpaddr)); + if (itlb_probe(tmpaddr + PAGE_SIZE) & 0x8) + invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE)); + + /* + * Map two consecutive pages starting at the physical address + * of this function to the temporary mapping area. + */ + write_itlb_entry(__pte((paddr & PAGE_MASK) | + _PAGE_HW_VALID | + _PAGE_HW_EXEC | + _PAGE_CA_BYPASS), + tmpaddr & PAGE_MASK); + write_itlb_entry(__pte(((paddr & PAGE_MASK) + PAGE_SIZE) | + _PAGE_HW_VALID | + _PAGE_HW_EXEC | + _PAGE_CA_BYPASS), + (tmpaddr & PAGE_MASK) + PAGE_SIZE); + + /* Reinitialize TLB */ + __asm__ __volatile__ ("movi %0, 1f\n\t" + "movi %3, 2f\n\t" + "add %0, %0, %4\n\t" + "add %3, %3, %5\n\t" + "jx %0\n" + /* + * No literal, data or stack access + * below this point + */ + "1:\n\t" + /* Initialize *tlbcfg */ + "movi %0, 0\n\t" + "wsr %0, itlbcfg\n\t" + "wsr %0, dtlbcfg\n\t" + /* Invalidate TLB way 5 */ + "movi %0, 4\n\t" + "movi %1, 5\n" + "1:\n\t" + "iitlb %1\n\t" + "idtlb %1\n\t" + "add %1, %1, %6\n\t" + "addi %0, %0, -1\n\t" + "bnez %0, 1b\n\t" + /* Initialize TLB way 6 */ + "movi %0, 7\n\t" + "addi %1, %9, 3\n\t" + "addi %2, %9, 6\n" + "1:\n\t" + "witlb %1, %2\n\t" + "wdtlb %1, %2\n\t" + "add %1, %1, %7\n\t" + "add %2, %2, %7\n\t" + "addi %0, %0, -1\n\t" + "bnez %0, 1b\n\t" + /* Jump to identity mapping */ + "jx %3\n" + "2:\n\t" + /* Complete way 6 initialization */ + "witlb %1, %2\n\t" + "wdtlb %1, %2\n\t" + /* Invalidate temporary mapping */ + "sub %0, %9, %7\n\t" + "iitlb %0\n\t" + "add %0, %0, %8\n\t" + "iitlb %0" + : "=&a"(tmp0), "=&a"(tmp1), "=&a"(tmp2), + "=&a"(tmp3) + : "a"(tmpaddr - vaddr), + "a"(paddr - vaddr), + "a"(SZ_128M), "a"(SZ_512M), + "a"(PAGE_SIZE), + "a"((tmpaddr + SZ_512M) & PAGE_MASK) + : "memory"); + } +#endif +#endif + __asm__ __volatile__ ("movi a2, 0\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"); + for (;;) + ; +} + void machine_restart(char * cmd) { platform_restart(); 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 <chris@zankel.net> */ +#include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/time.h> @@ -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/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index c417cbe4ec87..72cfe3587dd8 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -30,10 +30,6 @@ jiffies = jiffies_64 + 4; jiffies = jiffies_64; #endif -#ifndef KERNELOFFSET -#define KERNELOFFSET 0xd0003000 -#endif - /* Note: In the following macros, it would be nice to specify only the vector name and section kind and construct "sym" and "section" using CPP concatenation, but that does not work reliably. Concatenating a |