All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] mips: dts: add initial support for ls1c300 SoC
@ 2022-03-29 19:30 Du Huanpeng
  2022-03-30 20:46 ` Sean Anderson
  2022-03-30 23:24 ` Daniel Schwierzeck
  0 siblings, 2 replies; 6+ messages in thread
From: Du Huanpeng @ 2022-03-29 19:30 UTC (permalink / raw)
  To: u-boot; +Cc: seanga2, weijie.gao, jiaxun.yang, lukma, Du Huanpeng

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@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@0 {
+			device_type = "cpu";
+			reg = <0>;
+			compatible = "loongson,gs232", "mips,mips4Kc";
+			clocks = <&acc CLK_CPU>;
+		};
+	};
+
+	xtal: oscillator@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@1fe78030 {
+			compatible = "loongson,ls1c300-clk";
+			clocks = <&xtal>;
+			#clock-cells = <1>;
+			reg = <0x1fe78030 0x8>, <0x1fe7c010 0x4>;
+			u-boot,dm-pre-reloc;
+		};
+
+		uart0: serial@1fe40000 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART0>;
+			reg = <0x1fe40000 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart1: serial@1fe44000 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART1>;
+			reg = <0x1fe44000 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart2: serial@bfe48000 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART2>;
+			reg = <0xbfe48000 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart3: serial@1fe4c000 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART3>;
+			reg = <0x1fe4c000 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart4:  serial@1fe4c400 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART4>;
+			reg = <0x1fe4c400 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart5:  serial@1fe4c500 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART5>;
+			reg = <0x1fe4c500 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart6:  serial@1fe4c600 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART6>;
+			reg = <0x1fe4c600 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart7:  serial@1fe4c700 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART7>;
+			reg = <0x1fe4c700 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart8:  serial@1fe4c800 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART8>;
+			reg = <0x1fe4c800 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart9:  serial@1fe4c900 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART9>;
+			reg = <0x1fe4c900 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart10: serial@1fe4ca00 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART10>;
+			reg = <0x1fe4ca00 0x100>;
+			reg-shift = <0>;
+		};
+
+		uart11: serial@1fe4cb00 {
+			compatible = "ns16550a";
+			clocks = <&acc CLK_UART11>;
+			reg = <0x1fe4cb00 0x100>;
+			reg-shift = <0>;
+		};
+
+		wdt: watchdog@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@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@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@mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu@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@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@mediatek.com>
+ *
+ * based on: arch/mips/mach-mtmips/mt7628/init.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@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@132MHz, CPU@297MHz, SPI@33MHz
+ *	SDRAM@100MHz, CPU@300MHz, SPI@50MHz
+ *	SDRAM@66MHz, CPU@132MHz, SPI@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@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@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@mediatek.com>
+ *
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
+ *
+ * Copyright (C) 2022 Du Huanpeng <dhu@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@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@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@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@mediatek.com>
+ *
+ * based on: drivers/watchdog/mtk_wdt.c
+ * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
+ * based on: include/configs/mt7628.h
+ * Copyright (C) 2022 Du Huanpeng <dhu@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@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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH] mips: dts: add initial support for ls1c300 SoC
  2022-03-29 19:30 [RFC PATCH] mips: dts: add initial support for ls1c300 SoC Du Huanpeng
