diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/config.mk | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/cache_v7.c | 21 | ||||
-rw-r--r-- | arch/arm/cpu/u-boot.lds | 27 | ||||
-rw-r--r-- | arch/arm/include/asm/system.h | 7 | ||||
-rw-r--r-- | arch/arm/lib/cache-cp15.c | 2 | ||||
-rw-r--r-- | arch/mips/Kconfig | 10 | ||||
-rw-r--r-- | arch/mips/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/cpu/start.S | 22 | ||||
-rw-r--r-- | arch/mips/dts/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/dts/pic32mzda.dtsi | 174 | ||||
-rw-r--r-- | arch/mips/dts/pic32mzda_sk.dts | 55 | ||||
-rw-r--r-- | arch/mips/include/asm/global_data.h | 3 | ||||
-rw-r--r-- | arch/mips/include/asm/io.h | 82 | ||||
-rw-r--r-- | arch/mips/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/lib/cache.c | 8 | ||||
-rw-r--r-- | arch/mips/lib/io.c | 12 | ||||
-rw-r--r-- | arch/mips/mach-pic32/Kconfig | 35 | ||||
-rw-r--r-- | arch/mips/mach-pic32/Makefile | 7 | ||||
-rw-r--r-- | arch/mips/mach-pic32/cpu.c | 156 | ||||
-rw-r--r-- | arch/mips/mach-pic32/include/mach/ddr.h | 32 | ||||
-rw-r--r-- | arch/mips/mach-pic32/include/mach/pic32.h | 79 | ||||
-rw-r--r-- | arch/mips/mach-pic32/lowlevel_init.S | 27 | ||||
-rw-r--r-- | arch/mips/mach-pic32/reset.c | 36 |
23 files changed, 702 insertions, 98 deletions
diff --git a/arch/arm/config.mk b/arch/arm/config.mk index a3e14a862b..8fa57ecfd8 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -107,6 +107,7 @@ ALL-y += checkarmreloc # instruction. Relocation is not supported for that case, so disable # such usage by requiring word relocations. PLATFORM_CPPFLAGS += $(call cc-option, -mword-relocations) +PLATFORM_CPPFLAGS += $(call cc-option, -fno-pic) endif # limit ourselves to the sections we want in the .bin. diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c index a5aa4fa643..94ff48859e 100644 --- a/arch/arm/cpu/armv7/cache_v7.c +++ b/arch/arm/cpu/armv7/cache_v7.c @@ -16,6 +16,23 @@ #define ARMV7_DCACHE_CLEAN_INVAL_RANGE 4 #ifndef CONFIG_SYS_DCACHE_OFF +static int check_cache_range(unsigned long start, unsigned long stop) +{ + int ok = 1; + + if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (!ok) + debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", + start, stop); + + return ok; +} + /* * Write the level and type you want to Cache Size Selection Register(CSSELR) * to get size details from Current Cache Size ID Register(CCSIDR) @@ -257,6 +274,8 @@ void flush_dcache_all(void) */ void invalidate_dcache_range(unsigned long start, unsigned long stop) { + check_cache_range(start, stop); + v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE); v7_outer_cache_inval_range(start, stop); @@ -269,6 +288,8 @@ void invalidate_dcache_range(unsigned long start, unsigned long stop) */ void flush_dcache_range(unsigned long start, unsigned long stop) { + check_cache_range(start, stop); + v7_dcache_maint_range(start, stop, ARMV7_DCACHE_CLEAN_INVAL_RANGE); v7_outer_cache_flush_range(start, stop); diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds index d48a905cf3..e148ab7513 100644 --- a/arch/arm/cpu/u-boot.lds +++ b/arch/arm/cpu/u-boot.lds @@ -14,23 +14,24 @@ OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { +#if defined(CONFIG_ARMV7_SECURE_BASE) && defined(CONFIG_ARMV7_NONSEC) /* - * Discard the relocation entries for secure text. - * The secure code is bundled with u-boot image, so there will - * be relocations entries for the secure code, since we use - * "-mword-relocations" to compile and "-pie" to link into the - * final image. We do not need the relocation entries for secure - * code, because secure code will not be relocated, it only needs - * to be copied from loading address to CONFIG_ARMV7_SECURE_BASE, - * which is the linking and running address for secure code. - * If keep the relocation entries in .rel.dyn section, - * "relocation offset + linking address" may locates into an - * address that is reserved by SoC, then will trigger data abort. + * If CONFIG_ARMV7_SECURE_BASE is true, secure code will not + * bundle with u-boot, and code offsets are fixed. Secure zone + * only needs to be copied from the loading address to + * CONFIG_ARMV7_SECURE_BASE, which is the linking and running + * address for secure code. * - * The reason that move .rel._secure at the beginning, is to - * avoid hole in the final image. + * If CONFIG_ARMV7_SECURE_BASE is undefined, the secure zone will + * be included in u-boot address space, and some absolute address + * were used in secure code. The absolute addresses of the secure + * code also needs to be relocated along with the accompanying u-boot + * code. + * + * So DISCARD is only for CONFIG_ARMV7_SECURE_BASE. */ /DISCARD/ : { *(.rel._secure*) } +#endif . = 0x00000000; . = ALIGN(4); diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 67cbbc2610..026e7ef83b 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -259,7 +259,7 @@ static inline void set_dacr(unsigned int val) isb(); } -#ifdef CONFIG_ARMV7 +#ifdef CONFIG_CPU_V7 /* Short-Descriptor Translation Table Level 1 Bits */ #define TTB_SECT_NS_MASK (1 << 19) #define TTB_SECT_NG_MASK (1 << 17) @@ -274,8 +274,7 @@ static inline void set_dacr(unsigned int val) /* options available for data cache on each page */ enum dcache_option { - DCACHE_OFF = TTB_SECT_S_MASK | TTB_SECT_DOMAIN(0) | - TTB_SECT_XN_MASK | TTB_SECT, + DCACHE_OFF = TTB_SECT_DOMAIN(0) | TTB_SECT_XN_MASK | TTB_SECT, DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK, DCACHE_WRITEBACK = DCACHE_WRITETHROUGH | TTB_SECT_B_MASK, DCACHE_WRITEALLOC = DCACHE_WRITEBACK | TTB_SECT_TEX(1), @@ -296,7 +295,7 @@ enum { MMU_SECTION_SIZE = 1 << MMU_SECTION_SHIFT, }; -#ifdef CONFIG_ARMV7 +#ifdef CONFIG_CPU_V7 /* TTBR0 bits */ #define TTBR0_BASE_ADDR_MASK 0xFFFFC000 #define TTBR0_RGN_NC (0 << 3) diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c index c65e068857..8e185383a5 100644 --- a/arch/arm/lib/cache-cp15.c +++ b/arch/arm/lib/cache-cp15.c @@ -96,7 +96,7 @@ static inline void mmu_setup(void) dram_bank_mmu_setup(i); } -#ifdef CONFIG_ARMV7 +#ifdef CONFIG_CPU_V7 /* Set TTBR0 */ reg = gd->arch.tlb_addr & TTBR0_BASE_ADDR_MASK; #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1b39c4c0c6..f852a1f1bb 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -23,6 +23,7 @@ config TARGET_QEMU_MIPS config TARGET_MALTA bool "Support malta" + select DYNAMIC_IO_PORT_BASE select SUPPORTS_BIG_ENDIAN select SUPPORTS_LITTLE_ENDIAN select SUPPORTS_CPU_MIPS32_R1 @@ -54,6 +55,11 @@ config TARGET_PB1X00 select SYS_MIPS_CACHE_INIT_RAM_LOAD select MIPS_TUNE_4KC +config MACH_PIC32 + bool "Support Microchip PIC32" + select OF_CONTROL + select DM + endchoice source "board/dbau1x00/Kconfig" @@ -61,6 +67,7 @@ source "board/imgtec/malta/Kconfig" source "board/micronas/vct/Kconfig" source "board/pb1x00/Kconfig" source "board/qemu-mips/Kconfig" +source "arch/mips/mach-pic32/Kconfig" if MIPS @@ -217,6 +224,9 @@ config MIPS_L1_CACHE_SHIFT default "4" if MIPS_L1_CACHE_SHIFT_4 default "5" +config DYNAMIC_IO_PORT_BASE + bool + endif endmenu diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 2133e7e065..aec5a1517a 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -8,6 +8,7 @@ libs-y += arch/mips/cpu/ libs-y += arch/mips/lib/ machine-$(CONFIG_SOC_AU1X00) += au1x00 +machine-$(CONFIG_MACH_PIC32) += pic32 machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y)) libs-y += $(machdirs) diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index e95cdca61e..d2c31ae781 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -115,7 +115,7 @@ reset: /* Clear watch registers */ MTC0 zero, CP0_WATCHLO - MTC0 zero, CP0_WATCHHI + mtc0 zero, CP0_WATCHHI /* WP(Watch Pending), SW0/1 should be cleared */ mtc0 zero, CP0_CAUSE @@ -161,14 +161,14 @@ reset: #endif /* Set up temporary stack */ - PTR_LI t0, -16 + li t0, -16 PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR and sp, t1, t0 # force 16 byte alignment PTR_SUB sp, sp, GD_SIZE # reserve space for gd and sp, sp, t0 # force 16 byte alignment move k0, sp # save gd pointer #ifdef CONFIG_SYS_MALLOC_F_LEN - PTR_LI t2, CONFIG_SYS_MALLOC_F_LEN + li t2, CONFIG_SYS_MALLOC_F_LEN PTR_SUB sp, sp, t2 # reserve space for early malloc and sp, sp, t0 # force 16 byte alignment #endif @@ -177,15 +177,15 @@ reset: /* Clear gd */ move t0, k0 1: - sw zero, 0(t0) + PTR_S zero, 0(t0) blt t0, t1, 1b - PTR_ADDI t0, 4 + PTR_ADDI t0, PTRSIZE #ifdef CONFIG_SYS_MALLOC_F_LEN - PTR_ADDU t0, k0, GD_MALLOC_BASE # gd->malloc_base offset - sw sp, 0(t0) + PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset #endif + move a0, zero # a0 <-- boot_flags = 0 PTR_LA t9, board_init_f jr t9 move ra, zero @@ -224,11 +224,11 @@ ENTRY(relocate_code) * t2 = source end address */ 1: - lw t3, 0(t0) - sw t3, 0(t1) - PTR_ADDU t0, 4 + PTR_L t3, 0(t0) + PTR_S t3, 0(t1) + PTR_ADDU t0, PTRSIZE blt t0, t2, 1b - PTR_ADDU t1, 4 + PTR_ADDU t1, PTRSIZE /* If caches were enabled, we would have to flush them here. */ PTR_SUB a1, t1, s2 # a1 <-- size diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile index 47b6eb50c3..b5139187c2 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-2.0+ # -dtb-y += +dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb targets += $(dtb-y) diff --git a/arch/mips/dts/pic32mzda.dtsi b/arch/mips/dts/pic32mzda.dtsi new file mode 100644 index 0000000000..7d180d9918 --- /dev/null +++ b/arch/mips/dts/pic32mzda.dtsi @@ -0,0 +1,174 @@ +/* + * Copyright 2015 Microchip Technology, Inc. + * Purna Chandra Mandal, <purna.mandal@microchip.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/clock/microchip,clock.h> +#include <dt-bindings/gpio/gpio.h> +#include "skeleton.dtsi" + +/ { + compatible = "microchip,pic32mzda", "microchip,pic32mz"; + + aliases { + gpio0 = &gpioA; + gpio1 = &gpioB; + gpio2 = &gpioC; + gpio3 = &gpioD; + gpio4 = &gpioE; + gpio5 = &gpioF; + gpio6 = &gpioG; + gpio7 = &gpioH; + gpio8 = &gpioJ; + gpio9 = &gpioK; + }; + + cpus { + cpu@0 { + compatible = "mips,mips14kc"; + }; + }; + + clock: clk@1f801200 { + compatible = "microchip,pic32mzda-clk"; + reg = <0x1f801200 0x1000>; + #clock-cells = <1>; + }; + + uart1: serial@1f822000 { + compatible = "microchip,pic32mzda-uart"; + reg = <0x1f822000 0x50>; + interrupts = <112 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + clocks = <&clock PB2CLK>; + }; + + uart2: serial@1f822200 { + compatible = "microchip,pic32mzda-uart"; + reg = <0x1f822200 0x50>; + interrupts = <145 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clock PB2CLK>; + status = "disabled"; + }; + + uart6: serial@1f822a00 { + compatible = "microchip,pic32mzda-uart"; + reg = <0x1f822a00 0x50>; + interrupts = <188 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clock PB2CLK>; + status = "disabled"; + }; + + evic: interrupt-controller@1f810000 { + compatible = "microchip,pic32mzda-evic"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x1f810000 0x1000>; + }; + + pinctrl: pinctrl@1f801400 { + compatible = "microchip,pic32mzda-pinctrl"; + reg = <0x1f801400 0x100>, /* in */ + <0x1f801500 0x200>, /* out */ + <0x1f860000 0xa00>; /* port */ + reg-names = "ppsin","ppsout","port"; + status = "disabled"; + + ranges = <0 0x1f860000 0xa00>; + #address-cells = <1>; + #size-cells = <1>; + gpioA: gpio0@0 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x000 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioB: gpio1@100 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x100 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioC: gpio2@200 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x200 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioD: gpio3@300 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x300 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioE: gpio4@400 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x400 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioF: gpio5@500 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x500 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioG: gpio6@600 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x600 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioH: gpio7@700 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x700 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioJ: gpio8@800 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x800 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + + gpioK: gpio9@900 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x900 0x48>; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + sdhci: sdhci@1f8ec000 { + compatible = "microchip,pic32mzda-sdhci"; + reg = <0x1f8ec000 0x100>; + interrupts = <191 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clock REF4CLK>, <&clock PB5CLK>; + clock-names = "base_clk", "sys_clk"; + clock-freq-min-max = <25000000>,<25000000>; + bus-width = <4>; + status = "disabled"; + }; + + ethernet: ethernet@1f882000 { + compatible = "microchip,pic32mzda-eth"; + reg = <0x1f882000 0x1000>; + interrupts = <153 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clock PB5CLK>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; +}; diff --git a/arch/mips/dts/pic32mzda_sk.dts b/arch/mips/dts/pic32mzda_sk.dts new file mode 100644 index 0000000000..e5ce0bdc2e --- /dev/null +++ b/arch/mips/dts/pic32mzda_sk.dts @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 Purna Chandra Mandal, purna.mandal@microchip.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include "pic32mzda.dtsi" + +/ { + model = "Microchip PIC32MZDASK"; + compatible = "microchip,pic32mzdask", "microchip,pic32mzda"; + + aliases { + console = &uart2; + serial0 = &uart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&clock { + microchip,refo2-frequency = <50000000>; + microchip,refo4-frequency = <25000000>; + microchip,refo5-frequency = <40000000>; + status = "okay"; + u-boot,dm-pre-reloc; +}; + +&pinctrl { + status = "okay"; + u-boot,dm-pre-reloc; +}; + +&uart2 { + status = "okay"; + u-boot,dm-pre-reloc; +}; + +&sdhci { + status = "okay"; +}; + +ðernet { + reset-gpios = <&gpioJ 15 0>; + status = "okay"; + phy-mode = "rmii"; + phy-handle = <ðernet_phy>; + ethernet_phy: lan8740_phy@0 { + reg = <0>; + }; +};
\ No newline at end of file diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h index 2d9a0c9e75..a1ca257db5 100644 --- a/arch/mips/include/asm/global_data.h +++ b/arch/mips/include/asm/global_data.h @@ -12,6 +12,9 @@ /* Architecture-specific global data */ struct arch_global_data { +#ifdef CONFIG_DYNAMIC_IO_PORT_BASE + unsigned long io_port_base; +#endif #ifdef CONFIG_JZSOC /* There are other clocks in the jz4740 */ unsigned long per_clk; /* Peripheral bus clock */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index f71e34231b..723a60a199 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -26,11 +26,6 @@ #include <spaces.h> /* - * Slowdown I/O port space accesses for antique hardware. - */ -#undef CONF_SLOWDOWN_IO - -/* * Raw operations are never swapped in software. OTOH values that raw * operations are working on may or may not have been swapped by the bus * hardware. An example use would be for flash memory that's used for @@ -46,57 +41,36 @@ #define IO_SPACE_LIMIT 0xffff -/* - * On MIPS I/O ports are memory mapped, so we access them using normal - * load/store instructions. mips_io_port_base is the virtual address to - * which all ports are being mapped. For sake of efficiency some code - * assumes that this is an address that can be loaded with a single lui - * instruction, so the lower 16 bits must be zero. Should be true on - * on any sane architecture; generic code does not use this assumption. - */ -extern const unsigned long mips_io_port_base; +#ifdef CONFIG_DYNAMIC_IO_PORT_BASE + +static inline ulong mips_io_port_base(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + return gd->arch.io_port_base; +} -/* - * Gcc will generate code to load the value of mips_io_port_base after each - * function call which may be fairly wasteful in some cases. So we don't - * play quite by the book. We tell gcc mips_io_port_base is a long variable - * which solves the code generation issue. Now we need to violate the - * aliasing rules a little to make initialization possible and finally we - * will need the barrier() to fight side effects of the aliasing chat. - * This trickery will eventually collapse under gcc's optimizer. Oh well. - */ static inline void set_io_port_base(unsigned long base) { - * (unsigned long *) &mips_io_port_base = base; + DECLARE_GLOBAL_DATA_PTR; + + gd->arch.io_port_base = base; barrier(); } -/* - * Thanks to James van Artsdalen for a better timing-fix than - * the two short jumps: using outb's to a nonexistent port seems - * to guarantee better timings even on fast machines. - * - * On the other hand, I'd like to be sure of a non-existent port: - * I feel a bit unsafe about using 0x80 (should be safe, though) - * - * Linus - * - */ +#else /* !CONFIG_DYNAMIC_IO_PORT_BASE */ -#define __SLOW_DOWN_IO \ - __asm__ __volatile__( \ - "sb\t$0,0x80(%0)" \ - : : "r" (mips_io_port_base)); +static inline ulong mips_io_port_base(void) +{ + return 0; +} -#ifdef CONF_SLOWDOWN_IO -#ifdef REALLY_SLOW_IO -#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } -#else -#define SLOW_DOWN_IO __SLOW_DOWN_IO -#endif -#else -#define SLOW_DOWN_IO -#endif +static inline void set_io_port_base(unsigned long base) +{ + BUG_ON(base); +} + +#endif /* !CONFIG_DYNAMIC_IO_PORT_BASE */ /* * virt_to_phys - map virtual addresses to physical @@ -316,7 +290,7 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ return pfx##ioswab##bwlq(__mem, __val); \ } -#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) \ +#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p) \ \ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ { \ @@ -325,7 +299,7 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ \ war_octeon_io_reorder_wmb(); \ \ - __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base() + port); \ \ __val = pfx##ioswab##bwlq(__addr, val); \ \ @@ -333,7 +307,6 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ \ *__addr = __val; \ - slow; \ } \ \ static inline type pfx##in##bwlq##p(unsigned long port) \ @@ -341,12 +314,11 @@ static inline type pfx##in##bwlq##p(unsigned long port) \ volatile type *__addr; \ type __val; \ \ - __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ + __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base() + port); \ \ BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ \ __val = *__addr; \ - slow; \ \ return pfx##ioswab##bwlq(__addr, __val); \ } @@ -367,8 +339,8 @@ BUILDIO_MEM(l, u32) BUILDIO_MEM(q, u64) #define __BUILD_IOPORT_PFX(bus, bwlq, type) \ - __BUILD_IOPORT_SINGLE(bus, bwlq, type, ,) \ - __BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO) + __BUILD_IOPORT_SINGLE(bus, bwlq, type, ) \ + __BUILD_IOPORT_SINGLE(bus, bwlq, type, _p) #define BUILDIO_IOPORT(bwlq, type) \ __BUILD_IOPORT_PFX(, bwlq, type) \ diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index ac536da674..b7ce5df765 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -7,7 +7,6 @@ obj-y += cache.o obj-y += cache_init.o -obj-y += io.o obj-$(CONFIG_CMD_BOOTM) += bootm.o diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c index bf8ff598ac..7482005b67 100644 --- a/arch/mips/lib/cache.c +++ b/arch/mips/lib/cache.c @@ -95,6 +95,10 @@ void flush_dcache_range(ulong start_addr, ulong stop) const void *addr = (const void *)(start_addr & ~(lsize - 1)); const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); + /* aend will be miscalculated when size is zero, so we return here */ + if (start_addr == stop) + return; + while (1) { mips_cache(HIT_WRITEBACK_INV_D, addr); if (addr == aend) @@ -109,6 +113,10 @@ void invalidate_dcache_range(ulong start_addr, ulong stop) const void *addr = (const void *)(start_addr & ~(lsize - 1)); const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); + /* aend will be miscalculated when size is zero, so we return here */ + if (start_addr == stop) + return; + while (1) { mips_cache(HIT_INVALIDATE_D, addr); if (addr == aend) diff --git a/arch/mips/lib/io.c b/arch/mips/lib/io.c deleted file mode 100644 index b2d4a094da..0000000000 --- a/arch/mips/lib/io.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * mips_io_port_base is the begin of the address space to which x86 style - * I/O ports are mapped. - */ -const unsigned long mips_io_port_base = -1; diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach-pic32/Kconfig new file mode 100644 index 0000000000..2e38bb7eca --- /dev/null +++ b/arch/mips/mach-pic32/Kconfig @@ -0,0 +1,35 @@ +menu "Microchip PIC32 platforms" + depends on MACH_PIC32 + +config SYS_SOC + default "pic32mzda" if SOC_PIC32MZDA + +choice + prompt "PIC32 SoC select" + +config SOC_PIC32MZDA + bool "Microchip PIC32MZ[DA] family" + select SUPPORTS_LITTLE_ENDIAN + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + select MIPS_L1_CACHE_SHIFT_4 + select SYS_MIPS_CACHE_INIT_RAM_LOAD + help + This supports Microchip PIC32MZ[DA] family of microcontrollers. + +endchoice + +choice + prompt "Board select" + +config TARGET_PIC32MZDASK + bool "Microchip PIC32MZ[DA] Starter Kit" + depends on SOC_PIC32MZDA + help + This supports Microchip PIC32MZ[DA] Starter Kit. + +endchoice + +source "board/microchip/pic32mzda/Kconfig" + +endmenu diff --git a/arch/mips/mach-pic32/Makefile b/arch/mips/mach-pic32/Makefile new file mode 100644 index 0000000000..e321e65fd4 --- /dev/null +++ b/arch/mips/mach-pic32/Makefile @@ -0,0 +1,7 @@ +# (C) Copyright 2015 +# Purna Chandra Mandal, purna.mandal@microchip.com. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o lowlevel_init.o reset.o
\ No newline at end of file diff --git a/arch/mips/mach-pic32/cpu.c b/arch/mips/mach-pic32/cpu.c new file mode 100644 index 0000000000..f2ee911df4 --- /dev/null +++ b/arch/mips/mach-pic32/cpu.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2015 + * Purna Chandra Mandal <purna.mandal@microchip.com> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <mach/pic32.h> +#include <mach/ddr.h> +#include <dt-bindings/clock/microchip,clock.h> + +/* Flash prefetch */ +#define PRECON 0x00 + +/* Flash ECCCON */ +#define ECC_MASK 0x03 +#define ECC_SHIFT 4 + +#define CLK_MHZ(x) ((x) / 1000000) + +DECLARE_GLOBAL_DATA_PTR; + +static ulong clk_get_cpu_rate(void) +{ + int ret; + struct udevice *dev; + + ret = uclass_get_device(UCLASS_CLK, 0, &dev); + if (ret) { + panic("uclass-clk: device not found\n"); + return 0; + } + + return clk_get_rate(dev); +} + +/* initialize prefetch module related to cpu_clk */ +static void prefetch_init(void) +{ + struct pic32_reg_atomic *regs; + const void __iomem *base; + int v, nr_waits; + ulong rate; + + /* cpu frequency in MHZ */ + rate = clk_get_cpu_rate() / 1000000; + + /* get flash ECC type */ + base = pic32_get_syscfg_base(); + v = (readl(base + CFGCON) >> ECC_SHIFT) & ECC_MASK; + + if (v < 2) { + if (rate < 66) + nr_waits = 0; + else if (rate < 133) + nr_waits = 1; + else + nr_waits = 2; + } else { + if (rate <= 83) + nr_waits = 0; + else if (rate <= 166) + nr_waits = 1; + else + nr_waits = 2; + } + + regs = ioremap(PREFETCH_BASE + PRECON, sizeof(*regs)); + writel(nr_waits, ®s->raw); + + /* Enable prefetch for all */ + writel(0x30, ®s->set); + iounmap(regs); +} + +/* arch specific CPU init after DM */ +int arch_cpu_init_dm(void) +{ + /* flash prefetch */ + prefetch_init(); + return 0; +} + +/* Un-gate DDR2 modules (gated by default) */ +static void ddr2_pmd_ungate(void) +{ + void __iomem *regs; + + regs = pic32_get_syscfg_base(); + writel(0, regs + PMD7); +} + +/* initialize the DDR2 Controller and DDR2 PHY */ +phys_size_t initdram(int board_type) +{ + ddr2_pmd_ungate(); + ddr2_phy_init(); + ddr2_ctrl_init(); + return ddr2_calculate_size(); +} + +int misc_init_r(void) +{ + set_io_port_base(0); + return 0; +} + +#ifdef CONFIG_DISPLAY_BOARDINFO +const char *get_core_name(void) +{ + u32 proc_id; + const char *str; + + proc_id = read_c0_prid(); + switch (proc_id) { + case 0x19e28: + str = "PIC32MZ[DA]"; + break; + default: + str = "UNKNOWN"; + } + + return str; +} +#endif +#ifdef CONFIG_CMD_CLK +int soc_clk_dump(void) +{ + int i, ret; + struct udevice *dev; + + ret = uclass_get_device(UCLASS_CLK, 0, &dev); + if (ret) { + printf("clk-uclass not found\n"); + return ret; + } + + printf("PLL Speed: %lu MHz\n", + CLK_MHZ(clk_get_periph_rate(dev, PLLCLK))); + printf("CPU Speed: %lu MHz\n", CLK_MHZ(clk_get_rate(dev))); + printf("MPLL Speed: %lu MHz\n", + CLK_MHZ(clk_get_periph_rate(dev, MPLL))); + + for (i = PB1CLK; i <= PB7CLK; i++) + printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK + 1, + CLK_MHZ(clk_get_periph_rate(dev, i))); + + for (i = REF1CLK; i <= REF5CLK; i++) + printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK + 1, + CLK_MHZ(clk_get_periph_rate(dev, i))); + return 0; +} +#endif diff --git a/arch/mips/mach-pic32/include/mach/ddr.h b/arch/mips/mach-pic32/include/mach/ddr.h new file mode 100644 index 0000000000..00abfa3ca9 --- /dev/null +++ b/arch/mips/mach-pic32/include/mach/ddr.h @@ -0,0 +1,32 @@ +/* + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#ifndef __MICROCHIP_PIC32_DDR_H +#define __MICROCHIP_PIC32_DDR_H + +/* called by initdram() function */ +void ddr2_phy_init(void); +void ddr2_ctrl_init(void); +phys_size_t ddr2_calculate_size(void); + +/* Maximum number of agents */ +#define NUM_AGENTS 5 + +/* Board can provide agent specific parameters for arbitration by + * filling struct ddr2_arbiter_params for all the agents and + * implementing board_get_ddr_arbiter_params() to return the filled + * structure. + */ +struct ddr2_arbiter_params { + u32 min_limit; /* min bursts to execute per arbitration */ + u32 req_period; /* request period threshold for accepted cmds */ + u32 min_cmd_acpt; /* min number of accepted cmds */ +}; + +const struct ddr2_arbiter_params *board_get_ddr_arbiter_params(void); + +#endif /* __MICROCHIP_PIC32_DDR_H */ diff --git a/arch/mips/mach-pic32/include/mach/pic32.h b/arch/mips/mach-pic32/include/mach/pic32.h new file mode 100644 index 0000000000..16bfacf818 --- /dev/null +++ b/arch/mips/mach-pic32/include/mach/pic32.h @@ -0,0 +1,79 @@ +/* + * (c) 2015 Paul Thacker <paul.thacker@microchip.com> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#ifndef __PIC32_REGS_H__ +#define __PIC32_REGS_H__ + +#include <asm/io.h> + +/* System Configuration */ +#define PIC32_CFG_BASE 0x1f800000 + +/* System config register offsets */ +#define CFGCON 0x0000 +#define DEVID 0x0020 +#define SYSKEY 0x0030 +#define PMD1 0x0040 +#define PMD7 0x00a0 +#define CFGEBIA 0x00c0 +#define CFGEBIC 0x00d0 +#define CFGPG 0x00e0 +#define CFGMPLL 0x0100 + +/* Non Volatile Memory (NOR flash) */ +#define PIC32_NVM_BASE (PIC32_CFG_BASE + 0x0600) +/* Oscillator Configuration */ +#define PIC32_OSC_BASE (PIC32_CFG_BASE + 0x1200) +/* Peripheral Pin Select Input */ +#define PPS_IN_BASE 0x1f801400 +/* Peripheral Pin Select Output */ +#define PPS_OUT_BASE 0x1f801500 +/* Pin Config */ +#define PINCTRL_BASE 0x1f860000 + +/* USB Core */ +#define PIC32_USB_CORE_BASE 0x1f8e3000 +#define PIC32_USB_CTRL_BASE 0x1f884000 + +/* SPI1-SPI6 */ +#define PIC32_SPI1_BASE 0x1f821000 + +/* Prefetch Module */ +#define PREFETCH_BASE 0x1f8e0000 + +/* DDR2 Controller */ +#define PIC32_DDR2C_BASE 0x1f8e8000 + +/* DDR2 PHY */ +#define PIC32_DDR2P_BASE 0x1f8e9100 + +/* EBI */ +#define PIC32_EBI_BASE 0x1f8e1000 + +/* SQI */ +#define PIC32_SQI_BASE 0x1f8e2000 + +struct pic32_reg_atomic { + u32 raw; + u32 clr; + u32 set; + u32 inv; +}; + +#define _CLR_OFFSET 0x04 +#define _SET_OFFSET 0x08 +#define _INV_OFFSET 0x0c + +static inline void __iomem *pic32_get_syscfg_base(void) +{ + return (void __iomem *)CKSEG1ADDR(PIC32_CFG_BASE); +} + +/* Core */ +const char *get_core_name(void); + +#endif /* __PIC32_REGS_H__ */ diff --git a/arch/mips/mach-pic32/lowlevel_init.S b/arch/mips/mach-pic32/lowlevel_init.S new file mode 100644 index 0000000000..e37bebb539 --- /dev/null +++ b/arch/mips/mach-pic32/lowlevel_init.S @@ -0,0 +1,27 @@ +/* + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com> + * + * SPDX-License-Identifier: GPL-2.0+ + * +*/ + +#include <config.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/asm.h> + +LEAF(lowlevel_init) + /* + * Establish Cause + * (set IV bit) + */ + li t1, 0x00800000 + mtc0 t1, CP0_CAUSE + + /* Establish Wired (and Random) */ + mtc0 zero, CP0_WIRED + nop + + jr ra + nop + END(lowlevel_init) diff --git a/arch/mips/mach-pic32/reset.c b/arch/mips/mach-pic32/reset.c new file mode 100644 index 0000000000..66c6833746 --- /dev/null +++ b/arch/mips/mach-pic32/reset.c @@ -0,0 +1,36 @@ +/* + * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com> + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include <common.h> +#include <asm/io.h> +#include <mach/pic32.h> + +/* SYSKEY */ +#define UNLOCK_KEY1 0xaa996655 +#define UNLOCK_KEY2 0x556699aa +#define LOCK_KEY 0 + +#define RSWRST 0x1250 + +void _machine_restart(void) +{ + void __iomem *base; + + base = pic32_get_syscfg_base(); + + /* unlock sequence */ + writel(LOCK_KEY, base + SYSKEY); + writel(UNLOCK_KEY1, base + SYSKEY); + writel(UNLOCK_KEY2, base + SYSKEY); + + /* soft reset */ + writel(0x1, base + RSWRST); + (void) readl(base + RSWRST); + + while (1) + ; +} |