Merge branch 'master' of git://git.denx.de/u-boot-socfpga
- stratix10 updates
diff --git a/MAINTAINERS b/MAINTAINERS
index 0fb0898..ae82501 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -512,6 +512,24 @@
T: git git://git.denx.de/u-boot-mips.git
F: arch/mips/
+MIPS MSCC
+M: Gregory CLEMENT <gregory.clement@bootlin.com>
+M: Lars Povlsen <lars.povlsen@microchip.com>
+M: Horatiu Vultur <horatiu.vultur@microchip.com>
+S: Maintained
+F: arch/mips/mach-mscc/
+F: arch/mips/dts/luton*
+F: arch/mips/dts/mscc*
+F: arch/mips/dts/ocelot*
+F: board/mscc/
+F: configs/mscc*
+F: include/configs/vcoreiii.h
+
+MIPS JZ4780
+M: Ezequiel Garcia <ezequiel@collabora.com>
+S: Maintained
+F: arch/mips/mach-jz47xx/
+
MMC
M: Jaehoon Chung <jh80.chung@samsung.com>
S: Maintained
diff --git a/arch/arm/dts/meson-axg-s400-u-boot.dtsi b/arch/arm/dts/meson-axg-s400-u-boot.dtsi
new file mode 100644
index 0000000..c46eb3f
--- /dev/null
+++ b/arch/arm/dts/meson-axg-s400-u-boot.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
+ */
+
+/* wifi module */
+&sd_emmc_b {
+ status = "disabled";
+};
+
+/* emmc storage */
+&sd_emmc_c {
+ status = "okay";
+};
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 1b1b1d7..194f4f3 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -59,6 +59,11 @@
select OF_CONTROL
imply CMD_DM
+config ARCH_MSCC
+ bool "Support MSCC VCore-III"
+ select OF_CONTROL
+ select DM
+
config ARCH_BMIPS
bool "Support BMIPS SoCs"
select CLK
@@ -79,7 +84,7 @@
select DM_SERIAL
imply DM_SPI
imply DM_SPI_FLASH
- select ARCH_MISC_INIT if WATCHDOG
+ select ARCH_MISC_INIT
select MIPS_TUNE_24KC
select OF_CONTROL
select ROM_EXCEPTION_VECTORS
@@ -88,6 +93,12 @@
select SUPPORTS_LITTLE_ENDIAN
select SYSRESET
+config ARCH_JZ47XX
+ bool "Support Ingenic JZ47xx"
+ select SUPPORT_SPL
+ select OF_CONTROL
+ select DM
+
config MACH_PIC32
bool "Support Microchip PIC32"
select DM
@@ -138,7 +149,9 @@
source "board/micronas/vct/Kconfig"
source "board/qemu-mips/Kconfig"
source "arch/mips/mach-ath79/Kconfig"
+source "arch/mips/mach-mscc/Kconfig"
source "arch/mips/mach-bmips/Kconfig"
+source "arch/mips/mach-jz47xx/Kconfig"
source "arch/mips/mach-pic32/Kconfig"
source "arch/mips/mach-mt7620/Kconfig"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 802244a..029d290 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -13,8 +13,10 @@
machine-$(CONFIG_ARCH_ATH79) += ath79
machine-$(CONFIG_ARCH_BMIPS) += bmips
+machine-$(CONFIG_ARCH_JZ47XX) += jz47xx
machine-$(CONFIG_MACH_PIC32) += pic32
machine-$(CONFIG_ARCH_MT7620) += mt7620
+machine-$(CONFIG_ARCH_MSCC) += mscc
machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
libs-y += $(machdirs)
diff --git a/arch/mips/cpu/cpu.c b/arch/mips/cpu/cpu.c
index 5c56ab0..a403ff7 100644
--- a/arch/mips/cpu/cpu.c
+++ b/arch/mips/cpu/cpu.c
@@ -28,16 +28,6 @@
}
#endif
-void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
-{
- write_c0_entrylo0(low0);
- write_c0_pagemask(pagemask);
- write_c0_entrylo1(low1);
- write_c0_entryhi(hi);
- write_c0_index(index);
- tlb_write_indexed();
-}
-
int arch_cpu_init(void)
{
mips_cache_probe();
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index b447141..647d2bf 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -16,6 +16,7 @@
dtb-$(CONFIG_BOARD_NETGEAR_DGND3700V2) += netgear,dgnd3700v2.dtb
dtb-$(CONFIG_BOARD_SAGEM_FAST1704) += sagem,f@st1704.dtb
dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
+dtb-$(CONFIG_TARGET_JZ4780_CI20) += ci20.dtb
targets += $(dtb-y)
diff --git a/arch/mips/dts/ar933x.dtsi b/arch/mips/dts/ar933x.dtsi
index 85fb14b..3735432 100644
--- a/arch/mips/dts/ar933x.dtsi
+++ b/arch/mips/dts/ar933x.dtsi
@@ -3,7 +3,6 @@
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
*/
-#include <dt-bindings/interrupt-controller/irq.h>
#include "skeleton.dtsi"
/ {
@@ -68,7 +67,6 @@
uart0: uart@18020000 {
compatible = "qca,ar9330-uart";
reg = <0x18020000 0x20>;
- interrupts = <128 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -103,7 +101,6 @@
spi0: spi@1f000000 {
compatible = "qca,ar7100-spi";
reg = <0x1f000000 0x10>;
- interrupts = <129 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index f75988b..d678dab 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm6318-clock.h>
+#include <dt-bindings/dma/bcm6318-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power-domain/bcm6318-power-domain.h>
#include <dt-bindings/reset/bcm6318-reset.h>
@@ -54,6 +55,12 @@
reg = <0x10000004 0x4>;
#clock-cells = <1>;
};
+
+ ubus_clk: ubus-clk {
+ compatible = "brcm,bcm6345-clk";
+ reg = <0x10000008 0x4>;
+ #clock-cells = <1>;
+ };
};
ubus {
@@ -182,5 +189,36 @@
status = "disabled";
};
+
+ enet: ethernet@10080000 {
+ compatible = "brcm,bcm6368-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x10080000 0x8000>;
+ clocks = <&periph_clk BCM6318_CLK_ROBOSW250>,
+ <&periph_clk BCM6318_CLK_ROBOSW025>,
+ <&ubus_clk BCM6318_UCLK_ROBOSW>;
+ resets = <&periph_rst BCM6318_RST_ENETSW>,
+ <&periph_rst BCM6318_RST_EPHY>;
+ dmas = <&iudma BCM6318_DMA_ENETSW_RX>,
+ <&iudma BCM6318_DMA_ENETSW_TX>;
+ dma-names = "rx",
+ "tx";
+ brcm,num-ports = <5>;
+
+ status = "disabled";
+ };
+
+ iudma: dma-controller@10088000 {
+ compatible = "brcm,bcm6368-iudma";
+ reg = <0x10088000 0x80>,
+ <0x10088200 0x80>,
+ <0x10088400 0x80>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
};
};
diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 62c440e..f8a72ef 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm63268-clock.h>
+#include <dt-bindings/dma/bcm63268-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power-domain/bcm63268-power-domain.h>
#include <dt-bindings/reset/bcm63268-reset.h>
@@ -217,5 +218,42 @@
reg = <0x10003000 0x894>;
u-boot,dm-pre-reloc;
};
+
+ iudma: dma-controller@1000d800 {
+ compatible = "brcm,bcm6368-iudma";
+ reg = <0x1000d800 0x80>,
+ <0x1000da00 0x80>,
+ <0x1000dc00 0x80>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
+
+ enet: ethernet@10700000 {
+ compatible = "brcm,bcm6368-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x10700000 0x10000>;
+ clocks = <&periph_clk BCM63268_CLK_GMAC>,
+ <&periph_clk BCM63268_CLK_ROBOSW>,
+ <&periph_clk BCM63268_CLK_ROBOSW250>,
+ <&timer_clk BCM63268_TCLK_EPHY1>,
+ <&timer_clk BCM63268_TCLK_EPHY2>,
+ <&timer_clk BCM63268_TCLK_EPHY3>,
+ <&timer_clk BCM63268_TCLK_GPHY>;
+ resets = <&periph_rst BCM63268_RST_ENETSW>,
+ <&periph_rst BCM63268_RST_EPHY>,
+ <&periph_rst BCM63268_RST_GPHY>;
+ dmas = <&iudma BCM63268_DMA_ENETSW_RX>,
+ <&iudma BCM63268_DMA_ENETSW_TX>;
+ dma-names = "rx",
+ "tx";
+ brcm,rgmii-override;
+ brcm,rgmii-timing;
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index e00a295..50beed4 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm6328-clock.h>
+#include <dt-bindings/dma/bcm6328-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power-domain/bcm6328-power-domain.h>
#include <dt-bindings/reset/bcm6328-reset.h>
@@ -187,5 +188,34 @@
reg = <0x10003000 0x864>;
u-boot,dm-pre-reloc;
};
+
+ iudma: dma-controller@1000d800 {
+ compatible = "brcm,bcm6368-iudma";
+ reg = <0x1000d800 0x80>,
+ <0x1000da00 0x80>,
+ <0x1000dc00 0x80>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
+
+ enet: ethernet@10e00000 {
+ compatible = "brcm,bcm6368-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x10e00000 0x10000>;
+ clocks = <&periph_clk BCM6328_CLK_ROBOSW>;
+ resets = <&periph_rst BCM6328_RST_ENETSW>,
+ <&periph_rst BCM6328_RST_EPHY>;
+ dmas = <&iudma BCM6328_DMA_ENETSW_RX>,
+ <&iudma BCM6328_DMA_ENETSW_TX>;
+ dma-names = "rx",
+ "tx";
+ brcm,num-ports = <5>;
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index bbd58cf..c547e94 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm6338-clock.h>
+#include <dt-bindings/dma/bcm6338-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/reset/bcm6338-reset.h>
#include "skeleton.dtsi"
@@ -130,5 +131,33 @@
reg = <0xfffe3100 0x38>;
u-boot,dm-pre-reloc;
};
+
+ iudma: dma-controller@fffe2400 {
+ compatible = "brcm,bcm6348-iudma";
+ reg = <0xfffe2400 0x1c>,
+ <0xfffe2500 0x60>,
+ <0xfffe2600 0x60>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <6>;
+ resets = <&periph_rst BCM6338_RST_DMAMEM>;
+ };
+
+ enet: ethernet@fffe2800 {
+ compatible = "brcm,bcm6348-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfffe2800 0x2dc>;
+ clocks = <&periph_clk BCM6338_CLK_ENET>;
+ resets = <&periph_rst BCM6338_RST_ENET>;
+ dmas = <&iudma BCM6338_DMA_ENET_RX>,
+ <&iudma BCM6338_DMA_ENET_TX>;
+ dma-names = "rx",
+ "tx";
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index cc80bbc..79e7bd8 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm6348-clock.h>
+#include <dt-bindings/dma/bcm6348-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/reset/bcm6348-reset.h>
#include "skeleton.dtsi"
@@ -159,5 +160,46 @@
reg = <0xfffe2300 0x38>;
u-boot,dm-pre-reloc;
};
+
+ enet0: ethernet@fffe6000 {
+ compatible = "brcm,bcm6348-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfffe6000 0x2dc>;
+ dmas = <&iudma BCM6348_DMA_ENET0_RX>,
+ <&iudma BCM6348_DMA_ENET0_TX>;
+ dma-names = "rx",
+ "tx";
+
+ status = "disabled";
+ };
+
+ enet1: ethernet@fffe6800 {
+ compatible = "brcm,bcm6348-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfffe6800 0x2dc>;
+ dmas = <&iudma BCM6348_DMA_ENET1_RX>,
+ <&iudma BCM6348_DMA_ENET1_TX>;
+ dma-names = "rx",
+ "tx";
+
+ status = "disabled";
+ };
+
+ iudma: dma-controller@fffe7000 {
+ compatible = "brcm,bcm6348-iudma";
+ reg = <0xfffe7000 0x1c>,
+ <0xfffe7100 0x40>,
+ <0xfffe7200 0x40>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <4>;
+ clocks = <&periph_clk BCM6348_CLK_ENET>;
+ resets = <&periph_rst BCM6348_RST_ENET>,
+ <&periph_rst BCM6348_RST_DMAMEM>;
+ };
};
};
diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 0617b46..5e9c9ad 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm6358-clock.h>
+#include <dt-bindings/dma/bcm6358-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/reset/bcm6358-reset.h>
#include "skeleton.dtsi"
@@ -190,5 +191,50 @@
status = "disabled";
};
+
+ enet0: ethernet@fffe4000 {
+ compatible = "brcm,bcm6348-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfffe4000 0x2dc>;
+ clocks = <&periph_clk BCM6358_CLK_ENET0>;
+ dmas = <&iudma BCM6358_DMA_ENET0_RX>,
+ <&iudma BCM6358_DMA_ENET0_TX>;
+ dma-names = "rx",
+ "tx";
+
+ status = "disabled";
+ };
+
+ enet1: ethernet@fffe4800 {
+ compatible = "brcm,bcm6348-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfffe4800 0x2dc>;
+ clocks = <&periph_clk BCM6358_CLK_ENET1>;
+ dmas = <&iudma BCM6358_DMA_ENET1_RX>,
+ <&iudma BCM6358_DMA_ENET1_TX>;
+ dma-names = "rx",
+ "tx";
+
+ status = "disabled";
+ };
+
+ iudma: dma-controller@fffe5000 {
+ compatible = "brcm,bcm6348-iudma";
+ reg = <0xfffe5000 0x24>,
+ <0xfffe5100 0x80>,
+ <0xfffe5200 0x80>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ clocks = <&periph_clk BCM6358_CLK_EMUSB>,
+ <&periph_clk BCM6358_CLK_USBSU>,
+ <&periph_clk BCM6358_CLK_EPHY>;
+ resets = <&periph_rst BCM6358_RST_ENET>,
+ <&periph_rst BCM6358_RST_EPHY>;
+ };
};
};
diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 3047b82..c77b80a 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm6362-clock.h>
+#include <dt-bindings/dma/bcm6362-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power-domain/bcm6362-power-domain.h>
#include <dt-bindings/reset/bcm6362-reset.h>
@@ -211,5 +212,36 @@
reg = <0x10003000 0x864>;
u-boot,dm-pre-reloc;
};
+
+ iudma: dma-controller@1000d800 {
+ compatible = "brcm,bcm6368-iudma";
+ reg = <0x1000d800 0x80>,
+ <0x1000da00 0x80>,
+ <0x1000dc00 0x80>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
+
+ enet: ethernet@10e00000 {
+ compatible = "brcm,bcm6368-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x10e00000 0x10000>;
+ clocks = <&periph_clk BCM6362_CLK_SWPKT_USB>,
+ <&periph_clk BCM6362_CLK_SWPKT_SAR>,
+ <&periph_clk BCM6362_CLK_ROBOSW>;
+ resets = <&periph_rst BCM6362_RST_ENETSW>,
+ <&periph_rst BCM6362_RST_EPHY>;
+ dmas = <&iudma BCM6362_DMA_ENETSW_RX>,
+ <&iudma BCM6362_DMA_ENETSW_TX>;
+ dma-names = "rx",
+ "tx";
+ brcm,num-ports = <6>;
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 65d769a..89590d6 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/bcm6368-clock.h>
+#include <dt-bindings/dma/bcm6368-dma.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/reset/bcm6368-reset.h>
#include "skeleton.dtsi"
@@ -192,5 +193,36 @@
status = "disabled";
};
+
+ iudma: dma-controller@10006800 {
+ compatible = "brcm,bcm6368-iudma";
+ reg = <0x10006800 0x80>,
+ <0x10006a00 0x80>,
+ <0x10006c00 0x80>;
+ reg-names = "dma",
+ "dma-channels",
+ "dma-sram";
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
+
+ enet: ethernet@10f00000 {
+ compatible = "brcm,bcm6368-enet";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x10f00000 0x10000>;
+ clocks = <&periph_clk BCM6368_CLK_SWPKT_USB>,
+ <&periph_clk BCM6368_CLK_SWPKT_SAR>,
+ <&periph_clk BCM6368_CLK_ROBOSW>;
+ resets = <&periph_rst BCM6368_RST_SWITCH>,
+ <&periph_rst BCM6368_RST_EPHY>;
+ dmas = <&iudma BCM6368_DMA_ENETSW_RX>,
+ <&iudma BCM6368_DMA_ENETSW_TX>;
+ dma-names = "rx",
+ "tx";
+ brcm,num-ports = <6>;
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/mips/dts/ci20.dts b/arch/mips/dts/ci20.dts
new file mode 100644
index 0000000..8d6417a
--- /dev/null
+++ b/arch/mips/dts/ci20.dts
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+#include "jz4780.dtsi"
+
+/ {
+ compatible = "img,ci20", "ingenic,jz4780";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ chosen {
+ stdout-path = "serial4:115200n8";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000
+ 0x30000000 0x30000000>;
+ };
+};
+
+&ext {
+ clock-frequency = <48000000>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&nemc {
+ status = "okay";
+
+ nandc: nand-controller@1 {
+ compatible = "ingenic,jz4780-nand";
+ reg = <1 0 0x1000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ingenic,bch-controller = <&bch>;
+
+ ingenic,nemc-tAS = <10>;
+ ingenic,nemc-tAH = <5>;
+ ingenic,nemc-tBP = <10>;
+ ingenic,nemc-tAW = <15>;
+ ingenic,nemc-tSTRV = <100>;
+
+ nand@1 {
+ reg = <1>;
+
+ nand-ecc-step-size = <1024>;
+ nand-ecc-strength = <24>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ partition@0 {
+ label = "u-boot-spl";
+ reg = <0x0 0x0 0x0 0x800000>;
+ };
+
+ partition@0x800000 {
+ label = "u-boot";
+ reg = <0x0 0x800000 0x0 0x200000>;
+ };
+
+ partition@0xa00000 {
+ label = "u-boot-env";
+ reg = <0x0 0xa00000 0x0 0x200000>;
+ };
+
+ partition@0xc00000 {
+ label = "boot";
+ reg = <0x0 0xc00000 0x0 0x4000000>;
+ };
+
+ partition@0x8c00000 {
+ label = "system";
+ reg = <0x0 0x4c00000 0x1 0xfb400000>;
+ };
+ };
+ };
+ };
+};
+
+&bch {
+ status = "okay";
+};
+
+&mmc0 {
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ status = "okay";
+};
+
+&mmc1 {
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ status = "okay";
+};
diff --git a/arch/mips/dts/comtrend,ar-5315u.dts b/arch/mips/dts/comtrend,ar-5315u.dts
index 4557018..eb60aaa 100644
--- a/arch/mips/dts/comtrend,ar-5315u.dts
+++ b/arch/mips/dts/comtrend,ar-5315u.dts
@@ -24,6 +24,38 @@
status = "okay";
};
+&enet {
+ status = "okay";
+
+ port@0 {
+ compatible = "brcm,enetsw-port";
+ reg = <0>;
+ label = "fe4";
+ brcm,phy-id = <1>;
+ };
+
+ port@1 {
+ compatible = "brcm,enetsw-port";
+ reg = <1>;
+ label = "fe3";
+ brcm,phy-id = <2>;
+ };
+
+ port@2 {
+ compatible = "brcm,enetsw-port";
+ reg = <2>;
+ label = "fe2";
+ brcm,phy-id = <3>;
+ };
+
+ port@3 {
+ compatible = "brcm,enetsw-port";
+ reg = <3>;
+ label = "fe1";
+ brcm,phy-id = <4>;
+ };
+};
+
&leds {
status = "okay";
diff --git a/arch/mips/dts/comtrend,ar-5387un.dts b/arch/mips/dts/comtrend,ar-5387un.dts
index e993b5c..03e3851 100644
--- a/arch/mips/dts/comtrend,ar-5387un.dts
+++ b/arch/mips/dts/comtrend,ar-5387un.dts
@@ -24,6 +24,38 @@
status = "okay";
};
+&enet {
+ status = "okay";
+
+ port@0 {
+ compatible = "brcm,enetsw-port";
+ reg = <0>;
+ label = "fe1";
+ brcm,phy-id = <1>;
+ };
+
+ port@1 {
+ compatible = "brcm,enetsw-port";
+ reg = <1>;
+ label = "fe2";
+ brcm,phy-id = <2>;
+ };
+
+ port@2 {
+ compatible = "brcm,enetsw-port";
+ reg = <2>;
+ label = "fe3";
+ brcm,phy-id = <3>;
+ };
+
+ port@3 {
+ compatible = "brcm,enetsw-port";
+ reg = <3>;
+ label = "fe4";
+ brcm,phy-id = <4>;
+ };
+};
+
&leds {
status = "okay";
diff --git a/arch/mips/dts/comtrend,ct-5361.dts b/arch/mips/dts/comtrend,ct-5361.dts
index 25747ca..f6b8a94 100644
--- a/arch/mips/dts/comtrend,ct-5361.dts
+++ b/arch/mips/dts/comtrend,ct-5361.dts
@@ -34,6 +34,18 @@
};
};
+&enet1 {
+ status = "okay";
+ phy = <&enet1phy>;
+ phy-mode = "mii";
+
+ enet1phy: fixed-link {
+ reg = <1>;
+ speed = <100>;
+ full-duplex;
+ };
+};
+
&gpio0 {
status = "okay";
};
diff --git a/arch/mips/dts/comtrend,vr-3032u.dts b/arch/mips/dts/comtrend,vr-3032u.dts
index 8c6a4a1..512cb52 100644
--- a/arch/mips/dts/comtrend,vr-3032u.dts
+++ b/arch/mips/dts/comtrend,vr-3032u.dts
@@ -24,6 +24,38 @@
status = "okay";
};
+&enet {
+ status = "okay";
+
+ port@0 {
+ compatible = "brcm,enetsw-port";
+ reg = <0>;
+ label = "fe2";
+ brcm,phy-id = <1>;
+ };
+
+ port@1 {
+ compatible = "brcm,enetsw-port";
+ reg = <1>;
+ label = "fe3";
+ brcm,phy-id = <2>;
+ };
+
+ port@2 {
+ compatible = "brcm,enetsw-port";
+ reg = <2>;
+ label = "fe4";
+ brcm,phy-id = <3>;
+ };
+
+ port@3 {
+ compatible = "brcm,enetsw-port";
+ reg = <3>;
+ label = "fe1";
+ brcm,phy-id = <4>;
+ };
+};
+
&leds {
status = "okay";
brcm,serial-leds;
diff --git a/arch/mips/dts/comtrend,wap-5813n.dts b/arch/mips/dts/comtrend,wap-5813n.dts
index bd41dab..7e835b2 100644
--- a/arch/mips/dts/comtrend,wap-5813n.dts
+++ b/arch/mips/dts/comtrend,wap-5813n.dts
@@ -54,6 +54,20 @@
status = "okay";
};
+&enet {
+ status = "okay";
+
+ port@4 {
+ compatible = "brcm,enetsw-port";
+ reg = <4>;
+ label = "rgmii";
+ brcm,phy-id = <0xff>;
+ speed = <1000>;
+ full-duplex;
+ bypass-link;
+ };
+};
+
&gpio0 {
status = "okay";
};
diff --git a/arch/mips/dts/huawei,hg556a.dts b/arch/mips/dts/huawei,hg556a.dts
index 60455c2..6a7fc1d 100644
--- a/arch/mips/dts/huawei,hg556a.dts
+++ b/arch/mips/dts/huawei,hg556a.dts
@@ -93,6 +93,18 @@
status = "okay";
};
+&enet1 {
+ status = "okay";
+ phy = <&enet1phy>;
+ phy-mode = "mii";
+
+ enet1phy: fixed-link {
+ reg = <1>;
+ speed = <100>;
+ full-duplex;
+ };
+};
+
&gpio0 {
status = "okay";
};
diff --git a/arch/mips/dts/jz4780.dtsi b/arch/mips/dts/jz4780.dtsi
new file mode 100644
index 0000000..f62a7a9
--- /dev/null
+++ b/arch/mips/dts/jz4780.dtsi
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <dt-bindings/clock/jz4780-cgu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4780";
+
+ cpuintc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: interrupt-controller@10001000 {
+ compatible = "ingenic,jz4780-intc";
+ reg = <0x10001000 0x50>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ rtc: rtc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4780-cgu@10000000 {
+ compatible = "ingenic,jz4780-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&rtc>;
+ clock-names = "ext", "rtc";
+
+ #clock-cells = <1>;
+ };
+
+ mmc0: mmc@13450000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13450000 0x1000>;
+
+ status = "disabled";
+
+ clocks = <&cgu JZ4780_CLK_MSC0>;
+ clock-names = "mmc";
+ };
+
+ mmc1: mmc@13460000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13460000 0x1000>;
+
+ clocks = <&cgu JZ4780_CLK_MSC1>;
+ clock-names = "mmc";
+
+ status = "disabled";
+ };
+
+ uart0: serial@10030000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10030000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <51>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART0>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart1: serial@10031000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10031000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <50>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART1>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart2: serial@10032000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10032000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <49>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART2>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart3: serial@10033000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10033000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <48>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART3>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart4: serial@10034000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10034000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <34>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART4>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ nemc: nemc@13410000 {
+ compatible = "ingenic,jz4780-nemc";
+ reg = <0x13410000 0x10000>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0 0x1b000000 0x1000000
+ 2 0 0x1a000000 0x1000000
+ 3 0 0x19000000 0x1000000
+ 4 0 0x18000000 0x1000000
+ 5 0 0x17000000 0x1000000
+ 6 0 0x16000000 0x1000000>;
+
+ clocks = <&cgu JZ4780_CLK_NEMC>;
+
+ status = "disabled";
+ };
+
+ bch: bch@134d0000 {
+ compatible = "ingenic,jz4780-bch";
+ reg = <0x134d0000 0x10000>;
+
+ clocks = <&cgu JZ4780_CLK_BCH>;
+
+ status = "disabled";
+ };
+};
diff --git a/arch/mips/dts/luton_pcb091.dts b/arch/mips/dts/luton_pcb091.dts
new file mode 100644
index 0000000..74f9274
--- /dev/null
+++ b/arch/mips/dts/luton_pcb091.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,luton.dtsi"
+
+/ {
+ model = "Luton10 PCB091 Reference Board";
+ compatible = "mscc,luton-pcb091", "mscc,luton";
+
+ aliases {
+ serial0 = &uart0;
+ spi0 = &spi0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+ spi-flash@0 {
+ compatible = "spi-flash";
+ spi-max-frequency = <18000000>; /* input clock */
+ reg = <0>; /* CS0 */
+ spi-cs-high;
+ };
+};
+
diff --git a/arch/mips/dts/mscc,luton.dtsi b/arch/mips/dts/mscc,luton.dtsi
new file mode 100644
index 0000000..6a4ad2a
--- /dev/null
+++ b/arch/mips/dts/mscc,luton.dtsi
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mscc,luton";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "mips,mips24KEc";
+ device_type = "cpu";
+ reg = <0>;
+ };
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ ahb_clk: ahb-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <208333333>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x60000000 0x10200000>;
+
+ uart0: serial@10100000 {
+ pinctrl-0 = <&uart_pins>;
+ pinctrl-names = "default";
+
+ compatible = "ns16550a";
+ reg = <0x10100000 0x20>;
+ clocks = <&ahb_clk>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+
+ status = "disabled";
+ };
+
+ gpio: pinctrl@70068 {
+ compatible = "mscc,luton-pinctrl";
+ reg = <0x70068 0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&gpio 0 0 32>;
+
+ uart_pins: uart-pins {
+ pins = "GPIO_30", "GPIO_31";
+ function = "uart";
+ };
+
+ };
+
+ gpio_spi_bitbang: gpio@10000064 {
+ compatible = "mscc,spi-bitbang-gpio";
+ reg = <0x10000064 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ };
+
+ spi0: spi-bitbang {
+ compatible = "spi-gpio";
+ status = "okay";
+ gpio-sck = <&gpio_spi_bitbang 6 0>;
+ gpio-miso = <&gpio_spi_bitbang 0 0>;
+ gpio-mosi = <&gpio_spi_bitbang 5 0>;
+ cs-gpios = <&gpio_spi_bitbang 1 0>;
+ num-chipselects = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
diff --git a/arch/mips/dts/mscc,ocelot.dtsi b/arch/mips/dts/mscc,ocelot.dtsi
new file mode 100644
index 0000000..87b4736
--- /dev/null
+++ b/arch/mips/dts/mscc,ocelot.dtsi
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mscc,ocelot";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "mips,mips24KEc";
+ device_type = "cpu";
+ clocks = <&cpu_clk>;
+ reg = <0>;
+ };
+ };
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ cpuintc: interrupt-controller@0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ cpu_clk: cpu-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <500000000>;
+ };
+
+ ahb_clk: ahb-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <250000000>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x70000000 0x2000000>;
+
+ interrupt-parent = <&intc>;
+
+ cpu_ctrl: syscon@0 {
+ compatible = "mscc,ocelot-cpu-syscon", "syscon";
+ reg = <0x0 0x2c>;
+ };
+
+ intc: interrupt-controller@70 {
+ compatible = "mscc,ocelot-icpu-intr";
+ reg = <0x70 0x70>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ uart0: serial@100000 {
+ pinctrl-0 = <&uart_pins>;
+ pinctrl-names = "default";
+ compatible = "ns16550a";
+ reg = <0x100000 0x20>;
+ interrupts = <6>;
+ clocks = <&ahb_clk>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+
+ status = "disabled";
+ };
+
+ uart2: serial@100800 {
+ pinctrl-0 = <&uart2_pins>;
+ pinctrl-names = "default";
+ compatible = "ns16550a";
+ reg = <0x100800 0x20>;
+ interrupts = <7>;
+ clocks = <&ahb_clk>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+
+ status = "disabled";
+ };
+
+ spi0: spi-master@101000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dw-apb-ssi";
+ reg = <0x101000 0x40>;
+ num-chipselect = <4>;
+ bus-num = <0>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ spi-max-frequency = <18000000>; /* input clock */
+ clocks = <&ahb_clk>;
+
+ status = "disabled";
+ };
+
+ reset@1070008 {
+ compatible = "mscc,ocelot-chip-reset";
+ reg = <0x1070008 0x4>;
+ };
+
+ gpio: pinctrl@1070034 {
+ compatible = "mscc,ocelot-pinctrl";
+ reg = <0x1070034 0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&gpio 0 0 22>;
+
+ uart_pins: uart-pins {
+ pins = "GPIO_6", "GPIO_7";
+ function = "uart";
+ };
+
+ uart2_pins: uart2-pins {
+ pins = "GPIO_12", "GPIO_13";
+ function = "uart2";
+ };
+
+ spi_cs1_pin: spi-cs1-pin {
+ pins = "GPIO_8";
+ function = "si";
+ };
+
+ spi_cs2_pin: spi-cs2-pin {
+ pins = "GPIO_9";
+ function = "si";
+ };
+
+ spi_cs3_pin: spi-cs3-pin {
+ pins = "GPIO_16";
+ function = "si";
+ };
+
+ spi_cs4_pin: spi-cs4-pin {
+ pins = "GPIO_17";
+ function = "si";
+ };
+ };
+ };
+};
diff --git a/arch/mips/dts/mscc,ocelot_pcb.dtsi b/arch/mips/dts/mscc,ocelot_pcb.dtsi
new file mode 100644
index 0000000..90725d3
--- /dev/null
+++ b/arch/mips/dts/mscc,ocelot_pcb.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,ocelot.dtsi"
+
+/ {
+ compatible = "mscc,ocelot";
+
+ aliases {
+ spi0 = &spi0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+ pinctrl-0 = <&spi_cs1_pin>;
+ pinctrl-names = "default";
+
+ spi-flash@0 {
+ compatible = "spi-flash";
+ spi-max-frequency = <18000000>; /* input clock */
+ reg = <0>; /* CS0 */
+ };
+
+ spi-nand@1 {
+ compatible = "spi-nand";
+ spi-max-frequency = <18000000>; /* input clock */
+ reg = <1>; /* CS1 */
+ };
+};
diff --git a/arch/mips/dts/netgear,dgnd3700v2.dts b/arch/mips/dts/netgear,dgnd3700v2.dts
index 322d156..2b72491 100644
--- a/arch/mips/dts/netgear,dgnd3700v2.dts
+++ b/arch/mips/dts/netgear,dgnd3700v2.dts
@@ -43,6 +43,20 @@
status = "okay";
};
+&enet {
+ status = "okay";
+
+ port@4 {
+ compatible = "brcm,enetsw-port";
+ reg = <4>;
+ label = "rgmii";
+ brcm,phy-id = <0xff>;
+ speed = <1000>;
+ full-duplex;
+ bypass-link;
+ };
+};
+
&gpio0 {
status = "okay";
};
diff --git a/arch/mips/dts/nexys4ddr.dts b/arch/mips/dts/nexys4ddr.dts
index e254ab1..6de8584 100644
--- a/arch/mips/dts/nexys4ddr.dts
+++ b/arch/mips/dts/nexys4ddr.dts
@@ -40,7 +40,6 @@
#address-cells = <1>;
#size-cells = <0>;
phy0: phy@1 {
- compatible = <0x0007c0f0 0xfffffff0>;
device_type = "ethernet-phy";
reg = <1>;
} ;
diff --git a/arch/mips/dts/ocelot_pcb120.dts b/arch/mips/dts/ocelot_pcb120.dts
new file mode 100644
index 0000000..47d305a
--- /dev/null
+++ b/arch/mips/dts/ocelot_pcb120.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,ocelot_pcb.dtsi"
+
+/ {
+ model = "Ocelot PCB120 Reference Board";
+ compatible = "mscc,ocelot-pcb120", "mscc,ocelot";
+};
diff --git a/arch/mips/dts/ocelot_pcb123.dts b/arch/mips/dts/ocelot_pcb123.dts
new file mode 100644
index 0000000..17d8d32
--- /dev/null
+++ b/arch/mips/dts/ocelot_pcb123.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+/dts-v1/;
+#include "mscc,ocelot_pcb.dtsi"
+
+/ {
+ model = "Ocelot PCB123 Reference Board";
+ compatible = "mscc,ocelot-pcb123", "mscc,ocelot";
+};
diff --git a/arch/mips/dts/qca953x.dtsi b/arch/mips/dts/qca953x.dtsi
index 599e809..ba29ea2 100644
--- a/arch/mips/dts/qca953x.dtsi
+++ b/arch/mips/dts/qca953x.dtsi
@@ -3,7 +3,6 @@
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
*/
-#include <dt-bindings/interrupt-controller/irq.h>
#include "skeleton.dtsi"
/ {
@@ -63,7 +62,6 @@
reg = <0x18020000 0x20>;
reg-shift = <2>;
clock-frequency = <25000000>;
- interrupts = <128 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
@@ -72,7 +70,6 @@
spi0: spi@1f000000 {
compatible = "qca,ar7100-spi";
reg = <0x1f000000 0x10>;
- interrupts = <129 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
diff --git a/arch/mips/dts/sagem,f@st1704.dts b/arch/mips/dts/sagem,f@st1704.dts
index 5300f8b..ec6846d 100644
--- a/arch/mips/dts/sagem,f@st1704.dts
+++ b/arch/mips/dts/sagem,f@st1704.dts
@@ -39,6 +39,18 @@
};
};
+&enet {
+ status = "okay";
+ phy = <&enetphy>;
+ phy-mode = "mii";
+
+ enetphy: fixed-link {
+ reg = <1>;
+ speed = <100>;
+ full-duplex;
+ };
+};
+
&gpio {
status = "okay";
};
diff --git a/arch/mips/dts/sfr,nb4-ser.dts b/arch/mips/dts/sfr,nb4-ser.dts
index bdc6f8a..dfbc414 100644
--- a/arch/mips/dts/sfr,nb4-ser.dts
+++ b/arch/mips/dts/sfr,nb4-ser.dts
@@ -53,6 +53,30 @@
status = "okay";
};
+&enet0 {
+ status = "okay";
+ phy = <&enet0phy>;
+ phy-mode = "internal";
+
+ enet0phy: fixed-link {
+ reg = <1>;
+ speed = <100>;
+ full-duplex;
+ };
+};
+
+&enet1 {
+ status = "okay";
+ phy = <&enet1phy>;
+ phy-mode = "mii";
+
+ enet1phy: fixed-link {
+ reg = <1>;
+ speed = <100>;
+ full-duplex;
+ };
+};
+
&gpio0 {
status = "okay";
};
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h
index 3161875..98b67cc 100644
--- a/arch/mips/include/asm/cacheops.h
+++ b/arch/mips/include/asm/cacheops.h
@@ -19,6 +19,25 @@
#endif
}
+#define MIPS32_WHICH_ICACHE 0x0
+#define MIPS32_FETCH_AND_LOCK 0x7
+
+#define ICACHE_LOAD_LOCK (MIPS32_WHICH_ICACHE | (MIPS32_FETCH_AND_LOCK << 2))
+
+/* Prefetch and lock instructions into cache */
+static inline void icache_lock(void *func, size_t len)
+{
+ int i, lines = ((len - 1) / ARCH_DMA_MINALIGN) + 1;
+
+ for (i = 0; i < lines; i++) {
+ asm volatile (" cache %0, %1(%2)"
+ : /* No Output */
+ : "I" ICACHE_LOAD_LOCK,
+ "n" (i * ARCH_DMA_MINALIGN),
+ "r" (func)
+ : /* No Clobbers */);
+ }
+}
#endif /* !__ASSEMBLY__ */
/*
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 48fa1f1..f80311e 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1013,9 +1013,7 @@
#define __read_64bit_c0_split(source, sel) \
({ \
unsigned long long __val; \
- unsigned long __flags; \
\
- local_irq_save(__flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
@@ -1034,16 +1032,12 @@
"dsra\t%L0, %L0, 32\n\t" \
".set\tmips0" \
: "=r" (__val)); \
- local_irq_restore(__flags); \
\
__val; \
})
#define __write_64bit_c0_split(source, sel, val) \
do { \
- unsigned long __flags; \
- \
- local_irq_save(__flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
@@ -1064,7 +1058,6 @@
"dmtc0\t%L0, " #source ", " #sel "\n\t" \
".set\tmips0" \
: : "r" (val)); \
- local_irq_restore(__flags); \
} while (0)
#define __readx_32bit_c0_register(source) \
@@ -2005,6 +1998,17 @@
return read_c0_ebase() & 0x3ff;
}
+static inline void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0,
+ u32 low1)
+{
+ write_c0_entrylo0(low0);
+ write_c0_pagemask(pagemask);
+ write_c0_entrylo1(low1);
+ write_c0_entryhi(hi);
+ write_c0_index(index);
+ tlb_write_indexed();
+}
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_MIPSREGS_H */
diff --git a/arch/mips/include/asm/spl.h b/arch/mips/include/asm/spl.h
new file mode 100644
index 0000000..0a847ed
--- /dev/null
+++ b/arch/mips/include/asm/spl.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2012
+ * Texas Instruments, <www.ti.com>
+ */
+#ifndef _ASM_SPL_H_
+#define _ASM_SPL_H_
+
+enum {
+ BOOT_DEVICE_RAM,
+ BOOT_DEVICE_MMC1,
+ BOOT_DEVICE_MMC2,
+ BOOT_DEVICE_MMC2_2,
+ BOOT_DEVICE_NAND,
+ BOOT_DEVICE_ONENAND,
+ BOOT_DEVICE_NOR,
+ BOOT_DEVICE_UART,
+ BOOT_DEVICE_SPI,
+ BOOT_DEVICE_USB,
+ BOOT_DEVICE_SATA,
+ BOOT_DEVICE_I2C,
+ BOOT_DEVICE_BOARD,
+ BOOT_DEVICE_DFU,
+ BOOT_DEVICE_XIP,
+ BOOT_DEVICE_BOOTROM,
+ BOOT_DEVICE_NONE
+};
+
+#ifndef CONFIG_DM
+extern gd_t gdata;
+#endif
+
+#endif
diff --git a/arch/mips/mach-jz47xx/Kconfig b/arch/mips/mach-jz47xx/Kconfig
new file mode 100644
index 0000000..dcaac01
--- /dev/null
+++ b/arch/mips/mach-jz47xx/Kconfig
@@ -0,0 +1,26 @@
+menu "Ingenic JZ47xx platforms"
+ depends on ARCH_JZ47XX
+
+config SYS_SOC
+ default "jz47xx"
+
+config SOC_JZ4780
+ bool
+ select SUPPORTS_LITTLE_ENDIAN
+ select SUPPORTS_CPU_MIPS32_R1
+ select SUPPORTS_CPU_MIPS32_R2
+ help
+ Support for Ingenic JZ4780 family SoCs.
+
+choice
+ prompt "Board select"
+
+config TARGET_JZ4780_CI20
+ bool "Creator CI20 Reference Board"
+ select SOC_JZ4780
+
+endchoice
+
+source "board/imgtec/ci20/Kconfig"
+
+endmenu
diff --git a/arch/mips/mach-jz47xx/Makefile b/arch/mips/mach-jz47xx/Makefile
new file mode 100644
index 0000000..dbb8229
--- /dev/null
+++ b/arch/mips/mach-jz47xx/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+extra-$(CONFIG_SPL_BUILD) := start.o
+
+obj-$(CONFIG_SOC_JZ4780) += jz4780/
diff --git a/arch/mips/mach-jz47xx/include/mach/jz4780.h b/arch/mips/mach-jz47xx/include/mach/jz4780.h
new file mode 100644
index 0000000..4422e50
--- /dev/null
+++ b/arch/mips/mach-jz47xx/include/mach/jz4780.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * JZ4780 definitions
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#ifndef __JZ4780_H__
+#define __JZ4780_H__
+
+/* AHB0 BUS Devices */
+#define DDRC_BASE 0xb3010000
+
+/* AHB2 BUS Devices */
+#define NEMC_BASE 0xb3410000
+#define BCH_BASE 0xb34d0000
+
+/* APB BUS Devices */
+#define CPM_BASE 0xb0000000
+#define TCU_BASE 0xb0002000
+#define WDT_BASE 0xb0002000
+#define GPIO_BASE 0xb0010000
+#define UART0_BASE 0xb0030000
+#define UART1_BASE 0xb0031000
+#define UART2_BASE 0xb0032000
+#define UART3_BASE 0xb0033000
+#define MSC0_BASE 0xb3450000
+#define MSC1_BASE 0xb3460000
+#define MSC2_BASE 0xb3470000
+
+/*
+ * GPIO
+ */
+/* n = 0,1,2,3,4,5 */
+#define GPIO_PXPIN(n) (0x00 + (n) * 0x100)
+#define GPIO_PXINT(n) (0x10 + (n) * 0x100)
+#define GPIO_PXINTS(n) (0x14 + (n) * 0x100)
+#define GPIO_PXINTC(n) (0x18 + (n) * 0x100)
+#define GPIO_PXMASK(n) (0x20 + (n) * 0x100)
+#define GPIO_PXMASKS(n) (0x24 + (n) * 0x100)
+#define GPIO_PXMASKC(n) (0x28 + (n) * 0x100)
+#define GPIO_PXPAT1(n) (0x30 + (n) * 0x100)
+#define GPIO_PXPAT1S(n) (0x34 + (n) * 0x100)
+#define GPIO_PXPAT1C(n) (0x38 + (n) * 0x100)
+#define GPIO_PXPAT0(n) (0x40 + (n) * 0x100)
+#define GPIO_PXPAT0S(n) (0x44 + (n) * 0x100)
+#define GPIO_PXPAT0C(n) (0x48 + (n) * 0x100)
+#define GPIO_PXFLG(n) (0x50 + (n) * 0x100)
+#define GPIO_PXFLGC(n) (0x54 + (n) * 0x100)
+#define GPIO_PXOEN(n) (0x60 + (n) * 0x100)
+#define GPIO_PXOENS(n) (0x64 + (n) * 0x100)
+#define GPIO_PXOENC(n) (0x68 + (n) * 0x100)
+#define GPIO_PXPEN(n) (0x70 + (n) * 0x100)
+#define GPIO_PXPENS(n) (0x74 + (n) * 0x100)
+#define GPIO_PXPENC(n) (0x78 + (n) * 0x100)
+#define GPIO_PXDS(n) (0x80 + (n) * 0x100)
+#define GPIO_PXDSS(n) (0x84 + (n) * 0x100)
+#define GPIO_PXDSC(n) (0x88 + (n) * 0x100)
+
+/* PLL setup */
+#define JZ4780_SYS_EXTAL 48000000
+#define JZ4780_SYS_MEM_SPEED (CONFIG_SYS_MHZ * 1000000)
+#define JZ4780_SYS_MEM_DIV 3
+#define JZ4780_SYS_AUDIO_SPEED (768 * 1000000)
+
+#define JZ4780_APLL_M 1
+#define JZ4780_APLL_N 1
+#define JZ4780_APLL_OD 1
+
+#define JZ4780_MPLL_M (JZ4780_SYS_MEM_SPEED / JZ4780_SYS_EXTAL * 2)
+#define JZ4780_MPLL_N 2
+#define JZ4780_MPLL_OD 1
+
+#define JZ4780_EPLL_M (JZ4780_SYS_AUDIO_SPEED * 2 / JZ4780_SYS_EXTAL)
+#define JZ4780_EPLL_N 1
+#define JZ4780_EPLL_OD 2
+
+#define JZ4780_VPLL_M ((888 * 1000000) * 2 / JZ4780_SYS_EXTAL)
+#define JZ4780_VPLL_N 1
+#define JZ4780_VPLL_OD 2
+
+#ifndef __ASSEMBLY__
+
+u32 sdram_size(int bank);
+
+const u32 jz4780_clk_get_efuse_clk(void);
+void jz4780_clk_ungate_ethernet(void);
+void jz4780_clk_ungate_mmc(void);
+void jz4780_clk_ungate_uart(const unsigned int uart);
+
+void jz4780_efuse_read(size_t addr, size_t count, u8 *buf);
+void jz4780_efuse_init(u32 ahb2_rate);
+
+void jz4780_tcu_wdt_start(void);
+
+#ifdef CONFIG_SPL_BUILD
+int jz_mmc_init(void __iomem *base);
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __JZ4780_H__ */
diff --git a/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h b/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h
new file mode 100644
index 0000000..92d431b
--- /dev/null
+++ b/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h
@@ -0,0 +1,456 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * JZ4780 DDR initialization - parameters definitions
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Matt Redfearn <matt.redfearn.com>
+ */
+
+#ifndef __JZ4780_DRAM_H__
+#define __JZ4780_DRAM_H__
+
+/*
+ * DDR
+ */
+#define DDRC_ST 0x0
+#define DDRC_CFG 0x4
+#define DDRC_CTRL 0x8
+#define DDRC_LMR 0xc
+#define DDRC_REFCNT 0x18
+#define DDRC_DQS 0x1c
+#define DDRC_DQS_ADJ 0x20
+#define DDRC_MMAP0 0x24
+#define DDRC_MMAP1 0x28
+#define DDRC_MDELAY 0x2c
+#define DDRC_CKEL 0x30
+#define DDRC_PMEMCTRL0 0x54
+#define DDRC_PMEMCTRL1 0x50
+#define DDRC_PMEMCTRL2 0x58
+#define DDRC_PMEMCTRL3 0x5c
+
+#define DDRC_TIMING(n) (0x60 + 4 * (n))
+#define DDRC_REMMAP(n) (0x9c + 4 * (n))
+
+/*
+ * DDR PHY
+ */
+#define DDR_MEM_PHY_BASE 0x20000000
+#define DDR_PHY_OFFSET 0x1000
+
+#define DDRP_PIR 0x4
+#define DDRP_PGCR 0x8
+#define DDRP_PGSR 0xc
+
+#define DDRP_PTR0 0x18
+#define DDRP_PTR1 0x1c
+#define DDRP_PTR2 0x20
+
+#define DDRP_ACIOCR 0x24
+#define DDRP_DXCCR 0x28
+#define DDRP_DSGCR 0x2c
+#define DDRP_DCR 0x30
+
+#define DDRP_DTPR0 0x34
+#define DDRP_DTPR1 0x38
+#define DDRP_DTPR2 0x3c
+#define DDRP_MR0 0x40
+#define DDRP_MR1 0x44
+#define DDRP_MR2 0x48
+#define DDRP_MR3 0x4c
+
+#define DDRP_ODTCR 0x50
+#define DDRP_DTAR 0x54
+#define DDRP_DTDR0 0x58
+#define DDRP_DTDR1 0x5c
+
+#define DDRP_DCUAR 0xc0
+#define DDRP_DCUDR 0xc4
+#define DDRP_DCURR 0xc8
+#define DDRP_DCULR 0xcc
+#define DDRP_DCUGCR 0xd0
+#define DDRP_DCUTPR 0xd4
+#define DDRP_DCUSR0 0xd8
+#define DDRP_DCUSR1 0xdc
+
+#define DDRP_ZQXCR0(n) (0x180 + ((n) * 0x10))
+#define DDRP_ZQXCR1(n) (0x184 + ((n) * 0x10))
+#define DDRP_ZQXSR0(n) (0x188 + ((n) * 0x10))
+#define DDRP_ZQXSR1(n) (0x18c + ((n) * 0x10))
+
+#define DDRP_DXGCR(n) (0x1c0 + ((n) * 0x40))
+#define DDRP_DXGSR0(n) (0x1c4 + ((n) * 0x40))
+#define DDRP_DXGSR1(n) (0x1c8 + ((n) * 0x40))
+#define DDRP_DXDQSTR(n) (0x1d4 + ((n) * 0x40))
+
+/* DDRC Status Register */
+#define DDRC_ST_ENDIAN BIT(7)
+#define DDRC_ST_DPDN BIT(5)
+#define DDRC_ST_PDN BIT(4)
+#define DDRC_ST_AREF BIT(3)
+#define DDRC_ST_SREF BIT(2)
+#define DDRC_ST_CKE1 BIT(1)
+#define DDRC_ST_CKE0 BIT(0)
+
+/* DDRC Configure Register */
+#define DDRC_CFG_ROW1_BIT 27
+#define DDRC_CFG_ROW1_MASK (0x7 << DDRC_CFG_ROW1_BIT)
+#define DDRC_CFG_COL1_BIT 24
+#define DDRC_CFG_COL1_MASK (0x7 << DDRC_CFG_COL1_BIT)
+#define DDRC_CFG_BA1 BIT(23)
+#define DDRC_CFG_IMBA BIT(22)
+#define DDRC_CFG_BL_8 BIT(21)
+
+#define DDRC_CFG_TYPE_BIT 17
+#define DDRC_CFG_TYPE_MASK (0x7 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_DDR1 (2 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_MDDR (3 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_DDR2 (4 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_LPDDR2 (5 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_DDR3 (6 << DDRC_CFG_TYPE_BIT)
+
+#define DDRC_CFG_ODT_EN BIT(16)
+
+#define DDRC_CFG_MPRT BIT(15)
+
+#define DDRC_CFG_ROW_BIT 11
+#define DDRC_CFG_ROW_MASK (0x7 << DDRC_CFG_ROW_BIT)
+#define DDRC_CFG_ROW_12 (0 << DDRC_CFG_ROW_BIT)
+#define DDRC_CFG_ROW_13 (1 << DDRC_CFG_ROW_BIT)
+#define DDRC_CFG_ROW_14 (2 << DDRC_CFG_ROW_BIT)
+
+#define DDRC_CFG_COL_BIT 8
+#define DDRC_CFG_COL_MASK (0x7 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_8 (0 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_9 (1 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_10 (2 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_11 (3 << DDRC_CFG_COL_BIT)
+
+#define DDRC_CFG_CS1EN BIT(7)
+#define DDRC_CFG_CS0EN BIT(6)
+#define DDRC_CFG_CL_BIT 2
+#define DDRC_CFG_CL_MASK (0xf << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_3 (0 << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_4 (1 << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_5 (2 << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_6 (3 << DDRC_CFG_CL_BIT)
+
+#define DDRC_CFG_BA BIT(1)
+#define DDRC_CFG_DW BIT(0)
+
+/* DDRC Control Register */
+#define DDRC_CTRL_DFI_RST BIT(23)
+#define DDRC_CTRL_DLL_RST BIT(22)
+#define DDRC_CTRL_CTL_RST BIT(21)
+#define DDRC_CTRL_CFG_RST BIT(20)
+#define DDRC_CTRL_ACTPD BIT(15)
+#define DDRC_CTRL_PDT_BIT 12
+#define DDRC_CTRL_PDT_MASK (0x7 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_DIS (0 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_8 (1 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_16 (2 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_32 (3 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_64 (4 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_128 (5 << DDRC_CTRL_PDT_BIT)
+
+#define DDRC_CTRL_PRET_BIT 8
+#define DDRC_CTRL_PRET_MASK (0x7 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_DIS (0 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_8 (1 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_16 (2 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_32 (3 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_64 (4 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_128 (5 << DDRC_CTRL_PRET_BIT)
+
+#define DDRC_CTRL_DPD BIT(6)
+#define DDRC_CTRL_SR BIT(5)
+#define DDRC_CTRL_UNALIGN BIT(4)
+#define DDRC_CTRL_ALH BIT(3)
+#define DDRC_CTRL_RDC BIT(2)
+#define DDRC_CTRL_CKE BIT(1)
+#define DDRC_CTRL_RESET BIT(0)
+
+/* DDRC Load-Mode-Register */
+#define DDRC_LMR_DDR_ADDR_BIT 16
+#define DDRC_LMR_DDR_ADDR_MASK (0x3fff << DDRC_LMR_DDR_ADDR_BIT)
+
+#define DDRC_LMR_BA_BIT 8
+#define DDRC_LMR_BA_MASK (0x7 << DDRC_LMR_BA_BIT)
+/* For DDR2 */
+#define DDRC_LMR_BA_MRS (0 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_EMRS1 (1 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_EMRS2 (2 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_EMRS3 (3 << DDRC_LMR_BA_BIT)
+/* For mobile DDR */
+#define DDRC_LMR_BA_M_MRS (0 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_M_EMRS (2 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_M_SR (1 << DDRC_LMR_BA_BIT)
+/* For Normal DDR1 */
+#define DDRC_LMR_BA_N_MRS (0 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_N_EMRS (1 << DDRC_LMR_BA_BIT)
+
+#define DDRC_LMR_CMD_BIT 4
+#define DDRC_LMR_CMD_MASK (0x3 << DDRC_LMR_CMD_BIT)
+#define DDRC_LMR_CMD_PREC (0 << DDRC_LMR_CMD_BIT)
+#define DDRC_LMR_CMD_AUREF (1 << DDRC_LMR_CMD_BIT)
+#define DDRC_LMR_CMD_LMR (2 << DDRC_LMR_CMD_BIT)
+
+#define DDRC_LMR_START BIT(0)
+
+/* DDRC Timing Config Register 1 */
+#define DDRC_TIMING1_TRTP_BIT 24
+#define DDRC_TIMING1_TRTP_MASK (0x3f << DDRC_TIMING1_TRTP_BIT)
+#define DDRC_TIMING1_TWTR_BIT 16
+#define DDRC_TIMING1_TWTR_MASK (0x3f << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_1 (0 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_2 (1 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_3 (2 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_4 (3 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWR_BIT 8
+#define DDRC_TIMING1_TWR_MASK (0x3f << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_1 (0 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_2 (1 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_3 (2 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_4 (3 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_5 (4 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_6 (5 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWL_BIT 0
+#define DDRC_TIMING1_TWL_MASK (0x3f << DDRC_TIMING1_TWL_BIT)
+
+/* DDRC Timing Config Register 2 */
+#define DDRC_TIMING2_TCCD_BIT 24
+#define DDRC_TIMING2_TCCD_MASK (0x3f << DDRC_TIMING2_TCCD_BIT)
+#define DDRC_TIMING2_TRAS_BIT 16
+#define DDRC_TIMING2_TRAS_MASK (0x3f << DDRC_TIMING2_TRAS_BIT)
+#define DDRC_TIMING2_TRCD_BIT 8
+#define DDRC_TIMING2_TRCD_MASK (0x3f << DDRC_TIMING2_TRCD_BIT)
+#define DDRC_TIMING2_TRL_BIT 0
+#define DDRC_TIMING2_TRL_MASK (0x3f << DDRC_TIMING2_TRL_BIT)
+
+/* DDRC Timing Config Register 3 */
+#define DDRC_TIMING3_ONUM 27
+#define DDRC_TIMING3_TCKSRE_BIT 24
+#define DDRC_TIMING3_TCKSRE_MASK (0x3f << DDRC_TIMING3_TCKSRE_BIT)
+#define DDRC_TIMING3_TRP_BIT 16
+#define DDRC_TIMING3_TRP_MASK (0x3f << DDRC_TIMING3_TRP_BIT)
+#define DDRC_TIMING3_TRRD_BIT 8
+#define DDRC_TIMING3_TRRD_MASK (0x3f << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_DISABLE (0 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_2 (1 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_3 (2 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_4 (3 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRC_BIT 0
+#define DDRC_TIMING3_TRC_MASK (0x3f << DDRC_TIMING3_TRC_BIT)
+
+/* DDRC Timing Config Register 4 */
+#define DDRC_TIMING4_TRFC_BIT 24
+#define DDRC_TIMING4_TRFC_MASK (0x3f << DDRC_TIMING4_TRFC_BIT)
+#define DDRC_TIMING4_TEXTRW_BIT 21
+#define DDRC_TIMING4_TEXTRW_MASK (0x7 << DDRC_TIMING4_TEXTRW_BIT)
+#define DDRC_TIMING4_TRWCOV_BIT 19
+#define DDRC_TIMING4_TRWCOV_MASK (0x3 << DDRC_TIMING4_TRWCOV_BIT)
+#define DDRC_TIMING4_TCKE_BIT 16
+#define DDRC_TIMING4_TCKE_MASK (0x7 << DDRC_TIMING4_TCKE_BIT)
+#define DDRC_TIMING4_TMINSR_BIT 8
+#define DDRC_TIMING4_TMINSR_MASK (0xf << DDRC_TIMING4_TMINSR_BIT)
+#define DDRC_TIMING4_TXP_BIT 4
+#define DDRC_TIMING4_TXP_MASK (0x7 << DDRC_TIMING4_TXP_BIT)
+#define DDRC_TIMING4_TMRD_BIT 0
+#define DDRC_TIMING4_TMRD_MASK (0x3 << DDRC_TIMING4_TMRD_BIT)
+
+/* DDRC Timing Config Register 5 */
+#define DDRC_TIMING5_TCTLUPD_BIT 24
+#define DDRC_TIMING4_TCTLUPD_MASK (0x3f << DDRC_TIMING5_TCTLUDP_BIT)
+#define DDRC_TIMING5_TRTW_BIT 16
+#define DDRC_TIMING5_TRTW_MASK (0x3f << DDRC_TIMING5_TRTW_BIT)
+#define DDRC_TIMING5_TRDLAT_BIT 8
+#define DDRC_TIMING5_TRDLAT_MASK (0x3f << DDRC_TIMING5_TRDLAT_BIT)
+#define DDRC_TIMING5_TWDLAT_BIT 0
+#define DDRC_TIMING5_TWDLAT_MASK (0x3f << DDRC_TIMING5_TWDLAT_BIT)
+
+/* DDRC Timing Config Register 6 */
+#define DDRC_TIMING6_TXSRD_BIT 24
+#define DDRC_TIMING6_TXSRD_MASK (0x3f << DDRC_TIMING6_TXSRD_BIT)
+#define DDRC_TIMING6_TFAW_BIT 16
+#define DDRC_TIMING6_TFAW_MASK (0x3f << DDRC_TIMING6_TFAW_BIT)
+#define DDRC_TIMING6_TCFGW_BIT 8
+#define DDRC_TIMING6_TCFGW_MASK (0x3f << DDRC_TIMING6_TCFGW_BIT)
+#define DDRC_TIMING6_TCFGR_BIT 0
+#define DDRC_TIMING6_TCFGR_MASK (0x3f << DDRC_TIMING6_TCFGR_BIT)
+
+/* DDRC Auto-Refresh Counter */
+#define DDRC_REFCNT_CON_BIT 16
+#define DDRC_REFCNT_CON_MASK (0xff << DDRC_REFCNT_CON_BIT)
+#define DDRC_REFCNT_CNT_BIT 8
+#define DDRC_REFCNT_CNT_MASK (0xff << DDRC_REFCNT_CNT_BIT)
+#define DDRC_REFCNT_CLKDIV_BIT 1
+#define DDRC_REFCNT_CLKDIV_MASK (0x7 << DDRC_REFCNT_CLKDIV_BIT)
+#define DDRC_REFCNT_REF_EN BIT(0)
+
+/* DDRC DQS Delay Control Register */
+#define DDRC_DQS_ERROR BIT(29)
+#define DDRC_DQS_READY BIT(28)
+#define DDRC_DQS_AUTO BIT(23)
+#define DDRC_DQS_DET BIT(24)
+#define DDRC_DQS_SRDET BIT(25)
+#define DDRC_DQS_CLKD_BIT 16
+#define DDRC_DQS_CLKD_MASK (0x3f << DDRC_DQS_CLKD_BIT)
+#define DDRC_DQS_WDQS_BIT 8
+#define DDRC_DQS_WDQS_MASK (0x3f << DDRC_DQS_WDQS_BIT)
+#define DDRC_DQS_RDQS_BIT 0
+#define DDRC_DQS_RDQS_MASK (0x3f << DDRC_DQS_RDQS_BIT)
+
+/* DDRC DQS Delay Adjust Register */
+#define DDRC_DQS_ADJWDQS_BIT 8
+#define DDRC_DQS_ADJWDQS_MASK (0x1f << DDRC_DQS_ADJWDQS_BIT)
+#define DDRC_DQS_ADJRDQS_BIT 0
+#define DDRC_DQS_ADJRDQS_MASK (0x1f << DDRC_DQS_ADJRDQS_BIT)
+
+/* DDRC Memory Map Config Register */
+#define DDRC_MMAP_BASE_BIT 8
+#define DDRC_MMAP_BASE_MASK (0xff << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP_MASK_BIT 0
+#define DDRC_MMAP_MASK_MASK (0xff << DDRC_MMAP_MASK_BIT)
+
+#define DDRC_MMAP0_BASE (0x20 << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP1_BASE_64M (0x24 << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP1_BASE_128M (0x28 << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP1_BASE_256M (0x30 << DDRC_MMAP_BASE_BIT)
+
+#define DDRC_MMAP_MASK_64_64 (0xfc << DDRC_MMAP_MASK_BIT)
+#define DDRC_MMAP_MASK_128_128 (0xf8 << DDRC_MMAP_MASK_BIT)
+#define DDRC_MMAP_MASK_256_256 (0xf0 << DDRC_MMAP_MASK_BIT)
+
+/* DDRP PHY Initialization Register */
+#define DDRP_PIR_INIT BIT(0)
+#define DDRP_PIR_DLLSRST BIT(1)
+#define DDRP_PIR_DLLLOCK BIT(2)
+#define DDRP_PIR_ZCAL BIT(3)
+#define DDRP_PIR_ITMSRST BIT(4)
+#define DDRP_PIR_DRAMRST BIT(5)
+#define DDRP_PIR_DRAMINT BIT(6)
+#define DDRP_PIR_QSTRN BIT(7)
+#define DDRP_PIR_EYETRN BIT(8)
+#define DDRP_PIR_DLLBYP BIT(17)
+/* DDRP PHY General Configurate Register */
+#define DDRP_PGCR_ITMDMD BIT(0)
+#define DDRP_PGCR_DQSCFG BIT(1)
+#define DDRP_PGCR_DFTCMP BIT(2)
+#define DDRP_PGCR_DFTLMT_BIT 3
+#define DDRP_PGCR_DTOSEL_BIT 5
+#define DDRP_PGCR_CKEN_BIT 9
+#define DDRP_PGCR_CKDV_BIT 12
+#define DDRP_PGCR_CKINV BIT(14)
+#define DDRP_PGCR_RANKEN_BIT 18
+#define DDRP_PGCR_ZCKSEL_32 (2 << 22)
+#define DDRP_PGCR_PDDISDX BIT(24)
+/* DDRP PHY General Status Register */
+#define DDRP_PGSR_IDONE BIT(0)
+#define DDRP_PGSR_DLDONE BIT(1)
+#define DDRP_PGSR_ZCDONE BIT(2)
+#define DDRP_PGSR_DIDONE BIT(3)
+#define DDRP_PGSR_DTDONE BIT(4)
+#define DDRP_PGSR_DTERR BIT(5)
+#define DDRP_PGSR_DTIERR BIT(6)
+#define DDRP_PGSR_DFTEERR BIT(7)
+/* DDRP DRAM Configuration Register */
+#define DDRP_DCR_TYPE_BIT 0
+#define DDRP_DCR_TYPE_MASK (0x7 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_MDDR (0 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_DDR (1 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_DDR2 (2 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_DDR3 (3 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_LPDDR2 (4 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_DDR8BNK_BIT 3
+#define DDRP_DCR_DDR8BNK_MASK (1 << DDRP_DCR_DDR8BNK_BIT)
+#define DDRP_DCR_DDR8BNK (1 << DDRP_DCR_DDR8BNK_BIT)
+#define DDRP_DCR_DDR8BNK_DIS (0 << DDRP_DCR_DDR8BNK_BIT)
+
+#define DRP_DTRP1_RTODT BIT(11)
+
+#define DDRP_DXGCR_DXEN BIT(0)
+
+#define DDRP_ZQXCR_ZDEN_BIT 28
+#define DDRP_ZQXCR_ZDEN (1 << DDRP_ZQXCR_ZDEN_BIT)
+#define DDRP_ZQXCR_PULLUP_IMPE_BIT 5
+#define DDRP_ZQXCR_PULLDOWN_IMPE_BIT 0
+
+/* DDR3 Mode Register Set */
+#define DDR3_MR0_BL_BIT 0
+#define DDR3_MR0_BL_MASK (3 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BL_8 (0 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BL_fly (1 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BL_4 (2 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BT_BIT 3
+#define DDR3_MR0_BT_MASK (1 << DDR3_MR0_BT_BIT)
+#define DDR3_MR0_BT_SEQ (0 << DDR3_MR0_BT_BIT)
+#define DDR3_MR0_BT_INTER (1 << DDR3_MR0_BT_BIT)
+#define DDR3_MR0_WR_BIT 9
+
+#define DDR3_MR1_DLL_DISABLE 1
+#define DDR3_MR1_DIC_6 (0 << 5 | 0 << 1)
+#define DDR3_MR1_DIC_7 (0 << 5 | BIT(1))
+#define DDR3_MR1_RTT_DIS (0 << 9 | 0 << 6 | 0 << 2)
+#define DDR3_MR1_RTT_4 (0 << 9 | 0 << 6 | BIT(2))
+#define DDR3_MR1_RTT_2 (0 << 9 | BIT(6) | 0 << 2)
+#define DDR3_MR1_RTT_6 (0 << 9 | BIT(6) | BIT(2))
+#define DDR3_MR1_RTT_12 (BIT(9) | 0 << 6 | 0 << 2)
+#define DDR3_MR1_RTT_8 (BIT(9) | 0 << 6 | BIT(2))
+
+#define DDR3_MR2_CWL_BIT 3
+
+/* Parameters common to all RAM devices used */
+
+/* Chip Select */
+/* CSEN : whether a ddr chip exists 0 - un-used, 1 - used */
+#define DDR_CS0EN 1
+/* CSEN : whether a ddr chip exists 0 - un-used, 1 - used */
+#define DDR_CS1EN 0
+
+/* ROW : 12 to 18 row address, 1G only 512MB */
+#define DDR_ROW 15
+/* COL : 8 to 14 column address */
+#define DDR_COL 10
+/* Banks each chip: 0-4bank, 1-8bank */
+#define DDR_BANK8 1
+/* 0 - 16-bit data width, 1 - 32-bit data width */
+#define DDR_DW32 1
+
+/* Refresh period: 64ms / 32768 = 1.95 us , 2 ^ 15 = 32768 */
+#define DDR_tREFI 7800
+/* Clock Divider */
+#define DDR_CLK_DIV 1
+
+/* DDR3 Burst length: 0 - 8 burst, 2 - 4 burst , 1 - 4 or 8 (on the fly) */
+#define DDR_BL 8
+
+/* CAS latency: 5 to 14, tCK */
+#define DDR_CL 6
+/* DDR3 only: CAS Write Latency, 5 to 8 */
+#define DDR_tCWL (DDR_CL - 1)
+
+/* Structure representing per-RAM type configuration */
+
+struct jz4780_ddr_config {
+ u32 timing[6]; /* Timing1..6 register value */
+
+ /* DDR PHY control */
+ u16 mr0; /* Mode Register 0 */
+ u16 mr1; /* Mode Register 1 */
+
+ u32 ptr0; /* PHY Timing Register 0 */
+ u32 ptr1; /* PHY Timing Register 1 */
+ u32 ptr2; /* PHY Timing Register 1 */
+
+ u32 dtpr0; /* DRAM Timing Parameters Register 0 */
+ u32 dtpr1; /* DRAM Timing Parameters Register 1 */
+ u32 dtpr2; /* DRAM Timing Parameters Register 2 */
+
+ u8 pullup; /* PHY pullup impedance */
+ u8 pulldn; /* PHY pulldown impedance */
+};
+
+void pll_init(void);
+void sdram_init(void);
+
+#endif /* __JZ4780_DRAM_H__ */
+
diff --git a/arch/mips/mach-jz47xx/include/mach/jz4780_gpio.h b/arch/mips/mach-jz47xx/include/mach/jz4780_gpio.h
new file mode 100644
index 0000000..37f0892
--- /dev/null
+++ b/arch/mips/mach-jz47xx/include/mach/jz4780_gpio.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __JZ4780_GPIO_H__
+#define __JZ4780_GPIO_H__
+
+#define JZ_GPIO(bank, pin) ((32 * (bank)) + (pin))
+
+int jz47xx_gpio_get_value(unsigned int gpio);
+void jz47xx_gpio_direction_input(unsigned int gpio);
+void jz47xx_gpio_direction_output(unsigned int gpio, int value);
+
+#endif
diff --git a/arch/mips/mach-jz47xx/jz4780/Makefile b/arch/mips/mach-jz47xx/jz4780/Makefile
new file mode 100644
index 0000000..5b3c354
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y := gpio.o jz4780.o pll.o reset.o sdram.o timer.o
diff --git a/arch/mips/mach-jz47xx/jz4780/TODO b/arch/mips/mach-jz47xx/jz4780/TODO
new file mode 100644
index 0000000..99ad622
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/TODO
@@ -0,0 +1,4 @@
+- dm gpio driver
+- ethernet driver for the dm9000
+- reduce the hundreds of definitions of register addresses to the ones really needed in assembly or SPL.
+- define the remaining register base addresses as physical addresses and establish a mapping with ioremap_nocache()
diff --git a/arch/mips/mach-jz47xx/jz4780/gpio.c b/arch/mips/mach-jz47xx/jz4780/gpio.c
new file mode 100644
index 0000000..cee2328
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/gpio.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <mach/jz4780.h>
+
+int jz47xx_gpio_get_value(unsigned int gpio)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int port = gpio / 32;
+ int pin = gpio % 32;
+
+ return readl(gpio_regs + GPIO_PXPIN(port)) & BIT(pin);
+}
+
+void jz47xx_gpio_direction_input(unsigned int gpio)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int port = gpio / 32;
+ int pin = gpio % 32;
+
+ writel(BIT(pin), gpio_regs + GPIO_PXINTC(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXMASKS(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXPAT1S(port));
+}
+
+void jz47xx_gpio_direction_output(unsigned int gpio, int value)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int port = gpio / 32;
+ int pin = gpio % 32;
+
+ writel(BIT(pin), gpio_regs + GPIO_PXINTC(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXMASKS(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXPAT1C(port));
+ writel(BIT(pin), gpio_regs +
+ (value ? GPIO_PXPAT0S(port) : GPIO_PXPAT0C(port)));
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/jz4780.c b/arch/mips/mach-jz47xx/jz4780/jz4780.c
new file mode 100644
index 0000000..dbd328c
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/jz4780.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * JZ4780 common routines
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <mach/jz4780.h>
+#include <mach/jz4780_dram.h>
+#include <mmc.h>
+#include <spl.h>
+
+#ifdef CONFIG_SPL_BUILD
+/* Pointer to the global data structure for SPL */
+DECLARE_GLOBAL_DATA_PTR;
+gd_t gdata __attribute__ ((section(".bss")));
+
+void board_init_f(ulong dummy)
+{
+ typedef void __noreturn (*image_entry_noargs_t)(void);
+ struct mmc *mmc;
+ unsigned long count;
+ struct image_header *header;
+ int ret;
+
+ /* Set global data pointer */
+ gd = &gdata;
+
+ timer_init();
+ pll_init();
+ sdram_init();
+ enable_caches();
+
+ /* Clear the BSS */
+ memset(__bss_start, 0, (char *)&__bss_end - __bss_start);
+
+ gd->flags |= GD_FLG_SPL_INIT;
+
+ ret = mmc_initialize(NULL);
+ if (ret)
+ hang();
+
+ mmc = find_mmc_device(BOOT_DEVICE_MMC1);
+ if (ret)
+ hang();
+
+ ret = mmc_init(mmc);
+ if (ret)
+ hang();
+
+ header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
+ sizeof(struct image_header));
+
+ count = blk_dread(mmc_get_blk_desc(mmc),
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
+ 0x800, header);
+ if (count == 0)
+ hang();
+
+ image_entry_noargs_t image_entry =
+ (image_entry_noargs_t)CONFIG_SYS_TEXT_BASE;
+
+ image_entry();
+
+ hang();
+}
+#endif /* CONFIG_SPL_BUILD */
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ return CONFIG_SYS_SDRAM_BASE + (256 * 1024 * 1024);
+}
+
+int print_cpuinfo(void)
+{
+ printf("CPU: Ingenic JZ4780\n");
+ return 0;
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/pll.c b/arch/mips/mach-jz47xx/jz4780/pll.c
new file mode 100644
index 0000000..9a46198
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/pll.c
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * JZ4780 PLL setup
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <mach/jz4780.h>
+
+#define CPM_CPCCR 0x00
+#define CPM_LCR 0x04
+#define CPM_RSR 0x08
+#define CPM_CPPCR 0x0c
+#define CPM_CPAPCR 0x10
+#define CPM_CPMPCR 0x14
+#define CPM_CPEPCR 0x18
+#define CPM_CPVPCR 0x1c
+#define CPM_CLKGR0 0x20
+#define CPM_OPCR 0x24
+#define CPM_CLKGR1 0x28
+#define CPM_DDCDR 0x2c
+#define CPM_VPUCDR 0x30
+#define CPM_CPSPR 0x34
+#define CPM_CPSPPR 0x38
+#define CPM_USBPCR 0x3c
+#define CPM_USBRDT 0x40
+#define CPM_USBVBFIL 0x44
+#define CPM_USBPCR1 0x48
+#define CPM_USBCDR 0x50
+#define CPM_LPCDR 0x54
+#define CPM_I2SCDR 0x60
+#define CPM_LPCDR1 0x64
+#define CPM_MSCCDR 0x68
+#define CPM_UHCCDR 0x6c
+#define CPM_SSICDR 0x74
+#define CPM_CIMCDR 0x7c
+#define CPM_PCMCDR 0x84
+#define CPM_GPUCDR 0x88
+#define CPM_HDMICDR 0x8c
+#define CPM_I2S1CDR 0xa0
+#define CPM_MSCCDR1 0xa4
+#define CPM_MSCCDR2 0xa8
+#define CPM_BCHCDR 0xac
+#define CPM_SPCR0 0xb8
+#define CPM_SPCR1 0xbc
+#define CPM_CPCSR 0xd4
+#define CPM_PSWCST(n) ((0x4 * (n)) + 0x90)
+
+/* Clock control register */
+#define CPM_CPCCR_SEL_SRC_BIT 30
+#define CPM_CPCCR_SEL_SRC_MASK (0x3 << CPM_CPCCR_SEL_SRC_BIT)
+#define CPM_SRC_SEL_STOP 0
+#define CPM_SRC_SEL_APLL 1
+#define CPM_SRC_SEL_EXCLK 2
+#define CPM_SRC_SEL_RTCLK 3
+#define CPM_CPCCR_SEL_CPLL_BIT 28
+#define CPM_CPCCR_SEL_CPLL_MASK (0x3 << CPM_CPCCR_SEL_CPLL_BIT)
+#define CPM_CPCCR_SEL_H0PLL_BIT 26
+#define CPM_CPCCR_SEL_H0PLL_MASK (0x3 << CPM_CPCCR_SEL_H0PLL_BIT)
+#define CPM_CPCCR_SEL_H2PLL_BIT 24
+#define CPM_CPCCR_SEL_H2PLL_MASK (0x3 << CPM_CPCCR_SEL_H2PLL_BIT)
+#define CPM_PLL_SEL_STOP 0
+#define CPM_PLL_SEL_SRC 1
+#define CPM_PLL_SEL_MPLL 2
+#define CPM_PLL_SEL_EPLL 3
+#define CPM_CPCCR_CE_CPU (0x1 << 22)
+#define CPM_CPCCR_CE_AHB0 (0x1 << 21)
+#define CPM_CPCCR_CE_AHB2 (0x1 << 20)
+#define CPM_CPCCR_PDIV_BIT 16
+#define CPM_CPCCR_PDIV_MASK (0xf << CPM_CPCCR_PDIV_BIT)
+#define CPM_CPCCR_H2DIV_BIT 12
+#define CPM_CPCCR_H2DIV_MASK (0xf << CPM_CPCCR_H2DIV_BIT)
+#define CPM_CPCCR_H0DIV_BIT 8
+#define CPM_CPCCR_H0DIV_MASK (0x0f << CPM_CPCCR_H0DIV_BIT)
+#define CPM_CPCCR_L2DIV_BIT 4
+#define CPM_CPCCR_L2DIV_MASK (0x0f << CPM_CPCCR_L2DIV_BIT)
+#define CPM_CPCCR_CDIV_BIT 0
+#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT)
+
+/* Clock Status register */
+#define CPM_CPCSR_H2DIV_BUSY BIT(2)
+#define CPM_CPCSR_H0DIV_BUSY BIT(1)
+#define CPM_CPCSR_CDIV_BUSY BIT(0)
+
+/* PLL control register */
+#define CPM_CPPCR_PLLST_BIT 0
+#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT)
+
+/* XPLL control register */
+#define CPM_CPXPCR_XPLLM_BIT 19
+#define CPM_CPXPCR_XPLLM_MASK (0x1fff << CPM_CPXPCR_XPLLM_BIT)
+#define CPM_CPXPCR_XPLLN_BIT 13
+#define CPM_CPXPCR_XPLLN_MASK (0x3f << CPM_CPXPCR_XPLLN_BIT)
+#define CPM_CPXPCR_XPLLOD_BIT 9
+#define CPM_CPXPCR_XPLLOD_MASK (0xf << CPM_CPXPCR_XPLLOD_BIT)
+#define CPM_CPXPCR_XLOCK BIT(6)
+#define CPM_CPXPCR_XPLL_ON BIT(4)
+#define CPM_CPXPCR_XF_MODE BIT(3)
+#define CPM_CPXPCR_XPLLBP BIT(1)
+#define CPM_CPXPCR_XPLLEN BIT(0)
+
+/* CPM scratch protected register */
+#define CPM_CPSPPR_BIT 0
+#define CPM_CPSPPR_MASK (0xffff << CPM_CPSPPR_BIT)
+
+/* USB parameter control register */
+#define CPM_USBPCR_USB_MODE BIT(31) /* 1: OTG, 0: UDC*/
+#define CPM_USBPCR_AVLD_REG BIT(30)
+#define CPM_USBPCR_IDPULLUP_MASK_BIT 28
+#define CPM_USBPCR_IDPULLUP_MASK_MASK (0x02 << IDPULLUP_MASK_BIT)
+#define CPM_USBPCR_INCR_MASK BIT(27)
+#define CPM_USBPCR_CLK12_EN BIT(26)
+#define CPM_USBPCR_COMMONONN BIT(25)
+#define CPM_USBPCR_VBUSVLDEXT BIT(24)
+#define CPM_USBPCR_VBUSVLDEXTSEL BIT(23)
+#define CPM_USBPCR_POR BIT(22)
+#define CPM_USBPCR_SIDDQ BIT(21)
+#define CPM_USBPCR_OTG_DISABLE BIT(20)
+#define CPM_USBPCR_COMPDISTUNE_BIT 17
+#define CPM_USBPCR_COMPDISTUNE_MASK (0x07 << COMPDISTUNE_BIT)
+#define CPM_USBPCR_OTGTUNE_BIT 14
+#define CPM_USBPCR_OTGTUNE_MASK (0x07 << OTGTUNE_BIT)
+#define CPM_USBPCR_SQRXTUNE_BIT 11
+#define CPM_USBPCR_SQRXTUNE_MASK (0x7x << SQRXTUNE_BIT)
+#define CPM_USBPCR_TXFSLSTUNE_BIT 7
+#define CPM_USBPCR_TXFSLSTUNE_MASK (0x0f << TXFSLSTUNE_BIT)
+#define CPM_USBPCR_TXPREEMPHTUNE BIT(6)
+#define CPM_USBPCR_TXRISETUNE_BIT 4
+#define CPM_USBPCR_TXRISETUNE_MASK (0x03 << TXRISETUNE_BIT)
+#define CPM_USBPCR_TXVREFTUNE_BIT 0
+#define CPM_USBPCR_TXVREFTUNE_MASK (0x0f << TXVREFTUNE_BIT)
+
+/* DDR memory clock divider register */
+#define CPM_DDRCDR_DCS_BIT 30
+#define CPM_DDRCDR_DCS_MASK (0x3 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_DCS_STOP (0x0 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_DCS_SRC (0x1 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_DCS_MPLL (0x2 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_CE_DDR BIT(29)
+#define CPM_DDRCDR_DDR_BUSY BIT(28)
+#define CPM_DDRCDR_DDR_STOP BIT(27)
+#define CPM_DDRCDR_DDRDIV_BIT 0
+#define CPM_DDRCDR_DDRDIV_MASK (0xf << CPM_DDRCDR_DDRDIV_BIT)
+
+/* USB reset detect timer register */
+#define CPM_USBRDT_VBFIL_LD_EN BIT(25)
+#define CPM_USBRDT_IDDIG_EN BIT(24)
+#define CPM_USBRDT_IDDIG_REG BIT(23)
+#define CPM_USBRDT_USBRDT_BIT 0
+#define CPM_USBRDT_USBRDT_MASK (0x7fffff << CPM_USBRDT_USBRDT_BIT)
+
+/* USB OTG PHY clock divider register */
+#define CPM_USBCDR_UCS BIT(31)
+#define CPM_USBCDR_UPCS BIT(30)
+#define CPM_USBCDR_CEUSB BIT(29)
+#define CPM_USBCDR_USB_BUSY BIT(28)
+#define CPM_USBCDR_OTGDIV_BIT 0
+#define CPM_USBCDR_OTGDIV_MASK (0xff << CPM_USBCDR_OTGDIV_BIT)
+
+/* I2S device clock divider register */
+#define CPM_I2SCDR_I2CS BIT(31)
+#define CPM_I2SCDR_I2PCS BIT(30)
+#define CPM_I2SCDR_I2SDIV_BIT 0
+#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT)
+
+/* LCD0 pix clock divider register */
+#define CPM_LPCDR_LPCS_BIT 30
+#define CPM_LPCDR_LPCS_MASK (0x3 << CPM_LPCDR_LPCS_BIT)
+#define CPM_LPCDR_CELCD BIT(28)
+#define CPM_LPCDR_LCD_BUSY BIT(27)
+#define CPM_LPCDR_LCD_STOP BIT(26)
+#define CPM_LPCDR_PIXDIV_BIT 0
+#define CPM_LPCDR_PIXDIV_MASK (0xff << CPM_LPCDR_PIXDIV_BIT)
+
+/* MSC clock divider register */
+#define CPM_MSCCDR_MPCS_BIT 30
+#define CPM_MSCCDR_MPCS_MASK (3 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_MPCS_STOP (0x0 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_MPCS_SRC (0x1 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_MPCS_MPLL (0x2 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_CE BIT(29)
+#define CPM_MSCCDR_MSC_BUSY BIT(28)
+#define CPM_MSCCDR_MSC_STOP BIT(27)
+#define CPM_MSCCDR_MSC_CLK0_SEL BIT(15)
+#define CPM_MSCCDR_MSCDIV_BIT 0
+#define CPM_MSCCDR_MSCDIV_MASK (0xff << CPM_MSCCDR_MSCDIV_BIT)
+
+/* UHC 48M clock divider register */
+#define CPM_UHCCDR_UHCS_BIT 30
+#define CPM_UHCCDR_UHCS_MASK (0x3 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_SRC (0x0 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_MPLL (0x1 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_EPLL (0x2 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_OTG (0x3 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_CE_UHC BIT(29)
+#define CPM_UHCCDR_UHC_BUSY BIT(28)
+#define CPM_UHCCDR_UHC_STOP BIT(27)
+#define CPM_UHCCDR_UHCDIV_BIT 0
+#define CPM_UHCCDR_UHCDIV_MASK (0xff << CPM_UHCCDR_UHCDIV_BIT)
+
+/* SSI clock divider register */
+#define CPM_SSICDR_SCS BIT(31)
+#define CPM_SSICDR_SSIDIV_BIT 0
+#define CPM_SSICDR_SSIDIV_MASK (0x3f << CPM_SSICDR_SSIDIV_BIT)
+
+/* CIM MCLK clock divider register */
+#define CPM_CIMCDR_CIMDIV_BIT 0
+#define CPM_CIMCDR_CIMDIV_MASK (0xff << CPM_CIMCDR_CIMDIV_BIT)
+
+/* GPS clock divider register */
+#define CPM_GPSCDR_GPCS BIT(31)
+#define CPM_GPSCDR_GPSDIV_BIT 0
+#define CPM_GSPCDR_GPSDIV_MASK (0xf << CPM_GPSCDR_GPSDIV_BIT)
+
+/* PCM device clock divider register */
+#define CPM_PCMCDR_PCMS BIT(31)
+#define CPM_PCMCDR_PCMPCS BIT(30)
+#define CPM_PCMCDR_PCMDIV_BIT 0
+#define CPM_PCMCDR_PCMDIV_MASK (0x1ff << CPM_PCMCDR_PCMDIV_BIT)
+
+/* GPU clock divider register */
+#define CPM_GPUCDR_GPCS BIT(31)
+#define CPM_GPUCDR_GPUDIV_BIT 0
+#define CPM_GPUCDR_GPUDIV_MASK (0x7 << CPM_GPUCDR_GPUDIV_BIT)
+
+/* HDMI clock divider register */
+#define CPM_HDMICDR_HPCS_BIT 30
+#define CPM_HDMICDR_HPCS_MASK (0x3 << CPM_HDMICDR_HPCS_BIT)
+#define CPM_HDMICDR_CEHDMI BIT(29)
+#define CPM_HDMICDR_HDMI_BUSY BIT(28)
+#define CPM_HDMICDR_HDMI_STOP BIT(26)
+#define CPM_HDMICDR_HDMIDIV_BIT 0
+#define CPM_HDMICDR_HDMIDIV_MASK (0xff << CPM_HDMICDR_HDMIDIV_BIT)
+
+/* Low Power Control Register */
+#define CPM_LCR_PD_SCPU BIT(31)
+#define CPM_LCR_PD_VPU BIT(30)
+#define CPM_LCR_PD_GPU BIT(29)
+#define CPM_LCR_PD_GPS BIT(28)
+#define CPM_LCR_SCPUS BIT(27)
+#define CPM_LCR_VPUS BIT(26)
+#define CPM_LCR_GPUS BIT(25)
+#define CPM_LCR_GPSS BIT(24)
+#define CPM_LCR_GPU_IDLE BIT(20)
+#define CPM_LCR_PST_BIT 8
+#define CPM_LCR_PST_MASK (0xfff << CPM_LCR_PST_BIT)
+#define CPM_LCR_DOZE_DUTY_BIT 3
+#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT)
+#define CPM_LCR_DOZE_ON BIT(2)
+#define CPM_LCR_LPM_BIT 0
+#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT)
+#define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT)
+#define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT)
+
+/* Clock Gate Register0 */
+#define CPM_CLKGR0_DDR1 BIT(31)
+#define CPM_CLKGR0_DDR0 BIT(30)
+#define CPM_CLKGR0_IPU BIT(29)
+#define CPM_CLKGR0_LCD1 BIT(28)
+#define CPM_CLKGR0_LCD BIT(27)
+#define CPM_CLKGR0_CIM BIT(26)
+#define CPM_CLKGR0_I2C2 BIT(25)
+#define CPM_CLKGR0_UHC BIT(24)
+#define CPM_CLKGR0_MAC BIT(23)
+#define CPM_CLKGR0_GPS BIT(22)
+#define CPM_CLKGR0_PDMAC BIT(21)
+#define CPM_CLKGR0_SSI2 BIT(20)
+#define CPM_CLKGR0_SSI1 BIT(19)
+#define CPM_CLKGR0_UART3 BIT(18)
+#define CPM_CLKGR0_UART2 BIT(17)
+#define CPM_CLKGR0_UART1 BIT(16)
+#define CPM_CLKGR0_UART0 BIT(15)
+#define CPM_CLKGR0_SADC BIT(14)
+#define CPM_CLKGR0_KBC BIT(13)
+#define CPM_CLKGR0_MSC2 BIT(12)
+#define CPM_CLKGR0_MSC1 BIT(11)
+#define CPM_CLKGR0_OWI BIT(10)
+#define CPM_CLKGR0_TSSI BIT(9)
+#define CPM_CLKGR0_AIC BIT(8)
+#define CPM_CLKGR0_SCC BIT(7)
+#define CPM_CLKGR0_I2C1 BIT(6)
+#define CPM_CLKGR0_I2C0 BIT(5)
+#define CPM_CLKGR0_SSI0 BIT(4)
+#define CPM_CLKGR0_MSC0 BIT(3)
+#define CPM_CLKGR0_OTG BIT(2)
+#define CPM_CLKGR0_BCH BIT(1)
+#define CPM_CLKGR0_NEMC BIT(0)
+
+/* Clock Gate Register1 */
+#define CPM_CLKGR1_P1 BIT(15)
+#define CPM_CLKGR1_X2D BIT(14)
+#define CPM_CLKGR1_DES BIT(13)
+#define CPM_CLKGR1_I2C4 BIT(12)
+#define CPM_CLKGR1_AHB BIT(11)
+#define CPM_CLKGR1_UART4 BIT(10)
+#define CPM_CLKGR1_HDMI BIT(9)
+#define CPM_CLKGR1_OTG1 BIT(8)
+#define CPM_CLKGR1_GPVLC BIT(7)
+#define CPM_CLKGR1_AIC1 BIT(6)
+#define CPM_CLKGR1_COMPRES BIT(5)
+#define CPM_CLKGR1_GPU BIT(4)
+#define CPM_CLKGR1_PCM BIT(3)
+#define CPM_CLKGR1_VPU BIT(2)
+#define CPM_CLKGR1_TSSI1 BIT(1)
+#define CPM_CLKGR1_I2C3 BIT(0)
+
+/* Oscillator and Power Control Register */
+#define CPM_OPCR_O1ST_BIT 8
+#define CPM_OPCR_O1ST_MASK (0xff << CPM_OPCR_O1ST_BIT)
+#define CPM_OPCR_SPENDN BIT(7)
+#define CPM_OPCR_GPSEN BIT(6)
+#define CPM_OPCR_SPENDH BIT(5)
+#define CPM_OPCR_O1SE BIT(4)
+#define CPM_OPCR_ERCS BIT(2) /* 0: select EXCLK/512 clock, 1: RTCLK clock */
+#define CPM_OPCR_USBM BIT(0) /* 0: select EXCLK/512 clock, 1: RTCLK clock */
+
+/* Reset Status Register */
+#define CPM_RSR_P0R BIT(2)
+#define CPM_RSR_WR BIT(1)
+#define CPM_RSR_PR BIT(0)
+
+/* BCH clock divider register */
+#define CPM_BCHCDR_BPCS_BIT 30
+#define CPM_BCHCDR_BPCS_MASK (0x3 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_STOP (0X0 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_SRC_CLK (0x1 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_MPLL (0x2 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_EPLL (0x3 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_CE_BCH BIT(29)
+#define CPM_BCHCDR_BCH_BUSY BIT(28)
+#define CPM_BCHCDR_BCH_STOP BIT(27)
+#define CPM_BCHCDR_BCHCDR_BIT 0
+#define CPM_BCHCDR_BCHCDR_MASK (0x7 << CPM_BCHCDR_BCHCDR_BIT)
+
+/* CPM scratch pad protected register(CPSPPR) */
+#define CPSPPR_CPSPR_WRITABLE 0x00005a5a
+#define RECOVERY_SIGNATURE 0x1a1a /* means "RECY" */
+#define RECOVERY_SIGNATURE_SEC 0x800 /* means "RECY" */
+
+#define REBOOT_SIGNATURE 0x3535 /* means reboot */
+
+/* XPLL control register */
+#define XLOCK (1 << 6)
+#define XPLL_ON (1 << 4)
+#define XF_MODE (1 << 3)
+#define XPLLBP (1 << 1)
+#define XPLLEN (1 << 0)
+
+enum PLLS {
+ EXTCLK = 0,
+ APLL,
+ MPLL,
+ EPLL,
+ VPLL,
+};
+
+#define M_N_OD(m, n, od) \
+ ((((m) - 1) << 19) | (((n) - 1) << 13) | (((od) - 1) << 9))
+
+struct cgu_pll_select {
+ u8 reg;
+ u8 pll;
+ u8 pll_shift;
+};
+
+static void pll_init_one(int pll, int m, int n, int od)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ void __iomem *pll_reg = cpm_regs + CPM_CPAPCR + ((pll - 1) * 4);
+
+ setbits_le32(pll_reg, M_N_OD(m, n, od) | XPLLEN);
+
+ /* FIXME */
+ while (!(readl(pll_reg) & XPLL_ON))
+ ;
+}
+
+static void cpu_mux_select(int pll)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 clk_ctrl;
+ unsigned int selectplls[] = {
+ CPM_PLL_SEL_STOP,
+ CPM_PLL_SEL_SRC,
+ CPM_PLL_SEL_MPLL,
+ CPM_PLL_SEL_EPLL
+ };
+
+ /* Init CPU, L2CACHE, AHB0, AHB2, APB clock */
+ clk_ctrl = CPM_CPCCR_CE_CPU | CPM_CPCCR_CE_AHB0 | CPM_CPCCR_CE_AHB2 |
+ ((6 - 1) << CPM_CPCCR_H2DIV_BIT) |
+ ((3 - 1) << CPM_CPCCR_H0DIV_BIT) |
+ ((2 - 1) << CPM_CPCCR_L2DIV_BIT) |
+ ((1 - 1) << CPM_CPCCR_CDIV_BIT);
+
+ if (CONFIG_SYS_MHZ >= 1000)
+ clk_ctrl |= (12 - 1) << CPM_CPCCR_PDIV_BIT;
+ else
+ clk_ctrl |= (6 - 1) << CPM_CPCCR_PDIV_BIT;
+
+ clrsetbits_le32(cpm_regs + CPM_CPCCR, 0x00ffffff, clk_ctrl);
+
+ while (readl(cpm_regs + CPM_CPCSR) & (CPM_CPCSR_CDIV_BUSY |
+ CPM_CPCSR_H0DIV_BUSY | CPM_CPCSR_H2DIV_BUSY))
+ ;
+
+ clk_ctrl = (selectplls[pll] << CPM_CPCCR_SEL_CPLL_BIT) |
+ (selectplls[MPLL] << CPM_CPCCR_SEL_H0PLL_BIT) |
+ (selectplls[MPLL] << CPM_CPCCR_SEL_H2PLL_BIT);
+ if (pll == APLL)
+ clk_ctrl |= CPM_PLL_SEL_SRC << CPM_CPCCR_SEL_SRC_BIT;
+ else
+ clk_ctrl |= CPM_SRC_SEL_EXCLK << CPM_CPCCR_SEL_SRC_BIT;
+
+ clrsetbits_le32(cpm_regs + CPM_CPCCR, 0xff << 24, clk_ctrl);
+}
+
+static void ddr_mux_select(int pll)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ int selectplls[] = { CPM_DDRCDR_DCS_STOP,
+ CPM_DDRCDR_DCS_SRC,
+ CPM_DDRCDR_DCS_MPLL};
+
+ writel(selectplls[pll] | CPM_DDRCDR_CE_DDR | (JZ4780_SYS_MEM_DIV - 1),
+ cpm_regs + CPM_DDCDR);
+
+ while (readl(cpm_regs + CPM_DDCDR) & CPM_DDRCDR_DDR_BUSY)
+ ;
+
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_DDR0);
+
+ mdelay(200);
+}
+
+static void cgu_mux_init(struct cgu_pll_select *cgu, unsigned int num)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ unsigned int selectplls[] = {0, 1, 2, 3, 2, 6};
+ int i;
+
+ for (i = 0; i < num; i++)
+ writel(selectplls[cgu[i].pll] << cgu[i].pll_shift,
+ cpm_regs + cgu[i].reg);
+}
+
+void pll_init(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ struct cgu_pll_select cgu_mux[] = {
+ { CPM_MSCCDR, MPLL, 30 },
+ { CPM_LPCDR, VPLL, 30 },
+ { CPM_LPCDR1, VPLL, 30 },
+ { CPM_GPUCDR, MPLL, 30 },
+ { CPM_HDMICDR, VPLL, 30 },
+ { CPM_I2SCDR, EPLL, 30 },
+ { CPM_BCHCDR, MPLL, 30 },
+ { CPM_VPUCDR, 0x1, 30 },
+ { CPM_UHCCDR, 0x3, 30 },
+ { CPM_CIMCDR, 0x1, 31 },
+ { CPM_PCMCDR, 0x5, 29 },
+ { CPM_SSICDR, 0x3, 30 },
+ };
+
+ /* PLL stable time set to default -- 1ms */
+ clrsetbits_le32(cpm_regs + CPM_CPPCR, 0xfffff, (16 << 8) | 0x20);
+
+ pll_init_one(APLL, JZ4780_APLL_M, JZ4780_APLL_N, JZ4780_APLL_OD);
+ pll_init_one(MPLL, JZ4780_MPLL_M, JZ4780_MPLL_N, JZ4780_MPLL_OD);
+ pll_init_one(VPLL, JZ4780_VPLL_M, JZ4780_VPLL_N, JZ4780_VPLL_OD);
+ pll_init_one(EPLL, JZ4780_EPLL_M, JZ4780_EPLL_N, JZ4780_EPLL_OD);
+
+ cpu_mux_select(MPLL);
+ ddr_mux_select(MPLL);
+ cgu_mux_init(cgu_mux, ARRAY_SIZE(cgu_mux));
+}
+
+const u32 jz4780_clk_get_efuse_clk(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 cpccr = readl(cpm_regs + CPM_CPCCR);
+ u32 ahb2_div = ((cpccr & CPM_CPCCR_H2DIV_MASK) >>
+ CPM_CPCCR_H2DIV_BIT) + 1;
+ return JZ4780_SYS_MEM_SPEED / ahb2_div;
+}
+
+void jz4780_clk_ungate_ethernet(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_MAC);
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_NEMC);
+}
+
+void jz4780_clk_ungate_mmc(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 msc_cdr = JZ4780_SYS_MEM_SPEED / 24000000 / 2 - 1;
+
+ msc_cdr |= CPM_MSCCDR_MPCS_MPLL | CPM_MSCCDR_CE;
+ writel(msc_cdr, cpm_regs + CPM_MSCCDR);
+ writel(msc_cdr, cpm_regs + CPM_MSCCDR1);
+ writel(msc_cdr, cpm_regs + CPM_MSCCDR2);
+
+ /* The wait_for_bit() won't fit, thus unbounded loop here. */
+ while (readl(cpm_regs + CPM_MSCCDR1) & CPM_MSCCDR_MSC_BUSY)
+ ;
+}
+
+void jz4780_clk_ungate_uart(const unsigned int uart)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+
+ if (uart == 0)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART0);
+ else if (uart == 1)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART1);
+ else if (uart == 2)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART2);
+ else if (uart == 3)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART3);
+ else if (uart == 4)
+ clrbits_le32(cpm_regs + CPM_CLKGR1, CPM_CLKGR1_UART4);
+ else
+ printf("%s[%i]: Invalid UART %d\n", __func__, __LINE__, uart);
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/reset.c b/arch/mips/mach-jz47xx/jz4780/reset.c
new file mode 100644
index 0000000..73af347
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/reset.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * JZ4780 common routines
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <mach/jz4780.h>
+
+/* WDT */
+#define WDT_TDR 0x00
+#define WDT_TCER 0x04
+#define WDT_TCNT 0x08
+#define WDT_TCSR 0x0C
+
+/* Register definition */
+#define WDT_TCSR_PRESCALE_BIT 3
+#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT)
+#define WDT_TCSR_EXT_EN BIT(2)
+#define WDT_TCSR_RTC_EN BIT(1)
+#define WDT_TCSR_PCK_EN BIT(0)
+
+#define WDT_TCER_TCEN BIT(0)
+
+void _machine_restart(void)
+{
+ void __iomem *wdt_regs = (void __iomem *)WDT_BASE;
+
+ /* EXTAL as the timer clock input. */
+ writew(WDT_TCSR_PRESCALE1 | WDT_TCSR_EXT_EN, wdt_regs + WDT_TCSR);
+
+ /* Reset the WDT counter and timeout. */
+ writew(0, wdt_regs + WDT_TCNT);
+ writew(0, wdt_regs + WDT_TDR);
+
+ jz4780_tcu_wdt_start();
+
+ /* WDT start */
+ writeb(WDT_TCER_TCEN, wdt_regs + WDT_TCER);
+
+ for (;;)
+ ;
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/sdram.c b/arch/mips/mach-jz47xx/jz4780/sdram.c
new file mode 100644
index 0000000..5b25c8d
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/sdram.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * JZ4780 DDR initialization
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * Based on spl/common/{jz4780_ddr,jz_ddr3_init}.c from X-Boot
+ * Copyright (c) 2006-2013 Ingenic Semiconductor
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mach/jz4780.h>
+#include <mach/jz4780_dram.h>
+
+static const u32 get_mem_clk(void)
+{
+ const u32 mpll_out = ((u64)JZ4780_SYS_EXTAL * JZ4780_MPLL_M) /
+ (JZ4780_MPLL_N * JZ4780_MPLL_OD);
+ return mpll_out / JZ4780_SYS_MEM_DIV;
+}
+
+u32 sdram_size(int cs)
+{
+ u32 dw = DDR_DW32 ? 4 : 2;
+ u32 banks = DDR_BANK8 ? 8 : 4;
+ u32 size = 0;
+
+ if ((cs == 0) && DDR_CS0EN) {
+ size = (1 << (DDR_ROW + DDR_COL)) * dw * banks;
+ if (DDR_CS1EN && (size > 0x20000000))
+ size = 0x20000000;
+ } else if ((cs == 1) && DDR_CS1EN) {
+ size = (1 << (DDR_ROW + DDR_COL)) * dw * banks;
+ }
+
+ return size;
+}
+
+static void ddr_cfg_init(void)
+{
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ u32 ddrc_cfg, tmp;
+
+ tmp = DDR_CL;
+ if (tmp)
+ tmp--;
+ if (tmp > 4)
+ tmp = 4;
+
+ ddrc_cfg = DDRC_CFG_TYPE_DDR3 | DDRC_CFG_IMBA |
+ DDR_DW32 | DDRC_CFG_MPRT | ((tmp | 0x8) << 2) |
+ ((DDR_ROW - 12) << 11) | ((DDR_COL - 8) << 8) |
+ (DDR_CS0EN << 6) | (DDR_BANK8 << 1) |
+ ((DDR_ROW - 12) << 27) | ((DDR_COL - 8) << 24) |
+ (DDR_CS1EN << 7) | (DDR_BANK8 << 23);
+
+ if (DDR_BL > 4)
+ ddrc_cfg |= BIT(21);
+
+ writel(ddrc_cfg, ddr_ctl_regs + DDRC_CFG);
+}
+
+static void ddr_phy_init(const struct jz4780_ddr_config *ddr_config)
+{
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ void __iomem *ddr_phy_regs = ddr_ctl_regs + DDR_PHY_OFFSET;
+ unsigned int count = 0, i;
+ u32 reg, mask;
+
+ writel(DDRP_DCR_TYPE_DDR3 | (DDR_BANK8 << 3), ddr_phy_regs + DDRP_DCR);
+
+ writel(ddr_config->mr0, ddr_phy_regs + DDRP_MR0);
+ writel(ddr_config->mr1, ddr_phy_regs + DDRP_MR1);
+ writel(0, ddr_phy_regs + DDRP_ODTCR);
+ writel(0, ddr_phy_regs + DDRP_MR2);
+
+ writel(ddr_config->ptr0, ddr_phy_regs + DDRP_PTR0);
+ writel(ddr_config->ptr1, ddr_phy_regs + DDRP_PTR1);
+ writel(ddr_config->ptr2, ddr_phy_regs + DDRP_PTR2);
+
+ writel(ddr_config->dtpr0, ddr_phy_regs + DDRP_DTPR0);
+ writel(ddr_config->dtpr1, ddr_phy_regs + DDRP_DTPR1);
+ writel(ddr_config->dtpr2, ddr_phy_regs + DDRP_DTPR2);
+
+ writel(DDRP_PGCR_DQSCFG | (7 << DDRP_PGCR_CKEN_BIT) |
+ (2 << DDRP_PGCR_CKDV_BIT) |
+ (DDR_CS0EN | (DDR_CS1EN << 1)) << DDRP_PGCR_RANKEN_BIT |
+ DDRP_PGCR_ZCKSEL_32 | DDRP_PGCR_PDDISDX,
+ ddr_phy_regs + DDRP_PGCR);
+
+ for (i = 0; i < 8; i++)
+ clrbits_le32(ddr_phy_regs + DDRP_DXGCR(i), 0x3 << 9);
+
+ count = 0;
+ mask = DDRP_PGSR_IDONE | DDRP_PGSR_DLDONE | DDRP_PGSR_ZCDONE;
+ for (;;) {
+ reg = readl(ddr_phy_regs + DDRP_PGSR);
+ if ((reg == mask) || (reg == 0x1f))
+ break;
+ if (count++ == 10000)
+ hang();
+ }
+
+ /* DQS extension and early set to 1 */
+ clrsetbits_le32(ddr_phy_regs + DDRP_DSGCR, 0x7E << 4, 0x12 << 4);
+
+ /* 500 pull up and 500 pull down */
+ clrsetbits_le32(ddr_phy_regs + DDRP_DXCCR, 0xFF << 4, 0xC4 << 4);
+
+ /* Initialise phy */
+ writel(DDRP_PIR_INIT | DDRP_PIR_DRAMINT | DDRP_PIR_DRAMRST,
+ ddr_phy_regs + DDRP_PIR);
+
+ count = 0;
+ mask |= DDRP_PGSR_DIDONE;
+ for (;;) {
+ reg = readl(ddr_phy_regs + DDRP_PGSR);
+ if ((reg == mask) || (reg == 0x1f))
+ break;
+ if (count++ == 20000)
+ hang();
+ }
+
+ writel(DDRP_PIR_INIT | DDRP_PIR_QSTRN, ddr_phy_regs + DDRP_PIR);
+
+ count = 0;
+ mask |= DDRP_PGSR_DTDONE;
+ for (;;) {
+ reg = readl(ddr_phy_regs + DDRP_PGSR);
+ if (reg == mask)
+ break;
+ if (count++ != 50000)
+ continue;
+ reg &= DDRP_PGSR_DTDONE | DDRP_PGSR_DTERR | DDRP_PGSR_DTIERR;
+ if (reg)
+ hang();
+ count = 0;
+ }
+
+ /* Override impedance */
+ clrsetbits_le32(ddr_phy_regs + DDRP_ZQXCR0(0), 0x3ff,
+ ((ddr_config->pullup & 0x1f) << DDRP_ZQXCR_PULLUP_IMPE_BIT) |
+ ((ddr_config->pulldn & 0x1f) << DDRP_ZQXCR_PULLDOWN_IMPE_BIT) |
+ DDRP_ZQXCR_ZDEN);
+}
+
+#define JZBIT(bit) ((bit % 4) * 8)
+#define JZMASK(bit) (0x1f << JZBIT(bit))
+
+static void remap_swap(int a, int b)
+{
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ u32 remmap[2], tmp[2];
+
+ remmap[0] = readl(ddr_ctl_regs + DDRC_REMMAP(a / 4));
+ remmap[1] = readl(ddr_ctl_regs + DDRC_REMMAP(b / 4));
+
+ tmp[0] = (remmap[0] & JZMASK(a)) >> JZBIT(a);
+ tmp[1] = (remmap[1] & JZMASK(b)) >> JZBIT(b);
+
+ remmap[0] &= ~JZMASK(a);
+ remmap[1] &= ~JZMASK(b);
+
+ writel(remmap[0] | (tmp[1] << JZBIT(a)),
+ ddr_ctl_regs + DDRC_REMMAP(a / 4));
+ writel(remmap[1] | (tmp[0] << JZBIT(b)),
+ ddr_ctl_regs + DDRC_REMMAP(b / 4));
+}
+
+static void mem_remap(void)
+{
+ u32 start = (DDR_ROW + DDR_COL + (DDR_DW32 ? 4 : 2) / 2) - 12;
+ u32 num = DDR_BANK8 ? 3 : 2;
+
+ if (DDR_CS0EN && DDR_CS1EN)
+ num++;
+
+ for (; num > 0; num--)
+ remap_swap(0 + num - 1, start + num - 1);
+}
+
+/* Fetch DRAM config from board file */
+__weak const struct jz4780_ddr_config *jz4780_get_ddr_config(void)
+{
+ return NULL;
+}
+
+void sdram_init(void)
+{
+ const struct jz4780_ddr_config *ddr_config = jz4780_get_ddr_config();
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ void __iomem *ddr_phy_regs = ddr_ctl_regs + DDR_PHY_OFFSET;
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 mem_clk, tmp, i;
+ u32 mem_base0, mem_base1;
+ u32 mem_mask0, mem_mask1;
+ u32 mem_size0, mem_size1;
+
+ if (!ddr_config)
+ hang();
+
+ /* Reset DLL in DDR PHY */
+ writel(0x3, cpm_regs + 0xd0);
+ mdelay(400);
+ writel(0x1, cpm_regs + 0xd0);
+ mdelay(400);
+
+ /* Enter reset */
+ writel(0xf << 20, ddr_ctl_regs + DDRC_CTRL);
+
+ mem_clk = get_mem_clk();
+
+ tmp = 1000000000 / mem_clk;
+ if (1000000000 % mem_clk)
+ tmp++;
+ tmp = DDR_tREFI / tmp;
+ tmp = tmp / (16 * (1 << DDR_CLK_DIV)) - 1;
+ if (tmp > 0xff)
+ tmp = 0xff;
+ if (tmp < 1)
+ tmp = 1;
+
+ writel(0x0, ddr_ctl_regs + DDRC_CTRL);
+
+ writel(0x150000, ddr_phy_regs + DDRP_DTAR);
+ ddr_phy_init(ddr_config);
+
+ writel(DDRC_CTRL_CKE | DDRC_CTRL_ALH, ddr_ctl_regs + DDRC_CTRL);
+ writel(0x0, ddr_ctl_regs + DDRC_CTRL);
+
+ ddr_cfg_init();
+
+ for (i = 0; i < 6; i++)
+ writel(ddr_config->timing[i], ddr_ctl_regs + DDRC_TIMING(i));
+
+ mem_size0 = sdram_size(0);
+ mem_size1 = sdram_size(1);
+
+ if (!mem_size1 && mem_size0 > 0x20000000) {
+ mem_base0 = 0x0;
+ mem_mask0 = ~(((mem_size0 * 2) >> 24) - 1) & DDRC_MMAP_MASK_MASK;
+ } else {
+ mem_base0 = (DDR_MEM_PHY_BASE >> 24) & 0xff;
+ mem_mask0 = ~((mem_size0 >> 24) - 1) & DDRC_MMAP_MASK_MASK;
+ }
+
+ if (mem_size1) {
+ mem_mask1 = ~((mem_size1 >> 24) - 1) & DDRC_MMAP_MASK_MASK;
+ mem_base1 = ((DDR_MEM_PHY_BASE + mem_size0) >> 24) & 0xff;
+ } else {
+ mem_mask1 = 0;
+ mem_base1 = 0xff;
+ }
+
+ writel(mem_base0 << DDRC_MMAP_BASE_BIT | mem_mask0,
+ ddr_ctl_regs + DDRC_MMAP0);
+ writel(mem_base1 << DDRC_MMAP_BASE_BIT | mem_mask1,
+ ddr_ctl_regs + DDRC_MMAP1);
+ writel(DDRC_CTRL_CKE | DDRC_CTRL_ALH, ddr_ctl_regs + DDRC_CTRL);
+ writel((DDR_CLK_DIV << 1) | DDRC_REFCNT_REF_EN |
+ (tmp << DDRC_REFCNT_CON_BIT),
+ ddr_ctl_regs + DDRC_REFCNT);
+ writel((1 << 15) | (4 << 12) | (1 << 11) | (1 << 8) | (0 << 6) |
+ (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1),
+ ddr_ctl_regs + DDRC_CTRL);
+ mem_remap();
+ clrbits_le32(ddr_ctl_regs + DDRC_ST, 0x40);
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/timer.c b/arch/mips/mach-jz47xx/jz4780/timer.c
new file mode 100644
index 0000000..a689b9d
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/timer.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * JZ4780 timer
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <mach/jz4780.h>
+
+#define TCU_TSR 0x1C /* Timer Stop Register */
+#define TCU_TSSR 0x2C /* Timer Stop Set Register */
+#define TCU_TSCR 0x3C /* Timer Stop Clear Register */
+#define TCU_TER 0x10 /* Timer Counter Enable Register */
+#define TCU_TESR 0x14 /* Timer Counter Enable Set Register */
+#define TCU_TECR 0x18 /* Timer Counter Enable Clear Register */
+#define TCU_TFR 0x20 /* Timer Flag Register */
+#define TCU_TFSR 0x24 /* Timer Flag Set Register */
+#define TCU_TFCR 0x28 /* Timer Flag Clear Register */
+#define TCU_TMR 0x30 /* Timer Mask Register */
+#define TCU_TMSR 0x34 /* Timer Mask Set Register */
+#define TCU_TMCR 0x38 /* Timer Mask Clear Register */
+/* n = 0,1,2,3,4,5 */
+#define TCU_TDFR(n) (0x40 + (n) * 0x10) /* Timer Data Full Reg */
+#define TCU_TDHR(n) (0x44 + (n) * 0x10) /* Timer Data Half Reg */
+#define TCU_TCNT(n) (0x48 + (n) * 0x10) /* Timer Counter Reg */
+#define TCU_TCSR(n) (0x4C + (n) * 0x10) /* Timer Control Reg */
+
+#define TCU_OSTCNTL 0xe4
+#define TCU_OSTCNTH 0xe8
+#define TCU_OSTCSR 0xec
+#define TCU_OSTCNTHBUF 0xfc
+
+/* Register definitions */
+#define TCU_TCSR_PWM_SD BIT(9)
+#define TCU_TCSR_PWM_INITL_HIGH BIT(8)
+#define TCU_TCSR_PWM_EN BIT(7)
+#define TCU_TCSR_PRESCALE_BIT 3
+#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_EXT_EN BIT(2)
+#define TCU_TCSR_RTC_EN BIT(1)
+#define TCU_TCSR_PCK_EN BIT(0)
+
+#define TCU_TER_TCEN5 BIT(5)
+#define TCU_TER_TCEN4 BIT(4)
+#define TCU_TER_TCEN3 BIT(3)
+#define TCU_TER_TCEN2 BIT(2)
+#define TCU_TER_TCEN1 BIT(1)
+#define TCU_TER_TCEN0 BIT(0)
+
+#define TCU_TESR_TCST5 BIT(5)
+#define TCU_TESR_TCST4 BIT(4)
+#define TCU_TESR_TCST3 BIT(3)
+#define TCU_TESR_TCST2 BIT(2)
+#define TCU_TESR_TCST1 BIT(1)
+#define TCU_TESR_TCST0 BIT(0)
+
+#define TCU_TECR_TCCL5 BIT(5)
+#define TCU_TECR_TCCL4 BIT(4)
+#define TCU_TECR_TCCL3 BIT(3)
+#define TCU_TECR_TCCL2 BIT(2)
+#define TCU_TECR_TCCL1 BIT(1)
+#define TCU_TECR_TCCL0 BIT(0)
+
+#define TCU_TFR_HFLAG5 BIT(21)
+#define TCU_TFR_HFLAG4 BIT(20)
+#define TCU_TFR_HFLAG3 BIT(19)
+#define TCU_TFR_HFLAG2 BIT(18)
+#define TCU_TFR_HFLAG1 BIT(17)
+#define TCU_TFR_HFLAG0 BIT(16)
+#define TCU_TFR_FFLAG5 BIT(5)
+#define TCU_TFR_FFLAG4 BIT(4)
+#define TCU_TFR_FFLAG3 BIT(3)
+#define TCU_TFR_FFLAG2 BIT(2)
+#define TCU_TFR_FFLAG1 BIT(1)
+#define TCU_TFR_FFLAG0 BIT(0)
+
+#define TCU_TFSR_HFLAG5 BIT(21)
+#define TCU_TFSR_HFLAG4 BIT(20)
+#define TCU_TFSR_HFLAG3 BIT(19)
+#define TCU_TFSR_HFLAG2 BIT(18)
+#define TCU_TFSR_HFLAG1 BIT(17)
+#define TCU_TFSR_HFLAG0 BIT(16)
+#define TCU_TFSR_FFLAG5 BIT(5)
+#define TCU_TFSR_FFLAG4 BIT(4)
+#define TCU_TFSR_FFLAG3 BIT(3)
+#define TCU_TFSR_FFLAG2 BIT(2)
+#define TCU_TFSR_FFLAG1 BIT(1)
+#define TCU_TFSR_FFLAG0 BIT(0)
+
+#define TCU_TFCR_HFLAG5 BIT(21)
+#define TCU_TFCR_HFLAG4 BIT(20)
+#define TCU_TFCR_HFLAG3 BIT(19)
+#define TCU_TFCR_HFLAG2 BIT(18)
+#define TCU_TFCR_HFLAG1 BIT(17)
+#define TCU_TFCR_HFLAG0 BIT(16)
+#define TCU_TFCR_FFLAG5 BIT(5)
+#define TCU_TFCR_FFLAG4 BIT(4)
+#define TCU_TFCR_FFLAG3 BIT(3)
+#define TCU_TFCR_FFLAG2 BIT(2)
+#define TCU_TFCR_FFLAG1 BIT(1)
+#define TCU_TFCR_FFLAG0 BIT(0)
+
+#define TCU_TMR_HMASK5 BIT(21)
+#define TCU_TMR_HMASK4 BIT(20)
+#define TCU_TMR_HMASK3 BIT(19)
+#define TCU_TMR_HMASK2 BIT(18)
+#define TCU_TMR_HMASK1 BIT(17)
+#define TCU_TMR_HMASK0 BIT(16)
+#define TCU_TMR_FMASK5 BIT(5)
+#define TCU_TMR_FMASK4 BIT(4)
+#define TCU_TMR_FMASK3 BIT(3)
+#define TCU_TMR_FMASK2 BIT(2)
+#define TCU_TMR_FMASK1 BIT(1)
+#define TCU_TMR_FMASK0 BIT(0)
+
+#define TCU_TMSR_HMST5 BIT(21)
+#define TCU_TMSR_HMST4 BIT(20)
+#define TCU_TMSR_HMST3 BIT(19)
+#define TCU_TMSR_HMST2 BIT(18)
+#define TCU_TMSR_HMST1 BIT(17)
+#define TCU_TMSR_HMST0 BIT(16)
+#define TCU_TMSR_FMST5 BIT(5)
+#define TCU_TMSR_FMST4 BIT(4)
+#define TCU_TMSR_FMST3 BIT(3)
+#define TCU_TMSR_FMST2 BIT(2)
+#define TCU_TMSR_FMST1 BIT(1)
+#define TCU_TMSR_FMST0 BIT(0)
+
+#define TCU_TMCR_HMCL5 BIT(21)
+#define TCU_TMCR_HMCL4 BIT(20)
+#define TCU_TMCR_HMCL3 BIT(19)
+#define TCU_TMCR_HMCL2 BIT(18)
+#define TCU_TMCR_HMCL1 BIT(17)
+#define TCU_TMCR_HMCL0 BIT(16)
+#define TCU_TMCR_FMCL5 BIT(5)
+#define TCU_TMCR_FMCL4 BIT(4)
+#define TCU_TMCR_FMCL3 BIT(3)
+#define TCU_TMCR_FMCL2 BIT(2)
+#define TCU_TMCR_FMCL1 BIT(1)
+#define TCU_TMCR_FMCL0 BIT(0)
+
+#define TCU_TSR_WDTS BIT(16)
+#define TCU_TSR_STOP5 BIT(5)
+#define TCU_TSR_STOP4 BIT(4)
+#define TCU_TSR_STOP3 BIT(3)
+#define TCU_TSR_STOP2 BIT(2)
+#define TCU_TSR_STOP1 BIT(1)
+#define TCU_TSR_STOP0 BIT(0)
+
+#define TCU_TSSR_WDTSS BIT(16)
+#define TCU_TSSR_STPS5 BIT(5)
+#define TCU_TSSR_STPS4 BIT(4)
+#define TCU_TSSR_STPS3 BIT(3)
+#define TCU_TSSR_STPS2 BIT(2)
+#define TCU_TSSR_STPS1 BIT(1)
+#define TCU_TSSR_STPS0 BIT(0)
+
+#define TCU_TSSR_WDTSC BIT(16)
+#define TCU_TSSR_STPC5 BIT(5)
+#define TCU_TSSR_STPC4 BIT(4)
+#define TCU_TSSR_STPC3 BIT(3)
+#define TCU_TSSR_STPC2 BIT(2)
+#define TCU_TSSR_STPC1 BIT(1)
+#define TCU_TSSR_STPC0 BIT(0)
+
+#define TER_OSTEN BIT(15)
+
+#define OSTCSR_CNT_MD BIT(15)
+#define OSTCSR_SD BIT(9)
+#define OSTCSR_PRESCALE_16 (0x2 << 3)
+#define OSTCSR_EXT_EN BIT(2)
+
+int timer_init(void)
+{
+ void __iomem *regs = (void __iomem *)TCU_BASE;
+
+ writel(OSTCSR_SD, regs + TCU_OSTCSR);
+ reset_timer();
+ writel(OSTCSR_CNT_MD | OSTCSR_EXT_EN | OSTCSR_PRESCALE_16,
+ regs + TCU_OSTCSR);
+ writew(TER_OSTEN, regs + TCU_TESR);
+ return 0;
+}
+
+void reset_timer(void)
+{
+ void __iomem *regs = (void __iomem *)TCU_BASE;
+
+ writel(0, regs + TCU_OSTCNTH);
+ writel(0, regs + TCU_OSTCNTL);
+}
+
+static u64 get_timer64(void)
+{
+ void __iomem *regs = (void __iomem *)TCU_BASE;
+ u32 low = readl(regs + TCU_OSTCNTL);
+ u32 high = readl(regs + TCU_OSTCNTHBUF);
+
+ return ((u64)high << 32) | low;
+}
+
+ulong get_timer(ulong base)
+{
+ return lldiv(get_timer64(), 3000) - base;
+}
+
+void __udelay(unsigned long usec)
+{
+ /* OST count increments at 3MHz */
+ u64 end = get_timer64() + ((u64)usec * 3);
+
+ while (get_timer64() < end)
+ ;
+}
+
+unsigned long long get_ticks(void)
+{
+ return get_timer64();
+}
+
+void jz4780_tcu_wdt_start(void)
+{
+ void __iomem *tcu_regs = (void __iomem *)TCU_BASE;
+
+ /* Enable WDT clock */
+ writel(TCU_TSSR_WDTSC, tcu_regs + TCU_TSCR);
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds b/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
new file mode 100644
index 0000000..347cabc
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+ LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+ LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ .text :
+ {
+ __image_copy_start = .;
+ arch/mips/mach-jz47xx/start.o (.text*)
+ *(.text*)
+ } >.sram
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+ . = ALIGN(4);
+ .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+ . = ALIGN(4);
+ __image_copy_end = .;
+
+ .bss : {
+ . = ALIGN(4);
+ __bss_start = .;
+ *(.sbss.*)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end = .;
+ } >.sdram
+
+ /DISCARD/ : {
+ *(.dynbss)
+ *(.dynstr)
+ *(.dynamic)
+ *(.interp)
+ *(.hash)
+ *(.gnu.*)
+ *(.plt)
+ *(.got.plt)
+ *(.rel.plt)
+ *(.rel.dyn)
+ }
+}
diff --git a/arch/mips/mach-jz47xx/start.S b/arch/mips/mach-jz47xx/start.S
new file mode 100644
index 0000000..760d021
--- /dev/null
+++ b/arch/mips/mach-jz47xx/start.S
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Startup Code for MIPS32 XBURST CPU-core
+ *
+ * Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
+ */
+
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+#include <asm/cache.h>
+#include <mach/jz4780.h>
+
+ .set noreorder
+
+ .globl _start
+ .text
+_start:
+#ifdef CONFIG_SPL_BUILD
+
+ /* magic value ("MSPL") */
+ .word 0x4d53504c
+
+ /* Invalidate BTB */
+ mfc0 t0, CP0_CONFIG, 7
+ nop
+ ori t0, 2
+ mtc0 t0, CP0_CONFIG, 7
+ nop
+
+ /*
+ * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
+ */
+ li t0, 0x0040FC04
+ mtc0 t0, CP0_STATUS
+
+ /* CAUSE register */
+ /* IV=1, use the specical interrupt vector (0x200) */
+ li t1, 0x00800000
+ mtc0 t1, CP0_CAUSE
+
+#ifdef CONFIG_SOC_JZ4780
+ /* enable bridge radical mode */
+ la t0, CPM_BASE
+ lw t1, 0x24(t0)
+ ori t1, t1, 0x22
+ sw t1, 0x24(t0)
+#endif
+
+ /* Set up stack */
+ li sp, CONFIG_SPL_STACK
+
+ b board_init_f
+ nop
+
+#ifdef CONFIG_SOC_JZ4780
+
+ .globl enable_caches
+ .ent enable_caches
+enable_caches:
+ mtc0 zero, CP0_TAGLO
+ mtc0 zero, CP0_TAGHI
+
+ li t0, KSEG0
+ addu t1, t0, CONFIG_SYS_DCACHE_SIZE
+1:
+ cache INDEX_STORE_TAG_D, 0(t0)
+ bne t0, t1, 1b
+ addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE
+
+ li t0, KSEG0
+ addu t1, t0, CONFIG_SYS_ICACHE_SIZE
+2:
+ cache INDEX_STORE_TAG_I, 0(t0)
+ bne t0, t1, 2b
+ addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE
+
+ /* Invalidate BTB */
+ mfc0 t0, CP0_CONFIG, 7
+ nop
+ ori t0, 2
+ mtc0 t0, CP0_CONFIG, 7
+ nop
+
+ /* Enable caches */
+ li t0, CONF_CM_CACHABLE_NONCOHERENT
+ mtc0 t0, CP0_CONFIG
+ nop
+
+ jr ra
+ nop
+
+ .end enable_caches
+
+#endif /* CONFIG_SOC_JZ4780 */
+#endif /* !CONFIG_SPL_BUILD */
diff --git a/arch/mips/mach-mscc/Kconfig b/arch/mips/mach-mscc/Kconfig
new file mode 100644
index 0000000..0e35b77
--- /dev/null
+++ b/arch/mips/mach-mscc/Kconfig
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+menu "MSCC VCore-III platforms"
+ depends on ARCH_MSCC
+
+config SOC_VCOREIII
+ select MIPS_TUNE_24KC
+ select ROM_EXCEPTION_VECTORS
+ select SUPPORTS_BIG_ENDIAN
+ select SUPPORTS_CPU_MIPS32_R1
+ select SUPPORTS_CPU_MIPS32_R2
+ select SUPPORTS_LITTLE_ENDIAN
+ bool
+
+config SYS_SOC
+ default "mscc"
+
+config SOC_OCELOT
+ bool
+ select SOC_VCOREIII
+ help
+ This supports MSCC Ocelot family of SOCs.
+
+config SOC_LUTON
+ bool
+ select SOC_VCOREIII
+ help
+ This supports MSCC Luton family of SOCs.
+
+config SYS_CONFIG_NAME
+ default "vcoreiii"
+
+choice
+ prompt "Board select"
+
+config TARGET_OCELOT_PCB120
+ bool "MSCC PCB120 Reference Board (aka VSC5635EV)"
+ select SOC_OCELOT
+ help
+ When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
+ ocelot_pcb120
+
+config TARGET_OCELOT_PCB123
+ bool "MSCC PCB123 Reference Board (aka VSC7514EV))"
+ select SOC_OCELOT
+ help
+ When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
+ ocelot_pcb123
+
+config TARGET_LUTON_PCB091
+ bool "MSCC PCB091 Reference Board"
+ select SOC_LUTON
+ select MSCC_BITBANG_SPI_GPIO
+ help
+ When selected, CONFIG_DEFAULT_DEVICE_TREE should be set to
+ luton_pcb091
+endchoice
+
+choice
+ prompt "DDR type"
+
+config DDRTYPE_H5TQ4G63MFR
+ bool "Hynix H5TQ4G63MFR-PBC (4Gbit, DDR3-800, 256Mbitx16)"
+
+config DDRTYPE_MT41K256M16
+ bool "Micron MT41K256M16 (4Gbit, DDR3L-800, 256Mbitx16)"
+
+config DDRTYPE_H5TQ1G63BFA
+ bool "Hynix H5TQ1G63BFA (1Gbit DDR3, x16)"
+
+config DDRTYPE_MT41J128M16HA
+ bool "Micron MT41J128M16HA-15E:D (2Gbit DDR3, x16)"
+
+config DDRTYPE_MT41K128M16JT
+ bool "Micron MT41K128M16JT-125 (2Gbit DDR3L, 128Mbitx16)"
+
+config DDRTYPE_MT47H128M8HQ
+ bool "Micron MT47H128M8-3 (1Gbit, DDR-533@CL4 @ 4.80ns 16Mbisx8x8)"
+
+endchoice
+
+source "board/mscc/ocelot/Kconfig"
+
+source "board/mscc/luton/Kconfig"
+
+endmenu
diff --git a/arch/mips/mach-mscc/Makefile b/arch/mips/mach-mscc/Makefile
new file mode 100644
index 0000000..6c60f26
--- /dev/null
+++ b/arch/mips/mach-mscc/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+CFLAGS_cpu.o += -finline-limit=64000
+
+obj-y += cpu.o dram.o reset.o lowlevel_init.o
+obj-$(CONFIG_SOC_LUTON) += lowlevel_init_luton.o
diff --git a/arch/mips/mach-mscc/cpu.c b/arch/mips/mach-mscc/cpu.c
new file mode 100644
index 0000000..5be8ff6
--- /dev/null
+++ b/arch/mips/mach-mscc/cpu.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+#include <asm/types.h>
+
+#include <mach/tlb.h>
+#include <mach/ddr.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if CONFIG_SYS_SDRAM_SIZE <= SZ_64M
+#define MSCC_RAM_TLB_SIZE SZ_64M
+#define MSCC_ATTRIB2 MMU_REGIO_INVAL
+#elif CONFIG_SYS_SDRAM_SIZE <= SZ_128M
+#define MSCC_RAM_TLB_SIZE SZ_64M
+#define MSCC_ATTRIB2 MMU_REGIO_RW
+#elif CONFIG_SYS_SDRAM_SIZE <= SZ_256M
+#define MSCC_RAM_TLB_SIZE SZ_256M
+#define MSCC_ATTRIB2 MMU_REGIO_INVAL
+#elif CONFIG_SYS_SDRAM_SIZE <= SZ_512M
+#define MSCC_RAM_TLB_SIZE SZ_256M
+#define MSCC_ATTRIB2 MMU_REGIO_RW
+#else
+#define MSCC_RAM_TLB_SIZE SZ_512M
+#define MSCC_ATTRIB2 MMU_REGIO_RW
+#endif
+
+/* NOTE: lowlevel_init() function does not have access to the
+ * stack. Thus, all called functions must be inlined, and (any) local
+ * variables must be kept in registers.
+ */
+void vcoreiii_tlb_init(void)
+{
+ register int tlbix = 0;
+
+ /*
+ * Unlike most of the MIPS based SoCs, the IO register address
+ * are not in KSEG0. The mainline linux kernel built in legacy
+ * mode needs to access some of the registers very early in
+ * the boot and make the assumption that the bootloader has
+ * already configured them, so we have to match this
+ * expectation.
+ */
+ create_tlb(tlbix++, MSCC_IO_ORIGIN1_OFFSET, SZ_16M, MMU_REGIO_RW,
+ MMU_REGIO_RW);
+#ifdef CONFIG_SOC_LUTON
+ create_tlb(tlbix++, MSCC_IO_ORIGIN2_OFFSET, SZ_16M, MMU_REGIO_RW,
+ MMU_REGIO_RW);
+#endif
+
+#if CONFIG_SYS_TEXT_BASE == MSCC_FLASH_TO
+ /*
+ * If U-Boot is located in NOR then we want to be able to use
+ * the data cache in order to boot in a decent duration
+ */
+ create_tlb(tlbix++, MSCC_FLASH_TO, SZ_16M, MMU_REGIO_RO_C,
+ MMU_REGIO_RO_C);
+ create_tlb(tlbix++, MSCC_FLASH_TO + SZ_32M, SZ_16M, MMU_REGIO_RO_C,
+ MMU_REGIO_RO_C);
+
+ /*
+ * Using cache for RAM also helps to improve boot time. Thanks
+ * to this the time to relocate U-Boot in RAM went from 2.092
+ * secs to 0.104 secs.
+ */
+ create_tlb(tlbix++, MSCC_DDR_TO, MSCC_RAM_TLB_SIZE, MMU_REGIO_RW,
+ MSCC_ATTRIB2);
+
+ /* Enable caches by clearing the bit ERL, which is set on reset */
+ write_c0_status(read_c0_status() & ~BIT(2));
+#endif /* CONFIG_SYS_TEXT_BASE */
+}
+
+int mach_cpu_init(void)
+{
+ /* Speed up NOR flash access */
+#ifdef CONFIG_SOC_LUTON
+ writel(ICPU_PI_MST_CFG_TRISTATE_CTRL +
+ ICPU_PI_MST_CFG_CLK_DIV(4), BASE_CFG + ICPU_PI_MST_CFG);
+
+ writel(ICPU_SPI_MST_CFG_FAST_READ_ENA +
+ ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
+ ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
+#else
+ writel(ICPU_SPI_MST_CFG_CS_DESELECT_TIME(0x19) +
+ ICPU_SPI_MST_CFG_CLK_DIV(9), BASE_CFG + ICPU_SPI_MST_CFG);
+ /*
+ * Legacy and mainline linux kernel expect that the
+ * interruption map was set as it was done by redboot.
+ */
+ writel(~0, BASE_CFG + ICPU_DST_INTR_MAP(0));
+ writel(0, BASE_CFG + ICPU_DST_INTR_MAP(1));
+ writel(0, BASE_CFG + ICPU_DST_INTR_MAP(2));
+ writel(0, BASE_CFG + ICPU_DST_INTR_MAP(3));
+#endif
+ return 0;
+}
diff --git a/arch/mips/mach-mscc/dram.c b/arch/mips/mach-mscc/dram.c
new file mode 100644
index 0000000..309007c
--- /dev/null
+++ b/arch/mips/mach-mscc/dram.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+#include <asm/types.h>
+
+#include <mach/tlb.h>
+#include <mach/ddr.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static inline int vcoreiii_train_bytelane(void)
+{
+ int ret;
+
+ ret = hal_vcoreiii_train_bytelane(0);
+
+#ifdef CONFIG_SOC_OCELOT
+ if (ret)
+ return ret;
+ ret = hal_vcoreiii_train_bytelane(1);
+#endif
+
+ return ret;
+}
+
+int vcoreiii_ddr_init(void)
+{
+ int res;
+
+ if (!(readl(BASE_CFG + ICPU_MEMCTRL_STAT)
+ & ICPU_MEMCTRL_STAT_INIT_DONE)) {
+ hal_vcoreiii_init_memctl();
+ hal_vcoreiii_wait_memctl();
+ if (hal_vcoreiii_init_dqs() || vcoreiii_train_bytelane())
+ hal_vcoreiii_ddr_failed();
+ }
+#if (CONFIG_SYS_TEXT_BASE != 0x20000000)
+ res = dram_check();
+ if (res == 0)
+ hal_vcoreiii_ddr_verified();
+ else
+ hal_vcoreiii_ddr_failed();
+
+ /* Clear boot-mode and read-back to activate/verify */
+ clrbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
+ ICPU_GENERAL_CTRL_BOOT_MODE_ENA);
+ readl(BASE_CFG + ICPU_GENERAL_CTRL);
+#else
+ res = 0;
+#endif
+ return res;
+}
+
+int print_cpuinfo(void)
+{
+ printf("MSCC VCore-III MIPS 24Kec\n");
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ while (vcoreiii_ddr_init())
+ ;
+
+ gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+ return 0;
+}
diff --git a/arch/mips/mach-mscc/include/ioremap.h b/arch/mips/mach-mscc/include/ioremap.h
new file mode 100644
index 0000000..9024364
--- /dev/null
+++ b/arch/mips/mach-mscc/include/ioremap.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef __ASM_MACH_MSCC_IOREMAP_H
+#define __ASM_MACH_MSCC_IOREMAP_H
+
+#include <linux/types.h>
+#include <mach/common.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr,
+ phys_addr_t size)
+{
+ return phys_addr;
+}
+
+static inline int is_vcoreiii_internal_registers(phys_addr_t offset)
+{
+ if ((offset >= MSCC_IO_ORIGIN1_OFFSET &&
+ offset < (MSCC_IO_ORIGIN1_OFFSET + MSCC_IO_ORIGIN1_SIZE)) ||
+ (offset >= MSCC_IO_ORIGIN2_OFFSET &&
+ offset < (MSCC_IO_ORIGIN2_OFFSET + MSCC_IO_ORIGIN2_SIZE)))
+ return 1;
+
+ return 0;
+}
+
+static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
+ unsigned long flags)
+{
+ if (is_vcoreiii_internal_registers(offset))
+ return (void __iomem *)offset;
+
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return is_vcoreiii_internal_registers((unsigned long)addr);
+}
+
+#define _page_cachable_default _CACHE_CACHABLE_NONCOHERENT
+
+#endif /* __ASM_MACH_MSCC_IOREMAP_H */
diff --git a/arch/mips/mach-mscc/include/mach/common.h b/arch/mips/mach-mscc/include/mach/common.h
new file mode 100644
index 0000000..931ecd7
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/common.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef __ASM_MACH_COMMON_H
+#define __ASM_MACH_COMMON_H
+
+#if defined(CONFIG_SOC_OCELOT)
+#include <mach/ocelot/ocelot.h>
+#include <mach/ocelot/ocelot_devcpu_gcb.h>
+#include <mach/ocelot/ocelot_icpu_cfg.h>
+#elif defined(CONFIG_SOC_LUTON)
+#include <mach/luton/luton.h>
+#include <mach/luton/luton_devcpu_gcb.h>
+#include <mach/luton/luton_icpu_cfg.h>
+#else
+#error Unsupported platform
+#endif
+
+#define MSCC_DDR_TO 0x20000000 /* DDR RAM base offset */
+#define MSCC_MEMCTL1_TO 0x40000000 /* SPI/PI base offset */
+#define MSCC_MEMCTL2_TO 0x50000000 /* SPI/PI base offset */
+#define MSCC_FLASH_TO MSCC_MEMCTL1_TO /* Flash base offset */
+
+#define VCOREIII_TIMER_DIVIDER 25 /* Clock tick ~ 0.1 us */
+
+#endif /* __ASM_MACH_COMMON_H */
diff --git a/arch/mips/mach-mscc/include/mach/ddr.h b/arch/mips/mach-mscc/include/mach/ddr.h
new file mode 100644
index 0000000..f445e63
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/ddr.h
@@ -0,0 +1,814 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef __ASM_MACH_DDR_H
+#define __ASM_MACH_DDR_H
+
+#include <asm/cacheops.h>
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <mach/common.h>
+
+#define MIPS_VCOREIII_MEMORY_DDR3
+#define MIPS_VCOREIII_DDR_SIZE CONFIG_SYS_SDRAM_SIZE
+
+#if defined(CONFIG_DDRTYPE_H5TQ1G63BFA) /* Serval1 Refboard */
+
+/* Hynix H5TQ1G63BFA (1Gbit DDR3, x16) @ 3.20ns */
+#define VC3_MPAR_bank_addr_cnt 3
+#define VC3_MPAR_row_addr_cnt 13
+#define VC3_MPAR_col_addr_cnt 10
+#define VC3_MPAR_tREFI 2437
+#define VC3_MPAR_tRAS_min 12
+#define VC3_MPAR_CL 6
+#define VC3_MPAR_tWTR 4
+#define VC3_MPAR_tRC 16
+#define VC3_MPR_tFAW 16
+#define VC3_MPAR_tRP 5
+#define VC3_MPAR_tRRD 4
+#define VC3_MPAR_tRCD 5
+#define VC3_MPAR_tMRD 4
+#define VC3_MPAR_tRFC 35
+#define VC3_MPAR_CWL 5
+#define VC3_MPAR_tXPR 38
+#define VC3_MPAR_tMOD 12
+#define VC3_MPAR_tDLLK 512
+#define VC3_MPAR_tWR 5
+
+#elif defined(CONFIG_DDRTYPE_MT41J128M16HA) /* Validation board */
+
+/* Micron MT41J128M16HA-15E:D (2Gbit DDR3, x16) @ 3.20ns */
+#define VC3_MPAR_bank_addr_cnt 3
+#define VC3_MPAR_row_addr_cnt 14
+#define VC3_MPAR_col_addr_cnt 10
+#define VC3_MPAR_tREFI 2437
+#define VC3_MPAR_tRAS_min 12
+#define VC3_MPAR_CL 5
+#define VC3_MPAR_tWTR 4
+#define VC3_MPAR_tRC 16
+#define VC3_MPAR_tFAW 16
+#define VC3_MPAR_tRP 5
+#define VC3_MPAR_tRRD 4
+#define VC3_MPAR_tRCD 5
+#define VC3_MPAR_tMRD 4
+#define VC3_MPAR_tRFC 50
+#define VC3_MPAR_CWL 5
+#define VC3_MPAR_tXPR 54
+#define VC3_MPAR_tMOD 12
+#define VC3_MPAR_tDLLK 512
+#define VC3_MPAR_tWR 5
+
+#elif defined(CONFIG_DDRTYPE_MT41K256M16) /* JR2 Validation board */
+
+/* Micron MT41K256M16 (4Gbit, DDR3L-800, 256Mbitx16) @ 3.20ns */
+#define VC3_MPAR_bank_addr_cnt 3
+#define VC3_MPAR_row_addr_cnt 15
+#define VC3_MPAR_col_addr_cnt 10
+#define VC3_MPAR_tREFI 2437
+#define VC3_MPAR_tRAS_min 12
+#define VC3_MPAR_CL 5
+#define VC3_MPAR_tWTR 4
+#define VC3_MPAR_tRC 16
+#define VC3_MPAR_tFAW 16
+#define VC3_MPAR_tRP 5
+#define VC3_MPAR_tRRD 4
+#define VC3_MPAR_tRCD 5
+#define VC3_MPAR_tMRD 4
+#define VC3_MPAR_tRFC 82
+#define VC3_MPAR_CWL 5
+#define VC3_MPAR_tXPR 85
+#define VC3_MPAR_tMOD 12
+#define VC3_MPAR_tDLLK 512
+#define VC3_MPAR_tWR 5
+
+#elif defined(CONFIG_DDRTYPE_H5TQ4G63MFR) /* JR2 Reference board */
+
+/* Hynix H5TQ4G63MFR-PBC (4Gbit, DDR3-800, 256Mbitx16) - 2kb pages @ 3.20ns */
+#define VC3_MPAR_bank_addr_cnt 3
+#define VC3_MPAR_row_addr_cnt 15
+#define VC3_MPAR_col_addr_cnt 10
+#define VC3_MPAR_tREFI 2437
+#define VC3_MPAR_tRAS_min 12
+#define VC3_MPAR_CL 6
+#define VC3_MPAR_tWTR 4
+#define VC3_MPAR_tRC 17
+#define VC3_MPAR_tFAW 16
+#define VC3_MPAR_tRP 5
+#define VC3_MPAR_tRRD 4
+#define VC3_MPAR_tRCD 5
+#define VC3_MPAR_tMRD 4
+#define VC3_MPAR_tRFC 82
+#define VC3_MPAR_CWL 5
+#define VC3_MPAR_tXPR 85
+#define VC3_MPAR_tMOD 12
+#define VC3_MPAR_tDLLK 512
+#define VC3_MPAR_tWR 5
+
+#elif defined(CONFIG_DDRTYPE_MT41K128M16JT)
+
+/* Micron Micron MT41K128M16JT-125 (2Gbit DDR3L, 128Mbitx16) @ 3.20ns */
+#define VC3_MPAR_bank_addr_cnt 3
+#define VC3_MPAR_row_addr_cnt 14
+#define VC3_MPAR_col_addr_cnt 10
+#define VC3_MPAR_tREFI 2437
+#define VC3_MPAR_tRAS_min 12
+#define VC3_MPAR_CL 6
+#define VC3_MPAR_tWTR 4
+#define VC3_MPAR_tRC 16
+#define VC3_MPAR_tFAW 16
+#define VC3_MPAR_tRP 5
+#define VC3_MPAR_tRRD 4
+#define VC3_MPAR_tRCD 5
+#define VC3_MPAR_tMRD 4
+#define VC3_MPAR_tRFC 82
+#define VC3_MPAR_CWL 5
+#define VC3_MPAR_tXPR 85
+#define VC3_MPAR_tMOD 12
+#define VC3_MPAR_tDLLK 512
+#define VC3_MPAR_tWR 5
+
+#elif defined(CONFIG_DDRTYPE_MT47H128M8HQ) /* Luton10/26 Refboards */
+
+/* Micron 1Gb MT47H128M8-3 16Meg x 8 x 8 banks, DDR-533@CL4 @ 4.80ns */
+#define VC3_MPAR_bank_addr_cnt 3
+#define VC3_MPAR_row_addr_cnt 14
+#define VC3_MPAR_col_addr_cnt 10
+#define VC3_MPAR_tREFI 1625
+#define VC3_MPAR_tRAS_min 9
+#define VC3_MPAR_CL 4
+#define VC3_MPAR_tWTR 2
+#define VC3_MPAR_tRC 12
+#define VC3_MPAR_tFAW 8
+#define VC3_MPAR_tRP 4
+#define VC3_MPAR_tRRD 2
+#define VC3_MPAR_tRCD 4
+
+#define VC3_MPAR_tRPA 4
+#define VC3_MPAR_tRP 4
+
+#define VC3_MPAR_tMRD 2
+#define VC3_MPAR_tRFC 27
+
+#define VC3_MPAR__400_ns_dly 84
+
+#define VC3_MPAR_tWR 4
+#undef MIPS_VCOREIII_MEMORY_DDR3
+#else
+
+#error Unknown DDR system configuration - please add!
+
+#endif
+
+#ifdef CONFIG_SOC_OCELOT
+#define MIPS_VCOREIII_MEMORY_16BIT 1
+#endif
+
+#define MIPS_VCOREIII_MEMORY_SSTL_ODT 7
+#define MIPS_VCOREIII_MEMORY_SSTL_DRIVE 7
+#define VCOREIII_DDR_DQS_MODE_CALIBRATE
+
+#ifdef MIPS_VCOREIII_MEMORY_16BIT
+#define VC3_MPAR_16BIT 1
+#else
+#define VC3_MPAR_16BIT 0
+#endif
+
+#ifdef MIPS_VCOREIII_MEMORY_DDR3
+#define VC3_MPAR_DDR3_MODE 1 /* DDR3 */
+#define VC3_MPAR_BURST_LENGTH 8 /* Always 8 (1) for DDR3 */
+#ifdef MIPS_VCOREIII_MEMORY_16BIT
+#define VC3_MPAR_BURST_SIZE 1 /* Always 1 for DDR3/16bit */
+#else
+#define VC3_MPAR_BURST_SIZE 0
+#endif
+#else
+#define VC3_MPAR_DDR3_MODE 0 /* DDR2 */
+#ifdef MIPS_VCOREIII_MEMORY_16BIT
+#define VC3_MPAR_BURST_LENGTH 4 /* in DDR2 16-bit mode, use burstlen 4 */
+#else
+#define VC3_MPAR_BURST_LENGTH 8 /* For 8-bit IF we must run burst-8 */
+#endif
+#define VC3_MPAR_BURST_SIZE 0 /* Always 0 for DDR2 */
+#endif
+
+#define VC3_MPAR_RL VC3_MPAR_CL
+#if !defined(MIPS_VCOREIII_MEMORY_DDR3)
+#define VC3_MPAR_WL (VC3_MPAR_RL - 1)
+#define VC3_MPAR_MD VC3_MPAR_tMRD
+#define VC3_MPAR_ID VC3_MPAR__400_ns_dly
+#define VC3_MPAR_SD VC3_MPAR_tXSRD
+#define VC3_MPAR_OW (VC3_MPAR_WL - 2)
+#define VC3_MPAR_OR (VC3_MPAR_WL - 3)
+#define VC3_MPAR_RP (VC3_MPAR_bank_addr_cnt < 3 ? VC3_MPAR_tRP : VC3_MPAR_tRPA)
+#define VC3_MPAR_FAW (VC3_MPAR_bank_addr_cnt < 3 ? 1 : VC3_MPAR_tFAW)
+#define VC3_MPAR_BL (VC3_MPAR_BURST_LENGTH == 4 ? 2 : 4)
+#define MSCC_MEMPARM_MR0 \
+ (VC3_MPAR_BURST_LENGTH == 8 ? 3 : 2) | (VC3_MPAR_CL << 4) | \
+ ((VC3_MPAR_tWR - 1) << 9)
+/* DLL-on, Full-OD, AL=0, RTT=off, nDQS-on, RDQS-off, out-en */
+#define MSCC_MEMPARM_MR1 0x382
+#define MSCC_MEMPARM_MR2 0
+#define MSCC_MEMPARM_MR3 0
+#else
+#define VC3_MPAR_WL VC3_MPAR_CWL
+#define VC3_MPAR_MD VC3_MPAR_tMOD
+#define VC3_MPAR_ID VC3_MPAR_tXPR
+#define VC3_MPAR_SD VC3_MPAR_tDLLK
+#define VC3_MPAR_OW 2
+#define VC3_MPAR_OR 2
+#define VC3_MPAR_RP VC3_MPAR_tRP
+#define VC3_MPAR_FAW VC3_MPAR_tFAW
+#define VC3_MPAR_BL 4
+#define MSCC_MEMPARM_MR0 ((VC3_MPAR_RL - 4) << 4) | ((VC3_MPAR_tWR - 4) << 9)
+/* ODT_RTT: “0x0040” for 120ohm, and “0x0004” for 60ohm. */
+#define MSCC_MEMPARM_MR1 0x0040
+#define MSCC_MEMPARM_MR2 ((VC3_MPAR_WL - 5) << 3)
+#define MSCC_MEMPARM_MR3 0
+#endif /* MIPS_VCOREIII_MEMORY_DDR3 */
+
+#define MSCC_MEMPARM_MEMCFG \
+ ((MIPS_VCOREIII_DDR_SIZE > SZ_512M) ? \
+ ICPU_MEMCTRL_CFG_DDR_512MBYTE_PLUS : 0) | \
+ (VC3_MPAR_16BIT ? ICPU_MEMCTRL_CFG_DDR_WIDTH : 0) | \
+ (VC3_MPAR_DDR3_MODE ? ICPU_MEMCTRL_CFG_DDR_MODE : 0) | \
+ (VC3_MPAR_BURST_SIZE ? ICPU_MEMCTRL_CFG_BURST_SIZE : 0) | \
+ (VC3_MPAR_BURST_LENGTH == 8 ? ICPU_MEMCTRL_CFG_BURST_LEN : 0) | \
+ (VC3_MPAR_bank_addr_cnt == 3 ? ICPU_MEMCTRL_CFG_BANK_CNT : 0) | \
+ ICPU_MEMCTRL_CFG_MSB_ROW_ADDR(VC3_MPAR_row_addr_cnt - 1) | \
+ ICPU_MEMCTRL_CFG_MSB_COL_ADDR(VC3_MPAR_col_addr_cnt - 1)
+
+#ifdef CONFIG_SOC_OCELOT
+#define MSCC_MEMPARM_PERIOD \
+ ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(8) | \
+ ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(VC3_MPAR_tREFI)
+
+#define MSCC_MEMPARM_TIMING0 \
+ ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY(VC3_MPAR_RL + VC3_MPAR_BL + 1 - \
+ VC3_MPAR_WL) | \
+ ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY(VC3_MPAR_BL - 1) | \
+ ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY(VC3_MPAR_BL) | \
+ ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY(VC3_MPAR_tRAS_min - 1) | \
+ ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY(VC3_MPAR_WL + \
+ VC3_MPAR_BL + \
+ VC3_MPAR_tWR - 1) | \
+ ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY(VC3_MPAR_BL - 1) | \
+ ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY(VC3_MPAR_WL - 1) | \
+ ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY(VC3_MPAR_RL - 3)
+
+#define MSCC_MEMPARM_TIMING1 \
+ ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY(VC3_MPAR_tRC - 1) | \
+ ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY(VC3_MPAR_FAW - 1) | \
+ ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY(VC3_MPAR_RP - 1) | \
+ ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY(VC3_MPAR_tRRD - 1) | \
+ ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY(VC3_MPAR_tRCD - 1) | \
+ ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY(VC3_MPAR_WL + \
+ VC3_MPAR_BL + \
+ VC3_MPAR_tWTR - 1)
+
+#define MSCC_MEMPARM_TIMING2 \
+ ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY(VC3_MPAR_RP - 1) | \
+ ICPU_MEMCTRL_TIMING2_MDSET_DLY(VC3_MPAR_MD - 1) | \
+ ICPU_MEMCTRL_TIMING2_REF_DLY(VC3_MPAR_tRFC - 1) | \
+ ICPU_MEMCTRL_TIMING2_INIT_DLY(VC3_MPAR_ID - 1)
+
+#define MSCC_MEMPARM_TIMING3 \
+ ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY(VC3_MPAR_WL + \
+ VC3_MPAR_tWTR - 1) |\
+ ICPU_MEMCTRL_TIMING3_ODT_RD_DLY(VC3_MPAR_OR - 1) | \
+ ICPU_MEMCTRL_TIMING3_ODT_WR_DLY(VC3_MPAR_OW - 1) | \
+ ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY(VC3_MPAR_RL - 3)
+
+#else
+#define MSCC_MEMPARM_PERIOD \
+ ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(1) | \
+ ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(VC3_MPAR_tREFI)
+
+#define MSCC_MEMPARM_TIMING0 \
+ ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY(VC3_MPAR_tRAS_min - 1) | \
+ ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY(VC3_MPAR_CL + \
+ (VC3_MPAR_BURST_LENGTH == 8 ? 2 : 0) + \
+ VC3_MPAR_tWR) | \
+ ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY(VC3_MPAR_BURST_LENGTH == 8 ? 3 : 1) | \
+ ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY(VC3_MPAR_CL - 3) | \
+ ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY(VC3_MPAR_CL - 3)
+
+#define MSCC_MEMPARM_TIMING1 \
+ ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY(VC3_MPAR_tRC - 1) | \
+ ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY(VC3_MPAR_tFAW - 1) | \
+ ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY(VC3_MPAR_tRP - 1) | \
+ ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY(VC3_MPAR_tRRD - 1) | \
+ ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY(VC3_MPAR_tRCD - 1) | \
+ ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY(VC3_MPAR_CL + \
+ (VC3_MPAR_BURST_LENGTH == 8 ? 2 : 0) + \
+ VC3_MPAR_tWTR)
+#define MSCC_MEMPARM_TIMING2 \
+ ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY(VC3_MPAR_tRPA - 1) | \
+ ICPU_MEMCTRL_TIMING2_MDSET_DLY(VC3_MPAR_tMRD - 1) | \
+ ICPU_MEMCTRL_TIMING2_REF_DLY(VC3_MPAR_tRFC - 1) | \
+ ICPU_MEMCTRL_TIMING2_FOUR_HUNDRED_NS_DLY(VC3_MPAR__400_ns_dly)
+
+#define MSCC_MEMPARM_TIMING3 \
+ ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY(VC3_MPAR_CL - 1) | \
+ ICPU_MEMCTRL_TIMING3_ODT_WR_DLY(VC3_MPAR_CL - 1) | \
+ ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY(VC3_MPAR_CL - 1)
+
+#endif
+
+enum {
+ DDR_TRAIN_OK,
+ DDR_TRAIN_CONTINUE,
+ DDR_TRAIN_ERROR,
+};
+
+/*
+ * We actually have very few 'pause' possibilities apart from
+ * these assembly nops (at this very early stage).
+ */
+#define PAUSE() asm volatile("nop; nop; nop; nop; nop; nop; nop; nop")
+
+/* NB: Assumes inlining as no stack is available! */
+static inline void set_dly(u32 bytelane, u32 dly)
+{
+ register u32 r = readl(BASE_CFG + ICPU_MEMCTRL_DQS_DLY(bytelane));
+
+ r &= ~ICPU_MEMCTRL_DQS_DLY_DQS_DLY_M;
+ r |= ICPU_MEMCTRL_DQS_DLY_DQS_DLY(dly);
+ writel(r, BASE_CFG + ICPU_MEMCTRL_DQS_DLY(bytelane));
+}
+
+static inline bool incr_dly(u32 bytelane)
+{
+ register u32 r = readl(BASE_CFG + ICPU_MEMCTRL_DQS_DLY(bytelane));
+
+ if (ICPU_MEMCTRL_DQS_DLY_DQS_DLY(r) < 31) {
+ writel(r + 1, BASE_CFG + ICPU_MEMCTRL_DQS_DLY(bytelane));
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool adjust_dly(int adjust)
+{
+ register u32 r = readl(BASE_CFG + ICPU_MEMCTRL_DQS_DLY(0));
+
+ if (ICPU_MEMCTRL_DQS_DLY_DQS_DLY(r) < 31) {
+ writel(r + adjust, BASE_CFG + ICPU_MEMCTRL_DQS_DLY(0));
+ return true;
+ }
+
+ return false;
+}
+
+/* NB: Assumes inlining as no stack is available! */
+static inline void center_dly(u32 bytelane, u32 start)
+{
+ register u32 r = readl(BASE_CFG + ICPU_MEMCTRL_DQS_DLY(bytelane)) - start;
+
+ writel(start + (r >> 1), BASE_CFG + ICPU_MEMCTRL_DQS_DLY(bytelane));
+}
+
+static inline void memphy_soft_reset(void)
+{
+ setbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_FIFO_RST);
+ PAUSE();
+ clrbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_FIFO_RST);
+ PAUSE();
+}
+
+#ifdef CONFIG_SOC_OCELOT
+static u8 training_data[] = { 0xfe, 0x11, 0x33, 0x55, 0x77, 0x99, 0xbb, 0xdd };
+
+static inline void sleep_100ns(u32 val)
+{
+ /* Set the timer tick generator to 100 ns */
+ writel(VCOREIII_TIMER_DIVIDER - 1, BASE_CFG + ICPU_TIMER_TICK_DIV);
+
+ /* Set the timer value */
+ writel(val, BASE_CFG + ICPU_TIMER_VALUE(0));
+
+ /* Enable timer 0 for one-shot */
+ writel(ICPU_TIMER_CTRL_ONE_SHOT_ENA | ICPU_TIMER_CTRL_TIMER_ENA,
+ BASE_CFG + ICPU_TIMER_CTRL(0));
+
+ /* Wait for timer 0 to reach 0 */
+ while (readl(BASE_CFG + ICPU_TIMER_VALUE(0)) != 0)
+ ;
+}
+
+static inline void hal_vcoreiii_ddr_reset_assert(void)
+{
+ /* DDR has reset pin on GPIO 19 toggle Low-High to release */
+ setbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
+ writel(BIT(19), BASE_DEVCPU_GCB + PERF_GPIO_OUT_CLR);
+ sleep_100ns(10000);
+}
+
+static inline void hal_vcoreiii_ddr_reset_release(void)
+{
+ /* DDR has reset pin on GPIO 19 toggle Low-High to release */
+ setbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
+ writel(BIT(19), BASE_DEVCPU_GCB + PERF_GPIO_OUT_SET);
+ sleep_100ns(10000);
+}
+
+/*
+ * DDR memory sanity checking failed, tally and do hard reset
+ *
+ * NB: Assumes inlining as no stack is available!
+ */
+static inline void hal_vcoreiii_ddr_failed(void)
+{
+ register u32 reset;
+
+ writel(readl(BASE_CFG + ICPU_GPR(6)) + 1, BASE_CFG + ICPU_GPR(6));
+
+ clrbits_le32(BASE_DEVCPU_GCB + PERF_GPIO_OE, BIT(19));
+
+ /* We have to execute the reset function from cache. Indeed,
+ * the reboot workaround in _machine_restart() will change the
+ * SPI NOR into SW bitbang.
+ *
+ * This will render the CPU unable to execute directly from
+ * the NOR, which is why the reset instructions are prefetched
+ * into the I-cache.
+ *
+ * When failing the DDR initialization we are executing from
+ * NOR.
+ *
+ * The last instruction in _machine_restart() will reset the
+ * MIPS CPU (and the cache), and the CPU will start executing
+ * from the reset vector.
+ */
+ reset = KSEG0ADDR(_machine_restart);
+ icache_lock((void *)reset, 128);
+ asm volatile ("jr %0"::"r" (reset));
+
+ panic("DDR init failed\n");
+}
+
+/*
+ * DDR memory sanity checking done, possibly enable ECC.
+ *
+ * NB: Assumes inlining as no stack is available!
+ */
+static inline void hal_vcoreiii_ddr_verified(void)
+{
+#ifdef MIPS_VCOREIII_MEMORY_ECC
+ /* Finally, enable ECC */
+ register u32 val = readl(BASE_CFG + ICPU_MEMCTRL_CFG);
+
+ val |= ICPU_MEMCTRL_CFG_DDR_ECC_ERR_ENA;
+ val &= ~ICPU_MEMCTRL_CFG_BURST_SIZE;
+
+ writel(val, BASE_CFG + ICPU_MEMCTRL_CFG);
+#endif
+
+ /* Reset Status register - sticky bits */
+ writel(readl(BASE_CFG + ICPU_MEMCTRL_STAT), BASE_CFG + ICPU_MEMCTRL_STAT);
+}
+
+/* NB: Assumes inlining as no stack is available! */
+static inline int look_for(u32 bytelane)
+{
+ register u32 i;
+
+ /* Reset FIFO in case any previous access failed */
+ for (i = 0; i < sizeof(training_data); i++) {
+ register u32 byte;
+
+ memphy_soft_reset();
+ /* Reset sticky bits */
+ writel(readl(BASE_CFG + ICPU_MEMCTRL_STAT),
+ BASE_CFG + ICPU_MEMCTRL_STAT);
+ /* Read data */
+ byte = __raw_readb((void __iomem *)MSCC_DDR_TO + bytelane +
+ (i * 4));
+
+ /*
+ * Prevent the compiler reordering the instruction so
+ * the read of RAM happens after the check of the
+ * errors.
+ */
+ rmb();
+ if (readl(BASE_CFG + ICPU_MEMCTRL_STAT) &
+ (ICPU_MEMCTRL_STAT_RDATA_MASKED |
+ ICPU_MEMCTRL_STAT_RDATA_DUMMY)) {
+ /* Noise on the line */
+ goto read_error;
+ }
+ /* If mismatch, increment DQS - if possible */
+ if (byte != training_data[i]) {
+ read_error:
+ if (!incr_dly(bytelane))
+ return DDR_TRAIN_ERROR;
+ return DDR_TRAIN_CONTINUE;
+ }
+ }
+ return DDR_TRAIN_OK;
+}
+
+/* NB: Assumes inlining as no stack is available! */
+static inline int look_past(u32 bytelane)
+{
+ register u32 i;
+
+ /* Reset FIFO in case any previous access failed */
+ for (i = 0; i < sizeof(training_data); i++) {
+ register u32 byte;
+
+ memphy_soft_reset();
+ /* Ack sticky bits */
+ writel(readl(BASE_CFG + ICPU_MEMCTRL_STAT),
+ BASE_CFG + ICPU_MEMCTRL_STAT);
+ byte = __raw_readb((void __iomem *)MSCC_DDR_TO + bytelane +
+ (i * 4));
+ /*
+ * Prevent the compiler reordering the instruction so
+ * the read of RAM happens after the check of the
+ * errors.
+ */
+ rmb();
+ if (readl(BASE_CFG + ICPU_MEMCTRL_STAT) &
+ (ICPU_MEMCTRL_STAT_RDATA_MASKED |
+ ICPU_MEMCTRL_STAT_RDATA_DUMMY)) {
+ /* Noise on the line */
+ goto read_error;
+ }
+ /* Bail out when we see first mismatch */
+ if (byte != training_data[i]) {
+ read_error:
+ return DDR_TRAIN_OK;
+ }
+ }
+ /* All data compares OK, increase DQS and retry */
+ if (!incr_dly(bytelane))
+ return DDR_TRAIN_ERROR;
+
+ return DDR_TRAIN_CONTINUE;
+}
+
+static inline int hal_vcoreiii_train_bytelane(u32 bytelane)
+{
+ register int res;
+ register u32 dqs_s;
+
+ set_dly(bytelane, 0); /* Start training at DQS=0 */
+ while ((res = look_for(bytelane)) == DDR_TRAIN_CONTINUE)
+ ;
+ if (res != DDR_TRAIN_OK)
+ return res;
+
+ dqs_s = readl(BASE_CFG + ICPU_MEMCTRL_DQS_DLY(bytelane));
+ while ((res = look_past(bytelane)) == DDR_TRAIN_CONTINUE)
+ ;
+ if (res != DDR_TRAIN_OK)
+ return res;
+ /* Reset FIFO - for good measure */
+ memphy_soft_reset();
+ /* Adjust to center [dqs_s;cur] */
+ center_dly(bytelane, dqs_s);
+ return DDR_TRAIN_OK;
+}
+
+/* This algorithm is converted from the TCL training algorithm used
+ * during silicon simulation.
+ * NB: Assumes inlining as no stack is available!
+ */
+static inline int hal_vcoreiii_init_dqs(void)
+{
+#define MAX_DQS 32
+ register u32 i, j;
+
+ for (i = 0; i < MAX_DQS; i++) {
+ set_dly(0, i); /* Byte-lane 0 */
+ for (j = 0; j < MAX_DQS; j++) {
+ __maybe_unused register u32 byte;
+
+ set_dly(1, j); /* Byte-lane 1 */
+ /* Reset FIFO in case any previous access failed */
+ memphy_soft_reset();
+ writel(readl(BASE_CFG + ICPU_MEMCTRL_STAT),
+ BASE_CFG + ICPU_MEMCTRL_STAT);
+ byte = __raw_readb((void __iomem *)MSCC_DDR_TO);
+ byte = __raw_readb((void __iomem *)(MSCC_DDR_TO + 1));
+ if (!(readl(BASE_CFG + ICPU_MEMCTRL_STAT) &
+ (ICPU_MEMCTRL_STAT_RDATA_MASKED |
+ ICPU_MEMCTRL_STAT_RDATA_DUMMY)))
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static inline int dram_check(void)
+{
+ register u32 i;
+
+ for (i = 0; i < 8; i++) {
+ __raw_writel(~i, (void __iomem *)(MSCC_DDR_TO + (i * 4)));
+ if (__raw_readl((void __iomem *)(MSCC_DDR_TO + (i * 4))) != ~i)
+ return 1;
+ }
+ return 0;
+}
+#else /* Luton */
+
+static inline void sleep_100ns(u32 val)
+{
+}
+
+static inline void hal_vcoreiii_ddr_reset_assert(void)
+{
+ setbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_RST);
+ setbits_le32(BASE_CFG + ICPU_RESET, ICPU_RESET_MEM_RST_FORCE);
+}
+
+static inline void hal_vcoreiii_ddr_reset_release(void)
+{
+}
+
+static inline void hal_vcoreiii_ddr_failed(void)
+{
+ register u32 memphy_cfg = readl(BASE_CFG + ICPU_MEMPHY_CFG);
+
+ /* Do a fifo reset and start over */
+ writel(memphy_cfg | ICPU_MEMPHY_CFG_PHY_FIFO_RST,
+ BASE_CFG + ICPU_MEMPHY_CFG);
+ writel(memphy_cfg & ~ICPU_MEMPHY_CFG_PHY_FIFO_RST,
+ BASE_CFG + ICPU_MEMPHY_CFG);
+ writel(memphy_cfg | ICPU_MEMPHY_CFG_PHY_FIFO_RST,
+ BASE_CFG + ICPU_MEMPHY_CFG);
+}
+
+static inline void hal_vcoreiii_ddr_verified(void)
+{
+}
+
+static inline int look_for(u32 data)
+{
+ register u32 byte = __raw_readb((void __iomem *)MSCC_DDR_TO);
+
+ if (data != byte) {
+ if (!incr_dly(0))
+ return DDR_TRAIN_ERROR;
+ return DDR_TRAIN_CONTINUE;
+ }
+
+ return DDR_TRAIN_OK;
+}
+
+/* This algorithm is converted from the TCL training algorithm used
+ * during silicon simulation.
+ * NB: Assumes inlining as no stack is available!
+ */
+static inline int hal_vcoreiii_train_bytelane(u32 bytelane)
+{
+ register int res;
+
+ set_dly(bytelane, 0); /* Start training at DQS=0 */
+ while ((res = look_for(0xff)) == DDR_TRAIN_CONTINUE)
+ ;
+ if (res != DDR_TRAIN_OK)
+ return res;
+
+ set_dly(bytelane, 0); /* Start training at DQS=0 */
+ while ((res = look_for(0x00)) == DDR_TRAIN_CONTINUE)
+
+ ;
+
+ if (res != DDR_TRAIN_OK)
+ return res;
+
+ adjust_dly(-3);
+
+ return DDR_TRAIN_OK;
+}
+
+static inline int hal_vcoreiii_init_dqs(void)
+{
+ return 0;
+}
+
+static inline int dram_check(void)
+{
+ register u32 i;
+
+ for (i = 0; i < 8; i++) {
+ __raw_writel(~i, (void __iomem *)(MSCC_DDR_TO + (i * 4)));
+
+ if (__raw_readl((void __iomem *)(MSCC_DDR_TO + (i * 4))) != ~i)
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+/*
+ * NB: Called *early* to init memory controller - assumes inlining as
+ * no stack is available!
+ */
+static inline void hal_vcoreiii_init_memctl(void)
+{
+ /* Ensure DDR is in reset */
+ hal_vcoreiii_ddr_reset_assert();
+
+ /* Wait maybe not needed, but ... */
+ PAUSE();
+
+ /* Drop sys ctl memory controller forced reset */
+ clrbits_le32(BASE_CFG + ICPU_RESET, ICPU_RESET_MEM_RST_FORCE);
+
+ PAUSE();
+
+ /* Drop Reset, enable SSTL */
+ writel(ICPU_MEMPHY_CFG_PHY_SSTL_ENA, BASE_CFG + ICPU_MEMPHY_CFG);
+ PAUSE();
+
+ /* Start the automatic SSTL output and ODT drive-strength calibration */
+ writel(ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT(MIPS_VCOREIII_MEMORY_SSTL_ODT) |
+ /* drive strength */
+ ICPU_MEMPHY_ZCAL_ZCAL_PROG(MIPS_VCOREIII_MEMORY_SSTL_DRIVE) |
+ /* Start calibration process */
+ ICPU_MEMPHY_ZCAL_ZCAL_ENA, BASE_CFG + ICPU_MEMPHY_ZCAL);
+
+ /* Wait for ZCAL to clear */
+ while (readl(BASE_CFG + ICPU_MEMPHY_ZCAL) & ICPU_MEMPHY_ZCAL_ZCAL_ENA)
+ ;
+#ifdef CONFIG_SOC_OCELOT
+ /* Check no ZCAL_ERR */
+ if (readl(BASE_CFG + ICPU_MEMPHY_ZCAL_STAT)
+ & ICPU_MEMPHY_ZCAL_STAT_ZCAL_ERR)
+ hal_vcoreiii_ddr_failed();
+#endif
+ /* Drive CL, CK, ODT */
+ setbits_le32(BASE_CFG + ICPU_MEMPHY_CFG, ICPU_MEMPHY_CFG_PHY_ODT_OE |
+ ICPU_MEMPHY_CFG_PHY_CK_OE | ICPU_MEMPHY_CFG_PHY_CL_OE);
+
+ /* Initialize memory controller */
+ writel(MSCC_MEMPARM_MEMCFG, BASE_CFG + ICPU_MEMCTRL_CFG);
+ writel(MSCC_MEMPARM_PERIOD, BASE_CFG + ICPU_MEMCTRL_REF_PERIOD);
+
+#ifdef CONFIG_SOC_OCELOT
+ writel(MSCC_MEMPARM_TIMING0, BASE_CFG + ICPU_MEMCTRL_TIMING0);
+#else /* Luton */
+ clrbits_le32(BASE_CFG + ICPU_MEMCTRL_TIMING0, ((1 << 20) - 1));
+ setbits_le32(BASE_CFG + ICPU_MEMCTRL_TIMING0, MSCC_MEMPARM_TIMING0);
+#endif
+
+ writel(MSCC_MEMPARM_TIMING1, BASE_CFG + ICPU_MEMCTRL_TIMING1);
+ writel(MSCC_MEMPARM_TIMING2, BASE_CFG + ICPU_MEMCTRL_TIMING2);
+ writel(MSCC_MEMPARM_TIMING3, BASE_CFG + ICPU_MEMCTRL_TIMING3);
+ writel(MSCC_MEMPARM_MR0, BASE_CFG + ICPU_MEMCTRL_MR0_VAL);
+ writel(MSCC_MEMPARM_MR1, BASE_CFG + ICPU_MEMCTRL_MR1_VAL);
+ writel(MSCC_MEMPARM_MR2, BASE_CFG + ICPU_MEMCTRL_MR2_VAL);
+ writel(MSCC_MEMPARM_MR3, BASE_CFG + ICPU_MEMCTRL_MR3_VAL);
+
+#ifdef CONFIG_SOC_OCELOT
+ /* Termination setup - enable ODT */
+ writel(ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA |
+ /* Assert ODT0 for any write */
+ ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA(3),
+ BASE_CFG + ICPU_MEMCTRL_TERMRES_CTRL);
+
+ /* Release Reset from DDR */
+ hal_vcoreiii_ddr_reset_release();
+
+ writel(readl(BASE_CFG + ICPU_GPR(7)) + 1, BASE_CFG + ICPU_GPR(7));
+#else /* Luton */
+ /* Termination setup - disable ODT */
+ writel(0, BASE_CFG + ICPU_MEMCTRL_TERMRES_CTRL);
+
+#endif
+}
+
+static inline void hal_vcoreiii_wait_memctl(void)
+{
+ /* Now, rip it! */
+ writel(ICPU_MEMCTRL_CTRL_INITIALIZE, BASE_CFG + ICPU_MEMCTRL_CTRL);
+
+ while (!(readl(BASE_CFG + ICPU_MEMCTRL_STAT)
+ & ICPU_MEMCTRL_STAT_INIT_DONE))
+ ;
+
+ /* Settle...? */
+ sleep_100ns(10000);
+#ifdef CONFIG_SOC_OCELOT
+ /* Establish data contents in DDR RAM for training */
+
+ __raw_writel(0xcacafefe, ((void __iomem *)MSCC_DDR_TO));
+ __raw_writel(0x22221111, ((void __iomem *)MSCC_DDR_TO + 0x4));
+ __raw_writel(0x44443333, ((void __iomem *)MSCC_DDR_TO + 0x8));
+ __raw_writel(0x66665555, ((void __iomem *)MSCC_DDR_TO + 0xC));
+ __raw_writel(0x88887777, ((void __iomem *)MSCC_DDR_TO + 0x10));
+ __raw_writel(0xaaaa9999, ((void __iomem *)MSCC_DDR_TO + 0x14));
+ __raw_writel(0xccccbbbb, ((void __iomem *)MSCC_DDR_TO + 0x18));
+ __raw_writel(0xeeeedddd, ((void __iomem *)MSCC_DDR_TO + 0x1C));
+#else
+ __raw_writel(0xff, ((void __iomem *)MSCC_DDR_TO));
+#endif
+}
+#endif /* __ASM_MACH_DDR_H */
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton.h b/arch/mips/mach-mscc/include/mach/luton/luton.h
new file mode 100644
index 0000000..19f02ed
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/luton/luton.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_H_
+#define _MSCC_OCELOT_H_
+
+#include <linux/bitops.h>
+#include <dm.h>
+
+/*
+ * Target offset base(s)
+ */
+#define MSCC_IO_ORIGIN1_OFFSET 0x60000000
+#define MSCC_IO_ORIGIN1_SIZE 0x01000000
+#define MSCC_IO_ORIGIN2_OFFSET 0x70000000
+#define MSCC_IO_ORIGIN2_SIZE 0x00200000
+#define BASE_CFG ((void __iomem *)0x70000000)
+#define BASE_DEVCPU_GCB ((void __iomem *)0x60070000)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
new file mode 100644
index 0000000..8c0b612
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/luton/luton_devcpu_gcb.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_DEVCPU_GCB_H_
+#define _MSCC_OCELOT_DEVCPU_GCB_H_
+
+#define PERF_SOFT_RST 0x90
+
+#define PERF_SOFT_RST_SOFT_SWC_RST BIT(1)
+#define PERF_SOFT_RST_SOFT_CHIP_RST BIT(0)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h b/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
new file mode 100644
index 0000000..9233f03
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/luton/luton_icpu_cfg.h
@@ -0,0 +1,245 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_ICPU_CFG_H_
+#define _MSCC_OCELOT_ICPU_CFG_H_
+
+#define ICPU_GPR(x) (0x4 * (x))
+#define ICPU_GPR_RSZ 0x4
+
+#define ICPU_RESET 0x20
+
+#define ICPU_RESET_CORE_RST_CPU_ONLY BIT(3)
+#define ICPU_RESET_CORE_RST_PROTECT BIT(2)
+#define ICPU_RESET_CORE_RST_FORCE BIT(1)
+#define ICPU_RESET_MEM_RST_FORCE BIT(0)
+
+#define ICPU_GENERAL_CTRL 0x24
+
+#define ICPU_GENERAL_CTRL_SWC_CLEAR_IF BIT(6)
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_SLEEP_DIS BIT(5)
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_WERR_ENA BIT(4)
+#define ICPU_GENERAL_CTRL_IF_MASTER_DIS BIT(3)
+#define ICPU_GENERAL_CTRL_IF_MASTER_SPI_ENA BIT(2)
+#define ICPU_GENERAL_CTRL_IF_MASTER_PI_ENA BIT(1)
+
+#define ICPU_GENERAL_CTRL_BOOT_MODE_ENA BIT(0)
+
+#define ICPU_PI_MST_CFG 0x2c
+
+#define ICPU_PI_MST_CFG_ATE_MODE_DIS BIT(7)
+#define ICPU_PI_MST_CFG_CLK_POL BIT(6)
+#define ICPU_PI_MST_CFG_TRISTATE_CTRL BIT(5)
+#define ICPU_PI_MST_CFG_CLK_DIV(x) ((x) & GENMASK(4, 0))
+#define ICPU_PI_MST_CFG_CLK_DIV_M GENMASK(4, 0)
+
+#define ICPU_SPI_MST_CFG 0x50
+
+#define ICPU_SPI_MST_CFG_FAST_READ_ENA BIT(10)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME(x) (((x) << 5) & GENMASK(9, 5))
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_M GENMASK(9, 5)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_X(x) (((x) & GENMASK(9, 5)) >> 5)
+#define ICPU_SPI_MST_CFG_CLK_DIV(x) ((x) & GENMASK(4, 0))
+#define ICPU_SPI_MST_CFG_CLK_DIV_M GENMASK(4, 0)
+
+#define ICPU_SW_MODE 0x64
+
+#define ICPU_SW_MODE_SW_PIN_CTRL_MODE BIT(13)
+#define ICPU_SW_MODE_SW_SPI_SCK BIT(12)
+#define ICPU_SW_MODE_SW_SPI_SCK_OE BIT(11)
+#define ICPU_SW_MODE_SW_SPI_SDO BIT(10)
+#define ICPU_SW_MODE_SW_SPI_SDO_OE BIT(9)
+#define ICPU_SW_MODE_SW_SPI_CS(x) (((x) << 5) & GENMASK(8, 5))
+#define ICPU_SW_MODE_SW_SPI_CS_M GENMASK(8, 5)
+#define ICPU_SW_MODE_SW_SPI_CS_X(x) (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_SW_MODE_SW_SPI_CS_OE(x) (((x) << 1) & GENMASK(4, 1))
+#define ICPU_SW_MODE_SW_SPI_CS_OE_M GENMASK(4, 1)
+#define ICPU_SW_MODE_SW_SPI_CS_OE_X(x) (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_SW_MODE_SW_SPI_SDI BIT(0)
+
+#define ICPU_INTR_ENA 0x88
+
+#define ICPU_INTR_IRQ0_ENA 0x98
+#define ICPU_INTR_IRQ0_ENA_IRQ0_ENA BIT(0)
+
+#define ICPU_MEMCTRL_CTRL 0x234
+
+#define ICPU_MEMCTRL_CTRL_PWR_DOWN BIT(3)
+#define ICPU_MEMCTRL_CTRL_MDSET BIT(2)
+#define ICPU_MEMCTRL_CTRL_STALL_REF_ENA BIT(1)
+#define ICPU_MEMCTRL_CTRL_INITIALIZE BIT(0)
+
+#define ICPU_MEMCTRL_CFG 0x238
+
+#define ICPU_MEMCTRL_CFG_DDR_512MBYTE_PLUS BIT(16)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ERR_ENA BIT(15)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_COR_ENA BIT(14)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ENA BIT(13)
+#define ICPU_MEMCTRL_CFG_DDR_WIDTH BIT(12)
+#define ICPU_MEMCTRL_CFG_DDR_MODE BIT(11)
+#define ICPU_MEMCTRL_CFG_BURST_SIZE BIT(10)
+#define ICPU_MEMCTRL_CFG_BURST_LEN BIT(9)
+#define ICPU_MEMCTRL_CFG_BANK_CNT BIT(8)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_STAT 0x23C
+
+#define ICPU_MEMCTRL_STAT_RDATA_MASKED BIT(5)
+#define ICPU_MEMCTRL_STAT_RDATA_DUMMY BIT(4)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_ERR BIT(3)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_COR BIT(2)
+#define ICPU_MEMCTRL_STAT_PWR_DOWN_ACK BIT(1)
+#define ICPU_MEMCTRL_STAT_INIT_DONE BIT(0)
+
+#define ICPU_MEMCTRL_REF_PERIOD 0x240
+
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(x) (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_M GENMASK(19, 16)
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(x) ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD_M GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_TIMING0 0x248
+
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY(x) (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_M GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_X(x) (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY(x) (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_M GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_X(x) (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY(x) (((x) << 20) & GENMASK(23, 20))
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_M GENMASK(23, 20)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_X(x) (((x) & GENMASK(23, 20)) >> 20)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY(x) (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_M GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY(x) (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_M GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_X(x) (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY(x) (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_M GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_X(x) (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING1 0x24c
+
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY(x) (((x) << 24) & GENMASK(31, 24))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_M GENMASK(31, 24)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_X(x) (((x) & GENMASK(31, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY(x) (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_M GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_X(x) (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY(x) (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_M GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_X(x) (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY(x) (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_M GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_X(x) (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING2 0x250
+
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY(x) (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_M GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_X(x) (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY(x) (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_M GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_X(x) (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY(x) (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_M GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_X(x) (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING2_FOUR_HUNDRED_NS_DLY(x) ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_TIMING2_FOUR_HUNDRED_NS_DLY_M GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_TIMING3 0x254
+
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY(x) (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_M GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY(x) (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_M GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_X(x) (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY(x) (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_M GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_X(x) (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_MR0_VAL 0x258
+
+#define ICPU_MEMCTRL_MR1_VAL 0x25c
+
+#define ICPU_MEMCTRL_MR2_VAL 0x260
+
+#define ICPU_MEMCTRL_MR3_VAL 0x264
+
+#define ICPU_MEMCTRL_TERMRES_CTRL 0x268
+
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_EXT BIT(11)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA(x) (((x) << 7) & GENMASK(10, 7))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_M GENMASK(10, 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_X(x) (((x) & GENMASK(10, 7)) >> 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_EXT BIT(6)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA(x) (((x) << 2) & GENMASK(5, 2))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_M GENMASK(5, 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_X(x) (((x) & GENMASK(5, 2)) >> 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_EXT BIT(1)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA BIT(0)
+
+#define ICPU_MEMCTRL_DQS_DLY(x) (0x270)
+
+#define ICPU_MEMCTRL_DQS_DLY_TRAIN_DQ_ENA BIT(11)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1(x) (((x) << 8) & GENMASK(10, 8))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_M GENMASK(10, 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_X(x) (((x) & GENMASK(10, 8)) >> 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0(x) (((x) << 5) & GENMASK(7, 5))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_M GENMASK(7, 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_X(x) (((x) & GENMASK(7, 5)) >> 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY(x) ((x) & GENMASK(4, 0))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_M GENMASK(4, 0)
+
+#define ICPU_MEMPHY_CFG 0x278
+
+#define ICPU_MEMPHY_CFG_PHY_FLUSH_DIS BIT(10)
+#define ICPU_MEMPHY_CFG_PHY_RD_ADJ_DIS BIT(9)
+#define ICPU_MEMPHY_CFG_PHY_DQS_EXT BIT(8)
+#define ICPU_MEMPHY_CFG_PHY_FIFO_RST BIT(7)
+#define ICPU_MEMPHY_CFG_PHY_DLL_BL_RST BIT(6)
+#define ICPU_MEMPHY_CFG_PHY_DLL_CL_RST BIT(5)
+#define ICPU_MEMPHY_CFG_PHY_ODT_OE BIT(4)
+#define ICPU_MEMPHY_CFG_PHY_CK_OE BIT(3)
+#define ICPU_MEMPHY_CFG_PHY_CL_OE BIT(2)
+#define ICPU_MEMPHY_CFG_PHY_SSTL_ENA BIT(1)
+#define ICPU_MEMPHY_CFG_PHY_RST BIT(0)
+#define ICPU_MEMPHY_DQ_DLY_TRM 0x180
+#define ICPU_MEMPHY_DQ_DLY_TRM_RSZ 0x4
+
+#define ICPU_MEMPHY_ZCAL 0x294
+
+#define ICPU_MEMPHY_ZCAL_ZCAL_CLK_SEL BIT(9)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT(x) (((x) << 5) & GENMASK(8, 5))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_M GENMASK(8, 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_X(x) (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG(x) (((x) << 1) & GENMASK(4, 1))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_M GENMASK(4, 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_X(x) (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_ENA BIT(0)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/ocelot/ocelot.h b/arch/mips/mach-mscc/include/mach/ocelot/ocelot.h
new file mode 100644
index 0000000..2cb2135
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/ocelot/ocelot.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_H_
+#define _MSCC_OCELOT_H_
+
+#include <linux/bitops.h>
+#include <dm.h>
+
+/*
+ * Target offset base(s)
+ */
+#define MSCC_IO_ORIGIN1_OFFSET 0x70000000
+#define MSCC_IO_ORIGIN1_SIZE 0x00200000
+#define MSCC_IO_ORIGIN2_OFFSET 0x71000000
+#define MSCC_IO_ORIGIN2_SIZE 0x01000000
+#define BASE_CFG ((void __iomem *)0x70000000)
+#define BASE_DEVCPU_GCB ((void __iomem *)0x71070000)
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h
new file mode 100644
index 0000000..f8aa97b
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_devcpu_gcb.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_DEVCPU_GCB_H_
+#define _MSCC_OCELOT_DEVCPU_GCB_H_
+
+#define PERF_SOFT_RST 0x8
+
+#define PERF_SOFT_RST_SOFT_NON_CFG_RST BIT(2)
+#define PERF_SOFT_RST_SOFT_SWC_RST BIT(1)
+#define PERF_SOFT_RST_SOFT_CHIP_RST BIT(0)
+
+#define PERF_GPIO_OUT_SET 0x34
+
+#define PERF_GPIO_OUT_CLR 0x38
+
+#define PERF_GPIO_OE 0x44
+
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/ocelot/ocelot_icpu_cfg.h b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_icpu_cfg.h
new file mode 100644
index 0000000..04cf70b
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/ocelot/ocelot_icpu_cfg.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_ICPU_CFG_H_
+#define _MSCC_OCELOT_ICPU_CFG_H_
+
+#define ICPU_GPR(x) (0x4 * (x))
+#define ICPU_GPR_RSZ 0x4
+
+#define ICPU_RESET 0x20
+
+#define ICPU_RESET_CORE_RST_CPU_ONLY BIT(3)
+#define ICPU_RESET_CORE_RST_PROTECT BIT(2)
+#define ICPU_RESET_CORE_RST_FORCE BIT(1)
+#define ICPU_RESET_MEM_RST_FORCE BIT(0)
+
+#define ICPU_GENERAL_CTRL 0x24
+
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_SLEEP_DIS BIT(14)
+#define ICPU_GENERAL_CTRL_CPU_BUSIF_WERR_ENA BIT(13)
+#define ICPU_GENERAL_CTRL_CPU_8051_IROM_ENA BIT(12)
+#define ICPU_GENERAL_CTRL_CPU_MIPS_DIS BIT(11)
+#define ICPU_GENERAL_CTRL_IF_MIIM_SLV_ADDR_SEL BIT(10)
+#define ICPU_GENERAL_CTRL_IF_MIIM_SLV_ENA BIT(9)
+#define ICPU_GENERAL_CTRL_IF_PI_SLV_DONEPOL BIT(8)
+#define ICPU_GENERAL_CTRL_IF_PI_MST_ENA BIT(7)
+#define ICPU_GENERAL_CTRL_IF_PI_SLV_ENA BIT(6)
+#define ICPU_GENERAL_CTRL_IF_SI_OWNER(x) (((x) << 4) & GENMASK(5, 4))
+#define ICPU_GENERAL_CTRL_IF_SI_OWNER_M GENMASK(5, 4)
+#define ICPU_GENERAL_CTRL_IF_SI_OWNER_X(x) (((x) & GENMASK(5, 4)) >> 4)
+#define ICPU_GENERAL_CTRL_SSI_MST_CONTENTION BIT(3)
+#define ICPU_GENERAL_CTRL_CPU_BE_ENA BIT(2)
+#define ICPU_GENERAL_CTRL_CPU_DIS BIT(1)
+#define ICPU_GENERAL_CTRL_BOOT_MODE_ENA BIT(0)
+#define ICPU_SPI_MST_CFG 0x3c
+
+#define ICPU_SPI_MST_CFG_A32B_ENA BIT(11)
+#define ICPU_SPI_MST_CFG_FAST_READ_ENA BIT(10)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME(x) (((x) << 5) & GENMASK(9, 5))
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_M GENMASK(9, 5)
+#define ICPU_SPI_MST_CFG_CS_DESELECT_TIME_X(x) (((x) & GENMASK(9, 5)) >> 5)
+#define ICPU_SPI_MST_CFG_CLK_DIV(x) ((x) & GENMASK(4, 0))
+#define ICPU_SPI_MST_CFG_CLK_DIV_M GENMASK(4, 0)
+
+#define ICPU_SW_MODE 0x50
+
+#define ICPU_SW_MODE_SW_PIN_CTRL_MODE BIT(13)
+#define ICPU_SW_MODE_SW_SPI_SCK BIT(12)
+#define ICPU_SW_MODE_SW_SPI_SCK_OE BIT(11)
+#define ICPU_SW_MODE_SW_SPI_SDO BIT(10)
+#define ICPU_SW_MODE_SW_SPI_SDO_OE BIT(9)
+#define ICPU_SW_MODE_SW_SPI_CS(x) (((x) << 5) & GENMASK(8, 5))
+#define ICPU_SW_MODE_SW_SPI_CS_M GENMASK(8, 5)
+#define ICPU_SW_MODE_SW_SPI_CS_X(x) (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_SW_MODE_SW_SPI_CS_OE(x) (((x) << 1) & GENMASK(4, 1))
+#define ICPU_SW_MODE_SW_SPI_CS_OE_M GENMASK(4, 1)
+#define ICPU_SW_MODE_SW_SPI_CS_OE_X(x) (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_SW_MODE_SW_SPI_SDI BIT(0)
+
+#define ICPU_INTR_ENA 0x88
+
+#define ICPU_DST_INTR_MAP(x) (0x98 + 0x4 * (x))
+#define ICPU_DST_INTR_MAP_RSZ 0x4
+
+#define ICPU_DST_INTR_IDENT 0xa8
+#define ICPU_DST_INTR_IDENT_RSZ 0x4
+
+#define ICPU_TIMER_TICK_DIV 0xe8
+#define ICPU_TIMER_VALUE(x) (0xec + 0x4 * (x))
+
+#define ICPU_TIMER_CTRL(x) (0x104 + 0x4 * (x))
+#define ICPU_TIMER_CTRL_MAX_FREQ_ENA BIT(3)
+#define ICPU_TIMER_CTRL_ONE_SHOT_ENA BIT(2)
+#define ICPU_TIMER_CTRL_TIMER_ENA BIT(1)
+#define ICPU_TIMER_CTRL_FORCE_RELOAD BIT(0)
+
+#define ICPU_MEMCTRL_CTRL 0x110
+#define ICPU_MEMCTRL_CTRL_PWR_DOWN BIT(3)
+#define ICPU_MEMCTRL_CTRL_MDSET BIT(2)
+#define ICPU_MEMCTRL_CTRL_STALL_REF_ENA BIT(1)
+#define ICPU_MEMCTRL_CTRL_INITIALIZE BIT(0)
+
+#define ICPU_MEMCTRL_CFG 0x114
+
+#define ICPU_MEMCTRL_CFG_DDR_512MBYTE_PLUS BIT(16)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ERR_ENA BIT(15)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_COR_ENA BIT(14)
+#define ICPU_MEMCTRL_CFG_DDR_ECC_ENA BIT(13)
+#define ICPU_MEMCTRL_CFG_DDR_WIDTH BIT(12)
+#define ICPU_MEMCTRL_CFG_DDR_MODE BIT(11)
+#define ICPU_MEMCTRL_CFG_BURST_SIZE BIT(10)
+#define ICPU_MEMCTRL_CFG_BURST_LEN BIT(9)
+#define ICPU_MEMCTRL_CFG_BANK_CNT BIT(8)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_CFG_MSB_ROW_ADDR_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_CFG_MSB_COL_ADDR_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_STAT 0x118
+
+#define ICPU_MEMCTRL_STAT_RDATA_MASKED BIT(5)
+#define ICPU_MEMCTRL_STAT_RDATA_DUMMY BIT(4)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_ERR BIT(3)
+#define ICPU_MEMCTRL_STAT_RDATA_ECC_COR BIT(2)
+#define ICPU_MEMCTRL_STAT_PWR_DOWN_ACK BIT(1)
+#define ICPU_MEMCTRL_STAT_INIT_DONE BIT(0)
+
+#define ICPU_MEMCTRL_REF_PERIOD 0x11c
+
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF(x) (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_M GENMASK(19, 16)
+#define ICPU_MEMCTRL_REF_PERIOD_MAX_PEND_REF_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD(x) ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_REF_PERIOD_REF_PERIOD_M GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_TIMING0 0x124
+
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY(x) (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_M GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_WR_DLY_X(x) (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY(x) (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_M GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING0_WR_CS_CHANGE_DLY_X(x) (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY(x) (((x) << 20) & GENMASK(23, 20))
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_M GENMASK(23, 20)
+#define ICPU_MEMCTRL_TIMING0_RD_CS_CHANGE_DLY_X(x) (((x) & GENMASK(23, 20)) >> 20)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY(x) (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_M GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING0_RAS_TO_PRECH_DLY_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY(x) (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_M GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING0_WR_TO_PRECH_DLY_X(x) (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY(x) (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_M GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING0_RD_TO_PRECH_DLY_X(x) (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING0_WR_DATA_XFR_DLY_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING0_RD_DATA_XFR_DLY_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING1 0x128
+
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY(x) (((x) << 24) & GENMASK(31, 24))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_M GENMASK(31, 24)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_SAME_BANK_DLY_X(x) (((x) & GENMASK(31, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY(x) (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_M GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING1_BANK8_FAW_DLY_X(x) (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY(x) (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_M GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING1_PRECH_TO_RAS_DLY_X(x) (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY(x) (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_M GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_RAS_DLY_X(x) (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING1_RAS_TO_CAS_DLY_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING1_WR_TO_RD_DLY_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_TIMING2 0x12c
+
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY(x) (((x) << 28) & GENMASK(31, 28))
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_M GENMASK(31, 28)
+#define ICPU_MEMCTRL_TIMING2_PRECH_ALL_DLY_X(x) (((x) & GENMASK(31, 28)) >> 28)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY(x) (((x) << 24) & GENMASK(27, 24))
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_M GENMASK(27, 24)
+#define ICPU_MEMCTRL_TIMING2_MDSET_DLY_X(x) (((x) & GENMASK(27, 24)) >> 24)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY(x) (((x) << 16) & GENMASK(23, 16))
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_M GENMASK(23, 16)
+#define ICPU_MEMCTRL_TIMING2_REF_DLY_X(x) (((x) & GENMASK(23, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING2_INIT_DLY(x) ((x) & GENMASK(15, 0))
+#define ICPU_MEMCTRL_TIMING2_INIT_DLY_M GENMASK(15, 0)
+
+#define ICPU_MEMCTRL_TIMING3 0x130
+
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY(x) (((x) << 16) & GENMASK(19, 16))
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_M GENMASK(19, 16)
+#define ICPU_MEMCTRL_TIMING3_RMW_DLY_X(x) (((x) & GENMASK(19, 16)) >> 16)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY(x) (((x) << 12) & GENMASK(15, 12))
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_M GENMASK(15, 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_RD_DLY_X(x) (((x) & GENMASK(15, 12)) >> 12)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY(x) (((x) << 8) & GENMASK(11, 8))
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_M GENMASK(11, 8)
+#define ICPU_MEMCTRL_TIMING3_ODT_WR_DLY_X(x) (((x) & GENMASK(11, 8)) >> 8)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY(x) (((x) << 4) & GENMASK(7, 4))
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_M GENMASK(7, 4)
+#define ICPU_MEMCTRL_TIMING3_LOCAL_ODT_RD_DLY_X(x) (((x) & GENMASK(7, 4)) >> 4)
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY(x) ((x) & GENMASK(3, 0))
+#define ICPU_MEMCTRL_TIMING3_WR_TO_RD_CS_CHANGE_DLY_M GENMASK(3, 0)
+
+#define ICPU_MEMCTRL_MR0_VAL 0x138
+
+#define ICPU_MEMCTRL_MR1_VAL 0x13c
+
+#define ICPU_MEMCTRL_MR2_VAL 0x140
+
+#define ICPU_MEMCTRL_MR3_VAL 0x144
+
+#define ICPU_MEMCTRL_TERMRES_CTRL 0x148
+
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_EXT BIT(11)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA(x) (((x) << 7) & GENMASK(10, 7))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_M GENMASK(10, 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_RD_ENA_X(x) (((x) & GENMASK(10, 7)) >> 7)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_EXT BIT(6)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA(x) (((x) << 2) & GENMASK(5, 2))
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_M GENMASK(5, 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_ODT_WR_ENA_X(x) (((x) & GENMASK(5, 2)) >> 2)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_EXT BIT(1)
+#define ICPU_MEMCTRL_TERMRES_CTRL_LOCAL_ODT_RD_ENA BIT(0)
+
+#define ICPU_MEMCTRL_DQS_DLY(x) (0x150 + 0x4 * (x))
+#define ICPU_MEMCTRL_DQS_DLY_RSZ 0x4
+
+#define ICPU_MEMCTRL_DQS_DLY_TRAIN_DQ_ENA BIT(11)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1(x) (((x) << 8) & GENMASK(10, 8))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_M GENMASK(10, 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM1_X(x) (((x) & GENMASK(10, 8)) >> 8)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0(x) (((x) << 5) & GENMASK(7, 5))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_M GENMASK(7, 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_TRM0_X(x) (((x) & GENMASK(7, 5)) >> 5)
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY(x) ((x) & GENMASK(4, 0))
+#define ICPU_MEMCTRL_DQS_DLY_DQS_DLY_M GENMASK(4, 0)
+
+#define ICPU_MEMPHY_CFG 0x160
+
+#define ICPU_MEMPHY_CFG_PHY_FLUSH_DIS BIT(10)
+#define ICPU_MEMPHY_CFG_PHY_RD_ADJ_DIS BIT(9)
+#define ICPU_MEMPHY_CFG_PHY_DQS_EXT BIT(8)
+#define ICPU_MEMPHY_CFG_PHY_FIFO_RST BIT(7)
+#define ICPU_MEMPHY_CFG_PHY_DLL_BL_RST BIT(6)
+#define ICPU_MEMPHY_CFG_PHY_DLL_CL_RST BIT(5)
+#define ICPU_MEMPHY_CFG_PHY_ODT_OE BIT(4)
+#define ICPU_MEMPHY_CFG_PHY_CK_OE BIT(3)
+#define ICPU_MEMPHY_CFG_PHY_CL_OE BIT(2)
+#define ICPU_MEMPHY_CFG_PHY_SSTL_ENA BIT(1)
+#define ICPU_MEMPHY_CFG_PHY_RST BIT(0)
+
+#define ICPU_MEMPHY_ZCAL 0x188
+
+#define ICPU_MEMPHY_ZCAL_ZCAL_CLK_SEL BIT(9)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT(x) (((x) << 5) & GENMASK(8, 5))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_M GENMASK(8, 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_ODT_X(x) (((x) & GENMASK(8, 5)) >> 5)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG(x) (((x) << 1) & GENMASK(4, 1))
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_M GENMASK(4, 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_PROG_X(x) (((x) & GENMASK(4, 1)) >> 1)
+#define ICPU_MEMPHY_ZCAL_ZCAL_ENA BIT(0)
+
+#define ICPU_MEMPHY_ZCAL_STAT 0x18c
+
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ZCTRL(x) (((x) << 12) & GENMASK(31, 12))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ZCTRL_M GENMASK(31, 12)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ZCTRL_X(x) (((x) & GENMASK(31, 12)) >> 12)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPU(x) (((x) << 8) & GENMASK(9, 8))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPU_M GENMASK(9, 8)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPU_X(x) (((x) & GENMASK(9, 8)) >> 8)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPD(x) (((x) << 6) & GENMASK(7, 6))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPD_M GENMASK(7, 6)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_ODTPD_X(x) (((x) & GENMASK(7, 6)) >> 6)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PU(x) (((x) << 4) & GENMASK(5, 4))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PU_M GENMASK(5, 4)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PU_X(x) (((x) & GENMASK(5, 4)) >> 4)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PD(x) (((x) << 2) & GENMASK(3, 2))
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PD_M GENMASK(3, 2)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_STAT_PD_X(x) (((x) & GENMASK(3, 2)) >> 2)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_ERR BIT(1)
+#define ICPU_MEMPHY_ZCAL_STAT_ZCAL_DONE BIT(0)
+#endif
diff --git a/arch/mips/mach-mscc/include/mach/tlb.h b/arch/mips/mach-mscc/include/mach/tlb.h
new file mode 100644
index 0000000..fdb554f
--- /dev/null
+++ b/arch/mips/mach-mscc/include/mach/tlb.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef __ASM_MACH_TLB_H
+#define __ASM_MACH_TLB_H
+
+#include <asm/mipsregs.h>
+#include <mach/common.h>
+#include <linux/sizes.h>
+
+#define TLB_HI_MASK 0xffffe000
+#define TLB_LO_MASK 0x3fffffff /* Masks off Fill bits */
+#define TLB_LO_SHIFT 6 /* PFN Start bit */
+
+#define PAGEMASK_SHIFT 13
+
+#define MMU_PAGE_CACHED (3 << 3) /* C(5:3) Cache Coherency Attributes */
+#define MMU_PAGE_UNCACHED (2 << 3) /* C(5:3) Cache Coherency Attributes */
+#define MMU_PAGE_DIRTY BIT(2) /* = Writeable */
+#define MMU_PAGE_VALID BIT(1)
+#define MMU_PAGE_GLOBAL BIT(0)
+#define MMU_REGIO_RO_C (MMU_PAGE_CACHED | MMU_PAGE_VALID | MMU_PAGE_GLOBAL)
+#define MMU_REGIO_RO (MMU_PAGE_UNCACHED | MMU_PAGE_VALID | MMU_PAGE_GLOBAL)
+#define MMU_REGIO_RW (MMU_PAGE_DIRTY | MMU_REGIO_RO)
+#define MMU_REGIO_INVAL (MMU_PAGE_GLOBAL)
+
+#define TLB_COUNT_MASK GENMASK(5, 0)
+#define TLB_COUNT_OFF 25
+
+static inline u32 get_tlb_count(void)
+{
+ register u32 config1;
+
+ config1 = read_c0_config1();
+ config1 >>= TLB_COUNT_OFF;
+ config1 &= TLB_COUNT_MASK;
+
+ return 1 + config1;
+}
+
+static inline void create_tlb(int index, u32 offset, u32 size, u32 tlb_attrib1,
+ u32 tlb_attrib2)
+{
+ register u32 tlb_mask, tlb_lo0, tlb_lo1;
+
+ tlb_mask = ((size >> 12) - 1) << PAGEMASK_SHIFT;
+ tlb_lo0 = tlb_attrib1 | (offset >> TLB_LO_SHIFT);
+ tlb_lo1 = tlb_attrib2 | ((offset + size) >> TLB_LO_SHIFT);
+
+ write_one_tlb(index, tlb_mask, offset & TLB_HI_MASK,
+ tlb_lo0 & TLB_LO_MASK, tlb_lo1 & TLB_LO_MASK);
+}
+#endif /* __ASM_MACH_TLB_H */
diff --git a/arch/mips/mach-mscc/lowlevel_init.S b/arch/mips/mach-mscc/lowlevel_init.S
new file mode 100644
index 0000000..dfbe067
--- /dev/null
+++ b/arch/mips/mach-mscc/lowlevel_init.S
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+ .set noreorder
+ .extern vcoreiii_tlb_init
+#ifdef CONFIG_SOC_LUTON
+ .extern pll_init
+#endif
+
+LEAF(lowlevel_init)
+ /*
+ * As we have no stack yet, we can assume the restricted
+ * luxury of the sX-registers without saving them
+ */
+ move s0,ra
+
+ jal vcoreiii_tlb_init
+ nop
+#ifdef CONFIG_SOC_LUTON
+ jal pll_init
+ nop
+#endif
+ jr s0
+ nop
+ END(lowlevel_init)
diff --git a/arch/mips/mach-mscc/lowlevel_init_luton.S b/arch/mips/mach-mscc/lowlevel_init_luton.S
new file mode 100644
index 0000000..8a528fa
--- /dev/null
+++ b/arch/mips/mach-mscc/lowlevel_init_luton.S
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define BASE_MACRO 0x600a0000
+#define REG_OFFSET(t, o) (t + (o*4))
+#define REG_MACRO(x) REG_OFFSET(BASE_MACRO, x)
+#define BIT(nr) (1 << (nr))
+
+#define MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0 REG_MACRO(6)
+#define MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS BIT(0)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2 REG_MACRO(2)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0 REG_MACRO(0)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV (0x3F << 6)
+#define MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV_ENC(x) (x << 6)
+
+ .set noreorder
+LEAF(pll_init)
+ /* Make sure PLL is locked */
+ lw v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0
+ andi v1, v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS
+ bne v1, zero, 1f
+ nop
+
+ /* Black magic from frontend */
+ li v1, 0x00610400
+ sw v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+ li v1, 0x00610c00
+ sw v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+ li v1, 0x00610800
+ sw v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+ li v1, 0x00610000
+ sw v1, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG2
+
+ /* Wait for lock */
+2: lw v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0
+ andi v1, v0, MACRO_CTRL_PLL5G_STATUS_PLL5G_STATUS0_LOCK_STATUS
+ /* Keep looping if zero (no lock bit yet) */
+ beq v1, zero, 2b
+ nop
+
+ /* Setup PLL CPU clock divider for 416MHz */
+1: lw v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0
+
+ /* Keep reserved bits */
+ li v1, ~MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV
+ and v0, v0, v1
+
+ /* Set code 6 ~ 416.66 MHz */
+ ori v0, v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0_CPU_CLK_DIV_ENC(6)
+
+ sw v0, MACRO_CTRL_PLL5G_CFG_PLL5G_CFG0
+ jr ra
+ nop
+ END(pll_init)
diff --git a/arch/mips/mach-mscc/reset.c b/arch/mips/mach-mscc/reset.c
new file mode 100644
index 0000000..390bbd0
--- /dev/null
+++ b/arch/mips/mach-mscc/reset.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+
+#include <asm/reboot.h>
+
+void _machine_restart(void)
+{
+ register u32 resetbits = PERF_SOFT_RST_SOFT_CHIP_RST;
+ (void)readl(BASE_DEVCPU_GCB + PERF_SOFT_RST);
+
+ /* Make sure VCore is NOT protected from reset */
+ clrbits_le32(BASE_CFG + ICPU_RESET, ICPU_RESET_CORE_RST_PROTECT);
+
+ /* Change to SPI bitbang for SPI reset workaround... */
+ writel(ICPU_SW_MODE_SW_SPI_CS_OE(1) | ICPU_SW_MODE_SW_SPI_CS(1) |
+ ICPU_SW_MODE_SW_PIN_CTRL_MODE, BASE_CFG + ICPU_SW_MODE);
+
+ /* Do the global reset */
+ writel(resetbits, BASE_DEVCPU_GCB + PERF_SOFT_RST);
+
+ while (1)
+ ; /* NOP */
+}
diff --git a/arch/mips/mach-mt7620/cpu.c b/arch/mips/mach-mt7620/cpu.c
index 87cc973..9e0ca71 100644
--- a/arch/mips/mach-mt7620/cpu.c
+++ b/arch/mips/mach-mt7620/cpu.c
@@ -89,9 +89,21 @@
wdt_reset(watchdog_dev);
}
}
+#endif
int arch_misc_init(void)
{
+ /*
+ * It has been noticed, that sometimes the d-cache is not in a
+ * "clean-state" when U-Boot is running on MT7688. This was
+ * detected when using the ethernet driver (which uses d-cache)
+ * and a TFTP command does not complete. Flushing the complete
+ * d-cache (again?) here seems to fix this issue.
+ */
+ flush_dcache_range(gd->bd->bi_memstart,
+ gd->bd->bi_memstart + gd->ram_size - 1);
+
+#ifdef CONFIG_WATCHDOG
/* Init watchdog */
if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) {
debug("Watchdog: Not found by seq!\n");
@@ -103,7 +115,7 @@
wdt_start(watchdog_dev, 60000, 0); /* 60 seconds */
printf("Watchdog: Started\n");
+#endif
return 0;
}
-#endif
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 732a357..c45e4d7 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -22,6 +22,7 @@
# platform-specific options below
source "arch/riscv/cpu/ax25/Kconfig"
+source "arch/riscv/cpu/qemu/Kconfig"
# architecture-specific options below
@@ -44,6 +45,40 @@
endchoice
+choice
+ prompt "Code Model"
+ default CMODEL_MEDLOW
+
+config CMODEL_MEDLOW
+ bool "medium low code model"
+ help
+ U-Boot and its statically defined symbols must lie within a single 2 GiB
+ address range and must lie between absolute addresses -2 GiB and +2 GiB.
+
+config CMODEL_MEDANY
+ bool "medium any code model"
+ help
+ U-Boot and its statically defined symbols must be within any single 2 GiB
+ address range.
+
+endchoice
+
+choice
+ prompt "Run Mode"
+ default RISCV_MMODE
+
+config RISCV_MMODE
+ bool "Machine"
+ help
+ Choose this option to build U-Boot for RISC-V M-Mode.
+
+config RISCV_SMODE
+ bool "Supervisor"
+ help
+ Choose this option to build U-Boot for RISC-V S-Mode.
+
+endchoice
+
config RISCV_ISA_C
bool "Emit compressed instructions"
default y
@@ -55,15 +90,30 @@
config RISCV_ISA_A
def_bool y
-config RISCV_SMODE
- bool "Run in S-Mode"
- help
- Enable this option to build U-Boot for RISC-V S-Mode
-
config 32BIT
bool
config 64BIT
bool
+config SIFIVE_CLINT
+ bool
+ depends on RISCV_MMODE
+ select REGMAP
+ select SYSCON
+ help
+ The SiFive CLINT block holds memory-mapped control and status registers
+ associated with software and timer interrupts.
+
+config RISCV_RDTIME
+ bool
+ default y if RISCV_SMODE
+ help
+ The provides the riscv_get_time() API that is implemented using the
+ standard rdtime instruction. This is the case for S-mode U-Boot, and
+ is useful for processors that support rdtime in M-mode too.
+
+config SYS_MALLOC_F_LEN
+ default 0x1000
+
endmenu
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 55d7c65..0b80eb8 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -17,8 +17,15 @@
ifeq ($(CONFIG_RISCV_ISA_C),y)
ARCH_C = c
endif
+ifeq ($(CONFIG_CMODEL_MEDLOW),y)
+ CMODEL = medlow
+endif
+ifeq ($(CONFIG_CMODEL_MEDANY),y)
+ CMODEL = medany
+endif
-ARCH_FLAGS = -march=$(ARCH_BASE)$(ARCH_A)$(ARCH_C) -mabi=$(ABI)
+ARCH_FLAGS = -march=$(ARCH_BASE)$(ARCH_A)$(ARCH_C) -mabi=$(ABI) \
+ -mcmodel=$(CMODEL)
PLATFORM_CPPFLAGS += $(ARCH_FLAGS)
CFLAGS_EFI += $(ARCH_FLAGS)
diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile
index 2cc6757..6bf6f91 100644
--- a/arch/riscv/cpu/Makefile
+++ b/arch/riscv/cpu/Makefile
@@ -4,4 +4,4 @@
extra-y = start.o
-obj-y += cpu.o
+obj-y += cpu.o mtrap.o
diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig
index 6c7022f..e9dbca2 100644
--- a/arch/riscv/cpu/ax25/Kconfig
+++ b/arch/riscv/cpu/ax25/Kconfig
@@ -1,7 +1,14 @@
config RISCV_NDS
- bool "AndeStar V5 ISA support"
- default n
+ bool
help
- Say Y here if you plan to run U-Boot on AndeStar v5
- platforms and use some specific features which are
- provided by Andes Technology AndeStar V5 Families.
+ Run U-Boot on AndeStar V5 platforms and use some specific features
+ which are provided by Andes Technology AndeStar V5 families.
+
+if RISCV_NDS
+
+config RISCV_NDS_CACHE
+ bool "AndeStar V5 families specific cache support"
+ help
+ Provide Andes Technology AndeStar V5 families specific cache support.
+
+endif
diff --git a/arch/riscv/cpu/ax25/cache.c b/arch/riscv/cpu/ax25/cache.c
index 6600ac2..8d6ae17 100644
--- a/arch/riscv/cpu/ax25/cache.c
+++ b/arch/riscv/cpu/ax25/cache.c
@@ -9,7 +9,7 @@
void icache_enable(void)
{
#ifndef CONFIG_SYS_ICACHE_OFF
-#ifdef CONFIG_RISCV_NDS
+#ifdef CONFIG_RISCV_NDS_CACHE
asm volatile (
"csrr t1, mcache_ctl\n\t"
"ori t0, t1, 0x1\n\t"
@@ -22,7 +22,7 @@
void icache_disable(void)
{
#ifndef CONFIG_SYS_ICACHE_OFF
-#ifdef CONFIG_RISCV_NDS
+#ifdef CONFIG_RISCV_NDS_CACHE
asm volatile (
"fence.i\n\t"
"csrr t1, mcache_ctl\n\t"
@@ -36,7 +36,7 @@
void dcache_enable(void)
{
#ifndef CONFIG_SYS_DCACHE_OFF
-#ifdef CONFIG_RISCV_NDS
+#ifdef CONFIG_RISCV_NDS_CACHE
asm volatile (
"csrr t1, mcache_ctl\n\t"
"ori t0, t1, 0x2\n\t"
@@ -49,7 +49,7 @@
void dcache_disable(void)
{
#ifndef CONFIG_SYS_DCACHE_OFF
-#ifdef CONFIG_RISCV_NDS
+#ifdef CONFIG_RISCV_NDS_CACHE
asm volatile (
"fence\n\t"
"csrr t1, mcache_ctl\n\t"
@@ -64,7 +64,7 @@
{
int ret = 0;
-#ifdef CONFIG_RISCV_NDS
+#ifdef CONFIG_RISCV_NDS_CACHE
asm volatile (
"csrr t1, mcache_ctl\n\t"
"andi %0, t1, 0x01\n\t"
@@ -81,7 +81,7 @@
{
int ret = 0;
-#ifdef CONFIG_RISCV_NDS
+#ifdef CONFIG_RISCV_NDS_CACHE
asm volatile (
"csrr t1, mcache_ctl\n\t"
"andi %0, t1, 0x02\n\t"
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index d9f820c..e662140 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -4,7 +4,12 @@
*/
#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <log.h>
#include <asm/csr.h>
+#include <asm/encoding.h>
+#include <dm/uclass-internal.h>
/*
* prior_stage_fdt_address must be stored in the data section since it is used
@@ -12,44 +17,79 @@
*/
phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
-enum {
- ISA_INVALID = 0,
- ISA_32BIT,
- ISA_64BIT,
- ISA_128BIT
-};
-
-static const char * const isa_bits[] = {
- [ISA_INVALID] = NULL,
- [ISA_32BIT] = "32",
- [ISA_64BIT] = "64",
- [ISA_128BIT] = "128"
-};
-
static inline bool supports_extension(char ext)
{
+#ifdef CONFIG_CPU
+ struct udevice *dev;
+ char desc[32];
+
+ uclass_find_first_device(UCLASS_CPU, &dev);
+ if (!dev) {
+ debug("unable to find the RISC-V cpu device\n");
+ return false;
+ }
+ if (!cpu_get_desc(dev, desc, sizeof(desc))) {
+ /* skip the first 4 characters (rv32|rv64) */
+ if (strchr(desc + 4, ext))
+ return true;
+ }
+
+ return false;
+#else /* !CONFIG_CPU */
+#ifdef CONFIG_RISCV_MMODE
return csr_read(misa) & (1 << (ext - 'a'));
+#else /* !CONFIG_RISCV_MMODE */
+#warning "There is no way to determine the available extensions in S-mode."
+#warning "Please convert your board to use the RISC-V CPU driver."
+ return false;
+#endif /* CONFIG_RISCV_MMODE */
+#endif /* CONFIG_CPU */
}
-int print_cpuinfo(void)
+static int riscv_cpu_probe(void)
{
- char name[32];
- char *s = name;
- int bit;
+#ifdef CONFIG_CPU
+ int ret;
- s += sprintf(name, "rv");
- bit = csr_read(misa) >> (sizeof(long) * 8 - 2);
- s += sprintf(s, isa_bits[bit]);
-
- supports_extension('i') ? *s++ = 'i' : 'r';
- supports_extension('m') ? *s++ = 'm' : 'i';
- supports_extension('a') ? *s++ = 'a' : 's';
- supports_extension('f') ? *s++ = 'f' : 'c';
- supports_extension('d') ? *s++ = 'd' : '-';
- supports_extension('c') ? *s++ = 'c' : 'v';
- *s++ = '\0';
-
- printf("CPU: %s\n", name);
+ /* probe cpus so that RISC-V timer can be bound */
+ ret = cpu_probe_all();
+ if (ret)
+ return log_msg_ret("RISC-V cpus probe failed\n", ret);
+#endif
return 0;
}
+
+int arch_cpu_init_dm(void)
+{
+ int ret;
+
+ ret = riscv_cpu_probe();
+ if (ret)
+ return ret;
+
+ /* Enable FPU */
+ if (supports_extension('d') || supports_extension('f')) {
+ csr_set(MODE_PREFIX(status), MSTATUS_FS);
+ csr_write(fcsr, 0);
+ }
+
+ if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
+ /*
+ * Enable perf counters for cycle, time,
+ * and instret counters only
+ */
+ csr_write(mcounteren, GENMASK(2, 0));
+
+ /* Disable paging */
+ if (supports_extension('s'))
+ csr_write(satp, 0);
+ }
+
+ return 0;
+}
+
+int arch_early_init_r(void)
+{
+ return riscv_cpu_probe();
+}
diff --git a/arch/riscv/cpu/mtrap.S b/arch/riscv/cpu/mtrap.S
new file mode 100644
index 0000000..407ecfa
--- /dev/null
+++ b/arch/riscv/cpu/mtrap.S
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * M-mode Trap Handler Code for RISC-V Core
+ *
+ * Copyright (c) 2017 Microsemi Corporation.
+ * Copyright (c) 2017 Padmarao Begari <Padmarao.Begari@microsemi.com>
+ *
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ *
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/encoding.h>
+
+#ifdef CONFIG_32BIT
+#define LREG lw
+#define SREG sw
+#define REGBYTES 4
+#else
+#define LREG ld
+#define SREG sd
+#define REGBYTES 8
+#endif
+
+ .text
+
+ /* trap entry */
+ .align 2
+ .global trap_entry
+trap_entry:
+ addi sp, sp, -32 * REGBYTES
+ SREG x1, 1 * REGBYTES(sp)
+ SREG x2, 2 * REGBYTES(sp)
+ SREG x3, 3 * REGBYTES(sp)
+ SREG x4, 4 * REGBYTES(sp)
+ SREG x5, 5 * REGBYTES(sp)
+ SREG x6, 6 * REGBYTES(sp)
+ SREG x7, 7 * REGBYTES(sp)
+ SREG x8, 8 * REGBYTES(sp)
+ SREG x9, 9 * REGBYTES(sp)
+ SREG x10, 10 * REGBYTES(sp)
+ SREG x11, 11 * REGBYTES(sp)
+ SREG x12, 12 * REGBYTES(sp)
+ SREG x13, 13 * REGBYTES(sp)
+ SREG x14, 14 * REGBYTES(sp)
+ SREG x15, 15 * REGBYTES(sp)
+ SREG x16, 16 * REGBYTES(sp)
+ SREG x17, 17 * REGBYTES(sp)
+ SREG x18, 18 * REGBYTES(sp)
+ SREG x19, 19 * REGBYTES(sp)
+ SREG x20, 20 * REGBYTES(sp)
+ SREG x21, 21 * REGBYTES(sp)
+ SREG x22, 22 * REGBYTES(sp)
+ SREG x23, 23 * REGBYTES(sp)
+ SREG x24, 24 * REGBYTES(sp)
+ SREG x25, 25 * REGBYTES(sp)
+ SREG x26, 26 * REGBYTES(sp)
+ SREG x27, 27 * REGBYTES(sp)
+ SREG x28, 28 * REGBYTES(sp)
+ SREG x29, 29 * REGBYTES(sp)
+ SREG x30, 30 * REGBYTES(sp)
+ SREG x31, 31 * REGBYTES(sp)
+ csrr a0, MODE_PREFIX(cause)
+ csrr a1, MODE_PREFIX(epc)
+ mv a2, sp
+ jal handle_trap
+ csrw MODE_PREFIX(epc), a0
+
+ LREG x1, 1 * REGBYTES(sp)
+ LREG x3, 3 * REGBYTES(sp)
+ LREG x4, 4 * REGBYTES(sp)
+ LREG x5, 5 * REGBYTES(sp)
+ LREG x6, 6 * REGBYTES(sp)
+ LREG x7, 7 * REGBYTES(sp)
+ LREG x8, 8 * REGBYTES(sp)
+ LREG x9, 9 * REGBYTES(sp)
+ LREG x10, 10 * REGBYTES(sp)
+ LREG x11, 11 * REGBYTES(sp)
+ LREG x12, 12 * REGBYTES(sp)
+ LREG x13, 13 * REGBYTES(sp)
+ LREG x14, 14 * REGBYTES(sp)
+ LREG x15, 15 * REGBYTES(sp)
+ LREG x16, 16 * REGBYTES(sp)
+ LREG x17, 17 * REGBYTES(sp)
+ LREG x18, 18 * REGBYTES(sp)
+ LREG x19, 19 * REGBYTES(sp)
+ LREG x20, 20 * REGBYTES(sp)
+ LREG x21, 21 * REGBYTES(sp)
+ LREG x22, 22 * REGBYTES(sp)
+ LREG x23, 23 * REGBYTES(sp)
+ LREG x24, 24 * REGBYTES(sp)
+ LREG x25, 25 * REGBYTES(sp)
+ LREG x26, 26 * REGBYTES(sp)
+ LREG x27, 27 * REGBYTES(sp)
+ LREG x28, 28 * REGBYTES(sp)
+ LREG x29, 29 * REGBYTES(sp)
+ LREG x30, 30 * REGBYTES(sp)
+ LREG x31, 31 * REGBYTES(sp)
+ LREG x2, 2 * REGBYTES(sp)
+ addi sp, sp, 32 * REGBYTES
+ MODE_PREFIX(ret)
diff --git a/arch/riscv/cpu/qemu/Kconfig b/arch/riscv/cpu/qemu/Kconfig
new file mode 100644
index 0000000..f48751e
--- /dev/null
+++ b/arch/riscv/cpu/qemu/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+
+config QEMU_RISCV
+ bool
+ select ARCH_EARLY_INIT_R
+ imply CPU
+ imply CPU_RISCV
+ imply RISCV_TIMER
+ imply SIFIVE_CLINT if RISCV_MMODE
+ imply CMD_CPU
diff --git a/arch/riscv/cpu/qemu/cpu.c b/arch/riscv/cpu/qemu/cpu.c
index 25d97d0..ad2950c 100644
--- a/arch/riscv/cpu/qemu/cpu.c
+++ b/arch/riscv/cpu/qemu/cpu.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
+#include <dm.h>
/*
* cleanup_before_linux() is called just before we call linux
@@ -19,3 +20,16 @@
return 0;
}
+
+/* To enumerate devices on the /soc/ node, create a "simple-bus" driver */
+static const struct udevice_id riscv_virtio_soc_ids[] = {
+ { .compatible = "riscv-virtio-soc" },
+ { }
+};
+
+U_BOOT_DRIVER(riscv_virtio_soc) = {
+ .name = "riscv_virtio_soc",
+ .id = UCLASS_SIMPLE_BUS,
+ .of_match = riscv_virtio_soc_ids,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 64246a4..81ea52b 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -14,6 +14,7 @@
#include <common.h>
#include <elf.h>
#include <asm/encoding.h>
+#include <generated/asm-offsets.h>
#ifdef CONFIG_32BIT
#define LREG lw
@@ -70,6 +71,9 @@
jal board_init_f_init_reserve
+ /* save the boot hart id to global_data */
+ SREG s0, GD_BOOT_HART(gp)
+
mv a0, zero /* a0 <-- boot_flags = 0 */
la t5, board_init_f
jr t5 /* jump to board_init_f() */
@@ -198,92 +202,3 @@
* jump to it ...
*/
jr t4 /* jump to board_init_r() */
-
-/*
- * trap entry
- */
-.align 2
-trap_entry:
- addi sp, sp, -32*REGBYTES
- SREG x1, 1*REGBYTES(sp)
- SREG x2, 2*REGBYTES(sp)
- SREG x3, 3*REGBYTES(sp)
- SREG x4, 4*REGBYTES(sp)
- SREG x5, 5*REGBYTES(sp)
- SREG x6, 6*REGBYTES(sp)
- SREG x7, 7*REGBYTES(sp)
- SREG x8, 8*REGBYTES(sp)
- SREG x9, 9*REGBYTES(sp)
- SREG x10, 10*REGBYTES(sp)
- SREG x11, 11*REGBYTES(sp)
- SREG x12, 12*REGBYTES(sp)
- SREG x13, 13*REGBYTES(sp)
- SREG x14, 14*REGBYTES(sp)
- SREG x15, 15*REGBYTES(sp)
- SREG x16, 16*REGBYTES(sp)
- SREG x17, 17*REGBYTES(sp)
- SREG x18, 18*REGBYTES(sp)
- SREG x19, 19*REGBYTES(sp)
- SREG x20, 20*REGBYTES(sp)
- SREG x21, 21*REGBYTES(sp)
- SREG x22, 22*REGBYTES(sp)
- SREG x23, 23*REGBYTES(sp)
- SREG x24, 24*REGBYTES(sp)
- SREG x25, 25*REGBYTES(sp)
- SREG x26, 26*REGBYTES(sp)
- SREG x27, 27*REGBYTES(sp)
- SREG x28, 28*REGBYTES(sp)
- SREG x29, 29*REGBYTES(sp)
- SREG x30, 30*REGBYTES(sp)
- SREG x31, 31*REGBYTES(sp)
- csrr a0, MODE_PREFIX(cause)
- csrr a1, MODE_PREFIX(epc)
- mv a2, sp
- jal handle_trap
- csrw MODE_PREFIX(epc), a0
-
-#ifdef CONFIG_RISCV_SMODE
-/*
- * Remain in S-mode after sret
- */
- li t0, SSTATUS_SPP
-#else
-/*
- * Remain in M-mode after mret
- */
- li t0, MSTATUS_MPP
-#endif
- csrs MODE_PREFIX(status), t0
- LREG x1, 1*REGBYTES(sp)
- LREG x2, 2*REGBYTES(sp)
- LREG x3, 3*REGBYTES(sp)
- LREG x4, 4*REGBYTES(sp)
- LREG x5, 5*REGBYTES(sp)
- LREG x6, 6*REGBYTES(sp)
- LREG x7, 7*REGBYTES(sp)
- LREG x8, 8*REGBYTES(sp)
- LREG x9, 9*REGBYTES(sp)
- LREG x10, 10*REGBYTES(sp)
- LREG x11, 11*REGBYTES(sp)
- LREG x12, 12*REGBYTES(sp)
- LREG x13, 13*REGBYTES(sp)
- LREG x14, 14*REGBYTES(sp)
- LREG x15, 15*REGBYTES(sp)
- LREG x16, 16*REGBYTES(sp)
- LREG x17, 17*REGBYTES(sp)
- LREG x18, 18*REGBYTES(sp)
- LREG x19, 19*REGBYTES(sp)
- LREG x20, 20*REGBYTES(sp)
- LREG x21, 21*REGBYTES(sp)
- LREG x22, 22*REGBYTES(sp)
- LREG x23, 23*REGBYTES(sp)
- LREG x24, 24*REGBYTES(sp)
- LREG x25, 25*REGBYTES(sp)
- LREG x26, 26*REGBYTES(sp)
- LREG x27, 27*REGBYTES(sp)
- LREG x28, 28*REGBYTES(sp)
- LREG x29, 29*REGBYTES(sp)
- LREG x30, 30*REGBYTES(sp)
- LREG x31, 31*REGBYTES(sp)
- addi sp, sp, 32*REGBYTES
- MODE_PREFIX(ret)
diff --git a/arch/riscv/dts/ae350.dts b/arch/riscv/dts/ae350.dts
deleted file mode 100644
index e48c298..0000000
--- a/arch/riscv/dts/ae350.dts
+++ /dev/null
@@ -1,229 +0,0 @@
-/dts-v1/;
-
-/ {
- #address-cells = <2>;
- #size-cells = <2>;
- compatible = "andestech,ax25";
- model = "andestech,ax25";
-
- aliases {
- uart0 = &serial0;
- spi0 = &spi;
- };
-
- chosen {
- bootargs = "console=ttyS0,38400n8 debug loglevel=7";
- stdout-path = "uart0:38400n8";
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
- timebase-frequency = <60000000>;
- CPU0: cpu@0 {
- device_type = "cpu";
- reg = <0>;
- status = "okay";
- compatible = "riscv";
- riscv,isa = "rv64imafdc";
- mmu-type = "riscv,sv39";
- clock-frequency = <60000000>;
- d-cache-size = <0x8000>;
- d-cache-line-size = <32>;
- CPU0_intc: interrupt-controller {
- #interrupt-cells = <1>;
- interrupt-controller;
- compatible = "riscv,cpu-intc";
- };
- };
- };
-
- memory@0 {
- device_type = "memory";
- reg = <0x0 0x00000000 0x0 0x40000000>;
- };
-
- soc {
- #address-cells = <2>;
- #size-cells = <2>;
- compatible = "andestech,riscv-ae350-soc";
- ranges;
-
- plic0: interrupt-controller@e4000000 {
- compatible = "riscv,plic0";
- #address-cells = <2>;
- #interrupt-cells = <2>;
- interrupt-controller;
- reg = <0x0 0xe4000000 0x0 0x2000000>;
- riscv,ndev=<71>;
- interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
- };
-
- plic1: interrupt-controller@e6400000 {
- compatible = "riscv,plic1";
- #address-cells = <2>;
- #interrupt-cells = <2>;
- interrupt-controller;
- reg = <0x0 0xe6400000 0x0 0x400000>;
- riscv,ndev=<1>;
- interrupts-extended = <&CPU0_intc 3>;
- };
-
- plmt0@e6000000 {
- compatible = "riscv,plmt0";
- interrupts-extended = <&CPU0_intc 7>;
- reg = <0x0 0xe6000000 0x0 0x100000>;
- };
- };
-
- spiclk: virt_100mhz {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <100000000>;
- };
-
- timer0: timer@f0400000 {
- compatible = "andestech,atcpit100";
- reg = <0x0 0xf0400000 0x0 0x1000>;
- clock-frequency = <60000000>;
- interrupts = <3 4>;
- interrupt-parent = <&plic0>;
- };
-
- serial0: serial@f0300000 {
- compatible = "andestech,uart16550", "ns16550a";
- reg = <0x0 0xf0300000 0x0 0x1000>;
- interrupts = <9 4>;
- clock-frequency = <19660800>;
- reg-shift = <2>;
- reg-offset = <32>;
- no-loopback-test = <1>;
- interrupt-parent = <&plic0>;
- };
-
- mac0: mac@e0100000 {
- compatible = "andestech,atmac100";
- reg = <0x0 0xe0100000 0x0 0x1000>;
- interrupts = <19 4>;
- interrupt-parent = <&plic0>;
- };
-
- mmc0: mmc@f0e00000 {
- compatible = "andestech,atfsdc010";
- max-frequency = <100000000>;
- clock-freq-min-max = <400000 100000000>;
- fifo-depth = <0x10>;
- reg = <0x0 0xf0e00000 0x0 0x1000>;
- interrupts = <18 4>;
- cap-sd-highspeed;
- interrupt-parent = <&plic0>;
- };
-
- dma0: dma@f0c00000 {
- compatible = "andestech,atcdmac300";
- reg = <0x0 0xf0c00000 0x0 0x1000>;
- interrupts = <10 4 64 4 65 4 66 4 67 4 68 4 69 4 70 4 71 4>;
- dma-channels = <8>;
- interrupt-parent = <&plic0>;
- };
-
- lcd0: lcd@e0200000 {
- compatible = "andestech,atflcdc100";
- reg = <0x0 0xe0200000 0x0 0x1000>;
- interrupts = <20 4>;
- interrupt-parent = <&plic0>;
- };
-
- smc0: smc@e0400000 {
- compatible = "andestech,atfsmc020";
- reg = <0x0 0xe0400000 0x0 0x1000>;
- };
-
- snd0: snd@f0d00000 {
- compatible = "andestech,atfac97";
- reg = <0x0 0xf0d00000 0x0 0x1000>;
- interrupts = <17 4>;
- interrupt-parent = <&plic0>;
- };
-
- virtio_mmio@fe007000 {
- interrupts = <0x17 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe007000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- virtio_mmio@fe006000 {
- interrupts = <0x16 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe006000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- virtio_mmio@fe005000 {
- interrupts = <0x15 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe005000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- virtio_mmio@fe004000 {
- interrupts = <0x14 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe004000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- virtio_mmio@fe003000 {
- interrupts = <0x13 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe003000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- virtio_mmio@fe002000 {
- interrupts = <0x12 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe002000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- virtio_mmio@fe001000 {
- interrupts = <0x11 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe001000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- virtio_mmio@fe000000 {
- interrupts = <0x10 0x4>;
- interrupt-parent = <0x2>;
- reg = <0x0 0xfe000000 0x0 0x1000>;
- compatible = "virtio,mmio";
- };
-
- nor@0,0 {
- compatible = "cfi-flash";
- reg = <0x0 0x88000000 0x0 0x1000>;
- bank-width = <2>;
- device-width = <1>;
- };
-
- spi: spi@f0b00000 {
- compatible = "andestech,atcspi200";
- reg = <0x0 0xf0b00000 0x0 0x1000>;
- #address-cells = <1>;
- #size-cells = <0>;
- num-cs = <1>;
- clocks = <&spiclk>;
- interrupts = <4 4>;
- interrupt-parent = <&plic0>;
- flash@0 {
- compatible = "spi-flash";
- spi-max-frequency = <50000000>;
- reg = <0>;
- spi-cpol;
- spi-cpha;
- };
- };
-};
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 29624fd..86136f5 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -61,10 +61,12 @@
#ifndef __ASSEMBLY__
+#define xcsr(csr) #csr
+
#define csr_swap(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
- __asm__ __volatile__ ("csrrw %0, " #csr ", %1" \
+ __asm__ __volatile__ ("csrrw %0, " xcsr(csr) ", %1" \
: "=r" (__v) : "rK" (__v) \
: "memory"); \
__v; \
@@ -73,7 +75,7 @@
#define csr_read(csr) \
({ \
register unsigned long __v; \
- __asm__ __volatile__ ("csrr %0, " #csr \
+ __asm__ __volatile__ ("csrr %0, " xcsr(csr) \
: "=r" (__v) : \
: "memory"); \
__v; \
@@ -82,7 +84,7 @@
#define csr_write(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
- __asm__ __volatile__ ("csrw " #csr ", %0" \
+ __asm__ __volatile__ ("csrw " xcsr(csr) ", %0" \
: : "rK" (__v) \
: "memory"); \
})
@@ -90,7 +92,7 @@
#define csr_read_set(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
- __asm__ __volatile__ ("csrrs %0, " #csr ", %1" \
+ __asm__ __volatile__ ("csrrs %0, " xcsr(csr) ", %1" \
: "=r" (__v) : "rK" (__v) \
: "memory"); \
__v; \
@@ -99,7 +101,7 @@
#define csr_set(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
- __asm__ __volatile__ ("csrs " #csr ", %0" \
+ __asm__ __volatile__ ("csrs " xcsr(csr) ", %0" \
: : "rK" (__v) \
: "memory"); \
})
@@ -107,7 +109,7 @@
#define csr_read_clear(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
- __asm__ __volatile__ ("csrrc %0, " #csr ", %1" \
+ __asm__ __volatile__ ("csrrc %0, " xcsr(csr) ", %1" \
: "=r" (__v) : "rK" (__v) \
: "memory"); \
__v; \
@@ -116,7 +118,7 @@
#define csr_clear(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
- __asm__ __volatile__ ("csrc " #csr ", %0" \
+ __asm__ __volatile__ ("csrc " xcsr(csr) ", %0" \
: : "rK" (__v) \
: "memory"); \
})
diff --git a/arch/riscv/include/asm/encoding.h b/arch/riscv/include/asm/encoding.h
index 97cf906..772668c 100644
--- a/arch/riscv/include/asm/encoding.h
+++ b/arch/riscv/include/asm/encoding.h
@@ -85,6 +85,21 @@
#define IRQ_COP 12
#define IRQ_HOST 13
+#define CAUSE_MISALIGNED_FETCH 0
+#define CAUSE_FETCH_ACCESS 1
+#define CAUSE_ILLEGAL_INSTRUCTION 2
+#define CAUSE_BREAKPOINT 3
+#define CAUSE_MISALIGNED_LOAD 4
+#define CAUSE_LOAD_ACCESS 5
+#define CAUSE_MISALIGNED_STORE 6
+#define CAUSE_STORE_ACCESS 7
+#define CAUSE_USER_ECALL 8
+#define CAUSE_SUPERVISOR_ECALL 9
+#define CAUSE_MACHINE_ECALL 11
+#define CAUSE_FETCH_PAGE_FAULT 12
+#define CAUSE_LOAD_PAGE_FAULT 13
+#define CAUSE_STORE_PAGE_FAULT 15
+
#define DEFAULT_RSTVEC 0x00001000
#define DEFAULT_NMIVEC 0x00001004
#define DEFAULT_MTVEC 0x00001010
@@ -152,6 +167,227 @@
#define RISCV_PGSHIFT 12
#define RISCV_PGSIZE BIT(RISCV_PGSHIFT)
+/* CSR numbers */
+#define CSR_FFLAGS 0x1
+#define CSR_FRM 0x2
+#define CSR_FCSR 0x3
+
+#define CSR_SSTATUS 0x100
+#define CSR_SEDELEG 0x102
+#define CSR_SIDELEG 0x103
+#define CSR_SIE 0x104
+#define CSR_STVEC 0x105
+#define CSR_SCOUNTEREN 0x106
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SCAUSE 0x142
+#define CSR_STVAL 0x143
+#define CSR_SIP 0x144
+#define CSR_SATP 0x180
+
+#define CSR_MSTATUS 0x300
+#define CSR_MISA 0x301
+#define CSR_MEDELEG 0x302
+#define CSR_MIDELEG 0x303
+#define CSR_MIE 0x304
+#define CSR_MTVEC 0x305
+#define CSR_MCOUNTEREN 0x306
+#define CSR_MHPMEVENT3 0x323
+#define CSR_MHPMEVENT4 0x324
+#define CSR_MHPMEVENT5 0x325
+#define CSR_MHPMEVENT6 0x326
+#define CSR_MHPMEVENT7 0x327
+#define CSR_MHPMEVENT8 0x328
+#define CSR_MHPMEVENT9 0x329
+#define CSR_MHPMEVENT10 0x32a
+#define CSR_MHPMEVENT11 0x32b
+#define CSR_MHPMEVENT12 0x32c
+#define CSR_MHPMEVENT13 0x32d
+#define CSR_MHPMEVENT14 0x32e
+#define CSR_MHPMEVENT15 0x32f
+#define CSR_MHPMEVENT16 0x330
+#define CSR_MHPMEVENT17 0x331
+#define CSR_MHPMEVENT18 0x332
+#define CSR_MHPMEVENT19 0x333
+#define CSR_MHPMEVENT20 0x334
+#define CSR_MHPMEVENT21 0x335
+#define CSR_MHPMEVENT22 0x336
+#define CSR_MHPMEVENT23 0x337
+#define CSR_MHPMEVENT24 0x338
+#define CSR_MHPMEVENT25 0x339
+#define CSR_MHPMEVENT26 0x33a
+#define CSR_MHPMEVENT27 0x33b
+#define CSR_MHPMEVENT28 0x33c
+#define CSR_MHPMEVENT29 0x33d
+#define CSR_MHPMEVENT30 0x33e
+#define CSR_MHPMEVENT31 0x33f
+#define CSR_MSCRATCH 0x340
+#define CSR_MEPC 0x341
+#define CSR_MCAUSE 0x342
+#define CSR_MTVAL 0x343
+#define CSR_MIP 0x344
+#define CSR_PMPCFG0 0x3a0
+#define CSR_PMPCFG1 0x3a1
+#define CSR_PMPCFG2 0x3a2
+#define CSR_PMPCFG3 0x3a3
+#define CSR_PMPADDR0 0x3b0
+#define CSR_PMPADDR1 0x3b1
+#define CSR_PMPADDR2 0x3b2
+#define CSR_PMPADDR3 0x3b3
+#define CSR_PMPADDR4 0x3b4
+#define CSR_PMPADDR5 0x3b5
+#define CSR_PMPADDR6 0x3b6
+#define CSR_PMPADDR7 0x3b7
+#define CSR_PMPADDR8 0x3b8
+#define CSR_PMPADDR9 0x3b9
+#define CSR_PMPADDR10 0x3ba
+#define CSR_PMPADDR11 0x3bb
+#define CSR_PMPADDR12 0x3bc
+#define CSR_PMPADDR13 0x3bd
+#define CSR_PMPADDR14 0x3be
+#define CSR_PMPADDR15 0x3bf
+
+#define CSR_TSELECT 0x7a0
+#define CSR_TDATA1 0x7a1
+#define CSR_TDATA2 0x7a2
+#define CSR_TDATA3 0x7a3
+#define CSR_DCSR 0x7b0
+#define CSR_DPC 0x7b1
+#define CSR_DSCRATCH 0x7b2
+
+#define CSR_MCYCLE 0xb00
+#define CSR_MINSTRET 0xb02
+#define CSR_MHPMCOUNTER3 0xb03
+#define CSR_MHPMCOUNTER4 0xb04
+#define CSR_MHPMCOUNTER5 0xb05
+#define CSR_MHPMCOUNTER6 0xb06
+#define CSR_MHPMCOUNTER7 0xb07
+#define CSR_MHPMCOUNTER8 0xb08
+#define CSR_MHPMCOUNTER9 0xb09
+#define CSR_MHPMCOUNTER10 0xb0a
+#define CSR_MHPMCOUNTER11 0xb0b
+#define CSR_MHPMCOUNTER12 0xb0c
+#define CSR_MHPMCOUNTER13 0xb0d
+#define CSR_MHPMCOUNTER14 0xb0e
+#define CSR_MHPMCOUNTER15 0xb0f
+#define CSR_MHPMCOUNTER16 0xb10
+#define CSR_MHPMCOUNTER17 0xb11
+#define CSR_MHPMCOUNTER18 0xb12
+#define CSR_MHPMCOUNTER19 0xb13
+#define CSR_MHPMCOUNTER20 0xb14
+#define CSR_MHPMCOUNTER21 0xb15
+#define CSR_MHPMCOUNTER22 0xb16
+#define CSR_MHPMCOUNTER23 0xb17
+#define CSR_MHPMCOUNTER24 0xb18
+#define CSR_MHPMCOUNTER25 0xb19
+#define CSR_MHPMCOUNTER26 0xb1a
+#define CSR_MHPMCOUNTER27 0xb1b
+#define CSR_MHPMCOUNTER28 0xb1c
+#define CSR_MHPMCOUNTER29 0xb1d
+#define CSR_MHPMCOUNTER30 0xb1e
+#define CSR_MHPMCOUNTER31 0xb1f
+#define CSR_MCYCLEH 0xb80
+#define CSR_MINSTRETH 0xb82
+#define CSR_MHPMCOUNTER3H 0xb83
+#define CSR_MHPMCOUNTER4H 0xb84
+#define CSR_MHPMCOUNTER5H 0xb85
+#define CSR_MHPMCOUNTER6H 0xb86
+#define CSR_MHPMCOUNTER7H 0xb87
+#define CSR_MHPMCOUNTER8H 0xb88
+#define CSR_MHPMCOUNTER9H 0xb89
+#define CSR_MHPMCOUNTER10H 0xb8a
+#define CSR_MHPMCOUNTER11H 0xb8b
+#define CSR_MHPMCOUNTER12H 0xb8c
+#define CSR_MHPMCOUNTER13H 0xb8d
+#define CSR_MHPMCOUNTER14H 0xb8e
+#define CSR_MHPMCOUNTER15H 0xb8f
+#define CSR_MHPMCOUNTER16H 0xb90
+#define CSR_MHPMCOUNTER17H 0xb91
+#define CSR_MHPMCOUNTER18H 0xb92
+#define CSR_MHPMCOUNTER19H 0xb93
+#define CSR_MHPMCOUNTER20H 0xb94
+#define CSR_MHPMCOUNTER21H 0xb95
+#define CSR_MHPMCOUNTER22H 0xb96
+#define CSR_MHPMCOUNTER23H 0xb97
+#define CSR_MHPMCOUNTER24H 0xb98
+#define CSR_MHPMCOUNTER25H 0xb99
+#define CSR_MHPMCOUNTER26H 0xb9a
+#define CSR_MHPMCOUNTER27H 0xb9b
+#define CSR_MHPMCOUNTER28H 0xb9c
+#define CSR_MHPMCOUNTER29H 0xb9d
+#define CSR_MHPMCOUNTER30H 0xb9e
+#define CSR_MHPMCOUNTER31H 0xb9f
+
+#define CSR_CYCLE 0xc00
+#define CSR_TIME 0xc01
+#define CSR_INSTRET 0xc02
+#define CSR_HPMCOUNTER3 0xc03
+#define CSR_HPMCOUNTER4 0xc04
+#define CSR_HPMCOUNTER5 0xc05
+#define CSR_HPMCOUNTER6 0xc06
+#define CSR_HPMCOUNTER7 0xc07
+#define CSR_HPMCOUNTER8 0xc08
+#define CSR_HPMCOUNTER9 0xc09
+#define CSR_HPMCOUNTER10 0xc0a
+#define CSR_HPMCOUNTER11 0xc0b
+#define CSR_HPMCOUNTER12 0xc0c
+#define CSR_HPMCOUNTER13 0xc0d
+#define CSR_HPMCOUNTER14 0xc0e
+#define CSR_HPMCOUNTER15 0xc0f
+#define CSR_HPMCOUNTER16 0xc10
+#define CSR_HPMCOUNTER17 0xc11
+#define CSR_HPMCOUNTER18 0xc12
+#define CSR_HPMCOUNTER19 0xc13
+#define CSR_HPMCOUNTER20 0xc14
+#define CSR_HPMCOUNTER21 0xc15
+#define CSR_HPMCOUNTER22 0xc16
+#define CSR_HPMCOUNTER23 0xc17
+#define CSR_HPMCOUNTER24 0xc18
+#define CSR_HPMCOUNTER25 0xc19
+#define CSR_HPMCOUNTER26 0xc1a
+#define CSR_HPMCOUNTER27 0xc1b
+#define CSR_HPMCOUNTER28 0xc1c
+#define CSR_HPMCOUNTER29 0xc1d
+#define CSR_HPMCOUNTER30 0xc1e
+#define CSR_HPMCOUNTER31 0xc1f
+#define CSR_CYCLEH 0xc80
+#define CSR_TIMEH 0xc81
+#define CSR_INSTRETH 0xc82
+#define CSR_HPMCOUNTER3H 0xc83
+#define CSR_HPMCOUNTER4H 0xc84
+#define CSR_HPMCOUNTER5H 0xc85
+#define CSR_HPMCOUNTER6H 0xc86
+#define CSR_HPMCOUNTER7H 0xc87
+#define CSR_HPMCOUNTER8H 0xc88
+#define CSR_HPMCOUNTER9H 0xc89
+#define CSR_HPMCOUNTER10H 0xc8a
+#define CSR_HPMCOUNTER11H 0xc8b
+#define CSR_HPMCOUNTER12H 0xc8c
+#define CSR_HPMCOUNTER13H 0xc8d
+#define CSR_HPMCOUNTER14H 0xc8e
+#define CSR_HPMCOUNTER15H 0xc8f
+#define CSR_HPMCOUNTER16H 0xc90
+#define CSR_HPMCOUNTER17H 0xc91
+#define CSR_HPMCOUNTER18H 0xc92
+#define CSR_HPMCOUNTER19H 0xc93
+#define CSR_HPMCOUNTER20H 0xc94
+#define CSR_HPMCOUNTER21H 0xc95
+#define CSR_HPMCOUNTER22H 0xc96
+#define CSR_HPMCOUNTER23H 0xc97
+#define CSR_HPMCOUNTER24H 0xc98
+#define CSR_HPMCOUNTER25H 0xc99
+#define CSR_HPMCOUNTER26H 0xc9a
+#define CSR_HPMCOUNTER27H 0xc9b
+#define CSR_HPMCOUNTER28H 0xc9c
+#define CSR_HPMCOUNTER29H 0xc9d
+#define CSR_HPMCOUNTER30H 0xc9e
+#define CSR_HPMCOUNTER31H 0xc9f
+
+#define CSR_MVENDORID 0xf11
+#define CSR_MARCHID 0xf12
+#define CSR_MIMPID 0xf13
+#define CSR_MHARTID 0xf14
+
#endif /* __riscv */
#endif /* RISCV_CSR_ENCODING_H */
diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
index 4d5d623..a3a342c 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -12,6 +12,10 @@
/* Architecture-specific global data */
struct arch_global_data {
+ long boot_hart; /* boot hart id */
+#ifdef CONFIG_SIFIVE_CLINT
+ void __iomem *clint; /* clint base address */
+#endif
};
#include <asm-generic/global_data.h>
diff --git a/arch/riscv/include/asm/syscon.h b/arch/riscv/include/asm/syscon.h
new file mode 100644
index 0000000..d311ee6
--- /dev/null
+++ b/arch/riscv/include/asm/syscon.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#ifndef _ASM_SYSCON_H
+#define _ASM_SYSCON_H
+
+/*
+ * System controllers in a RISC-V system
+ *
+ * So far only SiFive's Core Local Interruptor (CLINT) is defined.
+ */
+enum {
+ RISCV_NONE,
+ RISCV_SYSCON_CLINT, /* Core Local Interruptor (CLINT) */
+};
+
+#endif /* _ASM_SYSCON_H */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index b58db89..edfa616 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -9,6 +9,8 @@
obj-$(CONFIG_CMD_BOOTM) += bootm.o
obj-$(CONFIG_CMD_GO) += boot.o
obj-y += cache.o
+obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
+obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
obj-y += interrupts.o
obj-y += reset.o
obj-y += setjmp.o
diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c
new file mode 100644
index 0000000..e0b71f5
--- /dev/null
+++ b/arch/riscv/lib/asm-offsets.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * From arch/x86/lib/asm-offsets.c
+ *
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ */
+
+#include <common.h>
+#include <linux/kbuild.h>
+
+int main(void)
+{
+ DEFINE(GD_BOOT_HART, offsetof(gd_t, arch.boot_hart));
+
+ return 0;
+}
diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index 124aeef..60b32cc 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -93,7 +93,7 @@
if (!fake) {
if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
- kernel(csr_read(mhartid), images->ft_addr);
+ kernel(gd->arch.boot_hart, images->ft_addr);
}
}
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
index 3aff006..e185933 100644
--- a/arch/riscv/lib/interrupts.c
+++ b/arch/riscv/lib/interrupts.c
@@ -12,7 +12,36 @@
#include <asm/system.h>
#include <asm/encoding.h>
-static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs);
+static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
+{
+ static const char * const exception_code[] = {
+ "Instruction address misaligned",
+ "Instruction access fault",
+ "Illegal instruction",
+ "Breakpoint",
+ "Load address misaligned",
+ "Load access fault",
+ "Store/AMO address misaligned",
+ "Store/AMO access fault",
+ "Environment call from U-mode",
+ "Environment call from S-mode",
+ "Reserved",
+ "Environment call from M-mode",
+ "Instruction page fault",
+ "Load page fault",
+ "Reserved",
+ "Store/AMO page fault",
+ };
+
+ if (code < ARRAY_SIZE(exception_code)) {
+ printf("exception code: %ld , %s , epc %lx , ra %lx\n",
+ code, exception_code[code], epc, regs->ra);
+ } else {
+ printf("Reserved\n");
+ }
+
+ hang();
+}
int interrupt_init(void)
{
@@ -72,34 +101,3 @@
__attribute__((weak)) void timer_interrupt(struct pt_regs *regs)
{
}
-
-static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
-{
- static const char * const exception_code[] = {
- "Instruction address misaligned",
- "Instruction access fault",
- "Illegal instruction",
- "Breakpoint",
- "Load address misaligned",
- "Load access fault",
- "Store/AMO address misaligned",
- "Store/AMO access fault",
- "Environment call from U-mode",
- "Environment call from S-mode",
- "Reserved",
- "Environment call from M-mode",
- "Instruction page fault",
- "Load page fault",
- "Reserved",
- "Store/AMO page fault",
- };
-
- if (code < ARRAY_SIZE(exception_code)) {
- printf("exception code: %ld , %s , epc %lx , ra %lx\n",
- code, exception_code[code], epc, regs->ra);
- } else {
- printf("Reserved\n");
- }
-
- hang();
-}
diff --git a/arch/riscv/lib/rdtime.c b/arch/riscv/lib/rdtime.c
new file mode 100644
index 0000000..e128d7f
--- /dev/null
+++ b/arch/riscv/lib/rdtime.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Anup Patel <anup@brainfault.org>
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * The riscv_get_time() API implementation that is using the
+ * standard rdtime instruction.
+ */
+
+#include <common.h>
+
+/* Implement the API required by RISC-V timer driver */
+int riscv_get_time(u64 *time)
+{
+#ifdef CONFIG_64BIT
+ u64 n;
+
+ __asm__ __volatile__ (
+ "rdtime %0"
+ : "=r" (n));
+
+ *time = n;
+#else
+ u32 lo, hi, tmp;
+
+ __asm__ __volatile__ (
+ "1:\n"
+ "rdtimeh %0\n"
+ "rdtime %1\n"
+ "rdtimeh %2\n"
+ "bne %0, %2, 1b"
+ : "=&r" (hi), "=&r" (lo), "=&r" (tmp));
+
+ *time = ((u64)hi << 32) | lo;
+#endif
+
+ return 0;
+}
diff --git a/arch/riscv/lib/sifive_clint.c b/arch/riscv/lib/sifive_clint.c
new file mode 100644
index 0000000..d24e0d5
--- /dev/null
+++ b/arch/riscv/lib/sifive_clint.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * U-Boot syscon driver for SiFive's Core Local Interruptor (CLINT).
+ * The CLINT block holds memory-mapped control and status registers
+ * associated with software and timer interrupts.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/syscon.h>
+
+/* MSIP registers */
+#define MSIP_REG(base, hart) ((ulong)(base) + (hart) * 4)
+/* mtime compare register */
+#define MTIMECMP_REG(base, hart) ((ulong)(base) + 0x4000 + (hart) * 8)
+/* mtime register */
+#define MTIME_REG(base) ((ulong)(base) + 0xbff8)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CLINT_BASE_GET(void) \
+ do { \
+ long *ret; \
+ \
+ if (!gd->arch.clint) { \
+ ret = syscon_get_first_range(RISCV_SYSCON_CLINT); \
+ if (IS_ERR(ret)) \
+ return PTR_ERR(ret); \
+ gd->arch.clint = ret; \
+ } \
+ } while (0)
+
+int riscv_get_time(u64 *time)
+{
+ CLINT_BASE_GET();
+
+ *time = readq((void __iomem *)MTIME_REG(gd->arch.clint));
+
+ return 0;
+}
+
+int riscv_set_timecmp(int hart, u64 cmp)
+{
+ CLINT_BASE_GET();
+
+ writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
+
+ return 0;
+}
+
+int riscv_send_ipi(int hart)
+{
+ CLINT_BASE_GET();
+
+ writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
+
+ return 0;
+}
+
+int riscv_clear_ipi(int hart)
+{
+ CLINT_BASE_GET();
+
+ writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
+
+ return 0;
+}
+
+static const struct udevice_id sifive_clint_ids[] = {
+ { .compatible = "riscv,clint0", .data = RISCV_SYSCON_CLINT },
+ { }
+};
+
+U_BOOT_DRIVER(sifive_clint) = {
+ .name = "sifive_clint",
+ .id = UCLASS_SYSCON,
+ .of_match = sifive_clint_ids,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/board/AndesTech/ax25-ae350/Kconfig b/board/AndesTech/ax25-ae350/Kconfig
index bb69ea3..44cb302 100644
--- a/board/AndesTech/ax25-ae350/Kconfig
+++ b/board/AndesTech/ax25-ae350/Kconfig
@@ -21,4 +21,8 @@
config ENV_OFFSET
default 0x140000 if ENV_IS_IN_SPI_FLASH
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select RISCV_NDS
+
endif
diff --git a/board/AndesTech/ax25-ae350/MAINTAINERS b/board/AndesTech/ax25-ae350/MAINTAINERS
index d87446e..b0a99e4 100644
--- a/board/AndesTech/ax25-ae350/MAINTAINERS
+++ b/board/AndesTech/ax25-ae350/MAINTAINERS
@@ -3,6 +3,5 @@
S: Maintained
F: board/AndesTech/ax25-ae350/
F: include/configs/ax25-ae350.h
-F: configs/a25-ae350_32_defconfig
-F: configs/ax25-ae350_64_defconfig
-F: configs/ax25-ae350_defconfig
+F: configs/ae350_rv32_defconfig
+F: configs/ae350_rv64_defconfig
diff --git a/board/emulation/qemu-riscv/Kconfig b/board/emulation/qemu-riscv/Kconfig
index 56bb533..0d865ac 100644
--- a/board/emulation/qemu-riscv/Kconfig
+++ b/board/emulation/qemu-riscv/Kconfig
@@ -18,6 +18,7 @@
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
+ select QEMU_RISCV
imply SYS_NS16550
imply VIRTIO_MMIO
imply VIRTIO_NET
@@ -32,5 +33,6 @@
imply CMD_FAT
imply BOARD_LATE_INIT
imply OF_BOARD_SETUP
+ imply SIFIVE_SERIAL
endif
diff --git a/board/imgtec/ci20/Kconfig b/board/imgtec/ci20/Kconfig
new file mode 100644
index 0000000..82bf65d
--- /dev/null
+++ b/board/imgtec/ci20/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_JZ4780_CI20
+
+config SYS_BOARD
+ default "ci20"
+
+config SYS_VENDOR
+ default "imgtec"
+
+config SYS_CONFIG_NAME
+ default "ci20"
+
+config SYS_TEXT_BASE
+ default 0x80000000
+
+endif
diff --git a/board/imgtec/ci20/MAINTAINERS b/board/imgtec/ci20/MAINTAINERS
new file mode 100644
index 0000000..dca6bf3
--- /dev/null
+++ b/board/imgtec/ci20/MAINTAINERS
@@ -0,0 +1,6 @@
+Creator CI20 BOARD
+M: Ezequiel Garcia <ezequiel@collabora.com>
+S: Maintained
+F: board/imgtec/ci20/
+F: include/configs/ci20.h
+F: configs/ci20_mmc_defconfig
diff --git a/board/imgtec/ci20/Makefile b/board/imgtec/ci20/Makefile
new file mode 100644
index 0000000..7843b46
--- /dev/null
+++ b/board/imgtec/ci20/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y := ci20.o
diff --git a/board/imgtec/ci20/README b/board/imgtec/ci20/README
new file mode 100644
index 0000000..07d89d7
--- /dev/null
+++ b/board/imgtec/ci20/README
@@ -0,0 +1,10 @@
+CI20 U-Boot
+
+Installation to an SD card:
+ Repartition your card with an MBR such that the first partition starts at an
+ offset of no less than 270KB. Then install U-Boot SPL & the full U-Boot image
+ to the card like so:
+
+ dd if=spl/u-boot-spl.bin of=/dev/sdX obs=512 seek=1
+ dd if=u-boot-dtb.img of=/dev/sdX obs=1K seek=14
+ sync
diff --git a/board/imgtec/ci20/ci20.c b/board/imgtec/ci20/ci20.c
new file mode 100644
index 0000000..9811ef5
--- /dev/null
+++ b/board/imgtec/ci20/ci20.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CI20 setup code
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#include <common.h>
+#include <environment.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <mach/jz4780.h>
+#include <mach/jz4780_dram.h>
+#include <mach/jz4780_gpio.h>
+
+struct ci20_otp {
+ u32 serial_number;
+ u32 date;
+ u8 manufacturer[2];
+ u8 mac[6];
+} __packed;
+
+static void ci20_mux_mmc(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* setup MSC1 pins */
+ writel(0x30f00000, gpio_regs + GPIO_PXINTC(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXMASKC(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXPAT1C(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXPAT0C(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXPENC(4));
+ jz4780_clk_ungate_mmc();
+}
+
+#ifndef CONFIG_SPL_BUILD
+
+static void ci20_mux_eth(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+#ifdef CONFIG_NAND
+ /* setup pins (some already setup for NAND) */
+ writel(0x04030000, gpio_regs + GPIO_PXINTC(0));
+ writel(0x04030000, gpio_regs + GPIO_PXMASKC(0));
+ writel(0x04030000, gpio_regs + GPIO_PXPAT1C(0));
+ writel(0x04030000, gpio_regs + GPIO_PXPAT0C(0));
+ writel(0x04030000, gpio_regs + GPIO_PXPENS(0));
+#else
+ /* setup pins (as above +NAND CS +RD/WE +SDx +SAx) */
+ writel(0x0dff00ff, gpio_regs + GPIO_PXINTC(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXMASKC(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXPAT1C(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXPAT0C(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXPENS(0));
+ writel(0x00000003, gpio_regs + GPIO_PXINTC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXMASKC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPENS(1));
+#endif
+}
+
+static void ci20_mux_jtag(void)
+{
+#ifdef CONFIG_JTAG
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* enable JTAG */
+ writel(3 << 30, gpio_regs + GPIO_PXINTC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXMASKC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0));
+ writel(3 << 30, gpio_regs + GPIO_PXPAT0C(0));
+#endif
+}
+
+static void ci20_mux_nand(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* setup pins */
+ writel(0x002c00ff, gpio_regs + GPIO_PXINTC(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXMASKC(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXPAT1C(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXPAT0C(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXPENS(0));
+ writel(0x00000003, gpio_regs + GPIO_PXINTC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXMASKC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPENS(1));
+
+ /* FRB0_N */
+ jz47xx_gpio_direction_input(JZ_GPIO(0, 20));
+ writel(20, gpio_regs + GPIO_PXPENS(0));
+
+ /* disable write protect */
+ jz47xx_gpio_direction_output(JZ_GPIO(5, 22), 1);
+}
+
+static void ci20_mux_uart(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* UART0 */
+ writel(0x9, gpio_regs + GPIO_PXINTC(5));
+ writel(0x9, gpio_regs + GPIO_PXMASKC(5));
+ writel(0x9, gpio_regs + GPIO_PXPAT1C(5));
+ writel(0x9, gpio_regs + GPIO_PXPAT0C(5));
+ writel(0x9, gpio_regs + GPIO_PXPENC(5));
+ jz4780_clk_ungate_uart(0);
+
+ /* UART 1 and 2 */
+ jz4780_clk_ungate_uart(1);
+ jz4780_clk_ungate_uart(2);
+
+#ifndef CONFIG_JTAG
+ /* UART3 */
+ writel(1 << 12, gpio_regs + GPIO_PXINTC(3));
+ writel(1 << 12, gpio_regs + GPIO_PXMASKS(3));
+ writel(1 << 12, gpio_regs + GPIO_PXPAT1S(3));
+ writel(1 << 12, gpio_regs + GPIO_PXPAT0C(3));
+ writel(3 << 30, gpio_regs + GPIO_PXINTC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXMASKC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0));
+ writel(1 << 30, gpio_regs + GPIO_PXPAT0C(0));
+ writel(1 << 31, gpio_regs + GPIO_PXPAT0S(0));
+ jz4780_clk_ungate_uart(3);
+#endif
+
+ /* UART4 */
+ writel(0x100400, gpio_regs + GPIO_PXINTC(2));
+ writel(0x100400, gpio_regs + GPIO_PXMASKC(2));
+ writel(0x100400, gpio_regs + GPIO_PXPAT1S(2));
+ writel(0x100400, gpio_regs + GPIO_PXPAT0C(2));
+ writel(0x100400, gpio_regs + GPIO_PXPENC(2));
+ jz4780_clk_ungate_uart(4);
+}
+
+int board_early_init_f(void)
+{
+ ci20_mux_jtag();
+ ci20_mux_uart();
+
+ ci20_mux_eth();
+ ci20_mux_mmc();
+ ci20_mux_nand();
+
+ /* SYS_POWER_IND high (LED blue, VBUS off) */
+ jz47xx_gpio_direction_output(JZ_GPIO(5, 15), 0);
+
+ /* LEDs off */
+ jz47xx_gpio_direction_output(JZ_GPIO(2, 0), 0);
+ jz47xx_gpio_direction_output(JZ_GPIO(2, 1), 0);
+ jz47xx_gpio_direction_output(JZ_GPIO(2, 2), 0);
+ jz47xx_gpio_direction_output(JZ_GPIO(2, 3), 0);
+
+ return 0;
+}
+
+int misc_init_r(void)
+{
+ const u32 efuse_clk = jz4780_clk_get_efuse_clk();
+ struct ci20_otp otp;
+ char manufacturer[3];
+
+ /* Read the board OTP data */
+ jz4780_efuse_init(efuse_clk);
+ jz4780_efuse_read(0x18, 16, (u8 *)&otp);
+
+ /* Set MAC address */
+ if (!is_valid_ethaddr(otp.mac)) {
+ /* no MAC assigned, generate one from the unique chip ID */
+ jz4780_efuse_read(0x8, 4, &otp.mac[0]);
+ jz4780_efuse_read(0x12, 2, &otp.mac[4]);
+ otp.mac[0] = (otp.mac[0] | 0x02) & ~0x01;
+ }
+ eth_env_set_enetaddr("ethaddr", otp.mac);
+
+ /* Put other board information into the environment */
+ env_set_ulong("serial#", otp.serial_number);
+ env_set_ulong("board_date", otp.date);
+ manufacturer[0] = otp.manufacturer[0];
+ manufacturer[1] = otp.manufacturer[1];
+ manufacturer[2] = 0;
+ env_set("board_mfr", manufacturer);
+
+ return 0;
+}
+
+#ifdef CONFIG_DRIVER_DM9000
+int board_eth_init(bd_t *bis)
+{
+ /* Enable clock */
+ jz4780_clk_ungate_ethernet();
+
+ /* Enable power (PB25) */
+ jz47xx_gpio_direction_output(JZ_GPIO(1, 25), 1);
+
+ /* Reset (PF12) */
+ mdelay(10);
+ jz47xx_gpio_direction_output(JZ_GPIO(5, 12), 0);
+ mdelay(10);
+ jz47xx_gpio_direction_output(JZ_GPIO(5, 12), 1);
+ mdelay(10);
+
+ return dm9000_initialize(bis);
+}
+#endif /* CONFIG_DRIVER_DM9000 */
+#endif
+
+static u8 ci20_revision(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int val;
+
+ jz47xx_gpio_direction_input(JZ_GPIO(2, 18));
+ jz47xx_gpio_direction_input(JZ_GPIO(2, 19));
+
+ /* Enable pullups */
+ writel(BIT(18) | BIT(19), gpio_regs + GPIO_PXPENC(2));
+
+ /* Read PC18/19 for version */
+ val = (!!jz47xx_gpio_get_value(JZ_GPIO(2, 18))) |
+ ((!!jz47xx_gpio_get_value(JZ_GPIO(2, 19))) << 1);
+
+ if (val == 3) /* Rev 1 boards had no pulldowns - giving 3 */
+ return 1;
+ if (val == 1) /* Rev 2 boards pulldown port C bit 18 giving 1 */
+ return 2;
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = sdram_size(0) + sdram_size(1);
+ return 0;
+}
+
+/* U-Boot common routines */
+int checkboard(void)
+{
+ printf("Board: Creator CI20 (rev.%d)\n", ci20_revision());
+ return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+
+#if defined(CONFIG_SPL_MMC_SUPPORT)
+int board_mmc_init(bd_t *bd)
+{
+ ci20_mux_mmc();
+ return jz_mmc_init((void __iomem *)MSC0_BASE);
+}
+#endif
+
+static const struct jz4780_ddr_config K4B2G0846Q_48_config = {
+ .timing = {
+ (4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) |
+ (6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT),
+
+ (4 << DDRC_TIMING2_TCCD_BIT) | (15 << DDRC_TIMING2_TRAS_BIT) |
+ (6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT),
+
+ (4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) |
+ (6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) |
+ (21 << DDRC_TIMING3_TRC_BIT),
+
+ (31 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) |
+ (4 << DDRC_TIMING4_TCKE_BIT) | (9 << DDRC_TIMING4_TMINSR_BIT) |
+ (8 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT),
+
+ (8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) |
+ (4 << DDRC_TIMING5_TWDLAT_BIT),
+
+ (25 << DDRC_TIMING6_TXSRD_BIT) | (12 << DDRC_TIMING6_TFAW_BIT) |
+ (2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT),
+ },
+
+ /* PHY */
+ /* Mode Register 0 */
+ .mr0 = 0x420,
+#ifdef SDRAM_DISABLE_DLL
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE),
+#else
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS),
+#endif
+
+ .ptr0 = 0x002000d4,
+ .ptr1 = 0x02230d40,
+ .ptr2 = 0x04013880,
+
+ .dtpr0 = 0x2a8f6690,
+ .dtpr1 = 0x00400860,
+ .dtpr2 = 0x10042a00,
+
+ .pullup = 0x0b,
+ .pulldn = 0x0b,
+};
+
+static const struct jz4780_ddr_config H5TQ2G83CFR_48_config = {
+ .timing = {
+ (4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) |
+ (6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT),
+
+ (4 << DDRC_TIMING2_TCCD_BIT) | (16 << DDRC_TIMING2_TRAS_BIT) |
+ (6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT),
+
+ (4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) |
+ (6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) |
+ (22 << DDRC_TIMING3_TRC_BIT),
+
+ (42 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) |
+ (4 << DDRC_TIMING4_TCKE_BIT) | (7 << DDRC_TIMING4_TMINSR_BIT) |
+ (3 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT),
+
+ (8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) |
+ (4 << DDRC_TIMING5_TWDLAT_BIT),
+
+ (25 << DDRC_TIMING6_TXSRD_BIT) | (20 << DDRC_TIMING6_TFAW_BIT) |
+ (2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT),
+ },
+
+ /* PHY */
+ /* Mode Register 0 */
+ .mr0 = 0x420,
+#ifdef SDRAM_DISABLE_DLL
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE),
+#else
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS),
+#endif
+
+ .ptr0 = 0x002000d4,
+ .ptr1 = 0x02d30d40,
+ .ptr2 = 0x04013880,
+
+ .dtpr0 = 0x2c906690,
+ .dtpr1 = 0x005608a0,
+ .dtpr2 = 0x10042a00,
+
+ .pullup = 0x0e,
+ .pulldn = 0x0e,
+};
+
+#if (CONFIG_SYS_MHZ != 1200)
+#error No DDR configuration for CPU speed
+#endif
+
+const struct jz4780_ddr_config *jz4780_get_ddr_config(void)
+{
+ const int board_revision = ci20_revision();
+
+ if (board_revision == 2)
+ return &K4B2G0846Q_48_config;
+ else /* Fall back to H5TQ2G83CFR RAM */
+ return &H5TQ2G83CFR_48_config;
+}
+#endif
diff --git a/board/mscc/luton/Kconfig b/board/mscc/luton/Kconfig
new file mode 100644
index 0000000..e119980
--- /dev/null
+++ b/board/mscc/luton/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+if SOC_LUTON
+
+config SYS_VENDOR
+ default "mscc"
+
+config SYS_BOARD
+ default "luton"
+
+config SYS_CONFIG_NAME
+ default "luton"
+
+endif
diff --git a/board/mscc/luton/Makefile b/board/mscc/luton/Makefile
new file mode 100644
index 0000000..b27f7c7
--- /dev/null
+++ b/board/mscc/luton/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+obj-$(CONFIG_SOC_LUTON) := luton.o
diff --git a/board/mscc/luton/luton.c b/board/mscc/luton/luton.c
new file mode 100644
index 0000000..41fc6d5
--- /dev/null
+++ b/board/mscc/luton/luton.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#define MSCC_GPIO_ALT0 0x88
+#define MSCC_GPIO_ALT1 0x8C
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_debug_uart_init(void)
+{
+ /* too early for the pinctrl driver, so configure the UART pins here */
+ setbits_le32(BASE_DEVCPU_GCB + MSCC_GPIO_ALT0, BIT(30) | BIT(31));
+}
+
+int board_early_init_r(void)
+{
+ /* Prepare SPI controller to be used in master mode */
+ writel(0, BASE_CFG + ICPU_SW_MODE);
+
+ /* Address of boot parameters */
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE;
+ return 0;
+}
diff --git a/board/mscc/ocelot/Kconfig b/board/mscc/ocelot/Kconfig
new file mode 100644
index 0000000..9ddc088
--- /dev/null
+++ b/board/mscc/ocelot/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+config SYS_VENDOR
+ default "mscc"
+
+if SOC_OCELOT
+
+config SYS_BOARD
+ default "ocelot"
+
+config SYS_CONFIG_NAME
+ default "ocelot"
+
+endif
diff --git a/board/mscc/ocelot/Makefile b/board/mscc/ocelot/Makefile
new file mode 100644
index 0000000..9f28c81
--- /dev/null
+++ b/board/mscc/ocelot/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+obj-$(CONFIG_SOC_OCELOT) := ocelot.o
+
diff --git a/board/mscc/ocelot/ocelot.c b/board/mscc/ocelot/ocelot.c
new file mode 100644
index 0000000..d521a61
--- /dev/null
+++ b/board/mscc/ocelot/ocelot.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <environment.h>
+#include <spi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MSCC_GPIO_ALT0 0x54
+#define MSCC_GPIO_ALT1 0x58
+
+void external_cs_manage(struct udevice *dev, bool enable)
+{
+ u32 cs = spi_chip_select(dev);
+ /* IF_SI0_OWNER, select the owner of the SI interface
+ * Encoding: 0: SI Slave
+ * 1: SI Boot Master
+ * 2: SI Master Controller
+ */
+ if (!enable) {
+ writel(ICPU_SW_MODE_SW_PIN_CTRL_MODE |
+ ICPU_SW_MODE_SW_SPI_CS(BIT(cs)), BASE_CFG + ICPU_SW_MODE);
+ clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
+ ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
+ ICPU_GENERAL_CTRL_IF_SI_OWNER(2));
+ } else {
+ writel(0, BASE_CFG + ICPU_SW_MODE);
+ clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
+ ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
+ ICPU_GENERAL_CTRL_IF_SI_OWNER(1));
+ }
+}
+
+void board_debug_uart_init(void)
+{
+ /* too early for the pinctrl driver, so configure the UART pins here */
+ setbits_le32(BASE_DEVCPU_GCB + MSCC_GPIO_ALT0, BIT(6) | BIT(7));
+ clrbits_le32(BASE_DEVCPU_GCB + MSCC_GPIO_ALT1, BIT(6) | BIT(7));
+}
+
+int board_early_init_r(void)
+{
+ /* Prepare SPI controller to be used in master mode */
+ writel(0, BASE_CFG + ICPU_SW_MODE);
+ clrsetbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
+ ICPU_GENERAL_CTRL_IF_SI_OWNER_M,
+ ICPU_GENERAL_CTRL_IF_SI_OWNER(2));
+
+ /* Address of boot parameters */
+ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE;
+ return 0;
+}
diff --git a/configs/a25-ae350_32_defconfig b/configs/ae350_rv32_defconfig
similarity index 100%
rename from configs/a25-ae350_32_defconfig
rename to configs/ae350_rv32_defconfig
diff --git a/configs/ax25-ae350_64_defconfig b/configs/ae350_rv64_defconfig
similarity index 100%
rename from configs/ax25-ae350_64_defconfig
rename to configs/ae350_rv64_defconfig
diff --git a/configs/ci20_mmc_defconfig b/configs/ci20_mmc_defconfig
new file mode 100644
index 0000000..c1b1c3f
--- /dev/null
+++ b/configs/ci20_mmc_defconfig
@@ -0,0 +1,48 @@
+CONFIG_MIPS=y
+CONFIG_SPL_LDSCRIPT="arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds"
+CONFIG_SYS_TEXT_BASE=0x80010000
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL=y
+CONFIG_ARCH_JZ47XX=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS4,115200 rw rootwait root=/dev/mmcblk0p1"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="ext4load mmc 0:1 0x88000000 /boot/uImage; bootm 0x88000000"
+CONFIG_MISC_INIT_R=y
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+# CONFIG_SPL_BANNER_PRINT is not set
+# CONFIG_TPL_BANNER_PRINT is not set
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_DM=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="ci20"
+CONFIG_ENV_IS_IN_MMC=y
+# CONFIG_DM_WARN is not set
+# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_JZ4780_EFUSE=y
+CONFIG_MMC=y
+CONFIG_MMC_BROKEN_CD=y
+CONFIG_DM_MMC=y
+# CONFIG_MMC_HW_PARTITIONING is not set
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
+# CONFIG_MMC_VERBOSE is not set
+CONFIG_SPL_MMC_TINY=y
+CONFIG_JZ47XX_MMC=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_LZO=y
diff --git a/configs/comtrend_ar5315u_ram_defconfig b/configs/comtrend_ar5315u_ram_defconfig
index d9ef52e..1b8e4e4 100644
--- a/configs/comtrend_ar5315u_ram_defconfig
+++ b/configs/comtrend_ar5315u_ram_defconfig
@@ -28,11 +28,14 @@
CONFIG_CMD_SF=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5315u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_LED=y
CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
CONFIG_PHY=y
CONFIG_BCM6318_USBH_PHY=y
CONFIG_BCM6328_POWER_DOMAIN=y
diff --git a/configs/comtrend_ar5387un_ram_defconfig b/configs/comtrend_ar5387un_ram_defconfig
index f129870..5ba401a 100644
--- a/configs/comtrend_ar5387un_ram_defconfig
+++ b/configs/comtrend_ar5387un_ram_defconfig
@@ -28,11 +28,14 @@
CONFIG_CMD_SF=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5387un"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_LED=y
CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
CONFIG_PHY=y
CONFIG_BCM6368_USBH_PHY=y
CONFIG_POWER_DOMAIN=y
diff --git a/configs/comtrend_ct5361_ram_defconfig b/configs/comtrend_ct5361_ram_defconfig
index 82f2070..6297e78 100644
--- a/configs/comtrend_ct5361_ram_defconfig
+++ b/configs/comtrend_ct5361_ram_defconfig
@@ -25,11 +25,14 @@
CONFIG_CMD_MEMINFO=y
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="comtrend,ct-5361"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_BCM6345_GPIO=y
CONFIG_LED=y
@@ -40,6 +43,9 @@
CONFIG_CFI_FLASH=y
CONFIG_SYS_FLASH_PROTECTION=y
CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
CONFIG_PHY=y
CONFIG_BCM6348_USBH_PHY=y
CONFIG_DM_RESET=y
diff --git a/configs/comtrend_vr3032u_ram_defconfig b/configs/comtrend_vr3032u_ram_defconfig
index 1689eec..47f5399 100644
--- a/configs/comtrend_vr3032u_ram_defconfig
+++ b/configs/comtrend_vr3032u_ram_defconfig
@@ -26,15 +26,20 @@
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="comtrend,vr-3032u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_LED=y
CONFIG_LED_BCM6328=y
CONFIG_LED_BLINK=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
CONFIG_PHY=y
CONFIG_BCM6368_USBH_PHY=y
CONFIG_POWER_DOMAIN=y
diff --git a/configs/comtrend_wap5813n_ram_defconfig b/configs/comtrend_wap5813n_ram_defconfig
index 987e4c3..fd5107b 100644
--- a/configs/comtrend_wap5813n_ram_defconfig
+++ b/configs/comtrend_wap5813n_ram_defconfig
@@ -25,11 +25,14 @@
CONFIG_CMD_MEMINFO=y
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="comtrend,wap-5813n"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_BCM6345_GPIO=y
CONFIG_LED=y
@@ -40,6 +43,9 @@
CONFIG_CFI_FLASH=y
CONFIG_SYS_FLASH_PROTECTION=y
CONFIG_SYS_FLASH_CFI=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
CONFIG_PHY=y
CONFIG_BCM6368_USBH_PHY=y
CONFIG_DM_RESET=y
diff --git a/configs/gardena-smart-gateway-mt7688-ram_defconfig b/configs/gardena-smart-gateway-mt7688-ram_defconfig
index 05e7cf9..ae8bf29 100644
--- a/configs/gardena-smart-gateway-mt7688-ram_defconfig
+++ b/configs/gardena-smart-gateway-mt7688-ram_defconfig
@@ -36,7 +36,6 @@
CONFIG_MTDIDS_DEFAULT="spi-nand0=gd5f,nor0=spi0.0"
CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);gd5f:-(nand)"
CONFIG_CMD_UBI=y
-CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="gardena-smart-gateway-mt7688"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/gardena-smart-gateway-mt7688_defconfig b/configs/gardena-smart-gateway-mt7688_defconfig
index a08d1db..b7024e3 100644
--- a/configs/gardena-smart-gateway-mt7688_defconfig
+++ b/configs/gardena-smart-gateway-mt7688_defconfig
@@ -39,7 +39,6 @@
CONFIG_MTDIDS_DEFAULT="spi-nand0=gd5f,nor0=spi0.0"
CONFIG_MTDPARTS_DEFAULT="spi0.0:640k(uboot),64k(uboot_env0),64k(uboot_env1),64k(factory),-(unused);gd5f:-(nand)"
CONFIG_CMD_UBI=y
-CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="gardena-smart-gateway-mt7688"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/huawei_hg556a_ram_defconfig b/configs/huawei_hg556a_ram_defconfig
index 6bb14ba..d4e6144 100644
--- a/configs/huawei_hg556a_ram_defconfig
+++ b/configs/huawei_hg556a_ram_defconfig
@@ -25,11 +25,14 @@
CONFIG_CMD_MEMINFO=y
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="huawei,hg556a"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_BCM6345_GPIO=y
CONFIG_LED=y
@@ -40,6 +43,9 @@
CONFIG_CFI_FLASH=y
CONFIG_SYS_FLASH_PROTECTION=y
CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
CONFIG_PHY=y
CONFIG_BCM6358_USBH_PHY=y
CONFIG_DM_RESET=y
diff --git a/configs/linkit-smart-7688-ram_defconfig b/configs/linkit-smart-7688-ram_defconfig
index 2d20e9e..2d3ab7e 100644
--- a/configs/linkit-smart-7688-ram_defconfig
+++ b/configs/linkit-smart-7688-ram_defconfig
@@ -26,7 +26,6 @@
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
-CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/linkit-smart-7688_defconfig b/configs/linkit-smart-7688_defconfig
index 5add29f..ad34aaf 100644
--- a/configs/linkit-smart-7688_defconfig
+++ b/configs/linkit-smart-7688_defconfig
@@ -30,7 +30,6 @@
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
-CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
diff --git a/configs/mscc_luton_defconfig b/configs/mscc_luton_defconfig
new file mode 100644
index 0000000..d7476c4
--- /dev/null
+++ b/configs/mscc_luton_defconfig
@@ -0,0 +1,64 @@
+CONFIG_MIPS=y
+CONFIG_SYS_TEXT_BASE=0x40000000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0x70100000
+CONFIG_DEBUG_UART_CLOCK=208333333
+CONFIG_ARCH_MSCC=y
+CONFIG_TARGET_LUTON_PCB091=y
+CONFIG_DDRTYPE_MT47H128M8HQ=y
+CONFIG_SYS_LITTLE_ENDIAN=y
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200"
+CONFIG_LOGLEVEL=7
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_SYS_PROMPT="pcb091 # "
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_DHCP=y
+# CONFIG_NET_TFTP_VARS is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:512k(UBoot),256k(Env),256k(conf),6m@1m(linux)"
+# CONFIG_ISO_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="luton_pcb091"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_SOFT_SPI=y
+CONFIG_LZMA=y
diff --git a/configs/mscc_ocelot_defconfig b/configs/mscc_ocelot_defconfig
new file mode 100644
index 0000000..5fa74db
--- /dev/null
+++ b/configs/mscc_ocelot_defconfig
@@ -0,0 +1,67 @@
+CONFIG_MIPS=y
+CONFIG_SYS_TEXT_BASE=0x40000000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0x70100000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_ARCH_MSCC=y
+CONFIG_TARGET_OCELOT_PCB123=y
+CONFIG_SYS_LITTLE_ENDIAN=y
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200"
+CONFIG_LOGLEVEL=7
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_SYS_PROMPT="pcb123 # "
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_DHCP=y
+# CONFIG_NET_TFTP_VARS is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:512k(UBoot),256k(Env),256k(conf),15m(linux),15m(linux.bk)"
+CONFIG_CMD_UBI=y
+# CONFIG_CMD_UBIFS is not set
+# CONFIG_ISO_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="ocelot_pcb123"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_LZMA=y
diff --git a/configs/mscc_ocelot_pcb120_defconfig b/configs/mscc_ocelot_pcb120_defconfig
new file mode 100644
index 0000000..c5a9f96
--- /dev/null
+++ b/configs/mscc_ocelot_pcb120_defconfig
@@ -0,0 +1,60 @@
+CONFIG_MIPS=y
+CONFIG_SYS_TEXT_BASE=0x40000000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ARCH_MSCC=y
+CONFIG_SYS_LITTLE_ENDIAN=y
+CONFIG_FIT=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200"
+CONFIG_LOGLEVEL=7
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_SYS_PROMPT="pcb120 # "
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_DHCP=y
+# CONFIG_NET_TFTP_VARS is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:512k(UBoot),256k(Env),256k(conf),15m(linux),15m(linux.bk)"
+CONFIG_CMD_UBI=y
+# CONFIG_CMD_UBIFS is not set
+# CONFIG_ISO_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="ocelot_pcb120"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DESIGNWARE_SPI=y
+CONFIG_LZMA=y
diff --git a/configs/netgear_dgnd3700v2_ram_defconfig b/configs/netgear_dgnd3700v2_ram_defconfig
index 1abc869..0f3914f 100644
--- a/configs/netgear_dgnd3700v2_ram_defconfig
+++ b/configs/netgear_dgnd3700v2_ram_defconfig
@@ -27,17 +27,23 @@
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="netgear,dgnd3700v2"
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_BCM6345_GPIO=y
CONFIG_LED=y
CONFIG_LED_BCM6328=y
CONFIG_LED_BLINK=y
CONFIG_LED_GPIO=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
CONFIG_PHY=y
CONFIG_BCM6368_USBH_PHY=y
CONFIG_POWER_DOMAIN=y
diff --git a/configs/sagem_f@st1704_ram_defconfig b/configs/sagem_f@st1704_ram_defconfig
index 91a9663..8c36f5d 100644
--- a/configs/sagem_f@st1704_ram_defconfig
+++ b/configs/sagem_f@st1704_ram_defconfig
@@ -27,11 +27,14 @@
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_SF=y
CONFIG_CMD_SPI=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="sagem,f@st1704"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_BCM6345_GPIO=y
CONFIG_LED=y
@@ -40,6 +43,9 @@
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
CONFIG_DM_RESET=y
CONFIG_RESET_BCM6345=y
# CONFIG_SPL_SERIAL_PRESENT is not set
diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig
index 12adfb0..3962287 100644
--- a/configs/sfr_nb4-ser_ram_defconfig
+++ b/configs/sfr_nb4-ser_ram_defconfig
@@ -26,11 +26,14 @@
CONFIG_CMD_MEMINFO=y
# CONFIG_CMD_LOADS is not set
CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
# CONFIG_CMD_MISC is not set
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
CONFIG_DM_GPIO=y
CONFIG_BCM6345_GPIO=y
CONFIG_LED=y
@@ -42,6 +45,9 @@
CONFIG_CFI_FLASH=y
CONFIG_SYS_FLASH_PROTECTION=y
CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
CONFIG_PHY=y
CONFIG_BCM6358_USBH_PHY=y
CONFIG_DM_RESET=y
diff --git a/doc/README.ae350 b/doc/README.ae350
index fe75b80..189a6b7 100644
--- a/doc/README.ae350
+++ b/doc/README.ae350
@@ -25,7 +25,7 @@
build:
1. Prepare the toolchains and make sure the $PATH to toolchains is correct.
-2. Use `make ax25-ae350_defconfig` in u-boot root to build the image.
+2. Use `make ae350_rv[32|64]_defconfig` in u-boot root to build the image for 32 or 64 bit.
Verification
====================
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
index d405200..3d5729f 100644
--- a/drivers/cpu/Kconfig
+++ b/drivers/cpu/Kconfig
@@ -13,3 +13,9 @@
select CLK_MPC83XX
help
Support CPU cores for SoCs of the MPC83xx series.
+
+config CPU_RISCV
+ bool "Enable RISC-V CPU driver"
+ depends on CPU && RISCV
+ help
+ Support CPU cores for RISC-V architecture.
diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile
index 858b037..be0300c 100644
--- a/drivers/cpu/Makefile
+++ b/drivers/cpu/Makefile
@@ -8,4 +8,5 @@
obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
+obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
obj-$(CONFIG_SANDBOX) += cpu_sandbox.o
diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c
new file mode 100644
index 0000000..5e15df5
--- /dev/null
+++ b/drivers/cpu/riscv_cpu.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size)
+{
+ const char *isa;
+
+ isa = dev_read_string(dev, "riscv,isa");
+ if (size < (strlen(isa) + 1))
+ return -ENOSPC;
+
+ strcpy(buf, isa);
+
+ return 0;
+}
+
+static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info)
+{
+ const char *mmu;
+
+ dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq);
+
+ mmu = dev_read_string(dev, "mmu-type");
+ if (!mmu)
+ info->features |= BIT(CPU_FEAT_MMU);
+
+ return 0;
+}
+
+static int riscv_cpu_get_count(struct udevice *dev)
+{
+ ofnode node;
+ int num = 0;
+
+ ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
+ const char *device_type;
+
+ device_type = ofnode_read_string(node, "device_type");
+ if (!device_type)
+ continue;
+ if (strcmp(device_type, "cpu") == 0)
+ num++;
+ }
+
+ return num;
+}
+
+static int riscv_cpu_bind(struct udevice *dev)
+{
+ struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+ struct driver *drv;
+ int ret;
+
+ /* save the hart id */
+ plat->cpu_id = dev_read_addr(dev);
+
+ /* first examine the property in current cpu node */
+ ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq);
+ /* if not found, then look at the parent /cpus node */
+ if (ret)
+ dev_read_u32(dev->parent, "timebase-frequency",
+ &plat->timebase_freq);
+
+ /*
+ * Bind riscv-timer driver on hart 0
+ *
+ * We only instantiate one timer device which is enough for U-Boot.
+ * Pass the "timebase-frequency" value as the driver data for the
+ * timer device.
+ *
+ * Return value is not checked since it's possible that the timer
+ * driver is not included.
+ */
+ if (!plat->cpu_id && plat->timebase_freq) {
+ drv = lists_driver_lookup_name("riscv_timer");
+ if (!drv) {
+ debug("Cannot find the timer driver, not included?\n");
+ return 0;
+ }
+
+ device_bind_with_driver_data(dev, drv, "riscv_timer",
+ plat->timebase_freq, ofnode_null(),
+ NULL);
+ }
+
+ return 0;
+}
+
+static const struct cpu_ops riscv_cpu_ops = {
+ .get_desc = riscv_cpu_get_desc,
+ .get_info = riscv_cpu_get_info,
+ .get_count = riscv_cpu_get_count,
+};
+
+static const struct udevice_id riscv_cpu_ids[] = {
+ { .compatible = "riscv" },
+ { }
+};
+
+U_BOOT_DRIVER(riscv_cpu) = {
+ .name = "riscv_cpu",
+ .id = UCLASS_CPU,
+ .of_match = riscv_cpu_ids,
+ .bind = riscv_cpu_bind,
+ .ops = &riscv_cpu_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8a4162e..1820676 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -26,6 +26,15 @@
Enable support for a test DMA uclass implementation. It stimulates
DMA transfer by simple copying data between channels.
+config BCM6348_IUDMA
+ bool "BCM6348 IUDMA driver"
+ depends on ARCH_BMIPS
+ select DMA_CHANNELS
+ help
+ Enable the BCM6348 IUDMA driver.
+ This driver support data transfer from devices to
+ memory and from memory to devices.
+
config TI_EDMA3
bool "TI EDMA3 driver"
help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index aff31f9..b5f9147 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
obj-$(CONFIG_APBH_DMA) += apbh_dma.o
+obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
obj-$(CONFIG_FSL_DMA) += fsl_dma.o
obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
new file mode 100644
index 0000000..1d3c192
--- /dev/null
+++ b/drivers/dma/bcm6348-iudma.c
@@ -0,0 +1,642 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/dma/bcm63xx-iudma.c:
+ * Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright (C) 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
+ * Copyright (C) 2010 Broadcom Corporation
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma-uclass.h>
+#include <memalign.h>
+#include <reset.h>
+#include <asm/io.h>
+
+#define DMA_RX_DESC 6
+#define DMA_TX_DESC 1
+
+/* DMA Channels */
+#define DMA_CHAN_FLOWC(x) ((x) >> 1)
+#define DMA_CHAN_MAX 16
+#define DMA_CHAN_SIZE 0x10
+#define DMA_CHAN_TOUT 500
+
+/* DMA Global Configuration register */
+#define DMA_CFG_REG 0x00
+#define DMA_CFG_ENABLE_SHIFT 0
+#define DMA_CFG_ENABLE_MASK (1 << DMA_CFG_ENABLE_SHIFT)
+#define DMA_CFG_FLOWC_ENABLE(x) BIT(DMA_CHAN_FLOWC(x) + 1)
+#define DMA_CFG_NCHANS_SHIFT 24
+#define DMA_CFG_NCHANS_MASK (0xf << DMA_CFG_NCHANS_SHIFT)
+
+/* DMA Global Flow Control registers */
+#define DMA_FLOWC_THR_LO_REG(x) (0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_THR_HI_REG(x) (0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_ALLOC_REG(x) (0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_ALLOC_FORCE_SHIFT 31
+#define DMA_FLOWC_ALLOC_FORCE_MASK (1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
+
+/* DMA Global Reset register */
+#define DMA_RST_REG 0x34
+#define DMA_RST_CHAN_SHIFT 0
+#define DMA_RST_CHAN_MASK(x) (1 << x)
+
+/* DMA Channel Configuration register */
+#define DMAC_CFG_REG(x) (DMA_CHAN_SIZE * (x) + 0x00)
+#define DMAC_CFG_ENABLE_SHIFT 0
+#define DMAC_CFG_ENABLE_MASK (1 << DMAC_CFG_ENABLE_SHIFT)
+#define DMAC_CFG_PKT_HALT_SHIFT 1
+#define DMAC_CFG_PKT_HALT_MASK (1 << DMAC_CFG_PKT_HALT_SHIFT)
+#define DMAC_CFG_BRST_HALT_SHIFT 2
+#define DMAC_CFG_BRST_HALT_MASK (1 << DMAC_CFG_BRST_HALT_SHIFT)
+
+/* DMA Channel Max Burst Length register */
+#define DMAC_BURST_REG(x) (DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA SRAM Descriptor Ring Start register */
+#define DMAS_RSTART_REG(x) (DMA_CHAN_SIZE * (x) + 0x00)
+
+/* DMA SRAM State/Bytes done/ring offset register */
+#define DMAS_STATE_DATA_REG(x) (DMA_CHAN_SIZE * (x) + 0x04)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_LEN_STATUS_REG(x) (DMA_CHAN_SIZE * (x) + 0x08)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_BASE_BUFPTR_REG(x) (DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA Descriptor Status */
+#define DMAD_ST_CRC_SHIFT 8
+#define DMAD_ST_CRC_MASK (1 << DMAD_ST_CRC_SHIFT)
+#define DMAD_ST_WRAP_SHIFT 12
+#define DMAD_ST_WRAP_MASK (1 << DMAD_ST_WRAP_SHIFT)
+#define DMAD_ST_SOP_SHIFT 13
+#define DMAD_ST_SOP_MASK (1 << DMAD_ST_SOP_SHIFT)
+#define DMAD_ST_EOP_SHIFT 14
+#define DMAD_ST_EOP_MASK (1 << DMAD_ST_EOP_SHIFT)
+#define DMAD_ST_OWN_SHIFT 15
+#define DMAD_ST_OWN_MASK (1 << DMAD_ST_OWN_SHIFT)
+
+#define DMAD6348_ST_OV_ERR_SHIFT 0
+#define DMAD6348_ST_OV_ERR_MASK (1 << DMAD6348_ST_OV_ERR_SHIFT)
+#define DMAD6348_ST_CRC_ERR_SHIFT 1
+#define DMAD6348_ST_CRC_ERR_MASK (1 << DMAD6348_ST_CRC_ERR_SHIFT)
+#define DMAD6348_ST_RX_ERR_SHIFT 2
+#define DMAD6348_ST_RX_ERR_MASK (1 << DMAD6348_ST_RX_ERR_SHIFT)
+#define DMAD6348_ST_OS_ERR_SHIFT 4
+#define DMAD6348_ST_OS_ERR_MASK (1 << DMAD6348_ST_OS_ERR_SHIFT)
+#define DMAD6348_ST_UN_ERR_SHIFT 9
+#define DMAD6348_ST_UN_ERR_MASK (1 << DMAD6348_ST_UN_ERR_SHIFT)
+
+struct bcm6348_dma_desc {
+ uint16_t length;
+ uint16_t status;
+ uint32_t address;
+};
+
+struct bcm6348_chan_priv {
+ void __iomem *dma_ring;
+ uint8_t dma_ring_size;
+ uint8_t desc_id;
+ uint8_t desc_cnt;
+ bool *busy_desc;
+ bool running;
+};
+
+struct bcm6348_iudma_hw {
+ uint16_t err_mask;
+};
+
+struct bcm6348_iudma_priv {
+ const struct bcm6348_iudma_hw *hw;
+ void __iomem *base;
+ void __iomem *chan;
+ void __iomem *sram;
+ struct bcm6348_chan_priv **ch_priv;
+ uint8_t n_channels;
+};
+
+static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
+{
+ return !(ch & 1);
+}
+
+static inline void bcm6348_iudma_fdc(void *ptr, ulong size)
+{
+ ulong start = (ulong) ptr;
+
+ flush_dcache_range(start, start + size);
+}
+
+static inline void bcm6348_iudma_idc(void *ptr, ulong size)
+{
+ ulong start = (ulong) ptr;
+
+ invalidate_dcache_range(start, start + size);
+}
+
+static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
+ uint8_t ch)
+{
+ unsigned int timeout = DMA_CHAN_TOUT;
+
+ do {
+ uint32_t cfg, halt;
+
+ if (timeout > DMA_CHAN_TOUT / 2)
+ halt = DMAC_CFG_PKT_HALT_MASK;
+ else
+ halt = DMAC_CFG_BRST_HALT_MASK;
+
+ /* try to stop dma channel */
+ writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
+ mb();
+
+ /* check if channel was stopped */
+ cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
+ if (!(cfg & DMAC_CFG_ENABLE_MASK))
+ break;
+
+ udelay(1);
+ } while (--timeout);
+
+ if (!timeout)
+ pr_err("unable to stop channel %u\n", ch);
+
+ /* reset dma channel */
+ setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+ mb();
+ clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+}
+
+static int bcm6348_iudma_disable(struct dma *dma)
+{
+ struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+
+ /* stop dma channel */
+ bcm6348_iudma_chan_stop(priv, dma->id);
+
+ /* dma flow control */
+ if (bcm6348_iudma_chan_is_rx(dma->id))
+ writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
+ DMA_FLOWC_ALLOC_REG(dma->id));
+
+ /* init channel config */
+ ch_priv->running = false;
+ ch_priv->desc_id = 0;
+ if (bcm6348_iudma_chan_is_rx(dma->id))
+ ch_priv->desc_cnt = 0;
+ else
+ ch_priv->desc_cnt = ch_priv->dma_ring_size;
+
+ return 0;
+}
+
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+ const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+ struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+ uint8_t i;
+
+ /* dma ring init */
+ for (i = 0; i < ch_priv->desc_cnt; i++) {
+ if (bcm6348_iudma_chan_is_rx(dma->id)) {
+ ch_priv->busy_desc[i] = false;
+ dma_desc->status |= DMAD_ST_OWN_MASK;
+ } else {
+ dma_desc->status = 0;
+ dma_desc->length = 0;
+ dma_desc->address = 0;
+ }
+
+ if (i == ch_priv->desc_cnt - 1)
+ dma_desc->status |= DMAD_ST_WRAP_MASK;
+
+ dma_desc++;
+ }
+
+ /* init to first descriptor */
+ ch_priv->desc_id = 0;
+
+ /* force cache writeback */
+ bcm6348_iudma_fdc(ch_priv->dma_ring,
+ sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+ /* clear sram */
+ writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
+ writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
+ writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
+
+ /* set dma ring start */
+ writel_be(virt_to_phys(ch_priv->dma_ring),
+ priv->sram + DMAS_RSTART_REG(dma->id));
+
+ /* set flow control */
+ if (bcm6348_iudma_chan_is_rx(dma->id)) {
+ u32 val;
+
+ setbits_be32(priv->base + DMA_CFG_REG,
+ DMA_CFG_FLOWC_ENABLE(dma->id));
+
+ val = ch_priv->desc_cnt / 3;
+ writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
+
+ val = (ch_priv->desc_cnt * 2) / 3;
+ writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
+
+ writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+ }
+
+ /* set dma max burst */
+ writel_be(ch_priv->desc_cnt,
+ priv->chan + DMAC_BURST_REG(dma->id));
+
+ /* kick rx dma channel */
+ if (bcm6348_iudma_chan_is_rx(dma->id))
+ setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
+ DMAC_CFG_ENABLE_MASK);
+
+ /* channel is now enabled */
+ ch_priv->running = true;
+
+ return 0;
+}
+
+static int bcm6348_iudma_request(struct dma *dma)
+{
+ const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ struct bcm6348_chan_priv *ch_priv;
+
+ /* check if channel is valid */
+ if (dma->id >= priv->n_channels)
+ return -ENODEV;
+
+ /* alloc channel private data */
+ priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
+ if (!priv->ch_priv[dma->id])
+ return -ENOMEM;
+ ch_priv = priv->ch_priv[dma->id];
+
+ /* alloc dma ring */
+ if (bcm6348_iudma_chan_is_rx(dma->id))
+ ch_priv->dma_ring_size = DMA_RX_DESC;
+ else
+ ch_priv->dma_ring_size = DMA_TX_DESC;
+
+ ch_priv->dma_ring =
+ malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
+ ch_priv->dma_ring_size);
+ if (!ch_priv->dma_ring)
+ return -ENOMEM;
+
+ /* init channel config */
+ ch_priv->running = false;
+ ch_priv->desc_id = 0;
+ if (bcm6348_iudma_chan_is_rx(dma->id)) {
+ ch_priv->desc_cnt = 0;
+ ch_priv->busy_desc = calloc(ch_priv->desc_cnt, sizeof(bool));
+ } else {
+ ch_priv->desc_cnt = ch_priv->dma_ring_size;
+ ch_priv->busy_desc = NULL;
+ }
+
+ return 0;
+}
+
+static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
+{
+ const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ const struct bcm6348_iudma_hw *hw = priv->hw;
+ struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+ struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring;
+ int ret;
+
+ /* get dma ring descriptor address */
+ dma_desc += ch_priv->desc_id;
+
+ /* invalidate cache data */
+ bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
+
+ /* check dma own */
+ if (dma_desc->status & DMAD_ST_OWN_MASK)
+ return -EAGAIN;
+
+ /* check pkt */
+ if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
+ !(dma_desc->status & DMAD_ST_SOP_MASK) ||
+ (dma_desc->status & hw->err_mask)) {
+ pr_err("invalid pkt received (ch=%ld desc=%u) (st=%04x)\n",
+ dma->id, ch_priv->desc_id, dma_desc->status);
+ ret = -EAGAIN;
+ } else {
+ /* set dma buffer address */
+ *dst = phys_to_virt(dma_desc->address);
+
+ /* invalidate cache data */
+ bcm6348_iudma_idc(*dst, dma_desc->length);
+
+ /* return packet length */
+ ret = dma_desc->length;
+ }
+
+ /* busy dma descriptor */
+ ch_priv->busy_desc[ch_priv->desc_id] = true;
+
+ /* increment dma descriptor */
+ ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
+
+ return ret;
+}
+
+static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
+ void *metadata)
+{
+ const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+ struct bcm6348_dma_desc *dma_desc;
+ uint16_t status;
+
+ /* flush cache */
+ bcm6348_iudma_fdc(src, len);
+
+ /* get dma ring descriptor address */
+ dma_desc = ch_priv->dma_ring;
+ dma_desc += ch_priv->desc_id;
+
+ /* config dma descriptor */
+ status = (DMAD_ST_OWN_MASK |
+ DMAD_ST_EOP_MASK |
+ DMAD_ST_CRC_MASK |
+ DMAD_ST_SOP_MASK);
+ if (ch_priv->desc_id == ch_priv->desc_cnt - 1)
+ status |= DMAD_ST_WRAP_MASK;
+
+ /* set dma descriptor */
+ dma_desc->address = virt_to_phys(src);
+ dma_desc->length = len;
+ dma_desc->status = status;
+
+ /* flush cache */
+ bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
+
+ /* kick tx dma channel */
+ setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+ /* poll dma status */
+ do {
+ /* invalidate cache */
+ bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
+
+ if (!(dma_desc->status & DMAD_ST_OWN_MASK))
+ break;
+ } while(1);
+
+ /* increment dma descriptor */
+ ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
+
+ return 0;
+}
+
+static int bcm6348_iudma_free_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+ const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+ struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+ uint16_t status;
+ uint8_t i;
+ u32 cfg;
+
+ /* get dirty dma descriptor */
+ for (i = 0; i < ch_priv->desc_cnt; i++) {
+ if (phys_to_virt(dma_desc->address) == dst)
+ break;
+
+ dma_desc++;
+ }
+
+ /* dma descriptor not found */
+ if (i == ch_priv->desc_cnt) {
+ pr_err("dirty dma descriptor not found\n");
+ return -ENOENT;
+ }
+
+ /* invalidate cache */
+ bcm6348_iudma_idc(ch_priv->dma_ring,
+ sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+ /* free dma descriptor */
+ ch_priv->busy_desc[i] = false;
+
+ status = DMAD_ST_OWN_MASK;
+ if (i == ch_priv->desc_cnt - 1)
+ status |= DMAD_ST_WRAP_MASK;
+
+ dma_desc->status |= status;
+ dma_desc->length = PKTSIZE_ALIGN;
+
+ /* tell dma we allocated one buffer */
+ writel_be(1, DMA_FLOWC_ALLOC_REG(dma->id));
+
+ /* flush cache */
+ bcm6348_iudma_fdc(ch_priv->dma_ring,
+ sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+ /* kick rx dma channel if disabled */
+ cfg = readl_be(priv->chan + DMAC_CFG_REG(dma->id));
+ if (!(cfg & DMAC_CFG_ENABLE_MASK))
+ setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
+ DMAC_CFG_ENABLE_MASK);
+
+ return 0;
+}
+
+static int bcm6348_iudma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+ const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+ struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+
+ /* no more dma descriptors available */
+ if (ch_priv->desc_cnt == ch_priv->dma_ring_size) {
+ pr_err("max number of buffers reached\n");
+ return -EINVAL;
+ }
+
+ /* get next dma descriptor */
+ dma_desc += ch_priv->desc_cnt;
+
+ /* init dma descriptor */
+ dma_desc->address = virt_to_phys(dst);
+ dma_desc->length = size;
+ dma_desc->status = 0;
+
+ /* flush cache */
+ bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
+
+ /* increment dma descriptors */
+ ch_priv->desc_cnt++;
+
+ return 0;
+}
+
+static int bcm6348_iudma_prepare_rcv_buf(struct dma *dma, void *dst,
+ size_t size)
+{
+ const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+ struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+
+ /* only add new rx buffers if channel isn't running */
+ if (ch_priv->running)
+ return bcm6348_iudma_free_rcv_buf(dma, dst, size);
+ else
+ return bcm6348_iudma_add_rcv_buf(dma, dst, size);
+}
+
+static const struct dma_ops bcm6348_iudma_ops = {
+ .disable = bcm6348_iudma_disable,
+ .enable = bcm6348_iudma_enable,
+ .prepare_rcv_buf = bcm6348_iudma_prepare_rcv_buf,
+ .request = bcm6348_iudma_request,
+ .receive = bcm6348_iudma_receive,
+ .send = bcm6348_iudma_send,
+};
+
+static const struct bcm6348_iudma_hw bcm6348_hw = {
+ .err_mask = (DMAD6348_ST_OV_ERR_MASK |
+ DMAD6348_ST_CRC_ERR_MASK |
+ DMAD6348_ST_RX_ERR_MASK |
+ DMAD6348_ST_OS_ERR_MASK |
+ DMAD6348_ST_UN_ERR_MASK),
+};
+
+static const struct bcm6348_iudma_hw bcm6368_hw = {
+ .err_mask = 0,
+};
+
+static const struct udevice_id bcm6348_iudma_ids[] = {
+ {
+ .compatible = "brcm,bcm6348-iudma",
+ .data = (ulong)&bcm6348_hw,
+ }, {
+ .compatible = "brcm,bcm6368-iudma",
+ .data = (ulong)&bcm6368_hw,
+ }, { /* sentinel */ }
+};
+
+static int bcm6348_iudma_probe(struct udevice *dev)
+{
+ struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
+ const struct bcm6348_iudma_hw *hw =
+ (const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
+ uint8_t ch;
+ int i;
+
+ uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
+ DMA_SUPPORTS_MEM_TO_DEV);
+ priv->hw = hw;
+
+ /* dma global base address */
+ priv->base = dev_remap_addr_name(dev, "dma");
+ if (!priv->base)
+ return -EINVAL;
+
+ /* dma channels base address */
+ priv->chan = dev_remap_addr_name(dev, "dma-channels");
+ if (!priv->chan)
+ return -EINVAL;
+
+ /* dma sram base address */
+ priv->sram = dev_remap_addr_name(dev, "dma-sram");
+ if (!priv->sram)
+ return -EINVAL;
+
+ /* get number of channels */
+ priv->n_channels = dev_read_u32_default(dev, "dma-channels", 8);
+ if (priv->n_channels > DMA_CHAN_MAX)
+ return -EINVAL;
+
+ /* try to enable clocks */
+ for (i = 0; ; i++) {
+ struct clk clk;
+ int ret;
+
+ ret = clk_get_by_index(dev, i, &clk);
+ if (ret < 0)
+ break;
+
+ ret = clk_enable(&clk);
+ if (ret < 0) {
+ pr_err("error enabling clock %d\n", i);
+ return ret;
+ }
+
+ ret = clk_free(&clk);
+ if (ret < 0) {
+ pr_err("error freeing clock %d\n", i);
+ return ret;
+ }
+ }
+
+ /* try to perform resets */
+ for (i = 0; ; i++) {
+ struct reset_ctl reset;
+ int ret;
+
+ ret = reset_get_by_index(dev, i, &reset);
+ if (ret < 0)
+ break;
+
+ ret = reset_deassert(&reset);
+ if (ret < 0) {
+ pr_err("error deasserting reset %d\n", i);
+ return ret;
+ }
+
+ ret = reset_free(&reset);
+ if (ret < 0) {
+ pr_err("error freeing reset %d\n", i);
+ return ret;
+ }
+ }
+
+ /* disable dma controller */
+ clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+ /* alloc channel private data pointers */
+ priv->ch_priv = calloc(priv->n_channels,
+ sizeof(struct bcm6348_chan_priv*));
+ if (!priv->ch_priv)
+ return -ENOMEM;
+
+ /* stop dma channels */
+ for (ch = 0; ch < priv->n_channels; ch++)
+ bcm6348_iudma_chan_stop(priv, ch);
+
+ /* enable dma controller */
+ setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_iudma) = {
+ .name = "bcm6348_iudma",
+ .id = UCLASS_DMA,
+ .of_match = bcm6348_iudma_ids,
+ .ops = &bcm6348_iudma_ops,
+ .priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
+ .probe = bcm6348_iudma_probe,
+};
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 35344e5..c8c6c60 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -99,6 +99,13 @@
help
Support for the LPC32XX GPIO driver.
+config MSCC_BITBANG_SPI_GPIO
+ bool "Microsemi bitbang spi GPIO driver"
+ depends on DM_GPIO && SOC_VCOREIII
+ help
+ Support controlling the GPIO used for SPI bitbang by software. Can
+ be used by the VCoreIII SoCs, but it was mainly useful for Luton.
+
config MSM_GPIO
bool "Qualcomm GPIO driver"
depends on DM_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 7ed9a4e..61feda1 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -59,3 +59,4 @@
obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o
obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o
obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o
+obj-$(CONFIG_MSCC_BITBANG_SPI_GPIO) += gpio-mscc-bitbang-spi.o
diff --git a/drivers/gpio/gpio-mscc-bitbang-spi.c b/drivers/gpio/gpio-mscc-bitbang-spi.c
new file mode 100644
index 0000000..b675f90
--- /dev/null
+++ b/drivers/gpio/gpio-mscc-bitbang-spi.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs pinctrl driver
+ *
+ * Author: <gregory.clement@bootlin.com>
+ * License: Dual MIT/GPL
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <asm-generic/gpio.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <errno.h>
+
+enum {
+ SDI,
+ CS0,
+ CS1,
+ CS2,
+ CS3,
+ SDO,
+ SCK
+};
+
+static const int pinmap[] = { 0, 5, 6, 7, 8, 10, 12 };
+
+#define SW_SPI_CSn_OE 0x1E /* bits 1 to 4 */
+#define SW_SPI_CS0_OE BIT(1)
+#define SW_SPI_SDO_OE BIT(9)
+#define SW_SPI_SCK_OE BIT(11)
+#define SW_PIN_CTRL_MODE BIT(13)
+
+struct mscc_bb_spi_gpio {
+ void __iomem *regs;
+ u32 cache_val;
+};
+
+static int mscc_bb_spi_gpio_set(struct udevice *dev, unsigned oft, int val)
+{
+ struct mscc_bb_spi_gpio *gpio = dev_get_priv(dev);
+
+ if (val)
+ gpio->cache_val |= BIT(pinmap[oft]);
+ else
+ gpio->cache_val &= ~BIT(pinmap[oft]);
+
+ writel(gpio->cache_val, gpio->regs);
+
+ return 0;
+}
+
+static int mscc_bb_spi_gpio_direction_output(struct udevice *dev, unsigned oft,
+ int val)
+{
+ if (oft == 0) {
+ pr_err("SW_SPI_DSI can't be used as output\n");
+ return -ENOTSUPP;
+ }
+
+ mscc_bb_spi_gpio_set(dev, oft, val);
+
+ return 0;
+}
+
+static int mscc_bb_spi_gpio_direction_input(struct udevice *dev, unsigned oft)
+{
+ return 0;
+}
+
+static int mscc_bb_spi_gpio_get(struct udevice *dev, unsigned int oft)
+{
+ struct mscc_bb_spi_gpio *gpio = dev_get_priv(dev);
+ u32 val = readl(gpio->regs);
+
+ return !!(val & BIT(pinmap[oft]));
+}
+
+static const struct dm_gpio_ops mscc_bb_spi_gpio_ops = {
+ .direction_output = mscc_bb_spi_gpio_direction_output,
+ .direction_input = mscc_bb_spi_gpio_direction_input,
+ .set_value = mscc_bb_spi_gpio_set,
+ .get_value = mscc_bb_spi_gpio_get,
+};
+
+static int mscc_bb_spi_gpio_probe(struct udevice *dev)
+{
+ struct mscc_bb_spi_gpio *gpio = dev_get_priv(dev);
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ gpio->regs = dev_remap_addr(dev);
+ if (!gpio->regs)
+ return -EINVAL;
+
+ uc_priv->bank_name = dev->name;
+ uc_priv->gpio_count = ARRAY_SIZE(pinmap);
+ /*
+ * Enable software mode to control the SPI pin, enables the
+ * output mode for most of the pin and initialize the cache
+ * value in the same time
+ */
+
+ gpio->cache_val = SW_PIN_CTRL_MODE | SW_SPI_SCK_OE | SW_SPI_SDO_OE |
+ SW_SPI_CS0_OE;
+ writel(gpio->cache_val, gpio->regs);
+
+ return 0;
+}
+
+static const struct udevice_id mscc_bb_spi_gpio_ids[] = {
+ {.compatible = "mscc,spi-bitbang-gpio"},
+ {}
+};
+
+U_BOOT_DRIVER(gpio_mscc_bb_spi) = {
+ .name = "gpio-mscc-spi-bitbang",
+ .id = UCLASS_GPIO,
+ .ops = &mscc_bb_spi_gpio_ops,
+ .probe = mscc_bb_spi_gpio_probe,
+ .of_match = of_match_ptr(mscc_bb_spi_gpio_ids),
+ .priv_auto_alloc_size = sizeof(struct mscc_bb_spi_gpio),
+};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 48febc4..704c8dd 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -120,6 +120,12 @@
Security Monitor can be transitioned on any security failures,
like software violations or hardware security violations.
+config JZ4780_EFUSE
+ bool "Ingenic JZ4780 eFUSE support"
+ depends on ARCH_JZ47XX
+ help
+ This selects support for the eFUSE on Ingenic JZ4780 SoCs.
+
config MXC_OCOTP
bool "Enable MXC OCOTP Driver"
help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 302d441..6bdf505 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,3 +62,4 @@
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
+obj-$(CONFIG_JZ4780_EFUSE) += jz4780_efuse.o
diff --git a/drivers/misc/jz4780_efuse.c b/drivers/misc/jz4780_efuse.c
new file mode 100644
index 0000000..bc3dc93
--- /dev/null
+++ b/drivers/misc/jz4780_efuse.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * JZ4780 EFUSE driver
+ *
+ * Copyright (c) 2014 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <errno.h>
+#include <mach/jz4780.h>
+#include <wait_bit.h>
+
+#define EFUSE_EFUCTRL 0xd0
+#define EFUSE_EFUCFG 0xd4
+#define EFUSE_EFUSTATE 0xd8
+#define EFUSE_EFUDATA(n) (0xdc + ((n) * 4))
+
+#define EFUSE_EFUCTRL_RD_EN BIT(0)
+#define EFUSE_EFUCTRL_LEN_BIT 16
+#define EFUSE_EFUCTRL_LEN_MASK 0x1f
+#define EFUSE_EFUCTRL_ADDR_BIT 21
+#define EFUSE_EFUCTRL_ADDR_MASK 0x1ff
+#define EFUSE_EFUCTRL_CS BIT(30)
+
+#define EFUSE_EFUCFG_RD_STROBE_BIT 16
+#define EFUSE_EFUCFG_RD_STROBE_MASK 0xf
+#define EFUSE_EFUCFG_RD_ADJ_BIT 20
+#define EFUSE_EFUCFG_RD_ADJ_MASK 0xf
+
+#define EFUSE_EFUSTATE_RD_DONE BIT(0)
+
+static void jz4780_efuse_read_chunk(size_t addr, size_t count, u8 *buf)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ size_t i;
+ u32 val;
+ int ret;
+
+ val = EFUSE_EFUCTRL_RD_EN |
+ ((count - 1) << EFUSE_EFUCTRL_LEN_BIT) |
+ (addr << EFUSE_EFUCTRL_ADDR_BIT) |
+ ((addr > 0x200) ? EFUSE_EFUCTRL_CS : 0);
+ writel(val, regs + EFUSE_EFUCTRL);
+
+ ret = wait_for_bit_le32(regs + EFUSE_EFUSTATE,
+ EFUSE_EFUSTATE_RD_DONE, true, 10000, false);
+ if (ret)
+ return;
+
+ if ((count % 4) == 0) {
+ for (i = 0; i < count / 4; i++) {
+ val = readl(regs + EFUSE_EFUDATA(i));
+ put_unaligned(val, (u32 *)(buf + (i * 4)));
+ }
+ } else {
+ val = readl(regs + EFUSE_EFUDATA(0));
+ if (count > 2)
+ buf[2] = (val >> 16) & 0xff;
+ if (count > 1)
+ buf[1] = (val >> 8) & 0xff;
+ buf[0] = val & 0xff;
+ }
+}
+
+static inline int jz4780_efuse_chunk_size(size_t count)
+{
+ if (count >= 32)
+ return 32;
+ else if ((count / 4) > 0)
+ return (count / 4) * 4;
+ else
+ return count % 4;
+}
+
+void jz4780_efuse_read(size_t addr, size_t count, u8 *buf)
+{
+ size_t chunk;
+
+ while (count > 0) {
+ chunk = jz4780_efuse_chunk_size(count);
+ jz4780_efuse_read_chunk(addr, chunk, buf);
+ addr += chunk;
+ buf += chunk;
+ count -= chunk;
+ }
+}
+
+void jz4780_efuse_init(u32 ahb2_rate)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ u32 rd_adj, rd_strobe, tmp;
+
+ rd_adj = (((6500 * (ahb2_rate / 1000000)) / 1000000) + 0xf) / 2;
+ tmp = (((35000 * (ahb2_rate / 1000000)) / 1000000) - 4) - rd_adj;
+ rd_strobe = ((tmp + 0xf) / 2 < 7) ? 7 : (tmp + 0xf) / 2;
+
+ tmp = (rd_adj << EFUSE_EFUCFG_RD_ADJ_BIT) |
+ (rd_strobe << EFUSE_EFUCFG_RD_STROBE_BIT);
+ writel(tmp, regs + EFUSE_EFUCFG);
+}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index fbd1396..496b2cb 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -332,6 +332,12 @@
If unsure, say N.
+config JZ47XX_MMC
+ bool "Ingenic JZ47xx SD/MMC Host Controller support"
+ depends on ARCH_JZ47XX
+ help
+ This selects support for the SD Card Controller on Ingenic JZ47xx SoCs.
+
config MMC_SANDBOX
bool "Sandbox MMC support"
depends on SANDBOX
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 801a26d..7892c46 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -40,6 +40,7 @@
obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
+obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
# SDHCI
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c
new file mode 100644
index 0000000..3132c3e
--- /dev/null
+++ b/drivers/mmc/jz_mmc.c
@@ -0,0 +1,488 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Ingenic JZ MMC driver
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <errno.h>
+#include <mach/jz4780.h>
+#include <wait_bit.h>
+
+/* Registers */
+#define MSC_STRPCL 0x000
+#define MSC_STAT 0x004
+#define MSC_CLKRT 0x008
+#define MSC_CMDAT 0x00c
+#define MSC_RESTO 0x010
+#define MSC_RDTO 0x014
+#define MSC_BLKLEN 0x018
+#define MSC_NOB 0x01c
+#define MSC_SNOB 0x020
+#define MSC_IMASK 0x024
+#define MSC_IREG 0x028
+#define MSC_CMD 0x02c
+#define MSC_ARG 0x030
+#define MSC_RES 0x034
+#define MSC_RXFIFO 0x038
+#define MSC_TXFIFO 0x03c
+#define MSC_LPM 0x040
+#define MSC_DMAC 0x044
+#define MSC_DMANDA 0x048
+#define MSC_DMADA 0x04c
+#define MSC_DMALEN 0x050
+#define MSC_DMACMD 0x054
+#define MSC_CTRL2 0x058
+#define MSC_RTCNT 0x05c
+#define MSC_DBG 0x0fc
+
+/* MSC Clock and Control Register (MSC_STRPCL) */
+#define MSC_STRPCL_EXIT_MULTIPLE BIT(7)
+#define MSC_STRPCL_EXIT_TRANSFER BIT(6)
+#define MSC_STRPCL_START_READWAIT BIT(5)
+#define MSC_STRPCL_STOP_READWAIT BIT(4)
+#define MSC_STRPCL_RESET BIT(3)
+#define MSC_STRPCL_START_OP BIT(2)
+#define MSC_STRPCL_CLOCK_CONTROL_STOP BIT(0)
+#define MSC_STRPCL_CLOCK_CONTROL_START BIT(1)
+
+/* MSC Status Register (MSC_STAT) */
+#define MSC_STAT_AUTO_CMD_DONE BIT(31)
+#define MSC_STAT_IS_RESETTING BIT(15)
+#define MSC_STAT_SDIO_INT_ACTIVE BIT(14)
+#define MSC_STAT_PRG_DONE BIT(13)
+#define MSC_STAT_DATA_TRAN_DONE BIT(12)
+#define MSC_STAT_END_CMD_RES BIT(11)
+#define MSC_STAT_DATA_FIFO_AFULL BIT(10)
+#define MSC_STAT_IS_READWAIT BIT(9)
+#define MSC_STAT_CLK_EN BIT(8)
+#define MSC_STAT_DATA_FIFO_FULL BIT(7)
+#define MSC_STAT_DATA_FIFO_EMPTY BIT(6)
+#define MSC_STAT_CRC_RES_ERR BIT(5)
+#define MSC_STAT_CRC_READ_ERROR BIT(4)
+#define MSC_STAT_CRC_WRITE_ERROR BIT(2)
+#define MSC_STAT_CRC_WRITE_ERROR_NOSTS BIT(4)
+#define MSC_STAT_TIME_OUT_RES BIT(1)
+#define MSC_STAT_TIME_OUT_READ BIT(0)
+
+/* MSC Bus Clock Control Register (MSC_CLKRT) */
+#define MSC_CLKRT_CLK_RATE_MASK 0x7
+
+/* MSC Command Sequence Control Register (MSC_CMDAT) */
+#define MSC_CMDAT_IO_ABORT BIT(11)
+#define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << 9)
+#define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << 9)
+#define MSC_CMDAT_DMA_EN BIT(8)
+#define MSC_CMDAT_INIT BIT(7)
+#define MSC_CMDAT_BUSY BIT(6)
+#define MSC_CMDAT_STREAM_BLOCK BIT(5)
+#define MSC_CMDAT_WRITE BIT(4)
+#define MSC_CMDAT_DATA_EN BIT(3)
+#define MSC_CMDAT_RESPONSE_MASK (0x7 << 0)
+#define MSC_CMDAT_RESPONSE_NONE (0x0 << 0) /* No response */
+#define MSC_CMDAT_RESPONSE_R1 (0x1 << 0) /* Format R1 and R1b */
+#define MSC_CMDAT_RESPONSE_R2 (0x2 << 0) /* Format R2 */
+#define MSC_CMDAT_RESPONSE_R3 (0x3 << 0) /* Format R3 */
+#define MSC_CMDAT_RESPONSE_R4 (0x4 << 0) /* Format R4 */
+#define MSC_CMDAT_RESPONSE_R5 (0x5 << 0) /* Format R5 */
+#define MSC_CMDAT_RESPONSE_R6 (0x6 << 0) /* Format R6 */
+
+/* MSC Interrupts Mask Register (MSC_IMASK) */
+#define MSC_IMASK_TIME_OUT_RES BIT(9)
+#define MSC_IMASK_TIME_OUT_READ BIT(8)
+#define MSC_IMASK_SDIO BIT(7)
+#define MSC_IMASK_TXFIFO_WR_REQ BIT(6)
+#define MSC_IMASK_RXFIFO_RD_REQ BIT(5)
+#define MSC_IMASK_END_CMD_RES BIT(2)
+#define MSC_IMASK_PRG_DONE BIT(1)
+#define MSC_IMASK_DATA_TRAN_DONE BIT(0)
+
+/* MSC Interrupts Status Register (MSC_IREG) */
+#define MSC_IREG_TIME_OUT_RES BIT(9)
+#define MSC_IREG_TIME_OUT_READ BIT(8)
+#define MSC_IREG_SDIO BIT(7)
+#define MSC_IREG_TXFIFO_WR_REQ BIT(6)
+#define MSC_IREG_RXFIFO_RD_REQ BIT(5)
+#define MSC_IREG_END_CMD_RES BIT(2)
+#define MSC_IREG_PRG_DONE BIT(1)
+#define MSC_IREG_DATA_TRAN_DONE BIT(0)
+
+struct jz_mmc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
+struct jz_mmc_priv {
+ void __iomem *regs;
+ u32 flags;
+/* priv flags */
+#define JZ_MMC_BUS_WIDTH_MASK 0x3
+#define JZ_MMC_BUS_WIDTH_1 0x0
+#define JZ_MMC_BUS_WIDTH_4 0x2
+#define JZ_MMC_BUS_WIDTH_8 0x3
+#define JZ_MMC_SENT_INIT BIT(2)
+};
+
+static int jz_mmc_clock_rate(void)
+{
+ return 24000000;
+}
+
+static int jz_mmc_send_cmd(struct mmc *mmc, struct jz_mmc_priv *priv,
+ struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ u32 stat, mask, cmdat = 0;
+ int i, ret;
+
+ /* stop the clock */
+ writel(MSC_STRPCL_CLOCK_CONTROL_STOP, priv->regs + MSC_STRPCL);
+ ret = wait_for_bit_le32(priv->regs + MSC_STAT,
+ MSC_STAT_CLK_EN, false, 10000, false);
+ if (ret)
+ return ret;
+
+ writel(0, priv->regs + MSC_DMAC);
+
+ /* setup command */
+ writel(cmd->cmdidx, priv->regs + MSC_CMD);
+ writel(cmd->cmdarg, priv->regs + MSC_ARG);
+
+ if (data) {
+ /* setup data */
+ cmdat |= MSC_CMDAT_DATA_EN;
+ if (data->flags & MMC_DATA_WRITE)
+ cmdat |= MSC_CMDAT_WRITE;
+
+ writel(data->blocks, priv->regs + MSC_NOB);
+ writel(data->blocksize, priv->regs + MSC_BLKLEN);
+ } else {
+ writel(0, priv->regs + MSC_NOB);
+ writel(0, priv->regs + MSC_BLKLEN);
+ }
+
+ /* setup response */
+ switch (cmd->resp_type) {
+ case MMC_RSP_NONE:
+ break;
+ case MMC_RSP_R1:
+ case MMC_RSP_R1b:
+ cmdat |= MSC_CMDAT_RESPONSE_R1;
+ break;
+ case MMC_RSP_R2:
+ cmdat |= MSC_CMDAT_RESPONSE_R2;
+ break;
+ case MMC_RSP_R3:
+ cmdat |= MSC_CMDAT_RESPONSE_R3;
+ break;
+ default:
+ break;
+ }
+
+ if (cmd->resp_type & MMC_RSP_BUSY)
+ cmdat |= MSC_CMDAT_BUSY;
+
+ /* set init for the first command only */
+ if (!(priv->flags & JZ_MMC_SENT_INIT)) {
+ cmdat |= MSC_CMDAT_INIT;
+ priv->flags |= JZ_MMC_SENT_INIT;
+ }
+
+ cmdat |= (priv->flags & JZ_MMC_BUS_WIDTH_MASK) << 9;
+
+ /* write the data setup */
+ writel(cmdat, priv->regs + MSC_CMDAT);
+
+ /* unmask interrupts */
+ mask = 0xffffffff & ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_TIME_OUT_RES);
+ if (data) {
+ mask &= ~MSC_IMASK_DATA_TRAN_DONE;
+ if (data->flags & MMC_DATA_WRITE) {
+ mask &= ~MSC_IMASK_TXFIFO_WR_REQ;
+ } else {
+ mask &= ~(MSC_IMASK_RXFIFO_RD_REQ |
+ MSC_IMASK_TIME_OUT_READ);
+ }
+ }
+ writel(mask, priv->regs + MSC_IMASK);
+
+ /* clear interrupts */
+ writel(0xffffffff, priv->regs + MSC_IREG);
+
+ /* start the command (& the clock) */
+ writel(MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START,
+ priv->regs + MSC_STRPCL);
+
+ /* wait for completion */
+ for (i = 0; i < 100; i++) {
+ stat = readl(priv->regs + MSC_IREG);
+ stat &= MSC_IREG_END_CMD_RES | MSC_IREG_TIME_OUT_RES;
+ if (stat)
+ break;
+ mdelay(1);
+ }
+ writel(stat, priv->regs + MSC_IREG);
+ if (stat & MSC_IREG_TIME_OUT_RES)
+ return -ETIMEDOUT;
+
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ /* read the response */
+ if (cmd->resp_type & MMC_RSP_136) {
+ u16 a, b, c, i;
+
+ a = readw(priv->regs + MSC_RES);
+ for (i = 0; i < 4; i++) {
+ b = readw(priv->regs + MSC_RES);
+ c = readw(priv->regs + MSC_RES);
+ cmd->response[i] =
+ (a << 24) | (b << 8) | (c >> 8);
+ a = c;
+ }
+ } else {
+ cmd->response[0] = readw(priv->regs + MSC_RES) << 24;
+ cmd->response[0] |= readw(priv->regs + MSC_RES) << 8;
+ cmd->response[0] |= readw(priv->regs + MSC_RES) & 0xff;
+ }
+ }
+
+ if (data && (data->flags & MMC_DATA_WRITE)) {
+ /* write the data */
+ int sz = DIV_ROUND_UP(data->blocks * data->blocksize, 4);
+ const void *buf = data->src;
+
+ while (sz--) {
+ u32 val = get_unaligned_le32(buf);
+
+ wait_for_bit_le32(priv->regs + MSC_IREG,
+ MSC_IREG_TXFIFO_WR_REQ,
+ true, 10000, false);
+ writel(val, priv->regs + MSC_TXFIFO);
+ buf += 4;
+ }
+ } else if (data && (data->flags & MMC_DATA_READ)) {
+ /* read the data */
+ int sz = data->blocks * data->blocksize;
+ void *buf = data->dest;
+
+ do {
+ stat = readl(priv->regs + MSC_STAT);
+
+ if (stat & MSC_STAT_TIME_OUT_READ)
+ return -ETIMEDOUT;
+ if (stat & MSC_STAT_CRC_READ_ERROR)
+ return -EINVAL;
+ if (stat & MSC_STAT_DATA_FIFO_EMPTY) {
+ udelay(10);
+ continue;
+ }
+ do {
+ u32 val = readl(priv->regs + MSC_RXFIFO);
+
+ if (sz == 1)
+ *(u8 *)buf = (u8)val;
+ else if (sz == 2)
+ put_unaligned_le16(val, buf);
+ else if (sz >= 4)
+ put_unaligned_le32(val, buf);
+ buf += 4;
+ sz -= 4;
+ stat = readl(priv->regs + MSC_STAT);
+ } while (!(stat & MSC_STAT_DATA_FIFO_EMPTY));
+ } while (!(stat & MSC_STAT_DATA_TRAN_DONE));
+ }
+
+ return 0;
+}
+
+static int jz_mmc_set_ios(struct mmc *mmc, struct jz_mmc_priv *priv)
+{
+ u32 real_rate = jz_mmc_clock_rate();
+ u8 clk_div = 0;
+
+ /* calculate clock divide */
+ while ((real_rate > mmc->clock) && (clk_div < 7)) {
+ real_rate >>= 1;
+ clk_div++;
+ }
+ writel(clk_div & MSC_CLKRT_CLK_RATE_MASK, priv->regs + MSC_CLKRT);
+
+ /* set the bus width for the next command */
+ priv->flags &= ~JZ_MMC_BUS_WIDTH_MASK;
+ if (mmc->bus_width == 8)
+ priv->flags |= JZ_MMC_BUS_WIDTH_8;
+ else if (mmc->bus_width == 4)
+ priv->flags |= JZ_MMC_BUS_WIDTH_4;
+ else
+ priv->flags |= JZ_MMC_BUS_WIDTH_1;
+
+ return 0;
+}
+
+static int jz_mmc_core_init(struct mmc *mmc)
+{
+ struct jz_mmc_priv *priv = mmc->priv;
+ int ret;
+
+ /* Reset */
+ writel(MSC_STRPCL_RESET, priv->regs + MSC_STRPCL);
+ ret = wait_for_bit_le32(priv->regs + MSC_STAT,
+ MSC_STAT_IS_RESETTING, false, 10000, false);
+ if (ret)
+ return ret;
+
+ /* Maximum timeouts */
+ writel(0xffff, priv->regs + MSC_RESTO);
+ writel(0xffffffff, priv->regs + MSC_RDTO);
+
+ /* Enable low power mode */
+ writel(0x1, priv->regs + MSC_LPM);
+
+ return 0;
+}
+
+#if !CONFIG_IS_ENABLED(DM_MMC)
+
+static int jz_mmc_legacy_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct jz_mmc_priv *priv = mmc->priv;
+
+ return jz_mmc_send_cmd(mmc, priv, cmd, data);
+}
+
+static int jz_mmc_legacy_set_ios(struct mmc *mmc)
+{
+ struct jz_mmc_priv *priv = mmc->priv;
+
+ return jz_mmc_set_ios(mmc, priv);
+};
+
+static const struct mmc_ops jz_msc_ops = {
+ .send_cmd = jz_mmc_legacy_send_cmd,
+ .set_ios = jz_mmc_legacy_set_ios,
+ .init = jz_mmc_core_init,
+};
+
+static struct jz_mmc_priv jz_mmc_priv_static;
+static struct jz_mmc_plat jz_mmc_plat_static = {
+ .cfg = {
+ .name = "MSC",
+ .ops = &jz_msc_ops,
+
+ .voltages = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 |
+ MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 |
+ MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36,
+ .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
+
+ .f_min = 375000,
+ .f_max = 48000000,
+ .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
+ },
+};
+
+int jz_mmc_init(void __iomem *base)
+{
+ struct mmc *mmc;
+
+ jz_mmc_priv_static.regs = base;
+
+ mmc = mmc_create(&jz_mmc_plat_static.cfg, &jz_mmc_priv_static);
+
+ return mmc ? 0 : -ENODEV;
+}
+
+#else /* CONFIG_DM_MMC */
+
+#include <dm.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+static int jz_mmc_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return jz_mmc_send_cmd(mmc, priv, cmd, data);
+}
+
+static int jz_mmc_dm_set_ios(struct udevice *dev)
+{
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return jz_mmc_set_ios(mmc, priv);
+};
+
+static const struct dm_mmc_ops jz_msc_ops = {
+ .send_cmd = jz_mmc_dm_send_cmd,
+ .set_ios = jz_mmc_dm_set_ios,
+};
+
+static int jz_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct jz_mmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_config *cfg;
+ int ret;
+
+ priv->regs = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
+ cfg = &plat->cfg;
+
+ cfg->name = "MSC";
+ cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+ ret = mmc_of_parse(dev, cfg);
+ if (ret < 0) {
+ dev_err(dev, "failed to parse host caps\n");
+ return ret;
+ }
+
+ cfg->f_min = 400000;
+ cfg->f_max = 52000000;
+
+ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ return 0;
+}
+
+static int jz_mmc_bind(struct udevice *dev)
+{
+ struct jz_mmc_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static int jz_mmc_probe(struct udevice *dev)
+{
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct jz_mmc_plat *plat = dev_get_platdata(dev);
+
+ plat->mmc.priv = priv;
+ upriv->mmc = &plat->mmc;
+ return jz_mmc_core_init(&plat->mmc);
+}
+
+static const struct udevice_id jz_mmc_ids[] = {
+ { .compatible = "ingenic,jz4780-mmc" },
+ { }
+};
+
+U_BOOT_DRIVER(jz_mmc_drv) = {
+ .name = "jz_mmc",
+ .id = UCLASS_MMC,
+ .of_match = jz_mmc_ids,
+ .ofdata_to_platdata = jz_mmc_ofdata_to_platdata,
+ .bind = jz_mmc_bind,
+ .probe = jz_mmc_probe,
+ .priv_auto_alloc_size = sizeof(struct jz_mmc_priv),
+ .platdata_auto_alloc_size = sizeof(struct jz_mmc_plat),
+ .ops = &jz_msc_ops,
+};
+#endif /* CONFIG_DM_MMC */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8fb365f..7044c6a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -72,6 +72,24 @@
by the BCM_SF2_ETH driver.
Say Y to any bcmcygnus based platforms.
+config BCM6348_ETH
+ bool "BCM6348 EMAC support"
+ depends on DM_ETH && ARCH_BMIPS
+ select DMA
+ select DMA_CHANNELS
+ select MII
+ select PHYLIB
+ help
+ This driver supports the BCM6348 Ethernet MAC.
+
+config BCM6368_ETH
+ bool "BCM6368 EMAC support"
+ depends on DM_ETH && ARCH_BMIPS
+ select DMA
+ select MII
+ help
+ This driver supports the BCM6368 Ethernet MAC.
+
config DWC_ETH_QOS
bool "Synopsys DWC Ethernet QOS device support"
depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 99056aa..0dbfa03 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -6,6 +6,8 @@
obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
obj-$(CONFIG_AG7XXX) += ag7xxx.o
obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
+obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
+obj-$(CONFIG_BCM6368_ETH) += bcm6368-eth.o
obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
new file mode 100644
index 0000000..7100e68
--- /dev/null
+++ b/drivers/net/bcm6348-eth.c
@@ -0,0 +1,537 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_RX_DESC PKTBUFSRX
+#define ETH_MAX_MTU_SIZE 1518
+#define ETH_TIMEOUT 100
+#define ETH_TX_WATERMARK 32
+
+/* ETH Receiver Configuration register */
+#define ETH_RXCFG_REG 0x00
+#define ETH_RXCFG_ENFLOW_SHIFT 5
+#define ETH_RXCFG_ENFLOW_MASK (1 << ETH_RXCFG_ENFLOW_SHIFT)
+
+/* ETH Receive Maximum Length register */
+#define ETH_RXMAXLEN_REG 0x04
+#define ETH_RXMAXLEN_SHIFT 0
+#define ETH_RXMAXLEN_MASK (0x7ff << ETH_RXMAXLEN_SHIFT)
+
+/* ETH Transmit Maximum Length register */
+#define ETH_TXMAXLEN_REG 0x08
+#define ETH_TXMAXLEN_SHIFT 0
+#define ETH_TXMAXLEN_MASK (0x7ff << ETH_TXMAXLEN_SHIFT)
+
+/* MII Status/Control register */
+#define MII_SC_REG 0x10
+#define MII_SC_MDCFREQDIV_SHIFT 0
+#define MII_SC_MDCFREQDIV_MASK (0x7f << MII_SC_MDCFREQDIV_SHIFT)
+#define MII_SC_PREAMBLE_EN_SHIFT 7
+#define MII_SC_PREAMBLE_EN_MASK (1 << MII_SC_PREAMBLE_EN_SHIFT)
+
+/* MII Data register */
+#define MII_DAT_REG 0x14
+#define MII_DAT_DATA_SHIFT 0
+#define MII_DAT_DATA_MASK (0xffff << MII_DAT_DATA_SHIFT)
+#define MII_DAT_TA_SHIFT 16
+#define MII_DAT_TA_MASK (0x3 << MII_DAT_TA_SHIFT)
+#define MII_DAT_REG_SHIFT 18
+#define MII_DAT_REG_MASK (0x1f << MII_DAT_REG_SHIFT)
+#define MII_DAT_PHY_SHIFT 23
+#define MII_DAT_PHY_MASK (0x1f << MII_DAT_PHY_SHIFT)
+#define MII_DAT_OP_SHIFT 28
+#define MII_DAT_OP_WRITE (0x5 << MII_DAT_OP_SHIFT)
+#define MII_DAT_OP_READ (0x6 << MII_DAT_OP_SHIFT)
+
+/* ETH Interrupts Mask register */
+#define ETH_IRMASK_REG 0x18
+
+/* ETH Interrupts register */
+#define ETH_IR_REG 0x1c
+#define ETH_IR_MII_SHIFT 0
+#define ETH_IR_MII_MASK (1 << ETH_IR_MII_SHIFT)
+
+/* ETH Control register */
+#define ETH_CTL_REG 0x2c
+#define ETH_CTL_ENABLE_SHIFT 0
+#define ETH_CTL_ENABLE_MASK (1 << ETH_CTL_ENABLE_SHIFT)
+#define ETH_CTL_DISABLE_SHIFT 1
+#define ETH_CTL_DISABLE_MASK (1 << ETH_CTL_DISABLE_SHIFT)
+#define ETH_CTL_RESET_SHIFT 2
+#define ETH_CTL_RESET_MASK (1 << ETH_CTL_RESET_SHIFT)
+#define ETH_CTL_EPHY_SHIFT 3
+#define ETH_CTL_EPHY_MASK (1 << ETH_CTL_EPHY_SHIFT)
+
+/* ETH Transmit Control register */
+#define ETH_TXCTL_REG 0x30
+#define ETH_TXCTL_FD_SHIFT 0
+#define ETH_TXCTL_FD_MASK (1 << ETH_TXCTL_FD_SHIFT)
+
+/* ETH Transmit Watermask register */
+#define ETH_TXWMARK_REG 0x34
+#define ETH_TXWMARK_WM_SHIFT 0
+#define ETH_TXWMARK_WM_MASK (0x3f << ETH_TXWMARK_WM_SHIFT)
+
+/* MIB Control register */
+#define MIB_CTL_REG 0x38
+#define MIB_CTL_RDCLEAR_SHIFT 0
+#define MIB_CTL_RDCLEAR_MASK (1 << MIB_CTL_RDCLEAR_SHIFT)
+
+/* ETH Perfect Match registers */
+#define ETH_PM_CNT 4
+#define ETH_PML_REG(x) (0x58 + (x) * 0x8)
+#define ETH_PMH_REG(x) (0x5c + (x) * 0x8)
+#define ETH_PMH_VALID_SHIFT 16
+#define ETH_PMH_VALID_MASK (1 << ETH_PMH_VALID_SHIFT)
+
+/* MIB Counters registers */
+#define MIB_REG_CNT 55
+#define MIB_REG(x) (0x200 + (x) * 4)
+
+/* ETH data */
+struct bcm6348_eth_priv {
+ void __iomem *base;
+ /* DMA */
+ struct dma rx_dma;
+ struct dma tx_dma;
+ /* PHY */
+ int phy_id;
+ struct phy_device *phy_dev;
+};
+
+static void bcm6348_eth_mac_disable(struct bcm6348_eth_priv *priv)
+{
+ /* disable emac */
+ clrsetbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK,
+ ETH_CTL_DISABLE_MASK);
+
+ /* wait until emac is disabled */
+ if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+ ETH_CTL_DISABLE_MASK, false,
+ ETH_TIMEOUT, false))
+ pr_err("%s: error disabling emac\n", __func__);
+}
+
+static void bcm6348_eth_mac_enable(struct bcm6348_eth_priv *priv)
+{
+ setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK);
+}
+
+static void bcm6348_eth_mac_reset(struct bcm6348_eth_priv *priv)
+{
+ /* reset emac */
+ writel_be(ETH_CTL_RESET_MASK, priv->base + ETH_CTL_REG);
+ wmb();
+
+ /* wait until emac is reset */
+ if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+ ETH_CTL_RESET_MASK, false,
+ ETH_TIMEOUT, false))
+ pr_err("%s: error resetting emac\n", __func__);
+}
+
+static int bcm6348_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+ return dma_prepare_rcv_buf(&priv->rx_dma, packet, len);
+}
+
+static int bcm6348_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+ return dma_receive(&priv->rx_dma, (void**)packetp, NULL);
+}
+
+static int bcm6348_eth_send(struct udevice *dev, void *packet, int length)
+{
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+ return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6348_eth_adjust_link(struct udevice *dev,
+ struct phy_device *phydev)
+{
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+ /* mac duplex parameters */
+ if (phydev->duplex)
+ setbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+ else
+ clrbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+
+ /* rx flow control (pause frame handling) */
+ if (phydev->pause)
+ setbits_be32(priv->base + ETH_RXCFG_REG,
+ ETH_RXCFG_ENFLOW_MASK);
+ else
+ clrbits_be32(priv->base + ETH_RXCFG_REG,
+ ETH_RXCFG_ENFLOW_MASK);
+
+ return 0;
+}
+
+static int bcm6348_eth_start(struct udevice *dev)
+{
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+ int ret, i;
+
+ /* prepare rx dma buffers */
+ for (i = 0; i < ETH_RX_DESC; i++) {
+ ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
+ PKTSIZE_ALIGN);
+ if (ret < 0)
+ break;
+ }
+
+ /* enable dma rx channel */
+ dma_enable(&priv->rx_dma);
+
+ /* enable dma tx channel */
+ dma_enable(&priv->tx_dma);
+
+ ret = phy_startup(priv->phy_dev);
+ if (ret) {
+ pr_err("%s: could not initialize phy\n", __func__);
+ return ret;
+ }
+
+ if (!priv->phy_dev->link) {
+ pr_err("%s: no phy link\n", __func__);
+ return -EIO;
+ }
+
+ bcm6348_eth_adjust_link(dev, priv->phy_dev);
+
+ /* zero mib counters */
+ for (i = 0; i < MIB_REG_CNT; i++)
+ writel_be(0, MIB_REG(i));
+
+ /* enable rx flow control */
+ setbits_be32(priv->base + ETH_RXCFG_REG, ETH_RXCFG_ENFLOW_MASK);
+
+ /* set max rx/tx length */
+ writel_be((ETH_MAX_MTU_SIZE << ETH_RXMAXLEN_SHIFT) &
+ ETH_RXMAXLEN_MASK, priv->base + ETH_RXMAXLEN_REG);
+ writel_be((ETH_MAX_MTU_SIZE << ETH_TXMAXLEN_SHIFT) &
+ ETH_TXMAXLEN_MASK, priv->base + ETH_TXMAXLEN_REG);
+
+ /* set correct transmit fifo watermark */
+ writel_be((ETH_TX_WATERMARK << ETH_TXWMARK_WM_SHIFT) &
+ ETH_TXWMARK_WM_MASK, priv->base + ETH_TXWMARK_REG);
+
+ /* enable emac */
+ bcm6348_eth_mac_enable(priv);
+
+ /* clear interrupts */
+ writel_be(0, priv->base + ETH_IRMASK_REG);
+
+ return 0;
+}
+
+static void bcm6348_eth_stop(struct udevice *dev)
+{
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+ /* disable dma rx channel */
+ dma_disable(&priv->rx_dma);
+
+ /* disable dma tx channel */
+ dma_disable(&priv->tx_dma);
+
+ /* disable emac */
+ bcm6348_eth_mac_disable(priv);
+}
+
+static int bcm6348_eth_write_hwaddr(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+ bool running = false;
+
+ /* check if emac is running */
+ if (readl_be(priv->base + ETH_CTL_REG) & ETH_CTL_ENABLE_MASK)
+ running = true;
+
+ /* disable emac */
+ if (running)
+ bcm6348_eth_mac_disable(priv);
+
+ /* set mac address */
+ writel_be((pdata->enetaddr[2] << 24) | (pdata->enetaddr[3]) << 16 |
+ (pdata->enetaddr[4]) << 8 | (pdata->enetaddr[5]),
+ priv->base + ETH_PML_REG(0));
+ writel_be((pdata->enetaddr[1]) | (pdata->enetaddr[0] << 8) |
+ ETH_PMH_VALID_MASK, priv->base + ETH_PMH_REG(0));
+
+ /* enable emac */
+ if (running)
+ bcm6348_eth_mac_enable(priv);
+
+ return 0;
+}
+
+static const struct eth_ops bcm6348_eth_ops = {
+ .free_pkt = bcm6348_eth_free_pkt,
+ .recv = bcm6348_eth_recv,
+ .send = bcm6348_eth_send,
+ .start = bcm6348_eth_start,
+ .stop = bcm6348_eth_stop,
+ .write_hwaddr = bcm6348_eth_write_hwaddr,
+};
+
+static const struct udevice_id bcm6348_eth_ids[] = {
+ { .compatible = "brcm,bcm6348-enet", },
+ { /* sentinel */ }
+};
+
+static int bcm6348_mdio_op(void __iomem *base, uint32_t data)
+{
+ /* make sure mii interrupt status is cleared */
+ writel_be(ETH_IR_MII_MASK, base + ETH_IR_REG);
+
+ /* issue mii op */
+ writel_be(data, base + MII_DAT_REG);
+
+ /* wait until emac is disabled */
+ return wait_for_bit_be32(base + ETH_IR_REG,
+ ETH_IR_MII_MASK, true,
+ ETH_TIMEOUT, false);
+}
+
+static int bcm6348_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+ int reg)
+{
+ void __iomem *base = bus->priv;
+ uint32_t val;
+
+ val = MII_DAT_OP_READ;
+ val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+ val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+ val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+
+ if (bcm6348_mdio_op(base, val)) {
+ pr_err("%s: timeout\n", __func__);
+ return -EINVAL;
+ }
+
+ val = readl_be(base + MII_DAT_REG) & MII_DAT_DATA_MASK;
+ val >>= MII_DAT_DATA_SHIFT;
+
+ return val;
+}
+
+static int bcm6348_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
+ int reg, u16 value)
+{
+ void __iomem *base = bus->priv;
+ uint32_t val;
+
+ val = MII_DAT_OP_WRITE;
+ val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+ val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+ val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+ val |= (value << MII_DAT_DATA_SHIFT) & MII_DAT_DATA_MASK;
+
+ if (bcm6348_mdio_op(base, val)) {
+ pr_err("%s: timeout\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int bcm6348_mdio_init(const char *name, void __iomem *base)
+{
+ struct mii_dev *bus;
+
+ bus = mdio_alloc();
+ if (!bus) {
+ pr_err("%s: failed to allocate MDIO bus\n", __func__);
+ return -ENOMEM;
+ }
+
+ bus->read = bcm6348_mdio_read;
+ bus->write = bcm6348_mdio_write;
+ bus->priv = base;
+ snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+ return mdio_register(bus);
+}
+
+static int bcm6348_phy_init(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+ struct mii_dev *bus;
+
+ /* get mii bus */
+ bus = miiphy_get_dev_by_name(dev->name);
+
+ /* phy connect */
+ priv->phy_dev = phy_connect(bus, priv->phy_id, dev,
+ pdata->phy_interface);
+ if (!priv->phy_dev) {
+ pr_err("%s: no phy device\n", __func__);
+ return -ENODEV;
+ }
+
+ priv->phy_dev->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_Pause |
+ SUPPORTED_MII);
+ priv->phy_dev->advertising = priv->phy_dev->supported;
+
+ /* phy config */
+ phy_config(priv->phy_dev);
+
+ return 0;
+}
+
+static int bcm6348_eth_probe(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args phy;
+ const char *phy_mode;
+ int ret, i;
+
+ /* get base address */
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -EINVAL;
+ pdata->iobase = (phys_addr_t) priv->base;
+
+ /* get phy mode */
+ pdata->phy_interface = PHY_INTERFACE_MODE_NONE;
+ phy_mode = dev_read_string(dev, "phy-mode");
+ if (phy_mode)
+ pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_NONE)
+ return -ENODEV;
+
+ /* get phy */
+ if (dev_read_phandle_with_args(dev, "phy", NULL, 0, 0, &phy))
+ return -ENOENT;
+ priv->phy_id = ofnode_read_u32_default(phy.node, "reg", -1);
+
+ /* get dma channels */
+ ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+ if (ret)
+ return -EINVAL;
+
+ ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+ if (ret)
+ return -EINVAL;
+
+ /* try to enable clocks */
+ for (i = 0; ; i++) {
+ struct clk clk;
+ int ret;
+
+ ret = clk_get_by_index(dev, i, &clk);
+ if (ret < 0)
+ break;
+
+ ret = clk_enable(&clk);
+ if (ret < 0) {
+ pr_err("%s: error enabling clock %d\n", __func__, i);
+ return ret;
+ }
+
+ ret = clk_free(&clk);
+ if (ret < 0) {
+ pr_err("%s: error freeing clock %d\n", __func__, i);
+ return ret;
+ }
+ }
+
+ /* try to perform resets */
+ for (i = 0; ; i++) {
+ struct reset_ctl reset;
+ int ret;
+
+ ret = reset_get_by_index(dev, i, &reset);
+ if (ret < 0)
+ break;
+
+ ret = reset_deassert(&reset);
+ if (ret < 0) {
+ pr_err("%s: error deasserting reset %d\n", __func__, i);
+ return ret;
+ }
+
+ ret = reset_free(&reset);
+ if (ret < 0) {
+ pr_err("%s: error freeing reset %d\n", __func__, i);
+ return ret;
+ }
+ }
+
+ /* disable emac */
+ bcm6348_eth_mac_disable(priv);
+
+ /* reset emac */
+ bcm6348_eth_mac_reset(priv);
+
+ /* select correct mii interface */
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
+ clrbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+ else
+ setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+
+ /* turn on mdc clock */
+ writel_be((0x1f << MII_SC_MDCFREQDIV_SHIFT) |
+ MII_SC_PREAMBLE_EN_MASK, priv->base + MII_SC_REG);
+
+ /* set mib counters to not clear when read */
+ clrbits_be32(priv->base + MIB_CTL_REG, MIB_CTL_RDCLEAR_MASK);
+
+ /* initialize perfect match registers */
+ for (i = 0; i < ETH_PM_CNT; i++) {
+ writel_be(0, priv->base + ETH_PML_REG(i));
+ writel_be(0, priv->base + ETH_PMH_REG(i));
+ }
+
+ /* init mii bus */
+ ret = bcm6348_mdio_init(dev->name, priv->base);
+ if (ret)
+ return ret;
+
+ /* init phy */
+ ret = bcm6348_phy_init(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_eth) = {
+ .name = "bcm6348_eth",
+ .id = UCLASS_ETH,
+ .of_match = bcm6348_eth_ids,
+ .ops = &bcm6348_eth_ops,
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+ .priv_auto_alloc_size = sizeof(struct bcm6348_eth_priv),
+ .probe = bcm6348_eth_probe,
+};
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
new file mode 100644
index 0000000..a31efba
--- /dev/null
+++ b/drivers/net/bcm6368-eth.c
@@ -0,0 +1,625 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_PORT_STR "brcm,enetsw-port"
+
+#define ETH_RX_DESC PKTBUFSRX
+#define ETH_ZLEN 60
+#define ETH_TIMEOUT 100
+
+#define ETH_MAX_PORT 8
+#define ETH_RGMII_PORT0 4
+
+/* Port traffic control */
+#define ETH_PTCTRL_REG(x) (0x0 + (x))
+#define ETH_PTCTRL_RXDIS_SHIFT 0
+#define ETH_PTCTRL_RXDIS_MASK (1 << ETH_PTCTRL_RXDIS_SHIFT)
+#define ETH_PTCTRL_TXDIS_SHIFT 1
+#define ETH_PTCTRL_TXDIS_MASK (1 << ETH_PTCTRL_TXDIS_SHIFT)
+
+/* Switch mode register */
+#define ETH_SWMODE_REG 0xb
+#define ETH_SWMODE_FWD_EN_SHIFT 1
+#define ETH_SWMODE_FWD_EN_MASK (1 << ETH_SWMODE_FWD_EN_SHIFT)
+
+/* IMP override Register */
+#define ETH_IMPOV_REG 0xe
+#define ETH_IMPOV_LINKUP_SHIFT 0
+#define ETH_IMPOV_LINKUP_MASK (1 << ETH_IMPOV_LINKUP_SHIFT)
+#define ETH_IMPOV_FDX_SHIFT 1
+#define ETH_IMPOV_FDX_MASK (1 << ETH_IMPOV_FDX_SHIFT)
+#define ETH_IMPOV_100_SHIFT 2
+#define ETH_IMPOV_100_MASK (1 << ETH_IMPOV_100_SHIFT)
+#define ETH_IMPOV_1000_SHIFT 3
+#define ETH_IMPOV_1000_MASK (1 << ETH_IMPOV_1000_SHIFT)
+#define ETH_IMPOV_RXFLOW_SHIFT 4
+#define ETH_IMPOV_RXFLOW_MASK (1 << ETH_IMPOV_RXFLOW_SHIFT)
+#define ETH_IMPOV_TXFLOW_SHIFT 5
+#define ETH_IMPOV_TXFLOW_MASK (1 << ETH_IMPOV_TXFLOW_SHIFT)
+#define ETH_IMPOV_FORCE_SHIFT 7
+#define ETH_IMPOV_FORCE_MASK (1 << ETH_IMPOV_FORCE_SHIFT)
+
+/* Port override Register */
+#define ETH_PORTOV_REG(x) (0x58 + (x))
+#define ETH_PORTOV_LINKUP_SHIFT 0
+#define ETH_PORTOV_LINKUP_MASK (1 << ETH_PORTOV_LINKUP_SHIFT)
+#define ETH_PORTOV_FDX_SHIFT 1
+#define ETH_PORTOV_FDX_MASK (1 << ETH_PORTOV_FDX_SHIFT)
+#define ETH_PORTOV_100_SHIFT 2
+#define ETH_PORTOV_100_MASK (1 << ETH_PORTOV_100_SHIFT)
+#define ETH_PORTOV_1000_SHIFT 3
+#define ETH_PORTOV_1000_MASK (1 << ETH_PORTOV_1000_SHIFT)
+#define ETH_PORTOV_RXFLOW_SHIFT 4
+#define ETH_PORTOV_RXFLOW_MASK (1 << ETH_PORTOV_RXFLOW_SHIFT)
+#define ETH_PORTOV_TXFLOW_SHIFT 5
+#define ETH_PORTOV_TXFLOW_MASK (1 << ETH_PORTOV_TXFLOW_SHIFT)
+#define ETH_PORTOV_ENABLE_SHIFT 6
+#define ETH_PORTOV_ENABLE_MASK (1 << ETH_PORTOV_ENABLE_SHIFT)
+
+/* Port RGMII control register */
+#define ETH_RGMII_CTRL_REG(x) (0x60 + (x))
+#define ETH_RGMII_CTRL_GMII_CLK_EN (1 << 7)
+#define ETH_RGMII_CTRL_MII_OVERRIDE_EN (1 << 6)
+#define ETH_RGMII_CTRL_MII_MODE_MASK (3 << 4)
+#define ETH_RGMII_CTRL_RGMII_MODE (0 << 4)
+#define ETH_RGMII_CTRL_MII_MODE (1 << 4)
+#define ETH_RGMII_CTRL_RVMII_MODE (2 << 4)
+#define ETH_RGMII_CTRL_TIMING_SEL_EN (1 << 0)
+
+/* Port RGMII timing register */
+#define ENETSW_RGMII_TIMING_REG(x) (0x68 + (x))
+
+/* MDIO control register */
+#define MII_SC_REG 0xb0
+#define MII_SC_EXT_SHIFT 16
+#define MII_SC_EXT_MASK (1 << MII_SC_EXT_SHIFT)
+#define MII_SC_REG_SHIFT 20
+#define MII_SC_PHYID_SHIFT 25
+#define MII_SC_RD_SHIFT 30
+#define MII_SC_RD_MASK (1 << MII_SC_RD_SHIFT)
+#define MII_SC_WR_SHIFT 31
+#define MII_SC_WR_MASK (1 << MII_SC_WR_SHIFT)
+
+/* MDIO data register */
+#define MII_DAT_REG 0xb4
+
+/* Global Management Configuration Register */
+#define ETH_GMCR_REG 0x200
+#define ETH_GMCR_RST_MIB_SHIFT 0
+#define ETH_GMCR_RST_MIB_MASK (1 << ETH_GMCR_RST_MIB_SHIFT)
+
+/* Jumbo control register port mask register */
+#define ETH_JMBCTL_PORT_REG 0x4004
+
+/* Jumbo control mib good frame register */
+#define ETH_JMBCTL_MAXSIZE_REG 0x4008
+
+/* ETH port data */
+struct bcm_enetsw_port {
+ bool used;
+ const char *name;
+ /* Config */
+ bool bypass_link;
+ int force_speed;
+ bool force_duplex_full;
+ /* PHY */
+ int phy_id;
+};
+
+/* ETH data */
+struct bcm6368_eth_priv {
+ void __iomem *base;
+ /* DMA */
+ struct dma rx_dma;
+ struct dma tx_dma;
+ /* Ports */
+ uint8_t num_ports;
+ struct bcm_enetsw_port used_ports[ETH_MAX_PORT];
+ int sw_port_link[ETH_MAX_PORT];
+ bool rgmii_override;
+ bool rgmii_timing;
+ /* PHY */
+ int phy_id;
+};
+
+static inline bool bcm_enet_port_is_rgmii(int portid)
+{
+ return portid >= ETH_RGMII_PORT0;
+}
+
+static int bcm6368_mdio_read(struct bcm6368_eth_priv *priv, uint8_t ext,
+ int phy_id, int reg)
+{
+ uint32_t val;
+
+ writel_be(0, priv->base + MII_SC_REG);
+
+ val = MII_SC_RD_MASK |
+ (phy_id << MII_SC_PHYID_SHIFT) |
+ (reg << MII_SC_REG_SHIFT);
+
+ if (ext)
+ val |= MII_SC_EXT_MASK;
+
+ writel_be(val, priv->base + MII_SC_REG);
+ udelay(50);
+
+ return readw_be(priv->base + MII_DAT_REG);
+}
+
+static int bcm6368_mdio_write(struct bcm6368_eth_priv *priv, uint8_t ext,
+ int phy_id, int reg, u16 data)
+{
+ uint32_t val;
+
+ writel_be(0, priv->base + MII_SC_REG);
+
+ val = MII_SC_WR_MASK |
+ (phy_id << MII_SC_PHYID_SHIFT) |
+ (reg << MII_SC_REG_SHIFT);
+
+ if (ext)
+ val |= MII_SC_EXT_MASK;
+
+ val |= data;
+
+ writel_be(val, priv->base + MII_SC_REG);
+ udelay(50);
+
+ return 0;
+}
+
+static int bcm6368_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+ struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+ return dma_prepare_rcv_buf(&priv->rx_dma, packet, len);
+}
+
+static int bcm6368_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+ return dma_receive(&priv->rx_dma, (void**)packetp, NULL);
+}
+
+static int bcm6368_eth_send(struct udevice *dev, void *packet, int length)
+{
+ struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+ /* pad packets smaller than ETH_ZLEN */
+ if (length < ETH_ZLEN) {
+ memset(packet + length, 0, ETH_ZLEN - length);
+ length = ETH_ZLEN;
+ }
+
+ return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6368_eth_adjust_link(struct udevice *dev)
+{
+ struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+ unsigned int i;
+
+ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm_enetsw_port *port;
+ int val, j, up, adv, lpa, speed, duplex, media;
+ int external_phy = bcm_enet_port_is_rgmii(i);
+ u8 override;
+
+ port = &priv->used_ports[i];
+ if (!port->used)
+ continue;
+
+ if (port->bypass_link)
+ continue;
+
+ /* dummy read to clear */
+ for (j = 0; j < 2; j++)
+ val = bcm6368_mdio_read(priv, external_phy,
+ port->phy_id, MII_BMSR);
+
+ if (val == 0xffff)
+ continue;
+
+ up = (val & BMSR_LSTATUS) ? 1 : 0;
+ if (!(up ^ priv->sw_port_link[i]))
+ continue;
+
+ priv->sw_port_link[i] = up;
+
+ /* link changed */
+ if (!up) {
+ dev_info(&priv->pdev->dev, "link DOWN on %s\n",
+ port->name);
+ writeb_be(ETH_PORTOV_ENABLE_MASK,
+ priv->base + ETH_PORTOV_REG(i));
+ writeb_be(ETH_PTCTRL_RXDIS_MASK |
+ ETH_PTCTRL_TXDIS_MASK,
+ priv->base + ETH_PTCTRL_REG(i));
+ continue;
+ }
+
+ adv = bcm6368_mdio_read(priv, external_phy,
+ port->phy_id, MII_ADVERTISE);
+
+ lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
+ MII_LPA);
+
+ /* figure out media and duplex from advertise and LPA values */
+ media = mii_nway_result(lpa & adv);
+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+
+ if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+ speed = 100;
+ else
+ speed = 10;
+
+ if (val & BMSR_ESTATEN) {
+ adv = bcm6368_mdio_read(priv, external_phy,
+ port->phy_id, MII_CTRL1000);
+
+ lpa = bcm6368_mdio_read(priv, external_phy,
+ port->phy_id, MII_STAT1000);
+
+ if ((adv & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
+ (lpa & (LPA_1000FULL | LPA_1000HALF))) {
+ speed = 1000;
+ duplex = (lpa & LPA_1000FULL);
+ }
+ }
+
+ pr_alert("link UP on %s, %dMbps, %s-duplex\n",
+ port->name, speed, duplex ? "full" : "half");
+
+ override = ETH_PORTOV_ENABLE_MASK |
+ ETH_PORTOV_LINKUP_MASK;
+
+ if (speed == 1000)
+ override |= ETH_PORTOV_1000_MASK;
+ else if (speed == 100)
+ override |= ETH_PORTOV_100_MASK;
+ if (duplex)
+ override |= ETH_PORTOV_FDX_MASK;
+
+ writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+ writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+ }
+
+ return 0;
+}
+
+static int bcm6368_eth_start(struct udevice *dev)
+{
+ struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+ uint8_t i;
+
+ /* prepare rx dma buffers */
+ for (i = 0; i < ETH_RX_DESC; i++) {
+ int ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
+ PKTSIZE_ALIGN);
+ if (ret < 0)
+ break;
+ }
+
+ /* enable dma rx channel */
+ dma_enable(&priv->rx_dma);
+
+ /* enable dma tx channel */
+ dma_enable(&priv->tx_dma);
+
+ /* apply override config for bypass_link ports here. */
+ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm_enetsw_port *port;
+ u8 override;
+
+ port = &priv->used_ports[i];
+ if (!port->used)
+ continue;
+
+ if (!port->bypass_link)
+ continue;
+
+ override = ETH_PORTOV_ENABLE_MASK |
+ ETH_PORTOV_LINKUP_MASK;
+
+ switch (port->force_speed) {
+ case 1000:
+ override |= ETH_PORTOV_1000_MASK;
+ break;
+ case 100:
+ override |= ETH_PORTOV_100_MASK;
+ break;
+ case 10:
+ break;
+ default:
+ pr_warn("%s: invalid forced speed on port %s\n",
+ __func__, port->name);
+ break;
+ }
+
+ if (port->force_duplex_full)
+ override |= ETH_PORTOV_FDX_MASK;
+
+ writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+ writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+ }
+
+ bcm6368_eth_adjust_link(dev);
+
+ return 0;
+}
+
+static void bcm6368_eth_stop(struct udevice *dev)
+{
+ struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+ /* disable dma rx channel */
+ dma_disable(&priv->rx_dma);
+
+ /* disable dma tx channel */
+ dma_disable(&priv->tx_dma);
+}
+
+static const struct eth_ops bcm6368_eth_ops = {
+ .free_pkt = bcm6368_eth_free_pkt,
+ .recv = bcm6368_eth_recv,
+ .send = bcm6368_eth_send,
+ .start = bcm6368_eth_start,
+ .stop = bcm6368_eth_stop,
+};
+
+static const struct udevice_id bcm6368_eth_ids[] = {
+ { .compatible = "brcm,bcm6368-enet", },
+ { /* sentinel */ }
+};
+
+static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv, int phy_id)
+{
+ uint8_t i;
+
+ for (i = 0; i < priv->num_ports; ++i) {
+ if (!priv->used_ports[i].used)
+ continue;
+ if (priv->used_ports[i].phy_id == phy_id)
+ return bcm_enet_port_is_rgmii(i);
+ }
+
+ return true;
+}
+
+static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+ int reg)
+{
+ struct bcm6368_eth_priv *priv = bus->priv;
+ bool ext = bcm6368_phy_is_external(priv, addr);
+
+ return bcm6368_mdio_read(priv, ext, addr, reg);
+}
+
+static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
+ int reg, u16 data)
+{
+ struct bcm6368_eth_priv *priv = bus->priv;
+ bool ext = bcm6368_phy_is_external(priv, addr);
+
+ return bcm6368_mdio_write(priv, ext, addr, reg, data);
+}
+
+static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
+{
+ struct mii_dev *bus;
+
+ bus = mdio_alloc();
+ if (!bus) {
+ pr_err("%s: failed to allocate MDIO bus\n", __func__);
+ return -ENOMEM;
+ }
+
+ bus->read = bcm6368_mii_mdio_read;
+ bus->write = bcm6368_mii_mdio_write;
+ bus->priv = priv;
+ snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+ return mdio_register(bus);
+}
+
+static int bcm6368_eth_probe(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+ int num_ports, ret, i;
+ uint32_t val;
+ ofnode node;
+
+ /* get base address */
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -EINVAL;
+ pdata->iobase = (phys_addr_t) priv->base;
+
+ /* get number of ports */
+ num_ports = dev_read_u32_default(dev, "brcm,num-ports", ETH_MAX_PORT);
+ if (!num_ports || num_ports > ETH_MAX_PORT)
+ return -EINVAL;
+
+ /* get dma channels */
+ ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+ if (ret)
+ return -EINVAL;
+
+ ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+ if (ret)
+ return -EINVAL;
+
+ /* try to enable clocks */
+ for (i = 0; ; i++) {
+ struct clk clk;
+ int ret;
+
+ ret = clk_get_by_index(dev, i, &clk);
+ if (ret < 0)
+ break;
+
+ ret = clk_enable(&clk);
+ if (ret < 0) {
+ pr_err("%s: error enabling clock %d\n", __func__, i);
+ return ret;
+ }
+
+ ret = clk_free(&clk);
+ if (ret < 0) {
+ pr_err("%s: error freeing clock %d\n", __func__, i);
+ return ret;
+ }
+ }
+
+ /* try to perform resets */
+ for (i = 0; ; i++) {
+ struct reset_ctl reset;
+ int ret;
+
+ ret = reset_get_by_index(dev, i, &reset);
+ if (ret < 0)
+ break;
+
+ ret = reset_deassert(&reset);
+ if (ret < 0) {
+ pr_err("%s: error deasserting reset %d\n", __func__, i);
+ return ret;
+ }
+
+ ret = reset_free(&reset);
+ if (ret < 0) {
+ pr_err("%s: error freeing reset %d\n", __func__, i);
+ return ret;
+ }
+ }
+
+ /* set priv data */
+ priv->num_ports = num_ports;
+ if (dev_read_bool(dev, "brcm,rgmii-override"))
+ priv->rgmii_override = true;
+ if (dev_read_bool(dev, "brcm,rgmii-timing"))
+ priv->rgmii_timing = true;
+
+ /* get ports */
+ dev_for_each_subnode(node, dev) {
+ const char *comp;
+ const char *label;
+ unsigned int p;
+ int phy_id;
+ int speed;
+
+ comp = ofnode_read_string(node, "compatible");
+ if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
+ continue;
+
+ p = ofnode_read_u32_default(node, "reg", ETH_MAX_PORT);
+ if (p >= num_ports)
+ return -EINVAL;
+
+ label = ofnode_read_string(node, "label");
+ if (!label) {
+ debug("%s: node %s has no label\n", __func__,
+ ofnode_get_name(node));
+ return -EINVAL;
+ }
+
+ phy_id = ofnode_read_u32_default(node, "brcm,phy-id", -1);
+
+ priv->used_ports[p].used = true;
+ priv->used_ports[p].name = label;
+ priv->used_ports[p].phy_id = phy_id;
+
+ if (ofnode_read_bool(node, "full-duplex"))
+ priv->used_ports[p].force_duplex_full = true;
+ if (ofnode_read_bool(node, "bypass-link"))
+ priv->used_ports[p].bypass_link = true;
+ speed = ofnode_read_u32_default(node, "speed", 0);
+ if (speed)
+ priv->used_ports[p].force_speed = speed;
+ }
+
+ /* init mii bus */
+ ret = bcm6368_mdio_init(dev->name, priv);
+ if (ret)
+ return ret;
+
+ /* disable all ports */
+ for (i = 0; i < priv->num_ports; i++) {
+ writeb_be(ETH_PORTOV_ENABLE_MASK,
+ priv->base + ETH_PORTOV_REG(i));
+ writeb_be(ETH_PTCTRL_RXDIS_MASK |
+ ETH_PTCTRL_TXDIS_MASK,
+ priv->base + ETH_PTCTRL_REG(i));
+
+ priv->sw_port_link[i] = 0;
+ }
+
+ /* enable external ports */
+ for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+ u8 rgmii_ctrl;
+
+ if (!priv->used_ports[i].used)
+ continue;
+
+ rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
+ rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
+ if (priv->rgmii_override)
+ rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
+ if (priv->rgmii_timing)
+ rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
+ writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
+ }
+
+ /* reset mib */
+ val = readb_be(priv->base + ETH_GMCR_REG);
+ val |= ETH_GMCR_RST_MIB_MASK;
+ writeb_be(val, priv->base + ETH_GMCR_REG);
+ mdelay(1);
+ val &= ~ETH_GMCR_RST_MIB_MASK;
+ writeb_be(val, priv->base + ETH_GMCR_REG);
+ mdelay(1);
+
+ /* force CPU port state */
+ val = readb_be(priv->base + ETH_IMPOV_REG);
+ val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
+ writeb_be(val, priv->base + ETH_IMPOV_REG);
+
+ /* enable switch forward engine */
+ val = readb_be(priv->base + ETH_SWMODE_REG);
+ val |= ETH_SWMODE_FWD_EN_MASK;
+ writeb_be(val, priv->base + ETH_SWMODE_REG);
+
+ /* enable jumbo on all ports */
+ writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
+ writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(bcm6368_eth) = {
+ .name = "bcm6368_eth",
+ .id = UCLASS_ETH,
+ .of_match = bcm6368_eth_ids,
+ .ops = &bcm6368_eth_ops,
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+ .priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
+ .probe = bcm6368_eth_probe,
+};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 7e6fad3..1dbe2b1 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -306,6 +306,7 @@
source "drivers/pinctrl/renesas/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/exynos/Kconfig"
+source "drivers/pinctrl/mscc/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/broadcom/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 293bad3..66d36b9 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,6 +17,7 @@
obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/
obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_MTK) += mediatek/
+obj-$(CONFIG_PINCTRL_MSCC) += mscc/
obj-$(CONFIG_ARCH_MVEBU) += mvebu/
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o
diff --git a/drivers/pinctrl/mscc/Kconfig b/drivers/pinctrl/mscc/Kconfig
new file mode 100644
index 0000000..cfc6c06
--- /dev/null
+++ b/drivers/pinctrl/mscc/Kconfig
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+config PINCTRL_MSCC
+ bool
+
+config PINCTRL_MSCC_OCELOT
+ depends on SOC_OCELOT && PINCTRL_FULL && OF_CONTROL
+ select PINCTRL_MSCC
+ default y
+ bool "Microsemi ocelot family pin control driver"
+ help
+ Support pin multiplexing and pin configuration control on
+ Microsemi ocelot SoCs.
+
+config PINCTRL_MSCC_LUTON
+ depends on SOC_LUTON && PINCTRL_FULL && OF_CONTROL
+ select PINCTRL_MSCC
+ default y
+ bool "Microsemi luton family pin control driver"
+ help
+ Support pin multiplexing and pin configuration control on
+ Microsemi luton SoCs.
diff --git a/drivers/pinctrl/mscc/Makefile b/drivers/pinctrl/mscc/Makefile
new file mode 100644
index 0000000..6910671
--- /dev/null
+++ b/drivers/pinctrl/mscc/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+obj-y += mscc-common.o
+obj-$(CONFIG_PINCTRL_MSCC_OCELOT) += pinctrl-ocelot.o
+obj-$(CONFIG_PINCTRL_MSCC_LUTON) += pinctrl-luton.o
diff --git a/drivers/pinctrl/mscc/mscc-common.c b/drivers/pinctrl/mscc/mscc-common.c
new file mode 100644
index 0000000..d74b8a6
--- /dev/null
+++ b/drivers/pinctrl/mscc/mscc-common.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs pinctrl driver
+ *
+ * Author: <alexandre.belloni@free-electrons.com>
+ * Author: <gregory.clement@bootlin.com>
+ * License: Dual MIT/GPL
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#include <asm/gpio.h>
+#include <asm/system.h>
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/io.h>
+#include "mscc-common.h"
+
+#define MSCC_GPIO_OUT_SET 0x0
+#define MSCC_GPIO_OUT_CLR 0x4
+#define MSCC_GPIO_OUT 0x8
+#define MSCC_GPIO_IN 0xc
+#define MSCC_GPIO_OE 0x10
+#define MSCC_GPIO_INTR 0x14
+#define MSCC_GPIO_INTR_ENA 0x18
+#define MSCC_GPIO_INTR_IDENT 0x1c
+#define MSCC_GPIO_ALT0 0x20
+#define MSCC_GPIO_ALT1 0x24
+
+static int mscc_get_functions_count(struct udevice *dev)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev);
+
+ return info->num_func;
+}
+
+static const char *mscc_get_function_name(struct udevice *dev,
+ unsigned int function)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev);
+
+ return info->function_names[function];
+}
+
+static int mscc_pin_function_idx(unsigned int pin, unsigned int function,
+ const struct mscc_pin_data *mscc_pins)
+{
+ struct mscc_pin_caps *p = mscc_pins[pin].drv_data;
+ int i;
+
+ for (i = 0; i < MSCC_FUNC_PER_PIN; i++) {
+ if (function == p->functions[i])
+ return i;
+ }
+
+ return -1;
+}
+
+static int mscc_pinmux_set_mux(struct udevice *dev,
+ unsigned int pin_selector, unsigned int selector)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev);
+ struct mscc_pin_caps *pin = info->mscc_pins[pin_selector].drv_data;
+ int f;
+
+ f = mscc_pin_function_idx(pin_selector, selector, info->mscc_pins);
+ if (f < 0)
+ return -EINVAL;
+ /*
+ * f is encoded on two bits.
+ * bit 0 of f goes in BIT(pin) of ALT0, bit 1 of f goes in BIT(pin) of
+ * ALT1
+ * This is racy because both registers can't be updated at the same time
+ * but it doesn't matter much for now.
+ */
+ if (f & BIT(0))
+ setbits_le32(info->regs + MSCC_GPIO_ALT0, BIT(pin->pin));
+ else
+ clrbits_le32(info->regs + MSCC_GPIO_ALT0, BIT(pin->pin));
+
+ if (f & BIT(1))
+ setbits_le32(info->regs + MSCC_GPIO_ALT1, BIT(pin->pin - 1));
+ else
+ clrbits_le32(info->regs + MSCC_GPIO_ALT1, BIT(pin->pin - 1));
+
+ return 0;
+}
+
+static int mscc_pctl_get_groups_count(struct udevice *dev)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev);
+
+ return info->num_pins;
+}
+
+static const char *mscc_pctl_get_group_name(struct udevice *dev,
+ unsigned int group)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev);
+
+ return info->mscc_pins[group].name;
+}
+
+static int mscc_create_group_func_map(struct udevice *dev,
+ struct mscc_pinctrl *info)
+{
+ u16 pins[info->num_pins];
+ int f, npins, i;
+
+ for (f = 0; f < info->num_func; f++) {
+ for (npins = 0, i = 0; i < info->num_pins; i++) {
+ if (mscc_pin_function_idx(i, f, info->mscc_pins) >= 0)
+ pins[npins++] = i;
+ }
+
+ info->func[f].ngroups = npins;
+ info->func[f].groups = devm_kzalloc(dev, npins *
+ sizeof(char *), GFP_KERNEL);
+ if (!info->func[f].groups)
+ return -ENOMEM;
+
+ for (i = 0; i < npins; i++)
+ info->func[f].groups[i] = info->mscc_pins[pins[i]].name;
+ }
+
+ return 0;
+}
+
+static int mscc_pinctrl_register(struct udevice *dev, struct mscc_pinctrl *info)
+{
+ int ret;
+
+ ret = mscc_create_group_func_map(dev, info);
+ if (ret) {
+ dev_err(dev, "Unable to create group func map.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mscc_gpio_get(struct udevice *dev, unsigned int offset)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev->parent);
+ unsigned int val;
+
+ val = readl(info->regs + MSCC_GPIO_IN);
+
+ return !!(val & BIT(offset));
+}
+
+static int mscc_gpio_set(struct udevice *dev, unsigned int offset, int value)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev->parent);
+
+ if (value)
+ writel(BIT(offset), info->regs + MSCC_GPIO_OUT_SET);
+ else
+ writel(BIT(offset), info->regs + MSCC_GPIO_OUT_CLR);
+
+ return 0;
+}
+
+static int mscc_gpio_get_direction(struct udevice *dev, unsigned int offset)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev->parent);
+ unsigned int val;
+
+ val = readl(info->regs + MSCC_GPIO_OE);
+
+ return (val & BIT(offset)) ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+static int mscc_gpio_direction_input(struct udevice *dev, unsigned int offset)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev->parent);
+
+ clrbits_le32(info->regs + MSCC_GPIO_OE, BIT(offset));
+
+ return 0;
+}
+
+static int mscc_gpio_direction_output(struct udevice *dev,
+ unsigned int offset, int value)
+{
+ struct mscc_pinctrl *info = dev_get_priv(dev->parent);
+
+ setbits_le32(info->regs + MSCC_GPIO_OE, BIT(offset));
+
+ return mscc_gpio_set(dev, offset, value);
+}
+
+const struct dm_gpio_ops mscc_gpio_ops = {
+ .set_value = mscc_gpio_set,
+ .get_value = mscc_gpio_get,
+ .get_function = mscc_gpio_get_direction,
+ .direction_input = mscc_gpio_direction_input,
+ .direction_output = mscc_gpio_direction_output,
+};
+
+const struct pinctrl_ops mscc_pinctrl_ops = {
+ .get_pins_count = mscc_pctl_get_groups_count,
+ .get_pin_name = mscc_pctl_get_group_name,
+ .get_functions_count = mscc_get_functions_count,
+ .get_function_name = mscc_get_function_name,
+ .pinmux_set = mscc_pinmux_set_mux,
+ .set_state = pinctrl_generic_set_state,
+};
+
+int mscc_pinctrl_probe(struct udevice *dev, int num_func,
+ const struct mscc_pin_data *mscc_pins, int num_pins,
+ char *const *function_names)
+{
+ struct mscc_pinctrl *priv = dev_get_priv(dev);
+ int ret;
+
+ priv->regs = dev_remap_addr(dev);
+ if (!priv->regs)
+ return -EINVAL;
+
+ priv->func = devm_kzalloc(dev, num_func * sizeof(struct mscc_pmx_func),
+ GFP_KERNEL);
+ priv->num_func = num_func;
+ priv->mscc_pins = mscc_pins;
+ priv->num_pins = num_pins;
+ priv->function_names = function_names;
+ ret = mscc_pinctrl_register(dev, priv);
+
+ return ret;
+}
diff --git a/drivers/pinctrl/mscc/mscc-common.h b/drivers/pinctrl/mscc/mscc-common.h
new file mode 100644
index 0000000..b0001db
--- /dev/null
+++ b/drivers/pinctrl/mscc/mscc-common.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi SoCs pinctrl driver
+ *
+ * Author: <alexandre.belloni@free-electrons.com>
+ * License: Dual MIT/GPL
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#define MSCC_FUNC_PER_PIN 4
+
+struct mscc_pin_caps {
+ unsigned int pin;
+ unsigned char functions[MSCC_FUNC_PER_PIN];
+};
+
+struct mscc_pin_data {
+ const char *name;
+ struct mscc_pin_caps *drv_data;
+};
+
+#define MSCC_P(p, f0, f1, f2) \
+static struct mscc_pin_caps mscc_pin_##p = { \
+ .pin = p, \
+ .functions = { \
+ FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2, \
+ }, \
+}
+
+struct mscc_pmx_func {
+ const char **groups;
+ unsigned int ngroups;
+};
+
+struct mscc_pinctrl {
+ struct udevice *dev;
+ struct pinctrl_dev *pctl;
+ void __iomem *regs;
+ struct mscc_pmx_func *func;
+ int num_func;
+ const struct mscc_pin_data *mscc_pins;
+ int num_pins;
+ char * const *function_names;
+};
+
+int mscc_pinctrl_probe(struct udevice *dev, int num_func,
+ const struct mscc_pin_data *mscc_pins, int num_pins,
+ char * const *function_names);
+const struct pinctrl_ops mscc_pinctrl_ops;
+
+const struct dm_gpio_ops mscc_gpio_ops;
diff --git a/drivers/pinctrl/mscc/pinctrl-luton.c b/drivers/pinctrl/mscc/pinctrl-luton.c
new file mode 100644
index 0000000..7166588
--- /dev/null
+++ b/drivers/pinctrl/mscc/pinctrl-luton.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs pinctrl driver
+ *
+ * Author: <gregory.clement@bootlin.com>
+ * License: Dual MIT/GPL
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/io.h>
+#include <asm/gpio.h>
+#include <asm/system.h>
+#include "mscc-common.h"
+
+enum {
+ FUNC_NONE,
+ FUNC_GPIO,
+ FUNC_SIO,
+ FUNC_TACHO,
+ FUNC_TWI,
+ FUNC_PHY_LED,
+ FUNC_EXT_IRQ,
+ FUNC_SFP,
+ FUNC_SI,
+ FUNC_PWM,
+ FUNC_UART,
+ FUNC_MAX
+};
+
+static char * const luton_function_names[] = {
+ [FUNC_NONE] = "none",
+ [FUNC_GPIO] = "gpio",
+ [FUNC_SIO] = "sio",
+ [FUNC_TACHO] = "tacho",
+ [FUNC_TWI] = "twi",
+ [FUNC_PHY_LED] = "phy_led",
+ [FUNC_EXT_IRQ] = "ext_irq",
+ [FUNC_SFP] = "sfp",
+ [FUNC_SI] = "si",
+ [FUNC_PWM] = "pwm",
+ [FUNC_UART] = "uart",
+};
+
+MSCC_P(0, SIO, NONE, NONE);
+MSCC_P(1, SIO, NONE, NONE);
+MSCC_P(2, SIO, NONE, NONE);
+MSCC_P(3, SIO, NONE, NONE);
+MSCC_P(4, TACHO, NONE, NONE);
+MSCC_P(5, TWI, PHY_LED, NONE);
+MSCC_P(6, TWI, PHY_LED, NONE);
+MSCC_P(7, NONE, PHY_LED, NONE);
+MSCC_P(8, EXT_IRQ, PHY_LED, NONE);
+MSCC_P(9, EXT_IRQ, PHY_LED, NONE);
+MSCC_P(10, SFP, PHY_LED, NONE);
+MSCC_P(11, SFP, PHY_LED, NONE);
+MSCC_P(12, SFP, PHY_LED, NONE);
+MSCC_P(13, SFP, PHY_LED, NONE);
+MSCC_P(14, SI, PHY_LED, NONE);
+MSCC_P(15, SI, PHY_LED, NONE);
+MSCC_P(16, SI, PHY_LED, NONE);
+MSCC_P(17, SFP, PHY_LED, NONE);
+MSCC_P(18, SFP, PHY_LED, NONE);
+MSCC_P(19, SFP, PHY_LED, NONE);
+MSCC_P(20, SFP, PHY_LED, NONE);
+MSCC_P(21, SFP, PHY_LED, NONE);
+MSCC_P(22, SFP, PHY_LED, NONE);
+MSCC_P(23, SFP, PHY_LED, NONE);
+MSCC_P(24, SFP, PHY_LED, NONE);
+MSCC_P(25, SFP, PHY_LED, NONE);
+MSCC_P(26, SFP, PHY_LED, NONE);
+MSCC_P(27, SFP, PHY_LED, NONE);
+MSCC_P(28, SFP, PHY_LED, NONE);
+MSCC_P(29, PWM, NONE, NONE);
+MSCC_P(30, UART, NONE, NONE);
+MSCC_P(31, UART, NONE, NONE);
+
+#define LUTON_PIN(n) { \
+ .name = "GPIO_"#n, \
+ .drv_data = &mscc_pin_##n \
+}
+
+static const struct mscc_pin_data luton_pins[] = {
+ LUTON_PIN(0),
+ LUTON_PIN(1),
+ LUTON_PIN(2),
+ LUTON_PIN(3),
+ LUTON_PIN(4),
+ LUTON_PIN(5),
+ LUTON_PIN(6),
+ LUTON_PIN(7),
+ LUTON_PIN(8),
+ LUTON_PIN(9),
+ LUTON_PIN(10),
+ LUTON_PIN(11),
+ LUTON_PIN(12),
+ LUTON_PIN(13),
+ LUTON_PIN(14),
+ LUTON_PIN(15),
+ LUTON_PIN(16),
+ LUTON_PIN(17),
+ LUTON_PIN(18),
+ LUTON_PIN(19),
+ LUTON_PIN(20),
+ LUTON_PIN(21),
+ LUTON_PIN(22),
+ LUTON_PIN(23),
+ LUTON_PIN(24),
+ LUTON_PIN(25),
+ LUTON_PIN(26),
+ LUTON_PIN(27),
+ LUTON_PIN(28),
+ LUTON_PIN(29),
+ LUTON_PIN(30),
+ LUTON_PIN(31),
+};
+
+static int luton_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv;
+
+ uc_priv = dev_get_uclass_priv(dev);
+ uc_priv->bank_name = "luton-gpio";
+ uc_priv->gpio_count = ARRAY_SIZE(luton_pins);
+
+ return 0;
+}
+
+static struct driver luton_gpio_driver = {
+ .name = "luton-gpio",
+ .id = UCLASS_GPIO,
+ .probe = luton_gpio_probe,
+ .ops = &mscc_gpio_ops,
+};
+
+int luton_pinctrl_probe(struct udevice *dev)
+{
+ int ret;
+
+ ret = mscc_pinctrl_probe(dev, FUNC_MAX, luton_pins,
+ ARRAY_SIZE(luton_pins), luton_function_names);
+
+ if (ret)
+ return ret;
+
+ ret = device_bind(dev, &luton_gpio_driver, "luton-gpio", NULL,
+ dev_of_offset(dev), NULL);
+
+ return 0;
+}
+
+static const struct udevice_id luton_pinctrl_of_match[] = {
+ {.compatible = "mscc,luton-pinctrl"},
+ {},
+};
+
+U_BOOT_DRIVER(luton_pinctrl) = {
+ .name = "luton-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(luton_pinctrl_of_match),
+ .probe = luton_pinctrl_probe,
+ .priv_auto_alloc_size = sizeof(struct mscc_pinctrl),
+ .ops = &mscc_pinctrl_ops,
+};
diff --git a/drivers/pinctrl/mscc/pinctrl-ocelot.c b/drivers/pinctrl/mscc/pinctrl-ocelot.c
new file mode 100644
index 0000000..10f9b90
--- /dev/null
+++ b/drivers/pinctrl/mscc/pinctrl-ocelot.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Microsemi SoCs pinctrl driver
+ *
+ * Author: <alexandre.belloni@free-electrons.com>
+ * Author: <gregory.clement@bootlin.com>
+ * License: Dual MIT/GPL
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#include <asm/gpio.h>
+#include <asm/system.h>
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/io.h>
+#include "mscc-common.h"
+
+enum {
+ FUNC_NONE,
+ FUNC_GPIO,
+ FUNC_IRQ0_IN,
+ FUNC_IRQ0_OUT,
+ FUNC_IRQ1_IN,
+ FUNC_IRQ1_OUT,
+ FUNC_MIIM1,
+ FUNC_PCI_WAKE,
+ FUNC_PTP0,
+ FUNC_PTP1,
+ FUNC_PTP2,
+ FUNC_PTP3,
+ FUNC_PWM,
+ FUNC_RECO_CLK0,
+ FUNC_RECO_CLK1,
+ FUNC_SFP0,
+ FUNC_SFP1,
+ FUNC_SFP2,
+ FUNC_SFP3,
+ FUNC_SFP4,
+ FUNC_SFP5,
+ FUNC_SG0,
+ FUNC_SI,
+ FUNC_TACHO,
+ FUNC_TWI,
+ FUNC_TWI_SCL_M,
+ FUNC_UART,
+ FUNC_UART2,
+ FUNC_MAX
+};
+
+static char * const ocelot_function_names[] = {
+ [FUNC_NONE] = "none",
+ [FUNC_GPIO] = "gpio",
+ [FUNC_IRQ0_IN] = "irq0_in",
+ [FUNC_IRQ0_OUT] = "irq0_out",
+ [FUNC_IRQ1_IN] = "irq1_in",
+ [FUNC_IRQ1_OUT] = "irq1_out",
+ [FUNC_MIIM1] = "miim1",
+ [FUNC_PCI_WAKE] = "pci_wake",
+ [FUNC_PTP0] = "ptp0",
+ [FUNC_PTP1] = "ptp1",
+ [FUNC_PTP2] = "ptp2",
+ [FUNC_PTP3] = "ptp3",
+ [FUNC_PWM] = "pwm",
+ [FUNC_RECO_CLK0] = "reco_clk0",
+ [FUNC_RECO_CLK1] = "reco_clk1",
+ [FUNC_SFP0] = "sfp0",
+ [FUNC_SFP1] = "sfp1",
+ [FUNC_SFP2] = "sfp2",
+ [FUNC_SFP3] = "sfp3",
+ [FUNC_SFP4] = "sfp4",
+ [FUNC_SFP5] = "sfp5",
+ [FUNC_SG0] = "sg0",
+ [FUNC_SI] = "si",
+ [FUNC_TACHO] = "tacho",
+ [FUNC_TWI] = "twi",
+ [FUNC_TWI_SCL_M] = "twi_scl_m",
+ [FUNC_UART] = "uart",
+ [FUNC_UART2] = "uart2",
+};
+
+MSCC_P(0, SG0, NONE, NONE);
+MSCC_P(1, SG0, NONE, NONE);
+MSCC_P(2, SG0, NONE, NONE);
+MSCC_P(3, SG0, NONE, NONE);
+MSCC_P(4, IRQ0_IN, IRQ0_OUT, TWI);
+MSCC_P(5, IRQ1_IN, IRQ1_OUT, PCI_WAKE);
+MSCC_P(6, UART, TWI_SCL_M, NONE);
+MSCC_P(7, UART, TWI_SCL_M, NONE);
+MSCC_P(8, SI, TWI_SCL_M, IRQ0_OUT);
+MSCC_P(9, SI, TWI_SCL_M, IRQ1_OUT);
+MSCC_P(10, PTP2, TWI_SCL_M, SFP0);
+MSCC_P(11, PTP3, TWI_SCL_M, SFP1);
+MSCC_P(12, UART2, TWI_SCL_M, SFP2);
+MSCC_P(13, UART2, TWI_SCL_M, SFP3);
+MSCC_P(14, MIIM1, TWI_SCL_M, SFP4);
+MSCC_P(15, MIIM1, TWI_SCL_M, SFP5);
+MSCC_P(16, TWI, NONE, SI);
+MSCC_P(17, TWI, TWI_SCL_M, SI);
+MSCC_P(18, PTP0, TWI_SCL_M, NONE);
+MSCC_P(19, PTP1, TWI_SCL_M, NONE);
+MSCC_P(20, RECO_CLK0, TACHO, NONE);
+MSCC_P(21, RECO_CLK1, PWM, NONE);
+
+#define OCELOT_PIN(n) { \
+ .name = "GPIO_"#n, \
+ .drv_data = &mscc_pin_##n \
+}
+
+static const struct mscc_pin_data ocelot_pins[] = {
+ OCELOT_PIN(0),
+ OCELOT_PIN(1),
+ OCELOT_PIN(2),
+ OCELOT_PIN(3),
+ OCELOT_PIN(4),
+ OCELOT_PIN(5),
+ OCELOT_PIN(6),
+ OCELOT_PIN(7),
+ OCELOT_PIN(8),
+ OCELOT_PIN(9),
+ OCELOT_PIN(10),
+ OCELOT_PIN(11),
+ OCELOT_PIN(12),
+ OCELOT_PIN(13),
+ OCELOT_PIN(14),
+ OCELOT_PIN(15),
+ OCELOT_PIN(16),
+ OCELOT_PIN(17),
+ OCELOT_PIN(18),
+ OCELOT_PIN(19),
+ OCELOT_PIN(20),
+ OCELOT_PIN(21),
+};
+
+static int ocelot_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv;
+
+ uc_priv = dev_get_uclass_priv(dev);
+ uc_priv->bank_name = "ocelot-gpio";
+ uc_priv->gpio_count = ARRAY_SIZE(ocelot_pins);
+
+ return 0;
+}
+
+static struct driver ocelot_gpio_driver = {
+ .name = "ocelot-gpio",
+ .id = UCLASS_GPIO,
+ .probe = ocelot_gpio_probe,
+ .ops = &mscc_gpio_ops,
+};
+
+int ocelot_pinctrl_probe(struct udevice *dev)
+{
+ int ret;
+
+ ret = mscc_pinctrl_probe(dev, FUNC_MAX, ocelot_pins,
+ ARRAY_SIZE(ocelot_pins),
+ ocelot_function_names);
+
+ if (ret)
+ return ret;
+
+ ret = device_bind(dev, &ocelot_gpio_driver, "ocelot-gpio", NULL,
+ dev_of_offset(dev), NULL);
+
+ return ret;
+}
+
+static const struct udevice_id ocelot_pinctrl_of_match[] = {
+ {.compatible = "mscc,ocelot-pinctrl"},
+ {},
+};
+
+U_BOOT_DRIVER(ocelot_pinctrl) = {
+ .name = "ocelot-pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = of_match_ptr(ocelot_pinctrl_of_match),
+ .probe = ocelot_pinctrl_probe,
+ .priv_auto_alloc_size = sizeof(struct mscc_pinctrl),
+ .ops = &mscc_pinctrl_ops,
+};
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 6252dd8..b7ff296 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -343,6 +343,13 @@
start up driver model. The driver will be available until the real
driver model serial is running.
+config DEBUG_UART_SIFIVE
+ bool "SiFive UART"
+ help
+ Select this to enable a debug UART using the serial_sifive driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
config DEBUG_UART_STM32
bool "STMicroelectronics STM32"
depends on STM32_SERIAL
@@ -679,6 +686,12 @@
If you have a machine based on a Marvell XScale PXA2xx CPU you
can enable its onboard serial ports by enabling this option.
+config SIFIVE_SERIAL
+ bool "SiFive UART support"
+ depends on DM_SERIAL
+ help
+ This driver supports the SiFive UART. If unsure say N.
+
config STI_ASC_SERIAL
bool "STMicroelectronics on-chip UART"
depends on DM_SERIAL && ARCH_STI
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 2f8d065..06ee306 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -67,6 +67,7 @@
obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
+obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_sifive.c b/drivers/serial/serial_sifive.c
new file mode 100644
index 0000000..341728a
--- /dev/null
+++ b/drivers/serial/serial_sifive.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Anup Patel <anup@brainfault.org>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_TXFIFO_FULL 0x80000000
+#define UART_RXFIFO_EMPTY 0x80000000
+#define UART_RXFIFO_DATA 0x000000ff
+#define UART_TXCTRL_TXEN 0x1
+#define UART_RXCTRL_RXEN 0x1
+
+struct uart_sifive {
+ u32 txfifo;
+ u32 rxfifo;
+ u32 txctrl;
+ u32 rxctrl;
+ u32 ie;
+ u32 ip;
+ u32 div;
+};
+
+struct sifive_uart_platdata {
+ unsigned int clock;
+ int saved_input_char;
+ struct uart_sifive *regs;
+};
+
+/* Set up the baud rate in gd struct */
+static void _sifive_serial_setbrg(struct uart_sifive *regs,
+ unsigned long clock, unsigned long baud)
+{
+ writel((u32)((clock / baud) - 1), ®s->div);
+}
+
+static void _sifive_serial_init(struct uart_sifive *regs)
+{
+ writel(UART_TXCTRL_TXEN, ®s->txctrl);
+ writel(UART_RXCTRL_RXEN, ®s->rxctrl);
+ writel(0, ®s->ie);
+}
+
+static int _sifive_serial_putc(struct uart_sifive *regs, const char c)
+{
+ if (readl(®s->txfifo) & UART_TXFIFO_FULL)
+ return -EAGAIN;
+
+ writel(c, ®s->txfifo);
+
+ return 0;
+}
+
+static int _sifive_serial_getc(struct uart_sifive *regs)
+{
+ int ch = readl(®s->rxfifo);
+
+ if (ch & UART_RXFIFO_EMPTY)
+ return -EAGAIN;
+ ch &= UART_RXFIFO_DATA;
+
+ return (!ch) ? -EAGAIN : ch;
+}
+
+static int sifive_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ int err;
+ struct clk clk;
+ struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
+
+ err = clk_get_by_index(dev, 0, &clk);
+ if (!err) {
+ err = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(err))
+ platdata->clock = err;
+ } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
+ debug("SiFive UART failed to get clock\n");
+ return err;
+ }
+
+ if (!platdata->clock)
+ platdata->clock = dev_read_u32_default(dev, "clock-frequency", 0);
+ if (!platdata->clock) {
+ debug("SiFive UART clock not defined\n");
+ return -EINVAL;
+ }
+
+ _sifive_serial_setbrg(platdata->regs, platdata->clock, baudrate);
+
+ return 0;
+}
+
+static int sifive_serial_probe(struct udevice *dev)
+{
+ struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
+
+ /* No need to reinitialize the UART after relocation */
+ if (gd->flags & GD_FLG_RELOC)
+ return 0;
+
+ platdata->saved_input_char = 0;
+ _sifive_serial_init(platdata->regs);
+
+ return 0;
+}
+
+static int sifive_serial_getc(struct udevice *dev)
+{
+ int c;
+ struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
+ struct uart_sifive *regs = platdata->regs;
+
+ if (platdata->saved_input_char > 0) {
+ c = platdata->saved_input_char;
+ platdata->saved_input_char = 0;
+ return c;
+ }
+
+ while ((c = _sifive_serial_getc(regs)) == -EAGAIN) ;
+
+ return c;
+}
+
+static int sifive_serial_putc(struct udevice *dev, const char ch)
+{
+ int rc;
+ struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
+
+ while ((rc = _sifive_serial_putc(platdata->regs, ch)) == -EAGAIN) ;
+
+ return rc;
+}
+
+static int sifive_serial_pending(struct udevice *dev, bool input)
+{
+ struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
+ struct uart_sifive *regs = platdata->regs;
+
+ if (input) {
+ if (platdata->saved_input_char > 0)
+ return 1;
+ platdata->saved_input_char = _sifive_serial_getc(regs);
+ return (platdata->saved_input_char > 0) ? 1 : 0;
+ } else {
+ return !!(readl(®s->txfifo) & UART_TXFIFO_FULL);
+ }
+}
+
+static int sifive_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
+
+ platdata->regs = (struct uart_sifive *)dev_read_addr(dev);
+ if (IS_ERR(platdata->regs))
+ return PTR_ERR(platdata->regs);
+
+ return 0;
+}
+
+static const struct dm_serial_ops sifive_serial_ops = {
+ .putc = sifive_serial_putc,
+ .getc = sifive_serial_getc,
+ .pending = sifive_serial_pending,
+ .setbrg = sifive_serial_setbrg,
+};
+
+static const struct udevice_id sifive_serial_ids[] = {
+ { .compatible = "sifive,uart0" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_sifive) = {
+ .name = "serial_sifive",
+ .id = UCLASS_SERIAL,
+ .of_match = sifive_serial_ids,
+ .ofdata_to_platdata = sifive_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct sifive_uart_platdata),
+ .probe = sifive_serial_probe,
+ .ops = &sifive_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_SIFIVE
+static inline void _debug_uart_init(void)
+{
+ struct uart_sifive *regs =
+ (struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
+
+ _sifive_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+ _sifive_serial_init(regs);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct uart_sifive *regs =
+ (struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
+
+ while (_sifive_serial_putc(regs, ch) == -EAGAIN)
+ WATCHDOG_RESET();
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 5cca414..02d9376 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -369,7 +369,13 @@
return 0;
}
-static void external_cs_manage(struct udevice *dev, bool on)
+/*
+ * We define external_cs_manage function as 'weak' as some targets
+ * (like MSCC Ocelot) don't control the external CS pin using a GPIO
+ * controller. These SoCs use specific registers to control by
+ * software the SPI pins (and especially the CS).
+ */
+__weak void external_cs_manage(struct udevice *dev, bool on)
{
#if defined(CONFIG_DM_GPIO) && !defined(CONFIG_SPL_BUILD)
struct dw_spi_priv *priv = dev_get_priv(dev->parent);
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index b0e6f32..df37a79 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -126,6 +126,13 @@
help
Select this to enable an timer for Omap devices.
+config RISCV_TIMER
+ bool "RISC-V timer support"
+ depends on TIMER && RISCV
+ help
+ Select this to enable support for the timer as defined
+ by the RISC-V privileged architecture spec.
+
config ROCKCHIP_TIMER
bool "Rockchip timer support"
depends on TIMER
diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile
index c4fbab2..d0bf218 100644
--- a/drivers/timer/Makefile
+++ b/drivers/timer/Makefile
@@ -13,6 +13,7 @@
obj-$(CONFIG_DESIGNWARE_APB_TIMER) += dw-apb-timer.o
obj-$(CONFIG_MPC83XX_TIMER) += mpc83xx_timer.o
obj-$(CONFIG_OMAP_TIMER) += omap-timer.o
+obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o
obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
obj-$(CONFIG_STI_TIMER) += sti-timer.o
diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
new file mode 100644
index 0000000..9f9f070
--- /dev/null
+++ b/drivers/timer/riscv_timer.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * RISC-V privileged architecture defined generic timer driver
+ *
+ * This driver relies on RISC-V platform codes to provide the essential API
+ * riscv_get_time() which is supposed to return the timer counter as defined
+ * by the RISC-V privileged architecture spec.
+ *
+ * This driver can be used in both M-mode and S-mode U-Boot.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <timer.h>
+#include <asm/io.h>
+
+/**
+ * riscv_get_time() - get the timer counter
+ *
+ * Platform codes should provide this API in order to make this driver function.
+ *
+ * @time: the 64-bit timer count as defined by the RISC-V privileged
+ * architecture spec.
+ * @return: 0 on success, -ve on error.
+ */
+extern int riscv_get_time(u64 *time);
+
+static int riscv_timer_get_count(struct udevice *dev, u64 *count)
+{
+ return riscv_get_time(count);
+}
+
+static int riscv_timer_probe(struct udevice *dev)
+{
+ struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ /* clock frequency was passed from the cpu driver as driver data */
+ uc_priv->clock_rate = dev->driver_data;
+
+ return 0;
+}
+
+static const struct timer_ops riscv_timer_ops = {
+ .get_count = riscv_timer_get_count,
+};
+
+U_BOOT_DRIVER(riscv_timer) = {
+ .name = "riscv_timer",
+ .id = UCLASS_TIMER,
+ .probe = riscv_timer_probe,
+ .ops = &riscv_timer_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/configs/bmips_common.h b/include/configs/bmips_common.h
index 39ca2e0..788f4af 100644
--- a/include/configs/bmips_common.h
+++ b/include/configs/bmips_common.h
@@ -6,6 +6,10 @@
#ifndef __CONFIG_BMIPS_COMMON_H
#define __CONFIG_BMIPS_COMMON_H
+/* ETH */
+#define CONFIG_PHY_RESET_DELAY 20
+#define CONFIG_SYS_RX_ETH_BUFFER 6
+
/* UART */
#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, \
230400, 500000, 1500000 }
@@ -16,7 +20,7 @@
/* Memory usage */
#define CONFIG_SYS_MAXARGS 24
-#define CONFIG_SYS_MALLOC_LEN (1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN (2 * 1024 * 1024)
#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024)
#define CONFIG_SYS_CBSIZE 512
diff --git a/include/configs/ci20.h b/include/configs/ci20.h
new file mode 100644
index 0000000..9a36213
--- /dev/null
+++ b/include/configs/ci20.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * CI20 configuration
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ */
+
+#ifndef __CONFIG_CI20_H__
+#define __CONFIG_CI20_H__
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/* Ingenic JZ4780 clock configuration. */
+#define CONFIG_SYS_HZ 1000
+#define CONFIG_SYS_MHZ 1200
+#define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000)
+
+/* Memory configuration */
+#define CONFIG_SYS_MONITOR_LEN (512 * 1024)
+#define CONFIG_SYS_MALLOC_LEN (64 * 1024 * 1024)
+#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024)
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* cached (KSEG0) address */
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+#define CONFIG_SYS_LOAD_ADDR 0x81000000
+#define CONFIG_LOADADDR CONFIG_SYS_LOAD_ADDR
+#define CONFIG_SYS_MEMTEST_START 0x80000000
+#define CONFIG_SYS_MEMTEST_END 0x88000000
+
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
+
+/* NS16550-ish UARTs */
+#define CONFIG_SYS_NS16550_CLK 48000000
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+/* Ethernet: davicom DM9000 */
+#define CONFIG_DRIVER_DM9000 1
+#define CONFIG_DM9000_BASE 0xb6000000
+#define DM9000_IO CONFIG_DM9000_BASE
+#define DM9000_DATA (CONFIG_DM9000_BASE + 2)
+
+/* Environment */
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_ENV_SIZE (32 << 10)
+#define CONFIG_ENV_OFFSET ((14 + 512) << 10)
+#define CONFIG_ENV_OVERWRITE
+
+/* Command line configuration. */
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O buffer size */
+#define CONFIG_SYS_MAXARGS 32 /* Max number of command args */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+ /* Boot argument buffer size */
+#define CONFIG_VERSION_VARIABLE /* U-BOOT version */
+
+/* Miscellaneous configuration options */
+#define CONFIG_SYS_BOOTM_LEN (64 << 20)
+
+/* SPL */
+#define CONFIG_SPL_STACK 0xf4008000 /* only max. 2KB spare! */
+
+#define CONFIG_SPL_TEXT_BASE 0xf4000a00
+#define CONFIG_SPL_MAX_SIZE ((14 * 1024) - 0xa00)
+
+#define CONFIG_SPL_BSS_START_ADDR 0xf4004000
+#define CONFIG_SPL_BSS_MAX_SIZE 0x00002000 /* 512KB, arbitrary */
+
+#define CONFIG_SPL_START_S_PATH "arch/mips/mach-jz47xx"
+
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x1c /* 14 KiB offset */
+
+#endif /* __CONFIG_CI20_H__ */
diff --git a/include/configs/vcoreiii.h b/include/configs/vcoreiii.h
new file mode 100644
index 0000000..df89cda
--- /dev/null
+++ b/include/configs/vcoreiii.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef __VCOREIII_H
+#define __VCOREIII_H
+
+#include <linux/sizes.h>
+
+/* Onboard devices */
+
+#define CONFIG_SYS_MALLOC_LEN 0x100000
+#define CONFIG_SYS_LOAD_ADDR 0x00100000
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+
+#define CPU_CLOCK_RATE 500000000 /* Clock for the MIPS core */
+#ifdef CONFIG_SOC_LUTON
+#define CONFIG_SYS_MIPS_TIMER_FREQ 208333333
+#else
+#define CONFIG_SYS_MIPS_TIMER_FREQ (CPU_CLOCK_RATE / 2)
+#endif
+#define CONFIG_SYS_NS16550_CLK CONFIG_SYS_MIPS_TIMER_FREQ
+
+#if defined(CONFIG_ENV_IS_IN_SPI_FLASH) && !defined(CONFIG_ENV_OFFSET)
+#define CONFIG_ENV_OFFSET (1024 * 1024)
+#define CONFIG_ENV_SIZE (256 * 1024)
+#define CONFIG_ENV_SECT_SIZE (256 * 1024)
+
+#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
+#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE
+#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SECT_SIZE)
+
+#define CONFIG_ENV_SPI_MAX_HZ 0 /* This force to read from DT */
+#define CONFIG_ENV_SPI_MODE 0 /* This force to read from DT */
+#endif
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000
+#if defined(CONFIG_DDRTYPE_H5TQ1G63BFA) || defined(CONFIG_DDRTYPE_MT47H128M8HQ)
+#define CONFIG_SYS_SDRAM_SIZE (128 * SZ_1M)
+#elif defined(CONFIG_DDRTYPE_MT41J128M16HA) || defined(CONFIG_DDRTYPE_MT41K128M16JT)
+#define CONFIG_SYS_SDRAM_SIZE (256 * SZ_1M)
+#elif defined(CONFIG_DDRTYPE_H5TQ4G63MFR) || defined(CONFIG_DDRTYPE_MT41K256M16)
+#define CONFIG_SYS_SDRAM_SIZE (512 * SZ_1M)
+#else
+#error Unknown DDR size - please add!
+#endif
+
+#define CONFIG_CONS_INDEX 1
+
+#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE - SZ_1M)
+
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_BOARD_EARLY_INIT_R
+#if defined(CONFIG_MTDIDS_DEFAULT) && defined(CONFIG_MTDPARTS_DEFAULT)
+#define VCOREIII_DEFAULT_MTD_ENV \
+ "mtdparts="CONFIG_MTDPARTS_DEFAULT"\0" \
+ "mtdids="CONFIG_MTDIDS_DEFAULT"\0"
+#else
+#define VCOREIII_DEFAULT_MTD_ENV /* Go away */
+#endif
+
+#define CONFIG_SYS_BOOTM_LEN (16 << 20) /* Increase max gunzip size */
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ VCOREIII_DEFAULT_MTD_ENV \
+ "loadaddr=0x81000000\0" \
+ "spi_image_off=0x00100000\0" \
+ "console=ttyS0,115200\0" \
+ "setup=setenv bootargs console=${console} ${mtdparts}" \
+ "${bootargs_extra}\0" \
+ "spiboot=run setup; sf probe; sf read ${loadaddr}" \
+ "${spi_image_off} 0x600000; bootm ${loadaddr}\0" \
+ "ubootfile=u-boot.bin\0" \
+ "update=sf probe;mtdparts;dhcp ${loadaddr} ${ubootfile};" \
+ "sf erase UBoot 0x100000;" \
+ "sf write ${loadaddr} UBoot ${filesize}\0" \
+ "bootcmd=run spiboot\0" \
+ ""
+#endif /* __VCOREIII_H */
diff --git a/include/cpu.h b/include/cpu.h
index 367c5f4..28dd48f 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -14,6 +14,8 @@
* @device_id: Driver-defined device identifier
* @family: DMTF CPU Family identifier
* @id: DMTF CPU Processor identifier
+ * @timebase_freq: the current frequency at which the cpu timer timebase
+ * registers are updated (in Hz)
*
* This can be accessed with dev_get_parent_platdata() for any UCLASS_CPU
* device.
@@ -24,6 +26,7 @@
ulong device_id;
u16 family;
u32 id[2];
+ u32 timebase_freq;
};
/* CPU features - mostly just a placeholder for now */
diff --git a/include/dt-bindings/clock/bcm6318-clock.h b/include/dt-bindings/clock/bcm6318-clock.h
index d5e13c5..3f10448 100644
--- a/include/dt-bindings/clock/bcm6318-clock.h
+++ b/include/dt-bindings/clock/bcm6318-clock.h
@@ -33,4 +33,15 @@
#define BCM6318_CLK_AFE 29
#define BCM6318_CLK_QPROC 30
+#define BCM6318_UCLK_ADSL 0
+#define BCM6318_UCLK_ARB 1
+#define BCM6318_UCLK_MIPS 2
+#define BCM6318_UCLK_PCIE 3
+#define BCM6318_UCLK_PERIPH 4
+#define BCM6318_UCLK_PHYMIPS 5
+#define BCM6318_UCLK_ROBOSW 6
+#define BCM6318_UCLK_SAR 7
+#define BCM6318_UCLK_SDR 8
+#define BCM6318_UCLK_USB 9
+
#endif /* __DT_BINDINGS_CLOCK_BCM6318_H */
diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
new file mode 100644
index 0000000..73214c5
--- /dev/null
+++ b/include/dt-bindings/clock/jz4780-cgu.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ * - external clocks
+ * - PLLs
+ * - muxes/dividers in the order they appear in the jz4780 programmers manual
+ * - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+
+#define JZ4780_CLK_EXCLK 0
+#define JZ4780_CLK_RTCLK 1
+#define JZ4780_CLK_APLL 2
+#define JZ4780_CLK_MPLL 3
+#define JZ4780_CLK_EPLL 4
+#define JZ4780_CLK_VPLL 5
+#define JZ4780_CLK_OTGPHY 6
+#define JZ4780_CLK_SCLKA 7
+#define JZ4780_CLK_CPUMUX 8
+#define JZ4780_CLK_CPU 9
+#define JZ4780_CLK_L2CACHE 10
+#define JZ4780_CLK_AHB0 11
+#define JZ4780_CLK_AHB2PMUX 12
+#define JZ4780_CLK_AHB2 13
+#define JZ4780_CLK_PCLK 14
+#define JZ4780_CLK_DDR 15
+#define JZ4780_CLK_VPU 16
+#define JZ4780_CLK_I2SPLL 17
+#define JZ4780_CLK_I2S 18
+#define JZ4780_CLK_LCD0PIXCLK 19
+#define JZ4780_CLK_LCD1PIXCLK 20
+#define JZ4780_CLK_MSCMUX 21
+#define JZ4780_CLK_MSC0 22
+#define JZ4780_CLK_MSC1 23
+#define JZ4780_CLK_MSC2 24
+#define JZ4780_CLK_UHC 25
+#define JZ4780_CLK_SSIPLL 26
+#define JZ4780_CLK_SSI 27
+#define JZ4780_CLK_CIMMCLK 28
+#define JZ4780_CLK_PCMPLL 29
+#define JZ4780_CLK_PCM 30
+#define JZ4780_CLK_GPU 31
+#define JZ4780_CLK_HDMI 32
+#define JZ4780_CLK_BCH 33
+#define JZ4780_CLK_NEMC 34
+#define JZ4780_CLK_OTG0 35
+#define JZ4780_CLK_SSI0 36
+#define JZ4780_CLK_SMB0 37
+#define JZ4780_CLK_SMB1 38
+#define JZ4780_CLK_SCC 39
+#define JZ4780_CLK_AIC 40
+#define JZ4780_CLK_TSSI0 41
+#define JZ4780_CLK_OWI 42
+#define JZ4780_CLK_KBC 43
+#define JZ4780_CLK_SADC 44
+#define JZ4780_CLK_UART0 45
+#define JZ4780_CLK_UART1 46
+#define JZ4780_CLK_UART2 47
+#define JZ4780_CLK_UART3 48
+#define JZ4780_CLK_SSI1 49
+#define JZ4780_CLK_SSI2 50
+#define JZ4780_CLK_PDMA 51
+#define JZ4780_CLK_GPS 52
+#define JZ4780_CLK_MAC 53
+#define JZ4780_CLK_SMB2 54
+#define JZ4780_CLK_CIM 55
+#define JZ4780_CLK_LCD 56
+#define JZ4780_CLK_TVE 57
+#define JZ4780_CLK_IPU 58
+#define JZ4780_CLK_DDR0 59
+#define JZ4780_CLK_DDR1 60
+#define JZ4780_CLK_SMB3 61
+#define JZ4780_CLK_TSSI1 62
+#define JZ4780_CLK_COMPRESS 63
+#define JZ4780_CLK_AIC1 64
+#define JZ4780_CLK_GPVLC 65
+#define JZ4780_CLK_OTG1 66
+#define JZ4780_CLK_UART4 67
+#define JZ4780_CLK_AHBMON 68
+#define JZ4780_CLK_SMB4 69
+#define JZ4780_CLK_DES 70
+#define JZ4780_CLK_X2D 71
+#define JZ4780_CLK_CORE1 72
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
diff --git a/include/dt-bindings/dma/bcm6318-dma.h b/include/dt-bindings/dma/bcm6318-dma.h
new file mode 100644
index 0000000..ad7c5ac
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6318-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6318_H
+#define __DT_BINDINGS_DMA_BCM6318_H
+
+#define BCM6318_DMA_ENETSW_RX 0
+#define BCM6318_DMA_ENETSW_TX 1
+
+#endif /* __DT_BINDINGS_DMA_BCM6318_H */
diff --git a/include/dt-bindings/dma/bcm63268-dma.h b/include/dt-bindings/dma/bcm63268-dma.h
new file mode 100644
index 0000000..7d02711
--- /dev/null
+++ b/include/dt-bindings/dma/bcm63268-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM63268_H
+#define __DT_BINDINGS_DMA_BCM63268_H
+
+#define BCM63268_DMA_ENETSW_RX 0
+#define BCM63268_DMA_ENETSW_TX 1
+
+#endif /* __DT_BINDINGS_DMA_BCM63268_H */
diff --git a/include/dt-bindings/dma/bcm6328-dma.h b/include/dt-bindings/dma/bcm6328-dma.h
new file mode 100644
index 0000000..7494df2
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6328-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6328_H
+#define __DT_BINDINGS_DMA_BCM6328_H
+
+#define BCM6328_DMA_ENETSW_RX 0
+#define BCM6328_DMA_ENETSW_TX 1
+
+#endif /* __DT_BINDINGS_DMA_BCM6328_H */
diff --git a/include/dt-bindings/dma/bcm6338-dma.h b/include/dt-bindings/dma/bcm6338-dma.h
new file mode 100644
index 0000000..f2e0b20
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6338-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6338_H
+#define __DT_BINDINGS_DMA_BCM6338_H
+
+#define BCM6338_DMA_ENET_RX 0
+#define BCM6338_DMA_ENET_TX 1
+
+#endif /* __DT_BINDINGS_DMA_BCM6338_H */
diff --git a/include/dt-bindings/dma/bcm6348-dma.h b/include/dt-bindings/dma/bcm6348-dma.h
new file mode 100644
index 0000000..36c2ffd
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6348-dma.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6348_H
+#define __DT_BINDINGS_DMA_BCM6348_H
+
+#define BCM6348_DMA_ENET0_RX 0
+#define BCM6348_DMA_ENET0_TX 1
+#define BCM6348_DMA_ENET1_RX 2
+#define BCM6348_DMA_ENET1_TX 3
+
+#endif /* __DT_BINDINGS_DMA_BCM6348_H */
diff --git a/include/dt-bindings/dma/bcm6358-dma.h b/include/dt-bindings/dma/bcm6358-dma.h
new file mode 100644
index 0000000..3118b9d
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6358-dma.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6358_H
+#define __DT_BINDINGS_DMA_BCM6358_H
+
+#define BCM6358_DMA_ENET0_RX 0
+#define BCM6358_DMA_ENET0_TX 1
+#define BCM6358_DMA_ENET1_RX 2
+#define BCM6358_DMA_ENET1_TX 3
+
+#endif /* __DT_BINDINGS_DMA_BCM6358_H */
diff --git a/include/dt-bindings/dma/bcm6362-dma.h b/include/dt-bindings/dma/bcm6362-dma.h
new file mode 100644
index 0000000..1e62236
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6362-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6362_H
+#define __DT_BINDINGS_DMA_BCM6362_H
+
+#define BCM6362_DMA_ENETSW_RX 0
+#define BCM6362_DMA_ENETSW_TX 1
+
+#endif /* __DT_BINDINGS_DMA_BCM6362_H */
diff --git a/include/dt-bindings/dma/bcm6368-dma.h b/include/dt-bindings/dma/bcm6368-dma.h
new file mode 100644
index 0000000..36c6caa
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6368-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6368_H
+#define __DT_BINDINGS_DMA_BCM6368_H
+
+#define BCM6368_DMA_ENETSW_RX 0
+#define BCM6368_DMA_ENETSW_TX 1
+
+#endif /* __DT_BINDINGS_DMA_BCM6368_H */