@ 2022-03-30 20:46 ` Sean Anderson
  2022-04-06  9:22   ` dhu
  2022-03-30 23:24 ` Daniel Schwierzeck
  1 sibling, 1 reply; 6+ messages in thread
From: Sean Anderson @ 2022-03-30 20:46 UTC (permalink / raw)
  To: Du Huanpeng, u-boot; +Cc: weijie.gao, jiaxun.yang, lukma

On 3/29/22 3:30 PM, Du Huanpeng wrote:
> 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/

Can you provide a direct link please? I looked around a bit but I don't
read Chinese and I was unable to figure out where to find more
documentation on this CPU.

> 
> introduce base support for the ls1c300 SoC.
> - debug UART2
> - serial console
> - clock
> - watchdog
> - sysreset
> - many uarts
> 
> Signed-off-by: Du Huanpeng <dhu@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

I'm mainly going to comment on clocks becuase you asked me about that,
but note that this should all be split up into several commits, one
per driver/subsystem.

You will also need some kind of entry in doc/boards.

> 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@0 {
> +			device_type = "cpu";
> +			reg = <0>;
> +			compatible = "loongson,gs232", "mips,mips4Kc";
> +			clocks = <&acc CLK_CPU>;
> +		};
> +	};
> +
> +	xtal: oscillator@0 {

No @address if there's no address.

> +		compatible = "fixed-clock";
> +		clock-frequency = <24000000>;
> +		#clock-cells = <0>;
> +	};

Should go under a "clocks" node (e.g. /clocks/osc)

> +
> +	soc {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		compatible = "simple-bus";
> +		ranges;
> +
> +		// TODO: add more device.
> +
> +		acc: clock-controller@1fe78030 {
> +			compatible = "loongson,ls1c300-clk";
> +			clocks = <&xtal>;
> +			#clock-cells = <1>;
> +			reg = <0x1fe78030 0x8>, <0x1fe7c010 0x4>;
> +			u-boot,dm-pre-reloc;
> +		};
> +
> +		uart0: serial@1fe40000 {
> +			compatible = "ns16550a";

Please add a soc-specific compatible here as well e.g.

	compatible = "loongson,ls1c300-uart", "ns16550a";

This goes for most things with generic bindings as well.

> +			clocks = <&acc CLK_UART0>;
> +			reg = <0x1fe40000 0x100>;
> +			reg-shift = <0>;
Do you have byte-sized registers?

> +		};
> +
> +		uart1: serial@1fe44000 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART1>;
> +			reg = <0x1fe44000 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart2: serial@bfe48000 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART2>;
> +			reg = <0xbfe48000 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart3: serial@1fe4c000 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART3>;
> +			reg = <0x1fe4c000 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart4:  serial@1fe4c400 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART4>;
> +			reg = <0x1fe4c400 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart5:  serial@1fe4c500 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART5>;
> +			reg = <0x1fe4c500 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart6:  serial@1fe4c600 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART6>;
> +			reg = <0x1fe4c600 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart7:  serial@1fe4c700 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART7>;
> +			reg = <0x1fe4c700 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart8:  serial@1fe4c800 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART8>;
> +			reg = <0x1fe4c800 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart9:  serial@1fe4c900 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART9>;
> +			reg = <0x1fe4c900 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart10: serial@1fe4ca00 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART10>;
> +			reg = <0x1fe4ca00 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart11: serial@1fe4cb00 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART11>;
> +			reg = <0x1fe4cb00 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		wdt: watchdog@1fe5c060 {
> +			compatible = "loongson,ls1c300-wdt";
> +			clocks = <&acc CLK_WDT>;
> +			reg = <0x1fe5c060 0x10>;
> +		};
> +
> +		reset-controller {
> +			compatible = "wdt-reboot";
> +			wdt = <&wdt>;
> +		};
> +
> +	};
> +};

You are missing some kind of memory node (and perhaps aliases).

How does this boot? JTAG?

> 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@hodcarrier.org>
> + */
> +
> +/dts-v1/;
> +
> +#include "loongson32-ls1c300b.dtsi"
> +
> +/ {
> +	compatible = "lsmips,ls1c300-soc";
> +	model = "ls1c300-eval";
> +
> +	aliases {
> +		console = &uart2;

uarts use serialX aliases.

> +	};
> +
> +	chosen {
> +		bootargs = "console=ttyS0,115200";
> +		stdout-path = &uart2;
> +	};
> +};
> +
> +&uart2 {
> +	status = "okay";

All devices implicitly have status = "okay". You should disable most
devices in the soc dtsi, and then re-enable them in the board dts.

> +};
> +
> 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@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

if (CONFIG_IS_ENABLED(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@mediatek.com>
> + *
> + * Copyright (C) 2022 Du Huanpeng <dhu@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@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;
> +}

Please consider using a real GPIO driver.

> 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@mediatek.com>
> + *
> + * based on: arch/mips/mach-mtmips/mt7628/init.c
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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);

You *must* call clk_request() before using a clock.

> +
> +	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@mediatek.com>
> + *
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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)

Why does this need to be done in assembly? Ditto for the rest.

> +
> +/* SPI: Dual IO@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@132MHz, CPU@297MHz, SPI@33MHz
> + *	SDRAM@100MHz, CPU@300MHz, SPI@50MHz
> + *	SDRAM@66MHz, CPU@132MHz, SPI@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@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@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__ */

All this should go in the device tree.

> 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@mediatek.com>
> + *
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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 ;
> +}

Please use a pinctrl driver for this. In particular, you may be able to use
pinctrl-simple, which can be configured through the device tree.

> 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@mediatek.com>
> + *
> + * Copyright (C) 2022 Du Huanpeng <dhu@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@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@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

Do you have normal uart working?

> +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

Where is the spi flash driver?

> +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@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;
> +}

You can use [1] once it is merged.

[1] https://lore.kernel.org/all/a5b44286-e2e3-5069-0c0a-d673b86a6e8b@oss.nxp.com/

> +static int ls1c300_clk_enable(struct clk *clk)
> +{
> +	/* Nothing to do on Octeon */

nit: this isn't 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;

One assignment per line, please.

> +	cl = clk_register_fixed_factor(NULL, "pll", parent_name, 0, mult, div);

You will need to create custom clock ops for your PLL. See e.g. drivers/clk/imx/clk-pllv3.c

> +	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);

This should be a divider, like above. Use CLK_DIVIDER_ONE_BASED. You will need
a second follow-up clock to do the fixed division by 16.

I encourage you to seriously consider not using CCF for your driver :)

> +	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;

Create a patch to create a clk_register_divider_table() function, and use that.

> +	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@mediatek.com>
> + *
> + * based on: drivers/watchdog/mtk_wdt.c
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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)

Please define this like

#define WDT_EN   0
#define WDT_TIME 4
#define WDT_SET  8

and use it like

writel(priv->timeout, priv->base + WDT_SET)

If you find that too verbose, you can also create a helper function like

static inline void lsmips_wdt_writel(struct lsmips_wdt_priv *priv, ulong val, ptrdiff_t offset)
{
	writel(val, priv->base + offset);
}

> +
> +struct lsmips_wdt_priv {
> +	void __iomem *base;
> +	ulong clock;
> +	unsigned long timeout;
> +};

Docment the fields here please.

> +
> +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);

why not start with this?

Also, please multiply first for better precision. And use MSEC_PER_SEC instead of 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;
> +	}

What's the logic here? Why is this clock optional?

> +
> +	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@mediatek.com>
> + * based on: include/configs/mt7628.h
> + * Copyright (C) 2022 Du Huanpeng <dhu@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@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

So are these different clocks? Why do they all have the same id?

> +#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH] mips: dts: add initial support for ls1c300 SoC
  2022-03-29 19:30 [RFC PATCH] mips: dts: add initial support for ls1c300 SoC Du Huanpeng
  2022-03-30 20:46 ` Sean Anderson
