[RFC PATCH] mips: dts: add initial support for ls1c300 SoC
Du Huanpeng
dhu at hodcarrier.org
Tue Mar 29 21:30:01 CEST 2022
Loongson 1C is a cost-effective SOC chip for industrial control and
the Internet of Things. The Loongson 1C includes a floating-point
processing unit, supports multiple types of memory, and supports
high-capacity MLC NAND Flash. Loongson 1C provides developers with a
wealth of peripheral interfaces and on-chip modules, including Camera
controller, USB OTG and USB HOST interfaces, AC97/I2S controller, LCD
controller, SPI interface, UART interface, etc., providing sufficient
computing power and multi-application connectivity.
Some highlights of this SoC are:
- Single core LS232, MIPS32 instruction set compatible, main frequency
300MHZ
- 16KB data cache and 16KB instruction cache
- 64 bit float unit, hardware division
- 8/16 bit SDRAM controller, 45 ~ 133MHz
- 8/16 bit SRAM, NAND
- I2S/AC97, LCD, MAC, USB, OTG, SPI, I2C, PWM, CAN, SDIO, ADC
- 12 UARTs
See Techinical Reference Manual for details: https://www.loongson.cn/
introduce base support for the ls1c300 SoC.
- debug UART2
- serial console
- clock
- watchdog
- sysreset
- many uarts
Signed-off-by: Du Huanpeng <dhu at hodcarrier.org>
---
arch/mips/Kconfig | 25 +++
arch/mips/Makefile | 1 +
arch/mips/dts/Makefile | 1 +
arch/mips/dts/loongson32-ls1c300b.dtsi | 138 +++++++++++++++++
arch/mips/dts/ls1c300-eval.dts | 27 ++++
arch/mips/mach-lsmips/Kconfig | 77 ++++++++++
arch/mips/mach-lsmips/Makefile | 6 +
arch/mips/mach-lsmips/cpu.c | 24 +++
arch/mips/mach-lsmips/include/mach/serial.h | 16 ++
arch/mips/mach-lsmips/ls1c300/Makefile | 6 +
arch/mips/mach-lsmips/ls1c300/gpio.c | 60 ++++++++
arch/mips/mach-lsmips/ls1c300/init.c | 60 ++++++++
arch/mips/mach-lsmips/ls1c300/lowlevel_init.S | 123 +++++++++++++++
arch/mips/mach-lsmips/ls1c300/ls1c300.h | 52 +++++++
arch/mips/mach-lsmips/ls1c300/serial.c | 112 ++++++++++++++
arch/mips/mach-lsmips/spl.c | 47 ++++++
board/loongson/ls1c300-eval/Kconfig | 12 ++
board/loongson/ls1c300-eval/MAINTAINERS | 7 +
board/loongson/ls1c300-eval/Makefile | 3 +
board/loongson/ls1c300-eval/board.c | 20 +++
configs/ls1c300_defconfig | 65 ++++++++
drivers/clk/Makefile | 1 +
drivers/clk/lsmips/Makefile | 3 +
drivers/clk/lsmips/clk-ls1c300.c | 145 ++++++++++++++++++
drivers/watchdog/Kconfig | 8 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/lsmips_wdt.c | 126 +++++++++++++++
include/configs/ls1c300.h | 61 ++++++++
include/dt-bindings/clock/ls1c300-clk.h | 48 ++++++
29 files changed, 1275 insertions(+)
create mode 100644 arch/mips/dts/loongson32-ls1c300b.dtsi
create mode 100644 arch/mips/dts/ls1c300-eval.dts
create mode 100644 arch/mips/mach-lsmips/Kconfig
create mode 100644 arch/mips/mach-lsmips/Makefile
create mode 100644 arch/mips/mach-lsmips/cpu.c
create mode 100644 arch/mips/mach-lsmips/include/mach/serial.h
create mode 100644 arch/mips/mach-lsmips/ls1c300/Makefile
create mode 100644 arch/mips/mach-lsmips/ls1c300/gpio.c
create mode 100644 arch/mips/mach-lsmips/ls1c300/init.c
create mode 100644 arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
create mode 100644 arch/mips/mach-lsmips/ls1c300/ls1c300.h
create mode 100644 arch/mips/mach-lsmips/ls1c300/serial.c
create mode 100644 arch/mips/mach-lsmips/spl.c
create mode 100644 board/loongson/ls1c300-eval/Kconfig
create mode 100644 board/loongson/ls1c300-eval/MAINTAINERS
create mode 100644 board/loongson/ls1c300-eval/Makefile
create mode 100644 board/loongson/ls1c300-eval/board.c
create mode 100644 configs/ls1c300_defconfig
create mode 100644 drivers/clk/lsmips/Makefile
create mode 100644 drivers/clk/lsmips/clk-ls1c300.c
create mode 100644 drivers/watchdog/lsmips_wdt.c
create mode 100644 include/configs/ls1c300.h
create mode 100644 include/dt-bindings/clock/ls1c300-clk.h
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 28234aa0bb..d95868ef4b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -93,6 +93,30 @@ config ARCH_MTMIPS
select SUPPORTS_LITTLE_ENDIAN
select SUPPORT_SPL
+config ARCH_LSMIPS
+ bool "Support Loongson MIPS platforms"
+ select CLK
+ imply CMD_DM
+ select DISPLAY_CPUINFO
+ select DM
+ imply DM_ETH
+ imply DM_GPIO
+ select DM_RESET
+ select DM_SERIAL
+ select PINCTRL
+ select PINMUX
+ select PINCONF
+ select RESET_LSMIPS
+ imply DM_SPI
+ imply DM_SPI_FLASH
+ select OF_CONTROL
+ select ROM_EXCEPTION_VECTORS
+ select SUPPORTS_CPU_MIPS32_R1
+ select SUPPORTS_CPU_MIPS32_R2
+ select SUPPORTS_LITTLE_ENDIAN
+ select SYSRESET
+ select SUPPORT_SPL
+
config ARCH_JZ47XX
bool "Support Ingenic JZ47xx"
select SUPPORT_SPL
@@ -174,6 +198,7 @@ source "arch/mips/mach-bmips/Kconfig"
source "arch/mips/mach-jz47xx/Kconfig"
source "arch/mips/mach-pic32/Kconfig"
source "arch/mips/mach-mtmips/Kconfig"
+source "arch/mips/mach-lsmips/Kconfig"
source "arch/mips/mach-octeon/Kconfig"
if MIPS
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6502aebd29..e944502497 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -16,6 +16,7 @@ machine-$(CONFIG_ARCH_BMIPS) += bmips
machine-$(CONFIG_ARCH_JZ47XX) += jz47xx
machine-$(CONFIG_MACH_PIC32) += pic32
machine-$(CONFIG_ARCH_MTMIPS) += mtmips
+machine-$(CONFIG_ARCH_LSMIPS) += lsmips
machine-$(CONFIG_ARCH_MSCC) += mscc
machine-${CONFIG_ARCH_OCTEON} += octeon
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 95144b24dc..915acfd573 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_BOARD_MT7620_MT7530_RFB) += mediatek,mt7620-mt7530-rfb.dtb
dtb-$(CONFIG_BOARD_MT7628_RFB) += mediatek,mt7628-rfb.dtb
dtb-$(CONFIG_BOARD_GARDENA_SMART_GATEWAY_MT7688) += gardena-smart-gateway-mt7688.dtb
dtb-$(CONFIG_BOARD_LINKIT_SMART_7688) += linkit-smart-7688.dtb
+dtb-$(CONFIG_BOARD_LS1C300) += ls1c300-eval.dtb
dtb-$(CONFIG_TARGET_OCTEON_EBB7304) += mrvl,octeon-ebb7304.dtb
dtb-$(CONFIG_TARGET_OCTEON_NIC23) += mrvl,octeon-nic23.dtb
dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb
diff --git a/arch/mips/dts/loongson32-ls1c300b.dtsi b/arch/mips/dts/loongson32-ls1c300b.dtsi
new file mode 100644
index 0000000000..a574495301
--- /dev/null
+++ b/arch/mips/dts/loongson32-ls1c300b.dtsi
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/ls1c300-clk.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "loongson,ls1c300-soc";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu at 0 {
+ device_type = "cpu";
+ reg = <0>;
+ compatible = "loongson,gs232", "mips,mips4Kc";
+ clocks = <&acc CLK_CPU>;
+ };
+ };
+
+ xtal: oscillator at 0 {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ #clock-cells = <0>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ // TODO: add more device.
+
+ acc: clock-controller at 1fe78030 {
+ compatible = "loongson,ls1c300-clk";
+ clocks = <&xtal>;
+ #clock-cells = <1>;
+ reg = <0x1fe78030 0x8>, <0x1fe7c010 0x4>;
+ u-boot,dm-pre-reloc;
+ };
+
+ uart0: serial at 1fe40000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART0>;
+ reg = <0x1fe40000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart1: serial at 1fe44000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART1>;
+ reg = <0x1fe44000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart2: serial at bfe48000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART2>;
+ reg = <0xbfe48000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart3: serial at 1fe4c000 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART3>;
+ reg = <0x1fe4c000 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart4: serial at 1fe4c400 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART4>;
+ reg = <0x1fe4c400 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart5: serial at 1fe4c500 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART5>;
+ reg = <0x1fe4c500 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart6: serial at 1fe4c600 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART6>;
+ reg = <0x1fe4c600 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart7: serial at 1fe4c700 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART7>;
+ reg = <0x1fe4c700 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart8: serial at 1fe4c800 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART8>;
+ reg = <0x1fe4c800 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart9: serial at 1fe4c900 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART9>;
+ reg = <0x1fe4c900 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart10: serial at 1fe4ca00 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART10>;
+ reg = <0x1fe4ca00 0x100>;
+ reg-shift = <0>;
+ };
+
+ uart11: serial at 1fe4cb00 {
+ compatible = "ns16550a";
+ clocks = <&acc CLK_UART11>;
+ reg = <0x1fe4cb00 0x100>;
+ reg-shift = <0>;
+ };
+
+ wdt: watchdog at 1fe5c060 {
+ compatible = "loongson,ls1c300-wdt";
+ clocks = <&acc CLK_WDT>;
+ reg = <0x1fe5c060 0x10>;
+ };
+
+ reset-controller {
+ compatible = "wdt-reboot";
+ wdt = <&wdt>;
+ };
+
+ };
+};
diff --git a/arch/mips/dts/ls1c300-eval.dts b/arch/mips/dts/ls1c300-eval.dts
new file mode 100644
index 0000000000..5bf1ec0985
--- /dev/null
+++ b/arch/mips/dts/ls1c300-eval.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+/dts-v1/;
+
+#include "loongson32-ls1c300b.dtsi"
+
+/ {
+ compatible = "lsmips,ls1c300-soc";
+ model = "ls1c300-eval";
+
+ aliases {
+ console = &uart2;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200";
+ stdout-path = &uart2;
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
diff --git a/arch/mips/mach-lsmips/Kconfig b/arch/mips/mach-lsmips/Kconfig
new file mode 100644
index 0000000000..cb679875a7
--- /dev/null
+++ b/arch/mips/mach-lsmips/Kconfig
@@ -0,0 +1,77 @@
+menu "Loongson MIPS platforms"
+ depends on ARCH_LSMIPS
+
+config SYS_MALLOC_F_LEN
+ default 0x1000
+
+config SYS_SOC
+ default "ls1c300" if SOC_LS1C300
+
+config SYS_DCACHE_SIZE
+ default 16384
+
+config SYS_DCACHE_LINE_SIZE
+ default 32
+
+config SYS_ICACHE_SIZE
+ default 16384
+
+config SYS_ICACHE_LINE_SIZE
+ default 32
+
+config SYS_TEXT_BASE
+ default 0xbfc00000 if !SPL
+ default 0x80200000 if SPL
+
+config SPL_TEXT_BASE
+ default 0xbfc00000
+
+config SPL_PAYLOAD
+ default "u-boot-lzma.img" if SPL_LZMA
+
+config BUILD_TARGET
+ default "u-boot-with-spl.bin" if SPL
+
+choice
+ prompt "Loongson MIPS SoC select"
+
+config SOC_LS1C300
+ bool "LS1C300"
+ select MIPS_L1_CACHE_SHIFT_5
+ select PINCTRL_LS1C300
+ select CLK_CCF
+ select SPL_SEPARATE_BSS if SPL
+ select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL
+ select SPL_LOADER_SUPPORT if SPL
+ select SPL_OF_CONTROL if SPL_DM
+ select SPL_SIMPLE_BUS if SPL_DM
+ select SPL_DM_SERIAL if SPL_DM
+ select SPL_CLK if SPL_DM && SPL_SERIAL
+ select SPL_SYSRESET if SPL_DM
+ select SPL_OF_LIBFDT if SPL_OF_CONTROL
+ help
+ This supports Loongson LS1C300
+
+endchoice
+
+choice
+ prompt "Board select"
+
+config BOARD_LS1C300
+ bool "Loongson LS1C300 Eval"
+ depends on SOC_LS1C300
+ help
+ ls1c300-eval board has a LS1C300 SoC with 64MiB of SDRAM
+ and 512KiB of flash (SPI NOR) and additional NAND storage.
+
+endchoice
+
+config CONS_PIN_SELECT
+ int "pin group used in uart"
+ default 0
+ help
+ Select pin group connected to UART for your board.
+
+source "board/loongson/ls1c300-eval/Kconfig"
+
+endmenu
diff --git a/arch/mips/mach-lsmips/Makefile b/arch/mips/mach-lsmips/Makefile
new file mode 100644
index 0000000000..654143a5f7
--- /dev/null
+++ b/arch/mips/mach-lsmips/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
+
+obj-$(CONFIG_SOC_LS1C300) += ls1c300/
diff --git a/arch/mips/mach-lsmips/cpu.c b/arch/mips/mach-lsmips/cpu.c
new file mode 100644
index 0000000000..00513253e8
--- /dev/null
+++ b/arch/mips/mach-lsmips/cpu.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <sr at denx.de>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+#ifdef CONFIG_SKIP_LOWLEVEL_INIT
+ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
+#else
+ gd->ram_size = SZ_64M;
+#endif
+
+ return 0;
+}
diff --git a/arch/mips/mach-lsmips/include/mach/serial.h b/arch/mips/mach-lsmips/include/mach/serial.h
new file mode 100644
index 0000000000..4da1cb434c
--- /dev/null
+++ b/arch/mips/mach-lsmips/include/mach/serial.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao at mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#ifndef __LSMIPS_SERIAL_H_
+#define __LSMIPS_SERIAL_H_
+
+void lsmips_spl_serial_init(void);
+int gpio_set_alternate(int gpio, int func);
+
+#endif /* __LSMIPS_SERIAL_H_ */
diff --git a/arch/mips/mach-lsmips/ls1c300/Makefile b/arch/mips/mach-lsmips/ls1c300/Makefile
new file mode 100644
index 0000000000..d30069e67e
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += lowlevel_init.o
+obj-y += init.o
+obj-y += gpio.o
+obj-$(CONFIG_SPL_BUILD) += serial.o
diff --git a/arch/mips/mach-lsmips/ls1c300/gpio.c b/arch/mips/mach-lsmips/ls1c300/gpio.c
new file mode 100644
index 0000000000..cca91aed93
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/gpio.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <linux/errno.h>
+#include <linux/bitops.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#define CBUS_FIRST0 0xbfd011c0
+#define CBUS_SECOND0 0xbfd011d0
+#define CBUS_THIRD0 0xbfd011e0
+#define CBUS_FOURTHT0 0xbfd011f0
+#define CBUS_FIFTHT0 0xbfd01200
+
+#define CBUS_FIRST1 0xbfd011c4
+#define CBUS_SECOND1 0xbfd011d4
+#define CBUS_THIRD1 0xbfd011e4
+#define CBUS_FOURTHT1 0xbfd011f4
+#define CBUS_FIFTHT1 0xbfd01204
+
+#define CBUS_FIRST2 0xbfd011c8
+#define CBUS_SECOND2 0xbfd011d8
+#define CBUS_THIRD2 0xbfd011e8
+#define CBUS_FOURTHT2 0xbfd011f8
+#define CBUS_FIFTHT2 0xbfd01208
+
+#define CBUS_FIRST3 0xbfd011cc
+#define CBUS_SECOND3 0xbfd011dc
+#define CBUS_THIRD3 0xbfd011ec
+#define CBUS_FOURTHT3 0xbfd011fc
+#define CBUS_FIFTHT3 0xbfd0120c
+
+int gpio_set_alternate(int gpio, int func)
+{
+ volatile void __iomem *addr;
+ int i;
+
+ if (gpio < 0 || gpio > 104)
+ return -ENODEV;
+ if (func < 0)
+ return -EINVAL;
+
+ if (func) {
+ i = func - 1;
+ addr = (void *)CBUS_FIRST0 + i * 16;
+ set_bit(gpio, addr);
+ } else {
+ /* GPIO, clear CBUS 1 ~ 5 */
+ i = 5;
+ }
+
+ while (i--) {
+ addr = (void *)CBUS_FIRST0 + 16 * i;
+ clear_bit(gpio, addr);
+ }
+
+ return 0;
+}
diff --git a/arch/mips/mach-lsmips/ls1c300/init.c b/arch/mips/mach-lsmips/ls1c300/init.c
new file mode 100644
index 0000000000..457beeedca
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/init.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao at mediatek.com>
+ *
+ * based on: arch/mips/mach-mtmips/mt7628/init.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/uclass.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include "ls1c300.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int print_cpuinfo(void)
+{
+ struct udevice *udev;
+ struct clk clk;
+ int ret;
+ ulong xtal;
+ char buf[SZ_32];
+
+ printf("CPU: Loongson ls1c300b\n");
+
+ ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(ls1c300_clk), &udev);
+
+ if (ret) {
+ printf("error: clock driver not found.\n");
+ return 0;
+ }
+
+ clk.dev = udev;
+
+ clk.id = CLK_XTAL;
+ xtal = clk_get_rate(&clk);
+
+ clk.id = CLK_CPU_THROT;
+ gd->cpu_clk = clk_get_rate(&clk);
+
+ clk.id = CLK_SDRAM;
+ gd->mem_clk = clk_get_rate(&clk);
+
+ printf("Clock: CPU: %sMHz, ", strmhz(buf, gd->cpu_clk));
+ printf("SDRAM: %sMHz, ", strmhz(buf, gd->mem_clk));
+ printf("XTAL: %sMHz\n", strmhz(buf, xtal));
+
+ return 0;
+}
+
+ulong notrace get_tbclk(void)
+{
+ return gd->cpu_clk;
+}
diff --git a/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
new file mode 100644
index 0000000000..f9e2f94e83
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao at mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <config.h>
+#include <asm-offsets.h>
+#include <asm/cacheops.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <linux/sizes.h>
+
+/* PLL */
+#define NAND_BASE 0xbfe78000
+#define START_FREQ 0xbfe78030
+#define CLK_DIV_PARAM 0xbfe78034
+
+/* SPI */
+#define SPI0_BASE 0xbfe80000
+
+/* SDRAM */
+#define SD_CONFIG 0xbfd00000
+#define SD_CONFIGL 0xbfd00410
+#define SD_CONFIGH 0xbfd00414
+
+ .set noreorder
+
+/* PLL: 264MHz CPU: 132MHz SDRAM: 66MHz */
+LEAF(ls1c300_pll_init)
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ li t0, NAND_BASE
+ li t2, 555844098
+ sw t2, 0x34 (t0)
+
+ li t1, 2147494924
+ sw t1, 0x30 (t0)
+
+ ori t2, 1
+ sw t2, 0x34 (t0)
+#endif
+/* TODO: recalc rate to v0 */
+ li v0, 132000000
+ jr ra
+ nop
+END(ls1c300_pll_init)
+
+/* SPI: Dual IO at 33MHz */
+LEAF(ls1c300_spi_init)
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ li t0, SPI0_BASE
+ li t1, 0x07
+ li t2, 0x05
+ sb t1, 0x4(t0)
+ sb t1, 0x6(t0)
+#endif
+ jr ra
+ nop
+END(ls1c300_spi_init)
+
+/* SDRAM: 66MHz */
+// 8M x 16Bit x 4 Banks */
+// Organization | Row Address | Column Address
+// 32Mx16 | A0~A12 | A0-A9
+
+// 128Mx4 | A0~A12 | A0-A9, A11, A12
+// 64Mx8 | A0~A12 | A0-A9, A11
+// 32Mx16 | A0~A12 | A0-A9
+
+LEAF(ls1c300_sdram_init)
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+ li t0, SD_CONFIG
+ li t1, 0x028A924A
+ li t2, 0x00000028
+sdram_cfg:
+ sw t1, 0x410(t0)
+ sw t2, 0x414(t0)
+ nop
+ sw t1, 0x410(t0)
+ sw t2, 0x414(t0)
+ ori t2, 0x200
+ sw t1, 0x410(t0)
+ sw t2, 0x414(t0)
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+ li v0, SZ_64M
+ jr ra
+ nop
+END(ls1c300_sdram_init)
+
+
+/*
+ * SDRAM at 132MHz, CPU at 297MHz, SPI at 33MHz
+ * SDRAM at 100MHz, CPU at 300MHz, SPI at 50MHz
+ * SDRAM at 66MHz, CPU at 132MHz, SPI at 33MHz <--
+ */
+
+NESTED(lowlevel_init, 0, ra)
+ /* Save ra and do real lowlevel initialization */
+ move s0, ra
+ /* Setup PLL @264MHz */
+ PTR_LA t9, ls1c300_pll_init
+ jalr t9
+ nop
+
+ /* Setup SPI Dual IO at 33MHz */
+ PTR_LA t9, ls1c300_spi_init
+ jalr t9
+ nop
+
+ /* Setup external SDRAM @66MHz */
+ PTR_LA t9, ls1c300_sdram_init
+ jalr t9
+ nop
+
+ move ra, s0
+ jr ra
+ nop
+END(lowlevel_init)
diff --git a/arch/mips/mach-lsmips/ls1c300/ls1c300.h b/arch/mips/mach-lsmips/ls1c300/ls1c300.h
new file mode 100644
index 0000000000..70a5def841
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/ls1c300.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#ifndef __LS1C300_H__
+#define __LS1C300_H__
+
+/* generated, don't edit */
+
+#define SDRAM_BASE 0x00000000
+#define CAMERA_BASE 0x1c280000
+#define DC_BASE 0x1c300000
+#define AXIMUX_BASE 0x1f000000
+
+#define SPI0MEM_BASE 0x1d000000
+#define SPI1MEM_BASE 0x1e000000
+#define Boot_BASE 0xbfc00000
+#define CONFREG_BASE 0x1fd00000
+#define OTG_BASE 0x1fe00000
+#define MAC_BASE 0x1fe10000
+#define USB_BASE 0x1fe20000
+#define APB_BASE 0x1fe40000
+#define SPI0_BASE 0x1fe80000
+#define SPI1_BASE 0x1fec0000
+
+#define UART0_BASE 0x1fe40000
+#define UART1_BASE 0x1fe44000
+#define UART2_BASE 0x1fe48000
+#define UART3_BASE 0x1fe4c000
+#define UART4_BASE 0x1fe4c400
+#define UART5_BASE 0x1fe4c500
+#define UART6_BASE 0x1fe4c600
+#define UART7_BASE 0x1fe4c700
+#define UART8_BASE 0x1fe4c800
+#define UART9_BASE 0x1fe4c900
+#define UART10_BASE 0x1fe4ca00
+#define UART11_BASE 0x1fe4cb00
+#define CAN0_BASE 0x1fe50000
+#define CAN1_BASE 0x1fe54000
+#define I2C0_BASE 0x1fe58000
+#define PWM_BASE 0x1fe5c000
+#define I2S_BASE 0x1fe60000
+#define RTC_BASE 0x1fe64000
+#define I2C1_BASE 0x1fe68000
+#define SDIO_BASE 0x1fe6c000
+#define I2C2_BASE 0x1fe70000
+#define ADC_BASE 0x1fe74000
+#define NAND_BASE 0x1fe78000
+#define HCNTR_BASE 0x1fe7c000
+
+#endif /* __LS1C300_H__ */
diff --git a/arch/mips/mach-lsmips/ls1c300/serial.c b/arch/mips/mach-lsmips/ls1c300/serial.c
new file mode 100644
index 0000000000..88bc18ef85
--- /dev/null
+++ b/arch/mips/mach-lsmips/ls1c300/serial.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao at mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mach/serial.h>
+#include <linux/kernel.h>
+#include "ls1c300.h"
+
+struct uart_pin_config {
+ char port;
+ char af;
+ char rx;
+ char tx;
+};
+
+struct uart_pin_config con[] = {
+#if CONFIG_CONS_INDEX == 0
+{ 0, 2, 74, 75 },
+{ 0, 3, 23, 24 },
+{ 0, 3, 99, 100 },
+
+#elif CONFIG_CONS_INDEX == 1
+{ 1, 1, 17, 18 },
+{ 1, 1, 101, 102 },
+{ 1, 2, 40, 41 },
+{ 1, 4, 2, 3 },
+
+#elif CONFIG_CONS_INDEX == 2
+{ 2, 2, 36, 37 },
+{ 2, 2, 42, 43 },
+{ 2, 3, 27, 28 },
+{ 2, 3, 103, 104 },
+{ 2, 4, 4, 5 },
+
+#elif CONFIG_CONS_INDEX == 3
+{ 3, 2, 17, 18 },
+{ 3, 2, 33, 34 },
+{ 3, 2, 44, 45 },
+{ 3, 4, 0, 1 },
+
+#elif CONFIG_CONS_INDEX == 4
+{ 4, 5, 23, 24 },
+{ 4, 5, 58, 59 },
+{ 4, 5, 80, 79 },
+
+#elif CONFIG_CONS_INDEX == 5
+{ 5, 5, 25, 26 },
+{ 5, 5, 60, 61 },
+{ 5, 5, 81, 78 },
+
+#elif CONFIG_CONS_INDEX == 6
+{ 6, 5, 27, 46 },
+{ 6, 5, 62, 63 },
+
+#elif CONFIG_CONS_INDEX == 7
+{ 7, 5, 57, 56 },
+{ 7, 5, 64, 65 },
+{ 7, 5, 87, 88 },
+
+#elif CONFIG_CONS_INDEX == 8
+{ 8, 5, 55, 54 },
+{ 8, 5, 66, 67 },
+{ 8, 5, 89, 90 },
+
+#elif CONFIG_CONS_INDEX == 9
+{ 9, 5, 53, 52 },
+{ 9, 5, 68, 69 },
+{ 9, 5, 85, 86 },
+
+#elif CONFIG_CONS_INDEX == 10
+{ 10, 5, 51, 50 },
+{ 10, 5, 70, 71 },
+{ 10, 5, 84, 82 },
+
+#elif CONFIG_CONS_INDEX == 11
+{ 11, 5, 49, 48 },
+{ 11, 5, 72, 73 },
+#endif /* CONFIG_CONS_INDEX */
+};
+
+#define UART2_RX 36
+#define UART2_TX 37
+#define AFUNC 2
+
+void lsmips_spl_serial_init(void)
+{
+#ifdef CONFIG_SPL_SERIAL
+ int pin_rx, pin_tx;
+ int afunc;
+
+ if (CONFIG_CONS_PIN_SELECT < ARRAY_SIZE(con)) {
+ pin_rx = con[CONFIG_CONS_PIN_SELECT].rx;
+ pin_tx = con[CONFIG_CONS_PIN_SELECT].tx;
+ afunc = con[CONFIG_CONS_PIN_SELECT].af;
+ } else {
+ pin_rx = UART2_RX;
+ pin_tx = UART2_TX;
+ afunc = AFUNC;
+ }
+
+ gpio_set_alternate(pin_rx, afunc);
+ gpio_set_alternate(pin_tx, afunc);
+#endif /* CONFIG_SPL_SERIAL */
+ return ;
+}
diff --git a/arch/mips/mach-lsmips/spl.c b/arch/mips/mach-lsmips/spl.c
new file mode 100644
index 0000000000..c7c28989f2
--- /dev/null
+++ b/arch/mips/mach-lsmips/spl.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Gao Weijie <weijie.gao at mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <spl.h>
+#include <asm/sections.h>
+#include <linux/libfdt.h>
+#include <linux/sizes.h>
+#include <mach/serial.h>
+
+void __noreturn board_init_f(ulong dummy)
+{
+ spl_init();
+
+#ifdef CONFIG_SPL_SERIAL
+ /*
+ * lsmips_spl_serial_init() is useful if debug uart is enabled,
+ * or DM based serial is not enabled.
+ */
+ lsmips_spl_serial_init();
+ preloader_console_init();
+#endif
+
+ board_init_r(NULL, 0);
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+ spl_boot_list[0] = BOOT_DEVICE_NOR;
+}
+
+unsigned long spl_nor_get_uboot_base(void)
+{
+ void *uboot_base = __image_copy_end;
+
+ if (fdt_magic(uboot_base) == FDT_MAGIC)
+ return (unsigned long)uboot_base + fdt_totalsize(uboot_base);
+
+ return (unsigned long)uboot_base;
+}
diff --git a/board/loongson/ls1c300-eval/Kconfig b/board/loongson/ls1c300-eval/Kconfig
new file mode 100644
index 0000000000..e427570a83
--- /dev/null
+++ b/board/loongson/ls1c300-eval/Kconfig
@@ -0,0 +1,12 @@
+if BOARD_LS1C300
+
+config SYS_BOARD
+ default "ls1c300-eval"
+
+config SYS_VENDOR
+ default "loongson"
+
+config SYS_CONFIG_NAME
+ default "ls1c300"
+
+endif
diff --git a/board/loongson/ls1c300-eval/MAINTAINERS b/board/loongson/ls1c300-eval/MAINTAINERS
new file mode 100644
index 0000000000..5420198dab
--- /dev/null
+++ b/board/loongson/ls1c300-eval/MAINTAINERS
@@ -0,0 +1,7 @@
+LS1C300_EVAL BOARD
+M: Du Huanpeng<dhu at hodcarrier.org>
+S: Maintained
+F: board/loongson/ls1c300-eval
+F: include/configs/ls1c300.h
+F: configs/ls1c300_defconfig
+F: arch/mips/dts/ls1c300-eval.dts
diff --git a/board/loongson/ls1c300-eval/Makefile b/board/loongson/ls1c300-eval/Makefile
new file mode 100644
index 0000000000..db129c5aba
--- /dev/null
+++ b/board/loongson/ls1c300-eval/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += board.o
diff --git a/board/loongson/ls1c300-eval/board.c b/board/loongson/ls1c300-eval/board.c
new file mode 100644
index 0000000000..2f588a0dcb
--- /dev/null
+++ b/board/loongson/ls1c300-eval/board.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <common.h>
+#include <mach/serial.h>
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+
+#define UART2_RX 36
+#define UART2_TX 37
+#define AFUNC 2
+
+void board_debug_uart_init(void)
+{
+ gpio_set_alternate(UART2_TX, AFUNC);
+ gpio_set_alternate(UART2_RX, AFUNC);
+}
+#endif
diff --git a/configs/ls1c300_defconfig b/configs/ls1c300_defconfig
new file mode 100644
index 0000000000..c47fe5b98f
--- /dev/null
+++ b/configs/ls1c300_defconfig
@@ -0,0 +1,65 @@
+CONFIG_MIPS=y
+CONFIG_SYS_MALLOC_F_LEN=0x40000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x1000
+CONFIG_ENV_OFFSET=0x30000
+CONFIG_ENV_SECT_SIZE=0x10000
+CONFIG_DEFAULT_DEVICE_TREE="ls1c300-eval"
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL_SIZE_LIMIT=0x100000
+CONFIG_SPL=y
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0xbfe48000
+CONFIG_DEBUG_UART_CLOCK=66000000
+CONFIG_ARCH_LSMIPS=y
+CONFIG_SPL_PAYLOAD="u-boot.img"
+# CONFIG_MIPS_CACHE_SETUP is not set
+# CONFIG_MIPS_CACHE_DISABLE is not set
+CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEBUG_UART=y
+CONFIG_SYS_LOAD_ADDR=0x80010000
+CONFIG_FIT=y
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_LOGLEVEL=9
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK=y
+CONFIG_SPL_SYS_MALLOC_SIMPLE=y
+CONFIG_SPL_NOR_SUPPORT=y
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_CLK=y
+# CONFIG_CMD_DM is not set
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_SPI=y
+CONFIG_CMD_WDT=y
+# CONFIG_PARTITIONS is not set
+CONFIG_OF_EMBED=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+# CONFIG_NET is not set
+# CONFIG_INPUT is not set
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_ISSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XMC=y
+CONFIG_CONS_INDEX=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_SYSRESET_WATCHDOG=y
+CONFIG_SYSRESET_WATCHDOG_AUTO=y
+CONFIG_WATCHDOG_TIMEOUT_MSECS=3000
+CONFIG_WDT_LSMIPS=y
+CONFIG_REGEX=y
+CONFIG_LZMA=y
+CONFIG_SPL_LZMA=y
+CONFIG_SPL_GZIP=y
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index bb4eee5d99..51562ca4a6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -17,6 +17,7 @@ obj-y += tegra/
obj-y += ti/
obj-$(CONFIG_$(SPL_TPL_)CLK_INTEL) += intel/
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_LSMIPS) += lsmips/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_MESON) += meson/
obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
diff --git a/drivers/clk/lsmips/Makefile b/drivers/clk/lsmips/Makefile
new file mode 100644
index 0000000000..0a47269cd3
--- /dev/null
+++ b/drivers/clk/lsmips/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SOC_LS1C300) += clk-ls1c300.o
diff --git a/drivers/clk/lsmips/clk-ls1c300.c b/drivers/clk/lsmips/clk-ls1c300.c
new file mode 100644
index 0000000000..c78e23d695
--- /dev/null
+++ b/drivers/clk/lsmips/clk-ls1c300.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * reference:
+ * drivers/clk/microchip/mpfs_clk.c
+ * drivers/clk/clk_octeon.c
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/ls1c300-clk.h>
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+/* START_FREQ */
+#define PLL_VALID BIT(31)
+#define RESERVED0 GENMASK(30, 24)
+#define FRAC_N GENMASK(23, 16)
+#define M_PLL GENMASK(15, 8)
+#define RESERVED1 GENMASK(7, 4)
+#define RST_TIME GENMASK(3, 2)
+#define SDRAM_DIV GENMASK(1, 0)
+/* CLK_DIV_PARAM */
+#define PIX_DIV GENMASK(31, 24)
+#define CAM_DIV GENMASK(23, 16)
+#define CPU_DIV GENMASK(15, 8)
+#define RESERVED2 GENMASK(7, 6)
+#define PIX_DIV_VALID BIT(5)
+#define PIX_SEL BIT(4)
+#define CAM_DIV_VALID BIT(3)
+#define CAM_SEL BIT(2)
+#define CPU_DIV_VALID BIT(1)
+#define CPU_SEL BIT(0)
+/* CPU_THROT */
+#define CPU_THROT GENMASK(3, 0)
+
+static const struct clk_div_table sdram_div_table[] = {
+ {.val = 0, .div = 2},
+ {.val = 1, .div = 4},
+ {.val = 2, .div = 3},
+ {.val = 3, .div = 3},
+};
+
+static ulong ls1c300_clk_get_rate(struct clk *clk)
+{
+ struct clk *cl;
+ ulong rate;
+ int err;
+
+ err = clk_get_by_id(clk->id, &cl);
+ if (err)
+ return err;
+
+ rate = clk_get_rate(cl);
+ return rate;
+}
+
+static int ls1c300_clk_enable(struct clk *clk)
+{
+ /* Nothing to do on Octeon */
+ return 0;
+}
+
+static const struct clk_ops ls1c300_clk_ops = {
+ .enable = ls1c300_clk_enable,
+ .get_rate = ls1c300_clk_get_rate,
+};
+
+static int ls1c300_clk_probe(struct udevice *dev)
+{
+ void __iomem *base;
+ void __iomem *cpu_throt;
+ void __iomem *addr;
+
+ struct clk *cl, clk;
+
+ int ret;
+ const char *parent_name;
+ unsigned int mult, div;
+ unsigned int val;
+ int flags;
+
+ base = (void *)dev_remap_addr_index(dev, 0);
+#define START_FREQ (0)
+#define CLK_DIV_PARAM (4)
+ cpu_throt = (void *)dev_remap_addr_index(dev, 1);
+
+ debug(" base: %p\n", base);
+ debug("cpu_throt: %p\n", cpu_throt);
+
+ val = readl(base + START_FREQ);
+ debug(" START_FREQ: [%08x]\n", val);
+ val = readl(base + CLK_DIV_PARAM);
+ debug("CLK_DIV_PARAM: [%08x]\n", val);
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_get_rate(&clk);
+
+ parent_name = clk.dev->name;
+ val = readl(base + START_FREQ);
+ mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val); div = 4;
+ cl = clk_register_fixed_factor(NULL, "pll", parent_name, 0, mult, div);
+ clk_dm(CLK_PLL, cl);
+
+ addr = base + CLK_DIV_PARAM;
+ flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
+ cl = clk_register_divider(NULL, "cpu_div", "pll", 0, addr, 8, 7, flags);
+ clk_dm(CLK_CPU, cl);
+ cl = clk_register_divider(NULL, "cam_div", "pll", 0, addr, 16, 7, flags);
+ clk_dm(CLK_CAMERA, cl);
+ cl = clk_register_divider(NULL, "pix_div", "pll", 0, addr, 24, 7, flags);
+ clk_dm(CLK_PIX, cl);
+
+ mult = FIELD_GET(CPU_THROT, readl(cpu_throt)) + 1; div = 16;
+ cl = clk_register_fixed_factor(NULL, "cpu_throt_factor", "cpu_div", CLK_GET_RATE_NOCACHE, mult, div);
+ clk_dm(CLK_CPU_THROT, cl);
+
+ addr = base + START_FREQ;
+ cl = clk_register_divider(NULL, "sdram_div", "cpu_div", 0, addr, 0, 2, 0);
+ to_clk_divider(cl)->table = sdram_div_table;
+ clk_dm(CLK_SDRAM, cl);
+
+ return 0;
+}
+
+static const struct udevice_id ls1c300_clk_ids[] = {
+ { .compatible = "loongson,ls1c300-clk" },
+ { }
+};
+
+U_BOOT_DRIVER(ls1c300_clk) = {
+ .name = "ls1c300-clk",
+ .id = UCLASS_CLK,
+ .of_match = ls1c300_clk_ids,
+ .probe = ls1c300_clk_probe,
+ .priv_auto = sizeof(struct clk),
+ .ops = &ls1c300_clk_ops,
+};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f90f0ca02b..289b568188 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -167,6 +167,14 @@ config WDT_GPIO
doc/device-tree-bindings/watchdog/gpio-wdt.txt for
information on how to describe the watchdog in device tree.
+config WDT_LSMIPS
+ bool "Loongson MIPS watchdog timer support"
+ depends on WDT
+ help
+ Select this to enable watchdog timer for Loongson SoCs.
+ The watchdog timer is stopped when initialized.
+ It performs full SoC reset.
+
config WDT_MPC8xx
bool "MPC8xx watchdog timer support"
depends on WDT && MPC8xx
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index a35bd559f5..cb596af904 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
obj-$(CONFIG_WDT_ORION) += orion_wdt.o
obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
+obj-$(CONFIG_WDT_LSMIPS) += lsmips_wdt.o
obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
diff --git a/drivers/watchdog/lsmips_wdt.c b/drivers/watchdog/lsmips_wdt.c
new file mode 100644
index 0000000000..ef91cae349
--- /dev/null
+++ b/drivers/watchdog/lsmips_wdt.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Watchdog driver for MediaTek SoCs
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee at mediatek.com>
+ *
+ * based on: drivers/watchdog/mtk_wdt.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <hang.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <clk.h>
+
+#define WDT_EN (priv->base + 0)
+#define WDT_TIMER (priv->base + 4)
+#define WDT_SET (priv->base + 8)
+
+struct lsmips_wdt_priv {
+ void __iomem *base;
+ ulong clock;
+ unsigned long timeout;
+};
+
+static int lsmips_wdt_reset(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(priv->timeout, WDT_TIMER);
+ writel(1, WDT_SET);
+
+ return 0;
+}
+
+static int lsmips_wdt_stop(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(0, WDT_EN);
+ return 0;
+}
+
+static int lsmips_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(1, WDT_EN);
+ writel(1, WDT_TIMER);
+ writel(1, WDT_SET);
+
+ hang();
+ return 0;
+}
+
+static int lsmips_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+ unsigned int timeout;
+
+ timeout = U32_MAX / (priv->clock / 1000);
+
+ if (timeout < timeout_ms)
+ timeout = U32_MAX;
+ else
+ timeout = timeout_ms * (priv->clock / 1000);
+
+ debug("WDT: reload = %08x\n", timeout);
+
+ writel(1, WDT_EN);
+ writel(timeout, WDT_TIMER);
+ writel(1, WDT_SET);
+
+ priv->timeout = timeout;
+
+ return 0;
+}
+
+static int lsmips_wdt_probe(struct udevice *dev)
+{
+ struct lsmips_wdt_priv *priv = dev_get_priv(dev);
+ struct clk cl;
+
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -ENOENT;
+
+ if (clk_get_by_index(dev, 0, &cl) == 0)
+ priv->clock = clk_get_rate(&cl);
+
+ if (priv->clock < 33000000 || priv->clock > 150000000) {
+ /* assume 67MHz by default */
+ priv->clock = 67108864;
+ }
+
+ debug("WDT: clock = %ld\n", priv->clock);
+
+ writel(0, WDT_EN);
+ return 0;
+}
+
+static const struct wdt_ops lsmips_wdt_ops = {
+ .start = lsmips_wdt_start,
+ .reset = lsmips_wdt_reset,
+ .stop = lsmips_wdt_stop,
+ .expire_now = lsmips_wdt_expire_now,
+};
+
+static const struct udevice_id lsmips_wdt_ids[] = {
+ { .compatible = "loongson,ls1c300-wdt"},
+ {}
+};
+
+U_BOOT_DRIVER(lsmips_wdt) = {
+ .name = "lsmips_wdt",
+ .id = UCLASS_WDT,
+ .of_match = lsmips_wdt_ids,
+ .priv_auto = sizeof(struct lsmips_wdt_priv),
+ .probe = lsmips_wdt_probe,
+ .ops = &lsmips_wdt_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/configs/ls1c300.h b/include/configs/ls1c300.h
new file mode 100644
index 0000000000..a96deb6bb2
--- /dev/null
+++ b/include/configs/ls1c300.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Gao Weijie <weijie.gao at mediatek.com>
+ * based on: include/configs/mt7628.h
+ * Copyright (C) 2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#ifndef __CONFIG_LS1C300_H__
+#define __CONFIG_LS1C300_H__
+
+#define CONFIG_SYS_HZ 1000
+
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000
+#define CONFIG_SYS_LOAD_ADDR 0x80010000
+
+#define CONFIG_SYS_INIT_SP_OFFSET 0x80000
+
+#define CONFIG_SYS_BOOTM_LEN 0x1000000
+
+#define CONFIG_SYS_MAXARGS 16
+#define CONFIG_SYS_CBSIZE 1024
+
+/* Serial SPL */
+#define CONFIG_SYS_NS16550_SERIAL
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL)
+#define CONFIG_SYS_NS16550_CLK 66000000
+#define CONFIG_SYS_NS16550_REG_SIZE (-1)
+#define CONFIG_SYS_NS16550_COM1 0xbfe44000
+#define CONFIG_SYS_NS16550_COM2 0xbfe48000
+#define CONFIG_SYS_NS16550_COM3 0xbfe4c000
+#define CONFIG_SYS_NS16550_COM4 0xbfe4c400
+#define CONFIG_SYS_NS16550_COM5 0xbfe4c500
+#define CONFIG_SYS_NS16550_COM6 0xbfe4c600
+#endif
+
+/* Serial common */
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }
+
+/* SPL */
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
+
+#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE
+#define CONFIG_SPL_BSS_START_ADDR 0x80010000
+#define CONFIG_SPL_BSS_MAX_SIZE 0x10000
+#define CONFIG_SPL_MAX_SIZE 0x10000
+#define CONFIG_SPL_PAD_TO 0
+
+#define CONFIG_MALLOC_F_ADDR 0x80100000 /* FIXME: find a proper place */
+
+/* Dummy value */
+#define CONFIG_SYS_UBOOT_BASE 0
+
+#endif /* __CONFIG_LS1C300_H__ */
diff --git a/include/dt-bindings/clock/ls1c300-clk.h b/include/dt-bindings/clock/ls1c300-clk.h
new file mode 100644
index 0000000000..735fa61789
--- /dev/null
+++ b/include/dt-bindings/clock/ls1c300-clk.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Du Huanpeng <dhu at hodcarrier.org>
+ */
+
+#ifndef __DT_BINDINGS_LS1C300_CLK_H__
+#define __DT_BINDINGS_LS1C300_CLK_H__
+
+/* Base clocks */
+#define CLK_XTAL 0
+#define CLK_PLL 1
+#define CLK_CPU 2
+#define CLK_CPU_THROT 7
+#define CLK_SDRAM 3
+
+#define CLK_CAMERA 4
+#define CLK_DC 5
+#define CLK_PIX 5
+#define CLK_AXIMUX 6
+
+/* Peripheral clocks */
+#define CLK_UART0 3
+#define CLK_UART1 3
+#define CLK_UART2 3
+#define CLK_UART3 3
+#define CLK_UART4 3
+#define CLK_UART5 3
+#define CLK_UART6 3
+#define CLK_UART7 3
+#define CLK_UART8 3
+#define CLK_UART9 3
+#define CLK_UART10 3
+#define CLK_UART11 3
+#define CLK_CAN0 3
+#define CLK_CAN1 3
+#define CLK_I2C0 3
+#define CLK_PWM 3
+#define CLK_I2S 3
+#define CLK_RTC 3
+#define CLK_I2C1 3
+#define CLK_SDIO 3
+#define CLK_I2C2 3
+#define CLK_ADC 3
+#define CLK_NAND 3
+
+#define CLK_WDT 3
+
+#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */
--
2.25.1
More information about the U-Boot
mailing list