summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-02-01 16:58:46 -0500
committerTom Rini <trini@konsulko.com>2016-02-01 16:58:46 -0500
commitd2427caf54a08ec80e8bfa5ef2c0b4377da55bab (patch)
treecccf177a353a50be781364a69f957e2a116cac45 /arch
parent735b1a2e5a61401868bb35702b6e5e18bce6eb97 (diff)
parent7d514a7407756d96996960c2ae539a4b464c65bc (diff)
downloadblackbird-obmc-uboot-d2427caf54a08ec80e8bfa5ef2c0b4377da55bab.tar.gz
blackbird-obmc-uboot-d2427caf54a08ec80e8bfa5ef2c0b4377da55bab.zip
Merge branch 'master' of git://git.denx.de/u-boot-mips
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig10
-rw-r--r--arch/mips/Makefile1
-rw-r--r--arch/mips/cpu/start.S22
-rw-r--r--arch/mips/dts/Makefile2
-rw-r--r--arch/mips/dts/pic32mzda.dtsi174
-rw-r--r--arch/mips/dts/pic32mzda_sk.dts55
-rw-r--r--arch/mips/include/asm/global_data.h3
-rw-r--r--arch/mips/include/asm/io.h82
-rw-r--r--arch/mips/lib/Makefile1
-rw-r--r--arch/mips/lib/cache.c8
-rw-r--r--arch/mips/lib/io.c12
-rw-r--r--arch/mips/mach-pic32/Kconfig35
-rw-r--r--arch/mips/mach-pic32/Makefile7
-rw-r--r--arch/mips/mach-pic32/cpu.c156
-rw-r--r--arch/mips/mach-pic32/include/mach/ddr.h32
-rw-r--r--arch/mips/mach-pic32/include/mach/pic32.h79
-rw-r--r--arch/mips/mach-pic32/lowlevel_init.S27
-rw-r--r--arch/mips/mach-pic32/reset.c36
18 files changed, 662 insertions, 80 deletions
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";
+};
+
+&ethernet {
+ reset-gpios = <&gpioJ 15 0>;
+ status = "okay";
+ phy-mode = "rmii";
+ phy-handle = <&ethernet_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, &regs->raw);
+
+ /* Enable prefetch for all */
+ writel(0x30, &regs->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)
+ ;
+}
OpenPOWER on IntegriCloud