@ 2022-03-30 23:24 ` Daniel Schwierzeck
  2022-04-06 11:24   ` Du Huanpeng
  1 sibling, 1 reply; 6+ messages in thread
From: Daniel Schwierzeck @ 2022-03-30 23:24 UTC (permalink / raw)
  To: Du Huanpeng, u-boot; +Cc: seanga2, weijie.gao, jiaxun.yang, lukma

Am Mittwoch, dem 30.03.2022 um 03:30 +0800 schrieb Du Huanpeng:
> 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@hodcarrier.org>

Sean already addressed most points, so only just some additional
comments below.

> ---
>  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 ++++++

you should use mach-loongson. If you copied the naming from mtmips,
then don't ;) mtmips only exists because mediatek was already used for
the ARM specific SoC's and we needed some different Kconfig symbols for
the MIPS SoC's.

>  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

the user should be able to disable this

> +	select DM

> +	imply DM_ETH
> +	imply DM_GPIO

only add this when you add GPIO or ethernet drivers

> +	select DM_RESET
> +	select DM_SERIAL
> +	select PINCTRL
> +	select PINMUX
> +	select PINCONF
> +	select RESET_LSMIPS

I don't see any pinctrl or reset drivers in this patch

> +	imply DM_SPI
> +	imply DM_SPI_FLASH
> +	select OF_CONTROL
> +	select ROM_EXCEPTION_VECTORS

you probably don't need this. This only makes sense on older CPUs
booting from parallel NOR flash or other XiP capable memory

> +	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@0 {
> +			device_type = "cpu";
> +			reg = <0>;
> +			compatible = "loongson,gs232", "mips,mips4Kc";
> +			clocks = <&acc CLK_CPU>;
> +		};
> +	};
> +
> +	xtal: oscillator@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@1fe78030 {
> +			compatible = "loongson,ls1c300-clk";
> +			clocks = <&xtal>;
> +			#clock-cells = <1>;
> +			reg = <0x1fe78030 0x8>, <0x1fe7c010 0x4>;
> +			u-boot,dm-pre-reloc;
> +		};
> +
> +		uart0: serial@1fe40000 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART0>;
> +			reg = <0x1fe40000 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart1: serial@1fe44000 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART1>;
> +			reg = <0x1fe44000 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart2: serial@bfe48000 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART2>;
> +			reg = <0xbfe48000 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart3: serial@1fe4c000 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART3>;
> +			reg = <0x1fe4c000 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart4:  serial@1fe4c400 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART4>;
> +			reg = <0x1fe4c400 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart5:  serial@1fe4c500 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART5>;
> +			reg = <0x1fe4c500 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart6:  serial@1fe4c600 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART6>;
> +			reg = <0x1fe4c600 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart7:  serial@1fe4c700 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART7>;
> +			reg = <0x1fe4c700 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart8:  serial@1fe4c800 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART8>;
> +			reg = <0x1fe4c800 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart9:  serial@1fe4c900 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART9>;
> +			reg = <0x1fe4c900 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart10: serial@1fe4ca00 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART10>;
> +			reg = <0x1fe4ca00 0x100>;
> +			reg-shift = <0>;
> +		};
> +
> +		uart11: serial@1fe4cb00 {
> +			compatible = "ns16550a";
> +			clocks = <&acc CLK_UART11>;
> +			reg = <0x1fe4cb00 0x100>;
> +			reg-shift = <0>;
> +		};

those nodes should be disabled by default and just one picked and
enabled by the board.


> +
> +		wdt: watchdog@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@hodcarrier.org>
> + */
> +
> +/dts-v1/;
> +
> +#include "loongson32-ls1c300b.dtsi"
> +
> +/ {
> +	compatible = "lsmips,ls1c300-soc";
> +	model = "ls1c300-eval";
> +
> +	aliases {
> +		console = &uart2;
> +	};
> +
> +	chosen {
> +		bootargs = "console=ttyS0,115200";

this is not needed and will be overwritten anyway by bootm

> +		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

I don't see amy pinctrl driver in this patch

> +	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.

this should be selected by the DT uart nodes via pinctrl

> +
> +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@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

either you can detect the RAM size from the memory controller settings
or just use a fixed value. Better to make that configurable for a
board.

> +
> +	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@mediatek.com>
> + *
> + * Copyright (C) 2022 Du Huanpeng <dhu@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@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;
> +}

use a pinctrl driver and device-tree for pin muxing

> 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@mediatek.com>
> + *
> + * based on: arch/mips/mach-mtmips/mt7628/init.c
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
> + *
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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)

don't use magic values for register values and offset. Use defines for
this to make that readable. And add some comments about what you are
configuring.

> +
> +	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@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@132MHz, CPU@297MHz, SPI@33MHz
> + *	SDRAM@100MHz, CPU@300MHz, SPI@50MHz
> + *	SDRAM@66MHz, CPU@132MHz, SPI@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@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@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@mediatek.com>
> + *
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
> + *
> + * Copyright (C) 2022 Du Huanpeng <dhu@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@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@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);
> +}

isn't that redundant to lsmips_spl_serial_init()?

> +#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=ylsmips_spl_serial_init
> +# 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

this needs to be generated with "make savedefconfig; cp defconfig
configs/ls1c300_defconfig" to just list options different from their
default values

> 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@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@mediatek.com>
> + *
> + * based on: drivers/watchdog/mtk_wdt.c
> + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
> + * based on: include/configs/mt7628.h
> + * Copyright (C) 2022 Du Huanpeng <dhu@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@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__ */
-- 
- Daniel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Re: [RFC PATCH] mips: dts: add initial support for ls1c300 SoC
  2022-03-30 20:46 ` Sean Anderson
@ 2022-04-06  9:22   ` dhu
  2022-04-06 17:05     ` Sean Anderson
  0 siblings, 1 reply; 6+ messages in thread
From: dhu @ 2022-04-06  9:22 UTC (permalink / raw)
  To: Sean Anderson, u-boot; +Cc: weijie.gao, jiaxun.yang, lukma

Hi, Sean,
thank you for the comments, I have fix most issues and sent a v2 patch.

> > See Techinical Reference Manual for details: https://www.loongson.cn/
> 
> Can you provide a direct link please? I looked around a bit but I don't
> read Chinese and I was unable to figure out where to find more
> documentation on this CPU.
I can't find direct link too, register is required to access this documents.


> How does this boot? JTAG?
use a flash programer and write the u-boot-with-spl.bin to the spi nor
flash. or load the ELF file `u-boot' by the shipped bootloader via tftp.

> > +#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)
> 
> Why does this need to be done in assembly? Ditto for the rest.
this SoC don't have onchip sram to use for initial stack. assembly code
prepare a working ram for C stack and heap use.
stack is needed in C nested call and the heap is needed in lzma
decompress.
the spi runs at clock about 0.75MHz on reset, this is very slow,
I tweat it to 33MHz.
> 
> > +
> > +/* SPI: Dual IO@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@132MHz, CPU@297MHz, SPI@33MHz
> > + *	SDRAM@100MHz, CPU@300MHz, SPI@50MHz
> > + *	SDRAM@66MHz, CPU@132MHz, SPI@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@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/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@mediatek.com>
> > + *
> > + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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 ;
> > +}
> 
> Please use a pinctrl driver for this. In particular, you may be able to use
> pinctrl-simple, which can be configured through the device tree.
this muxing is used in SPL at the very beginning. DM is not avaiable.

> 
> > 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@mediatek.com>
> > + *
> > + * Copyright (C) 2022 Du Huanpeng <dhu@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@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@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
> 
> Do you have normal uart working?
the normal uart works with  ns16550 uart driver. so no extra serial driver for this SoC.


> 
> > +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
> 
> Where is the spi flash driver?
TODO :).

> > +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);
> 
> why not start with this?
> 
> Also, please multiply first for better precision. And use MSEC_PER_SEC instead of 1000.
I want to avoid overflow first, so I do the division first.
the macro MSEC_PER_SEC seems not defined in public header, I find it is
private defined in multiple place, so I don't want to use this macro
this time.

> > +#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
> 
> So are these different clocks? Why do they all have the same id?
they are all the same clock, the apb bus clock.
> 
> > +#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */
> > 
> 
---
du huanpeng



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH] mips: dts: add initial support for ls1c300 SoC
  2022-03-30 23:24 ` Daniel Schwierzeck
@ 2022-04-06 11:24   ` Du Huanpeng
  0 siblings, 0 replies; 6+ messages in thread
From: Du Huanpeng @ 2022-04-06 11:24 UTC (permalink / raw)
  To: Daniel Schwierzeck; +Cc: u-boot, seanga2, weijie.gao, jiaxun.yang, lukma

hi,
On Thu, Mar 31, 2022 at 01:24:31AM +0200, Daniel Schwierzeck wrote:
> Am Mittwoch, dem 30.03.2022 um 03:30 +0800 schrieb Du Huanpeng:
> > 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@hodcarrier.org>
> 
> Sean already addressed most points, so only just some additional
> comments below.
> 
> > ---
> >  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 ++++++
> 
> you should use mach-loongson. If you copied the naming from mtmips,
> then don't ;) mtmips only exists because mediatek was already used for
> the ARM specific SoC's and we needed some different Kconfig symbols for
> the MIPS SoC's.
I copied from mediatek, loongson also has mips and one other architecture...

> 
> >  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
> 
> the user should be able to disable this
> 
> > +	select DM
> 
> > +	imply DM_ETH
> > +	imply DM_GPIO
> 
> only add this when you add GPIO or ethernet drivers
> 
> > +	select DM_RESET
> > +	select DM_SERIAL
> > +	select PINCTRL
> > +	select PINMUX
> > +	select PINCONF
> > +	select RESET_LSMIPS
> 
> I don't see any pinctrl or reset drivers in this patch
> 
> > +	imply DM_SPI
> > +	imply DM_SPI_FLASH
> > +	select OF_CONTROL
> > +	select ROM_EXCEPTION_VECTORS
> 
> you probably don't need this. This only makes sense on older CPUs
> booting from parallel NOR flash or other XiP capable memory
bfc0_0000 is mapped to nor flash or nand. mine mapped to spi nor flash.
it has 1MB size of memory supports XiP. I changed it to user
configureable.

> 
> > +	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@0 {
> > +			device_type = "cpu";
> > +			reg = <0>;
> > +			compatible = "loongson,gs232", "mips,mips4Kc";
> > +			clocks = <&acc CLK_CPU>;
> > +		};
> > +	};
> > +
> > +	xtal: oscillator@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@1fe78030 {
> > +			compatible = "loongson,ls1c300-clk";
> > +			clocks = <&xtal>;
> > +			#clock-cells = <1>;
> > +			reg = <0x1fe78030 0x8>, <0x1fe7c010 0x4>;
> > +			u-boot,dm-pre-reloc;
> > +		};
> > +
> > +		uart0: serial@1fe40000 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART0>;
> > +			reg = <0x1fe40000 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart1: serial@1fe44000 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART1>;
> > +			reg = <0x1fe44000 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart2: serial@bfe48000 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART2>;
> > +			reg = <0xbfe48000 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart3: serial@1fe4c000 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART3>;
> > +			reg = <0x1fe4c000 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart4:  serial@1fe4c400 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART4>;
> > +			reg = <0x1fe4c400 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart5:  serial@1fe4c500 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART5>;
> > +			reg = <0x1fe4c500 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart6:  serial@1fe4c600 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART6>;
> > +			reg = <0x1fe4c600 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart7:  serial@1fe4c700 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART7>;
> > +			reg = <0x1fe4c700 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart8:  serial@1fe4c800 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART8>;
> > +			reg = <0x1fe4c800 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart9:  serial@1fe4c900 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART9>;
> > +			reg = <0x1fe4c900 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart10: serial@1fe4ca00 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART10>;
> > +			reg = <0x1fe4ca00 0x100>;
> > +			reg-shift = <0>;
> > +		};
> > +
> > +		uart11: serial@1fe4cb00 {
> > +			compatible = "ns16550a";
> > +			clocks = <&acc CLK_UART11>;
> > +			reg = <0x1fe4cb00 0x100>;
> > +			reg-shift = <0>;
> > +		};
> 
> those nodes should be disabled by default and just one picked and
> enabled by the board.
> 
> 
> > +
> > +		wdt: watchdog@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@hodcarrier.org>
> > + */
> > +
> > +/dts-v1/;
> > +
> > +#include "loongson32-ls1c300b.dtsi"
> > +
> > +/ {
> > +	compatible = "lsmips,ls1c300-soc";
> > +	model = "ls1c300-eval";
> > +
> > +	aliases {
> > +		console = &uart2;
> > +	};
> > +
> > +	chosen {
> > +		bootargs = "console=ttyS0,115200";
> 
> this is not needed and will be overwritten anyway by bootm
> 
> > +		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
> 
> I don't see amy pinctrl driver in this patch
> 
> > +	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.
> 
> this should be selected by the DT uart nodes via pinctrl
this is used in SPL.

> 
> > +
> > +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@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
> 
> either you can detect the RAM size from the memory controller settings
> or just use a fixed value. Better to make that configurable for a
> board.
> 
> > +
> > +	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@mediatek.com>
> > + *
> > + * Copyright (C) 2022 Du Huanpeng <dhu@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@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;
> > +}
> 
> use a pinctrl driver and device-tree for pin muxing
this is use for debug_uart_init and spl.
the debug_uart_init call is called from ''start.S''.
> 
> > 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@mediatek.com>
> > + *
> > + * based on: arch/mips/mach-mtmips/mt7628/init.c
> > + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
> > + *
> > + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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)
> 
> don't use magic values for register values and offset. Use defines for
> this to make that readable. And add some comments about what you are
> configuring.
> 
> > +
> > +	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@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@132MHz, CPU@297MHz, SPI@33MHz
> > + *	SDRAM@100MHz, CPU@300MHz, SPI@50MHz
> > + *	SDRAM@66MHz, CPU@132MHz, SPI@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@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@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@mediatek.com>
> > + *
> > + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
> > + *
> > + * Copyright (C) 2022 Du Huanpeng <dhu@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@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@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);
> > +}
> 
> isn't that redundant to lsmips_spl_serial_init()?
... seems no, when CONFIG_DEBUG_UART=y is disabled, spl have to do the
mux for it's serial port.
> 
> > +#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=ylsmips_spl_serial_init
> > +# 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
> 
> this needs to be generated with "make savedefconfig; cp defconfig
> configs/ls1c300_defconfig" to just list options different from their
> default values
> 
> > 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@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@mediatek.com>
> > + *
> > + * based on: drivers/watchdog/mtk_wdt.c
> > + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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@mediatek.com>
> > + * based on: include/configs/mt7628.h
> > + * Copyright (C) 2022 Du Huanpeng <dhu@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@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__ */
> -- 
> - Daniel
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH] mips: dts: add initial support for ls1c300 SoC
  2022-04-06  9:22   ` dhu
@ 2022-04-06 17:05     ` Sean Anderson
  0 siblings, 0 replies; 6+ messages in thread
From: Sean Anderson @ 2022-04-06 17:05 UTC (permalink / raw)
  To: dhu, u-boot; +Cc: weijie.gao, jiaxun.yang, lukma

On 4/6/22 5:22 AM, dhu@hodcarrier.org wrote:
> Hi, Sean,
> thank you for the comments, I have fix most issues and sent a v2 patch.
> 
>>   > See Techinical Reference Manual for details: https://www.loongson.cn/
>>   
>>   Can you provide a direct link please? I looked around a bit but I don't
>>   read Chinese and I was unable to figure out where to find more
>>   documentation on this CPU.
> I can't find direct link too, register is required to access this documents.

That's fine.

A link to the CPU repo https://github.com/trivialmips/nontrivial-mips would be nice.

>>   How does this boot? JTAG?
> use a flash programer and write the u-boot-with-spl.bin to the spi nor
> flash. or load the ELF file `u-boot' by the shipped bootloader via tftp.

Please add a binding for the SPI device at least (since that seems to be what
you are using).

>>   > +#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)
>>   
>>   Why does this need to be done in assembly? Ditto for the rest.
> this SoC don't have onchip sram to use for initial stack. assembly code
> prepare a working ram for C stack and heap use.
> stack is needed in C nested call and the heap is needed in lzma
> decompress.
> the spi runs at clock about 0.75MHz on reset, this is very slow,
> I tweat it to 33MHz.

Can you put this in a comment or in the commit message?

>>   
>>   > +
>>   > +/* SPI: Dual IO@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

Can you add some comments on which fields you have initialized here? This
is an area where other people may need to modify (because e.g. they have
a different sdram config).

>>   > +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@132MHz, CPU@297MHz, SPI@33MHz
>>   > + *	SDRAM@100MHz, CPU@300MHz, SPI@50MHz
>>   > + *	SDRAM@66MHz, CPU@132MHz, SPI@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@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/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@mediatek.com>
>>   > + *
>>   > + * Copyright (C) 2020-2022 Du Huanpeng <dhu@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 ;
>>   > +}
>>   
>>   Please use a pinctrl driver for this. In particular, you may be able to use
>>   pinctrl-simple, which can be configured through the device tree.
> this muxing is used in SPL at the very beginning. DM is not avaiable.

You can use DM in SPL. How much space do you have in your flash? More than 64-128k
is enough to use SPL_DM. More than 512k is enough to skip SPL entirely. Presumably
since you are using the combined SPL/U-Boot image you have enough space to skip it.

>>   
>>   > 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@mediatek.com>
>>   > + *
>>   > + * Copyright (C) 2022 Du Huanpeng <dhu@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@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@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
>>   
>>   Do you have normal uart working?
> the normal uart works with  ns16550 uart driver. so no extra serial driver for this SoC.

Typically the debug uart should be disabled in the defconfig. Just document the parameters.

>>   
>>   > +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
>>   
>>   Where is the spi flash driver?
> TODO :).
> 
>>   > +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);
>>   
>>   why not start with this?
>>   
>>   Also, please multiply first for better precision. And use MSEC_PER_SEC instead of 1000.
> I want to avoid overflow first, so I do the division first.
> the macro MSEC_PER_SEC seems not defined in public header, I find it is
> private defined in multiple place, so I don't want to use this macro
> this time.

Define it. Make the code better.

>>   > +#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
>>   
>>   So are these different clocks? Why do they all have the same id?
> they are all the same clock, the apb bus clock.

OK, then just define CLK_APB to 3. Adding a prefix like LS1C300_CLK_APB
would be nice.

--Sean


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-04-06 17:05 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-29 19:30 [RFC PATCH] mips: dts: add initial support for ls1c300 SoC Du Huanpeng
2022-03-30 20:46 ` Sean Anderson
2022-04-06  9:22   ` dhu
2022-04-06 17:05     ` Sean Anderson
2022-03-30 23:24 ` Daniel Schwierzeck
2022-04-06 11:24   ` Du Huanpeng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.