[PATCH v3] mips: dts: add initial support for ls1c300 SoC

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 Technical 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 --- Changelog for v3: - change cpu clock id from CLK_CPU to CLK_CPU_THROT - migrate all APB dev's clock id to CLK_APB - remove uarts' <reg-shift> property to use default value <0> - move /clocks/acc node to /soc/acc - call clk_request() before use a clk - make get_tbclk() return 1/2 clock of cpu - disable debug_uart by default - add ops for cpu_throt_factor clk - declare MSEC_PER_SEC for converting between sec and msec - return a error code when the wdt clock is out of range - minor format and codingstyle fixes - rebase to [9859465bfe838bc8264d45e1a1bed847bba74bad]
Changelog for v2: 1. dtsi: add status disabled for uart0 ~ uart11 remove bootargs from chosen make serial0 alias for uart2 oscillator remove @0 unit-address change uart2 address to kuseg
2. cleanup Kconfig and update defconfig - make these options configurable, disabled by default: CMD_DM DM_ETH DM_GPIO DM_SPI DM_SPI_FLASH DM_RESET PINCONF PINCTRL PINMUX RESET_LSMIPS - make these options configurable, enabled by default: CLK DISPLAY_CPUINFO SYSRESET ROM_EXCEPTION_VECTORS - disabled: CONFIG_ENV_IS_IN_SPI_FLASH
3. fix codingstyle drivers/watchdog/lsmips-wdt.c - priv->base + offset - add comment for default clock value
4. remove address base definition header - remove arch/mips/mach-lsmips/ls1c300/ls1c300.h - clean up files uses this header
5. spl and debug uart - add comment for spl & debug uart pinmuxing - cleanup unused registers base header
6. dtsi - add "loongson,ls1c300-uart" to all uart node
7. board dts - add memory node to board dts, start at 0x80000000, size 64MB
8. Kconfig - make ROM_EXCEPTION_VECTORS user configureable - enable ROM_EXCEPTION_VECTORS in defconfig
9. - seperate sdram_init to sdram_init.S - add macro helpers to do sdram, pll lowlevel init
10. dtsi - move clock nodes to /clocks/xxx
11. - define CONFIG_SKIP_LOWLEVEL_INIT to 1
12. - remove option PINCTRL_LS1C300 from Kconfig
13. - dram_init, use get_ram_size() to detect ram size.
14. clk driver - create custom clock ops for PLL - remove debug code
15. - rebase to 59bffec43a657598b194b9eb30dc01eec06078c7 - remove CONFIG_SYS_MONITOR_BASE from include/configs/
commit e4d741f8abc4a92426d3a826f99390c3abe02d61 Author: Tom Rini trini@konsulko.com Date: Thu Mar 24 17:18:05 2022 -0400
Convert CONFIG_SYS_MONITOR_BASE to Kconfig
MAINTAINERS | 13 ++ arch/mips/Kconfig | 11 ++ arch/mips/Makefile | 1 + arch/mips/dts/Makefile | 1 + arch/mips/dts/loongson32-ls1c300b.dtsi | 141 ++++++++++++++ arch/mips/dts/ls1c300-eval.dts | 31 +++ arch/mips/mach-lsmips/Kconfig | 76 ++++++++ arch/mips/mach-lsmips/Makefile | 6 + arch/mips/mach-lsmips/cpu.c | 19 ++ arch/mips/mach-lsmips/include/mach/serial.h | 16 ++ arch/mips/mach-lsmips/ls1c300/Makefile | 7 + arch/mips/mach-lsmips/ls1c300/gpio.c | 66 +++++++ arch/mips/mach-lsmips/ls1c300/init.c | 63 ++++++ arch/mips/mach-lsmips/ls1c300/lowlevel_init.S | 136 +++++++++++++ arch/mips/mach-lsmips/ls1c300/sdram.S | 94 +++++++++ arch/mips/mach-lsmips/ls1c300/serial.c | 109 +++++++++++ arch/mips/mach-lsmips/spl.c | 46 +++++ 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 | 49 +++++ drivers/clk/Makefile | 1 + drivers/clk/lsmips/Makefile | 3 + drivers/clk/lsmips/clk-ls1c300.c | 180 ++++++++++++++++++ drivers/watchdog/Kconfig | 8 + drivers/watchdog/Makefile | 1 + drivers/watchdog/lsmips_wdt.c | 123 ++++++++++++ include/configs/ls1c300.h | 59 ++++++ include/dt-bindings/clock/ls1c300-clk.h | 18 ++ 30 files changed, 1320 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/sdram.S 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/MAINTAINERS b/MAINTAINERS index 34446127d4..e1714fb1fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -967,6 +967,19 @@ F: drivers/net/cortina_ni.c F: drivers/net/cortina_ni.h F: drivers/net/phy/ca_phy.c
+MIPS LOONGSON LS1C300 +M: Du Huanpeng dhu@hodcarrier.org +S: Maintained +F: arch/mips/dts/loongson32-ls1c300b.dtsi +F: arch/mips/dts/ls1c300-eval.dts +F: arch/mips/mach-lsmips/ +F: board/loongson/ls1c300-eval/ +F: configs/ls1c300_defconfig +F: drivers/clk/lsmips/ +F: drivers/watchdog/lsmips_wdt.c +F: include/configs/ls1c300.h +F: include/dt-bindings/clock/ls1c300-clk.h + MIPS MEDIATEK M: Weijie Gao weijie.gao@mediatek.com R: GSS_MTK_Uboot_upstream GSS_MTK_Uboot_upstream@mediatek.com diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 06cae68ee5..461bb2a99b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -93,6 +93,16 @@ config ARCH_MTMIPS select SUPPORTS_LITTLE_ENDIAN select SUPPORT_SPL
+config ARCH_LSMIPS + bool "Support Loongson MIPS platforms" + select DM + select DM_SERIAL + select OF_CONTROL + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + select SUPPORTS_LITTLE_ENDIAN + select SUPPORT_SPL + config ARCH_JZ47XX bool "Support Ingenic JZ47xx" select SUPPORT_SPL @@ -175,6 +185,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..b13bdf189d --- /dev/null +++ b/arch/mips/dts/loongson32-ls1c300b.dtsi @@ -0,0 +1,141 @@ +// 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_THROT>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + u-boot,dm-pre-reloc; + + xtal: oscillator { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + #clock-cells = <0>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + 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 = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe40000 0x100>; + status = "disabled"; + }; + + uart1: serial@1fe44000 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe44000 0x100>; + status = "disabled"; + }; + + uart2: serial@1fe48000 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe48000 0x100>; + status = "disabled"; + }; + + uart3: serial@1fe4c000 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4c000 0x100>; + status = "disabled"; + }; + + uart4: serial@1fe4c400 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4c400 0x100>; + status = "disabled"; + }; + + uart5: serial@1fe4c500 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4c500 0x100>; + status = "disabled"; + }; + + uart6: serial@1fe4c600 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4c600 0x100>; + status = "disabled"; + }; + + uart7: serial@1fe4c700 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4c700 0x100>; + status = "disabled"; + }; + + uart8: serial@1fe4c800 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4c800 0x100>; + status = "disabled"; + }; + + uart9: serial@1fe4c900 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4c900 0x100>; + status = "disabled"; + }; + + uart10: serial@1fe4ca00 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4ca00 0x100>; + status = "disabled"; + }; + + uart11: serial@1fe4cb00 { + compatible = "loongson,ls1c300-uart", "ns16550a"; + clocks = <&acc CLK_APB>; + reg = <0x1fe4cb00 0x100>; + status = "disabled"; + }; + + wdt: watchdog@1fe5c060 { + compatible = "loongson,ls1c300-wdt"; + clocks = <&acc CLK_APB>; + 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..eaf65b2d96 --- /dev/null +++ b/arch/mips/dts/ls1c300-eval.dts @@ -0,0 +1,31 @@ +// 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 { + serial0 = &uart2; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x4000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&uart2 { + status = "okay"; +}; + diff --git a/arch/mips/mach-lsmips/Kconfig b/arch/mips/mach-lsmips/Kconfig new file mode 100644 index 0000000000..2092e6ef35 --- /dev/null +++ b/arch/mips/mach-lsmips/Kconfig @@ -0,0 +1,76 @@ +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 + default "u-boot.bin" if !SPL + +choice + prompt "Loongson MIPS SoC select" + +config SOC_LS1C300 + bool "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 + 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..4205d8ef83 --- /dev/null +++ b/arch/mips/mach-lsmips/cpu.c @@ -0,0 +1,19 @@ +// 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) +{ + gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M); + 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..17b9d6fb9c --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-y += lowlevel_init.o +obj-y += sdram.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..2195738b2b --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/gpio.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Du Huanpeng dhu@hodcarrier.org + */ + +#include <linux/errno.h> +#include <asm/bitops.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 + +/* + * pinmux for debug uart and spl only, for others, please + * use a pinctrl driver and device-tree for pin muxing. + * + * @gpio: gpio number + * @func: alternate function 1 to 5, 0 for GPIO. + */ + +int gpio_set_alternate(int gpio, int func) +{ + volatile void __iomem *addr; + int i; + + if (gpio < 0 || gpio > 104) + return -ENODEV; + if (func < 0 || func > 5) + 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..d515bd2f86 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/init.c @@ -0,0 +1,63 @@ +// 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> + +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; + + ret = clk_request(udev, &clk); + if (ret < 0) + return ret; + + clk.id = CLK_XTAL; + xtal = clk_get_rate(&clk); + + clk.id = CLK_CPU_THROT; + gd->cpu_clk = clk_get_rate(&clk); + + clk.id = CLK_APB; + 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 / 2; +} 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..a8d1359cf5 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S @@ -0,0 +1,136 @@ +/* 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 control register */ +#define NAND_BASE 0xbfe70000 +#define START_FREQ 0x8030 +#define CLK_DIV_PARAM 0x8034 +#define CPU_THROT 0xc010 + +/* START_FREQ */ +#define PLL_VALID 31 +#define Reserved_24 24 +#define FRAC_N 16 +#define M_PLL 8 +#define Reserved_4 4 +#define RST_TIME 2 +#define SDRAM_DIV 0 + #define SDRAM_DIV2 0 + #define SDRAM_DIV4 1 + #define SDRAM_DIV3 2 + +/* CLK_DIV_PARAM */ +#define PIX_DIV 24 +#define CAM_DIV 16 +#define CPU_DIV 8 +#define PIX_DIV_VALID 5 +#define PIX_SEL 4 +#define CAM_DIV_VALID 3 +#define CAM_SEL 2 +#define CPU_DIV_VALID 1 +#define CPU_SEL 0 + +/* Document: + * Freq_PLL = XIN *(M_PLL + FRAC_N)/4 + */ +#define XIN 24000000 +#define PLL_VALID_1 (1<<PLL_VALID) +#define PREP_M_PLL(Freq_PLL) (((Freq_PLL * 4) / XIN) << M_PLL) +#define PREP_SDRAM_DIV(div) (div<<SDRAM_DIV) +#define PREP_CPU_DIV(div1) ((0x80|div1)<<CPU_DIV | (div1&&div1)<<CPU_DIV_VALID) +#define PREP_PIX_DIV(div2) (div2<<PIX_DIV) +#define PREP_CAM_DIV(div3) (div3<<CAM_DIV) + +/* PLL @264MHz, CPU @132MHz, SDRAM @66MHz */ +#define CFG_START_FREQ (PLL_VALID_1 | PREP_M_PLL(264000000) | SDRAM_DIV2) +#define CFG_CLK_DIV_PARAM (PREP_CPU_DIV(2) | PREP_PIX_DIV(0x24) | PREP_CAM_DIV(0x24)) +#define CFG_CPU_THROT 15 + +/* SPI0 control register */ +#define SPI0_BASE 0xbfe80000 +#define SPCR 0 +#define SPSR 1 +#define TxFIFO 2 +#define RxFIFO 2 +#define SPER 3 +#define SFC_PARAM 4 + #define CLK_DIV 4 + #define DUAL_IO 3 + #define FAST_READ 2 + #define BURST_EN 1 + #define MEMORY_EN 0 +#define SFC_SOFTCS 5 +#define SFC_TIMING 6 + #define T_FAST 2 + #define T_CSH 0 + + .set noreorder +LEAF(ls1c300_pll_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) + li t0, NAND_BASE + li t1, CFG_START_FREQ + li t2, CFG_CLK_DIV_PARAM + li t3, CFG_CPU_THROT + + sw t3, CPU_THROT (t0) + sw t2, CLK_DIV_PARAM (t0) + sw t1, START_FREQ (t0) + nop + + ori t2, 1<<CPU_SEL + sw t2, CLK_DIV_PARAM (t0) +#endif + li v0, 264000000 + jr ra + nop +END(ls1c300_pll_init) + +LEAF(ls1c300_spi_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) + li t0, SPI0_BASE + li t1, (1<<MEMORY_EN) | (1<<BURST_EN) | (1<<FAST_READ) | (1<<DUAL_IO) + sb t1, SFC_PARAM (t0) + li t2, (1<<T_FAST) | (1<<T_CSH) + sb t2, SFC_TIMING (t0) +#endif + jr ra + nop +END(ls1c300_spi_init) + +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/sdram.S b/arch/mips/mach-lsmips/ls1c300/sdram.S new file mode 100644 index 0000000000..95d21f0093 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/sdram.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * 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> + +/* sdram control 64 bit register */ +#define SD_CONFIG 0xbfd00000 +#define SD_CONFIGHI 0x414 +#define SD_CONFIGLO 0x410 + +#define CONFIG_VALID 41 +#define HANG_UP 40 +#define DEF_SEL 39 +#define TWR 37 +#define TREF 25 +#define TRAS 21 +#define TRFC 17 +#define TRP 14 +#define TCL 11 +#define TRCD 8 + +#define SD_BIT 6 + #define SD_8BIT (0<<SD_BIT) + #define SD_16BIT (1<<SD_BIT) + #define SD_32BIT (2<<SD_BIT) +#define SD_CSIZE 3 + #define SD_CSIZE_512 (0<<SD_CSIZE) + #define SD_CSIZE_1K (1<<SD_CSIZE) + #define SD_CSIZE_2K (2<<SD_CSIZE) + #define SD_CSIZE_4K (3<<SD_CSIZE) + #define SD_CSIZE_256 (7<<SD_CSIZE) +#define SD_RSIZE 0 + #define SD_RSIZE_2K (0<<SD_RSIZE) + #define SD_RSIZE_4K (1<<SD_RSIZE) + #define SD_RSIZE_8K (2<<SD_RSIZE) + #define SD_RSIZE_16K (3<<SD_RSIZE) + +#define SD_CFG_1(tWR, tREF, tRAS, tRFC, tRP, tCL, tRCD) \ + ((tWR<<TWR)|(tREF<<TREF)|(tRAS<<TRAS)|(tRFC<<TRFC)|(tRP<<TRP)|(tCL<<TCL)|(tRCD<<TRCD)) +#define CFG_SD_0(b, c, r) \ + ((b<<SD_BIT)|(c<<SD_CSIZE)|(r<<SD_RSIZE)) +/* + * recommended values by ls1c300 user manual, + * tweat to fit your board. + */ +#define SD_CONFIG_133MHz SD_CFG_1(2, 0x818, 6, 8, 3, 3, 3) +#define SD_CONFIG_100MHz SD_CFG_1(2, 0x620, 5, 6, 2, 3, 2) +#define SD_CONFIG_75MHz SD_CFG_1(1, 0x494, 4, 5, 2, 2, 2) +#define SD_CONFIG_33MHz SD_CFG_1(1, 0x204, 2, 2, 1, 2, 1) + +#define SD_CONFIG_66MHz SD_CFG_1(1, 0x401, 4, 4, 2, 2, 2) + +#define SD_CONFIG64 (SD_CONFIG_66MHz | SD_16BIT | SD_CSIZE_1K | SD_RSIZE_8K) +#define CFG_SDCONFIGHI (SD_CONFIG64 /(1<<32)) +#define CFG_SDCONFIGLO (SD_CONFIG64 %(1<<32)) + + .set noreorder +/* + * Loongson ls1c300 SoC do not have onchip sram for initial stack, + * initialize the external sdram on reset as early as possiable. + */ +LEAF(ls1c300_sdram_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) + li t0, SD_CONFIG + li t1, CFG_SDCONFIGLO + li t2, CFG_SDCONFIGHI + + sw t1, SD_CONFIGLO (t0) + sw t2, SD_CONFIGHI (t0) + nop + + sw t1, SD_CONFIGLO (t0) + sw t2, SD_CONFIGHI (t0) + nop + + ori t2, 1<<(CONFIG_VALID-32) + sw t1, SD_CONFIGLO (t0) + sw t2, SD_CONFIGHI (t0) +#endif + li v0, SZ_64M + jr ra + nop +END(ls1c300_sdram_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..93fd653385 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/serial.c @@ -0,0 +1,109 @@ +// 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 <mach/serial.h> +#include <linux/kernel.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) +{ +#if defined(CONFIG_SPL_SERIAL) + int pin_rx, pin_tx; + int afunc; + + if (CONFIG_CONS_PIN < ARRAY_SIZE(con)) { + pin_rx = con[CONFIG_CONS_PIN].rx; + pin_tx = con[CONFIG_CONS_PIN].tx; + afunc = con[CONFIG_CONS_PIN].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..21c49197ae --- /dev/null +++ b/arch/mips/mach-lsmips/spl.c @@ -0,0 +1,46 @@ +// 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(); + +#if defined(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 Huanpengdhu@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..6809d66515 --- /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> + +#if defined(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..3e630a0c0e --- /dev/null +++ b/configs/ls1c300_defconfig @@ -0,0 +1,49 @@ +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_DEFAULT_DEVICE_TREE="ls1c300-eval" +CONFIG_SPL_SERIAL=y +CONFIG_SPL_SIZE_LIMIT=0x100000 +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x80010000 +CONFIG_ARCH_LSMIPS=y +CONFIG_SPL_PAYLOAD="u-boot.img" +CONFIG_ROM_EXCEPTION_VECTORS=y +# 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_FIT=y +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set +CONFIG_LOGLEVEL=9 +CONFIG_DISPLAY_CPUINFO=y +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_LOADS is not set +# CONFIG_PARTITIONS is not set +CONFIG_OF_EMBED=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +# CONFIG_NET is not set +CONFIG_CLK=y +CONFIG_SPL_CLK_CCF=y +# CONFIG_INPUT is not set +# CONFIG_POWER is not set +CONFIG_CONS_INDEX=2 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_WATCHDOG=y +CONFIG_SYSRESET_WATCHDOG_AUTO=y +CONFIG_WATCHDOG_TIMEOUT_MSECS=3000 +CONFIG_WDT_LSMIPS=y +CONFIG_REGEX=y +# CONFIG_GZIP is not set 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..46a94e9748 --- /dev/null +++ b/drivers/clk/lsmips/clk-ls1c300.c @@ -0,0 +1,180 @@ +// 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> + +/* PLL/SDRAM Frequency Configuration Register */ +#define START_FREQ 0 +#define CLK_DIV_PARAM 4 + +/* 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}, +}; + +ulong ls1c300_pll_get_rate(struct clk *clk) +{ + unsigned int mult; + long long parent_rate; + void *base; + unsigned int val; + + parent_rate = clk_get_parent_rate(clk); + base = (void *)clk->data; + + val = readl(base + START_FREQ); + mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val); + return (mult * parent_rate) / 4; +} + +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_probe(struct udevice *dev) +{ + void __iomem *base; + void __iomem *cpu_throt; + void __iomem *addr; + + struct clk *cl, clk; + const char *parent_name; + int flags; + int ret; + + base = (void *)dev_remap_addr_index(dev, 0); + cpu_throt = (void *)dev_remap_addr_index(dev, 1); + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + + ret = clk_get_rate(&clk); + + parent_name = clk.dev->name; + + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + cl->data = (unsigned long)base; + ret = clk_register(cl, "clk_ls1c300_pll", "pll", parent_name); + 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); + + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + cl->data = (unsigned long)cpu_throt; + ret = clk_register(cl, "clk_cpu_throt", "cpu_throt_factor", "cpu_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_APB, cl); + + return 0; +} + +static ulong cpu_throt_get_rate(struct clk *clk) +{ + void __iomem *cpu_throt; + long long parent_rate; + ulong ret; + + parent_rate = clk_get_parent_rate(clk); + cpu_throt = (void *)clk->data; + + ret = readl(cpu_throt) + 1; + ret = parent_rate * ret / 16; + return ret; +} + +static const struct udevice_id ls1c300_clk_ids[] = { + { .compatible = "loongson,ls1c300-clk" }, + { } +}; + +static const struct clk_ops clk_cpu_throt_ops = { + .get_rate = cpu_throt_get_rate, +}; + +static const struct clk_ops clk_ls1c300_pll_ops = { + .get_rate = ls1c300_pll_get_rate, +}; + +static const struct clk_ops ls1c300_clk_ops = { + .get_rate = ls1c300_clk_get_rate, +}; + +U_BOOT_DRIVER(clk_ls1c300_cpu_throt) = { + .name = "clk_cpu_throt", + .id = UCLASS_CLK, + .ops = &clk_cpu_throt_ops, +}; + +U_BOOT_DRIVER(clk_ls1c300_pll) = { + .name = "clk_ls1c300_pll", + .id = UCLASS_CLK, + .ops = &clk_ls1c300_pll_ops, +}; + +U_BOOT_DRIVER(ls1c300_clk) = { + .name = "clk_ls1c300", + .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 5b614cfa6e..a9af5e5eb6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -168,6 +168,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..65e60ae656 --- /dev/null +++ b/drivers/watchdog/lsmips_wdt.c @@ -0,0 +1,123 @@ +// 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 <clk.h> + +struct lsmips_wdt_priv { + void __iomem *base; +#define WDT_EN 0 +#define WDT_TIMER 4 +#define WDT_SET 8 + 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, priv->base + WDT_TIMER); + writel(1, priv->base + WDT_SET); + + return 0; +} + +static int lsmips_wdt_stop(struct udevice *dev) +{ + struct lsmips_wdt_priv *priv = dev_get_priv(dev); + + writel(0, priv->base + 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, priv->base + WDT_EN); + writel(1, priv->base + WDT_TIMER); + writel(1, priv->base + 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; + const unsigned int MSEC_PER_SEC = 1000; + + timeout = U32_MAX / (priv->clock / MSEC_PER_SEC); + + if (timeout < timeout_ms) + timeout = U32_MAX; + else + timeout = timeout_ms * (priv->clock / MSEC_PER_SEC); + + debug("WDT: reload = %08x\n", timeout); + + writel(1, priv->base + WDT_EN); + writel(timeout, priv->base + WDT_TIMER); + writel(1, priv->base + 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 < 45000000 || priv->clock > 133000000) + return -EAGAIN; + + debug("WDT: clock = %ld\n", priv->clock); + + writel(0, priv->base + 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..c460b4564b --- /dev/null +++ b/include/configs/ls1c300.h @@ -0,0 +1,59 @@ +/* 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_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 1 +#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..66798f40c7 --- /dev/null +++ b/include/dt-bindings/clock/ls1c300-clk.h @@ -0,0 +1,18 @@ +/* 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__ + +#define CLK_XTAL 0 +#define CLK_PLL 1 +#define CLK_CPU 2 +#define CLK_APB 3 +#define CLK_CAMERA 4 +#define CLK_PIX 5 +#define CLK_AXIMUX 6 +#define CLK_CPU_THROT 7 + +#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */

On 4/18/22 4:45 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 Technical 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
Changelog for v3: - change cpu clock id from CLK_CPU to CLK_CPU_THROT - migrate all APB dev's clock id to CLK_APB - remove uarts' <reg-shift> property to use default value <0> - move /clocks/acc node to /soc/acc - call clk_request() before use a clk - make get_tbclk() return 1/2 clock of cpu - disable debug_uart by default - add ops for cpu_throt_factor clk - declare MSEC_PER_SEC for converting between sec and msec - return a error code when the wdt clock is out of range - minor format and codingstyle fixes - rebase to [9859465bfe838bc8264d45e1a1bed847bba74bad]
Changelog for v2:
dtsi: add status disabled for uart0 ~ uart11 remove bootargs from chosen make serial0 alias for uart2 oscillator remove @0 unit-address change uart2 address to kuseg
cleanup Kconfig and update defconfig
- make these options configurable, disabled by default: CMD_DM DM_ETH DM_GPIO DM_SPI DM_SPI_FLASH DM_RESET PINCONF PINCTRL PINMUX RESET_LSMIPS
- make these options configurable, enabled by default: CLK DISPLAY_CPUINFO SYSRESET ROM_EXCEPTION_VECTORS
- disabled: CONFIG_ENV_IS_IN_SPI_FLASH
- fix codingstyle drivers/watchdog/lsmips-wdt.c
- priv->base + offset
- add comment for default clock value
- remove address base definition header
- remove arch/mips/mach-lsmips/ls1c300/ls1c300.h
- clean up files uses this header
- spl and debug uart
- add comment for spl & debug uart pinmuxing
- cleanup unused registers base header
- dtsi
- add "loongson,ls1c300-uart" to all uart node
- board dts
- add memory node to board dts, start at 0x80000000, size 64MB
- Kconfig
- make ROM_EXCEPTION_VECTORS user configureable
- enable ROM_EXCEPTION_VECTORS in defconfig
- seperate sdram_init to sdram_init.S
- add macro helpers to do sdram, pll lowlevel init
- dtsi
- move clock nodes to /clocks/xxx
- define CONFIG_SKIP_LOWLEVEL_INIT to 1
- remove option PINCTRL_LS1C300 from Kconfig
- dram_init, use get_ram_size() to detect ram size.
- clk driver
- create custom clock ops for PLL
- remove debug code
- rebase to 59bffec43a657598b194b9eb30dc01eec06078c7
- remove CONFIG_SYS_MONITOR_BASE from include/configs/
commit e4d741f8abc4a92426d3a826f99390c3abe02d61 Author: Tom Rini trini@konsulko.com Date: Thu Mar 24 17:18:05 2022 -0400
Convert CONFIG_SYS_MONITOR_BASE to Kconfig
MAINTAINERS | 13 ++ arch/mips/Kconfig | 11 ++ arch/mips/Makefile | 1 + arch/mips/dts/Makefile | 1 + arch/mips/dts/loongson32-ls1c300b.dtsi | 141 ++++++++++++++ arch/mips/dts/ls1c300-eval.dts | 31 +++ arch/mips/mach-lsmips/Kconfig | 76 ++++++++ arch/mips/mach-lsmips/Makefile | 6 + arch/mips/mach-lsmips/cpu.c | 19 ++ arch/mips/mach-lsmips/include/mach/serial.h | 16 ++ arch/mips/mach-lsmips/ls1c300/Makefile | 7 + arch/mips/mach-lsmips/ls1c300/gpio.c | 66 +++++++ arch/mips/mach-lsmips/ls1c300/init.c | 63 ++++++ arch/mips/mach-lsmips/ls1c300/lowlevel_init.S | 136 +++++++++++++ arch/mips/mach-lsmips/ls1c300/sdram.S | 94 +++++++++ arch/mips/mach-lsmips/ls1c300/serial.c | 109 +++++++++++ arch/mips/mach-lsmips/spl.c | 46 +++++ 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 | 49 +++++ drivers/clk/Makefile | 1 + drivers/clk/lsmips/Makefile | 3 + drivers/clk/lsmips/clk-ls1c300.c | 180 ++++++++++++++++++ drivers/watchdog/Kconfig | 8 + drivers/watchdog/Makefile | 1 + drivers/watchdog/lsmips_wdt.c | 123 ++++++++++++ include/configs/ls1c300.h | 59 ++++++ include/dt-bindings/clock/ls1c300-clk.h | 18 ++ 30 files changed, 1320 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/sdram.S 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
Once again, please split this up into multiple patches. This makes the series much easier to review.
diff --git a/MAINTAINERS b/MAINTAINERS index 34446127d4..e1714fb1fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -967,6 +967,19 @@ F: drivers/net/cortina_ni.c F: drivers/net/cortina_ni.h F: drivers/net/phy/ca_phy.c
+MIPS LOONGSON LS1C300 +M: Du Huanpeng dhu@hodcarrier.org +S: Maintained +F: arch/mips/dts/loongson32-ls1c300b.dtsi +F: arch/mips/dts/ls1c300-eval.dts +F: arch/mips/mach-lsmips/ +F: board/loongson/ls1c300-eval/ +F: configs/ls1c300_defconfig +F: drivers/clk/lsmips/ +F: drivers/watchdog/lsmips_wdt.c +F: include/configs/ls1c300.h +F: include/dt-bindings/clock/ls1c300-clk.h
- MIPS MEDIATEK M: Weijie Gao weijie.gao@mediatek.com R: GSS_MTK_Uboot_upstream GSS_MTK_Uboot_upstream@mediatek.com
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 06cae68ee5..461bb2a99b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -93,6 +93,16 @@ config ARCH_MTMIPS select SUPPORTS_LITTLE_ENDIAN select SUPPORT_SPL
+config ARCH_LSMIPS
- bool "Support Loongson MIPS platforms"
- select DM
- select DM_SERIAL
- select OF_CONTROL
- select SUPPORTS_CPU_MIPS32_R1
- select SUPPORTS_CPU_MIPS32_R2
- select SUPPORTS_LITTLE_ENDIAN
- select SUPPORT_SPL
- config ARCH_JZ47XX bool "Support Ingenic JZ47xx" select SUPPORT_SPL
@@ -175,6 +185,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..b13bdf189d --- /dev/null +++ b/arch/mips/dts/loongson32-ls1c300b.dtsi @@ -0,0 +1,141 @@ +// 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_THROT>;
};
- };
- clocks {
#address-cells = <1>;
#size-cells = <1>;
u-boot,dm-pre-reloc;
xtal: oscillator {
compatible = "fixed-clock";
clock-frequency = <24000000>;
#clock-cells = <0>;
};
- };
- soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
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 = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe40000 0x100>;
status = "disabled";
};
uart1: serial@1fe44000 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe44000 0x100>;
status = "disabled";
};
uart2: serial@1fe48000 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe48000 0x100>;
status = "disabled";
};
uart3: serial@1fe4c000 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c000 0x100>;
status = "disabled";
};
uart4: serial@1fe4c400 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c400 0x100>;
status = "disabled";
};
uart5: serial@1fe4c500 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c500 0x100>;
status = "disabled";
};
uart6: serial@1fe4c600 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c600 0x100>;
status = "disabled";
};
uart7: serial@1fe4c700 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c700 0x100>;
status = "disabled";
};
uart8: serial@1fe4c800 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c800 0x100>;
status = "disabled";
};
uart9: serial@1fe4c900 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c900 0x100>;
status = "disabled";
};
uart10: serial@1fe4ca00 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4ca00 0x100>;
status = "disabled";
};
uart11: serial@1fe4cb00 {
compatible = "loongson,ls1c300-uart", "ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4cb00 0x100>;
status = "disabled";
};
wdt: watchdog@1fe5c060 {
compatible = "loongson,ls1c300-wdt";
clocks = <&acc CLK_APB>;
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..eaf65b2d96 --- /dev/null +++ b/arch/mips/dts/ls1c300-eval.dts @@ -0,0 +1,31 @@ +// 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 {
serial0 = &uart2;
- };
- memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x4000000>;
- };
- chosen {
stdout-path = "serial0:115200n8";
- };
+};
+&uart2 {
- status = "okay";
+};
diff --git a/arch/mips/mach-lsmips/Kconfig b/arch/mips/mach-lsmips/Kconfig new file mode 100644 index 0000000000..2092e6ef35 --- /dev/null +++ b/arch/mips/mach-lsmips/Kconfig @@ -0,0 +1,76 @@ +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
- default "u-boot.bin" if !SPL
+choice
- prompt "Loongson MIPS SoC select"
+config SOC_LS1C300
- bool "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
I just want to state for the record here that the size constraint on this processor is 1MiB XIP, so there is no need to use SPL AFAICT. If you insist on SPL you can enable SPL_DM. That way you can use pinctrl drivers.
+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
- 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..4205d8ef83 --- /dev/null +++ b/arch/mips/mach-lsmips/cpu.c @@ -0,0 +1,19 @@ +// 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) +{
- gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
- 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..17b9d6fb9c --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0
+obj-y += lowlevel_init.o +obj-y += sdram.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..2195738b2b --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/gpio.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2022 Du Huanpeng dhu@hodcarrier.org
- */
+#include <linux/errno.h> +#include <asm/bitops.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
+/*
- pinmux for debug uart and spl only, for others, please
- use a pinctrl driver and device-tree for pin muxing.
- @gpio: gpio number
- @func: alternate function 1 to 5, 0 for GPIO.
- */
+int gpio_set_alternate(int gpio, int func) +{
- volatile void __iomem *addr;
- int i;
- if (gpio < 0 || gpio > 104)
return -ENODEV;
- if (func < 0 || func > 5)
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;
+}
So this can e.g. be in a pinctrl 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..d515bd2f86 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/init.c @@ -0,0 +1,63 @@ +// 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>
+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);
nit: no blank line here
- if (ret) {
printf("error: clock driver not found.\n");
return 0;
- }
- clk.dev = udev;
- ret = clk_request(udev, &clk);
- if (ret < 0)
return ret;
- clk.id = CLK_XTAL;
- xtal = clk_get_rate(&clk);
- clk.id = CLK_CPU_THROT;
- gd->cpu_clk = clk_get_rate(&clk);
- clk.id = CLK_APB;
- gd->mem_clk = clk_get_rate(&clk);
Again, all these clocks must be requested first.
- 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 / 2;
+} 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..a8d1359cf5 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S @@ -0,0 +1,136 @@ +/* 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 control register */ +#define NAND_BASE 0xbfe70000 +#define START_FREQ 0x8030 +#define CLK_DIV_PARAM 0x8034 +#define CPU_THROT 0xc010
+/* START_FREQ */ +#define PLL_VALID 31 +#define Reserved_24 24 +#define FRAC_N 16 +#define M_PLL 8 +#define Reserved_4 4 +#define RST_TIME 2 +#define SDRAM_DIV 0
- #define SDRAM_DIV2 0
- #define SDRAM_DIV4 1
- #define SDRAM_DIV3 2
+/* CLK_DIV_PARAM */ +#define PIX_DIV 24 +#define CAM_DIV 16 +#define CPU_DIV 8 +#define PIX_DIV_VALID 5 +#define PIX_SEL 4 +#define CAM_DIV_VALID 3 +#define CAM_SEL 2 +#define CPU_DIV_VALID 1 +#define CPU_SEL 0
+/* Document:
- Freq_PLL = XIN *(M_PLL + FRAC_N)/4
- */
+#define XIN 24000000 +#define PLL_VALID_1 (1<<PLL_VALID) +#define PREP_M_PLL(Freq_PLL) (((Freq_PLL * 4) / XIN) << M_PLL) +#define PREP_SDRAM_DIV(div) (div<<SDRAM_DIV) +#define PREP_CPU_DIV(div1) ((0x80|div1)<<CPU_DIV | (div1&&div1)<<CPU_DIV_VALID) +#define PREP_PIX_DIV(div2) (div2<<PIX_DIV) +#define PREP_CAM_DIV(div3) (div3<<CAM_DIV)
+/* PLL @264MHz, CPU @132MHz, SDRAM @66MHz */ +#define CFG_START_FREQ (PLL_VALID_1 | PREP_M_PLL(264000000) | SDRAM_DIV2) +#define CFG_CLK_DIV_PARAM (PREP_CPU_DIV(2) | PREP_PIX_DIV(0x24) | PREP_CAM_DIV(0x24)) +#define CFG_CPU_THROT 15
+/* SPI0 control register */ +#define SPI0_BASE 0xbfe80000 +#define SPCR 0 +#define SPSR 1 +#define TxFIFO 2 +#define RxFIFO 2 +#define SPER 3 +#define SFC_PARAM 4
- #define CLK_DIV 4
- #define DUAL_IO 3
- #define FAST_READ 2
- #define BURST_EN 1
- #define MEMORY_EN 0
+#define SFC_SOFTCS 5 +#define SFC_TIMING 6
- #define T_FAST 2
- #define T_CSH 0
- .set noreorder
+LEAF(ls1c300_pll_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
- li t0, NAND_BASE
- li t1, CFG_START_FREQ
- li t2, CFG_CLK_DIV_PARAM
- li t3, CFG_CPU_THROT
- sw t3, CPU_THROT (t0)
- sw t2, CLK_DIV_PARAM (t0)
- sw t1, START_FREQ (t0)
nop
- ori t2, 1<<CPU_SEL
- sw t2, CLK_DIV_PARAM (t0)
+#endif
- li v0, 264000000
- jr ra
- nop
+END(ls1c300_pll_init)
+LEAF(ls1c300_spi_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
- li t0, SPI0_BASE
- li t1, (1<<MEMORY_EN) | (1<<BURST_EN) | (1<<FAST_READ) | (1<<DUAL_IO)
- sb t1, SFC_PARAM (t0)
- li t2, (1<<T_FAST) | (1<<T_CSH)
- sb t2, SFC_TIMING (t0)
+#endif
- jr ra
nop
+END(ls1c300_spi_init)
+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/sdram.S b/arch/mips/mach-lsmips/ls1c300/sdram.S new file mode 100644 index 0000000000..95d21f0093 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/sdram.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/*
- 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>
+/* sdram control 64 bit register */ +#define SD_CONFIG 0xbfd00000 +#define SD_CONFIGHI 0x414 +#define SD_CONFIGLO 0x410
+#define CONFIG_VALID 41 +#define HANG_UP 40 +#define DEF_SEL 39 +#define TWR 37 +#define TREF 25 +#define TRAS 21 +#define TRFC 17 +#define TRP 14 +#define TCL 11 +#define TRCD 8
+#define SD_BIT 6
- #define SD_8BIT (0<<SD_BIT)
- #define SD_16BIT (1<<SD_BIT)
- #define SD_32BIT (2<<SD_BIT)
+#define SD_CSIZE 3
- #define SD_CSIZE_512 (0<<SD_CSIZE)
- #define SD_CSIZE_1K (1<<SD_CSIZE)
- #define SD_CSIZE_2K (2<<SD_CSIZE)
- #define SD_CSIZE_4K (3<<SD_CSIZE)
- #define SD_CSIZE_256 (7<<SD_CSIZE)
+#define SD_RSIZE 0
- #define SD_RSIZE_2K (0<<SD_RSIZE)
- #define SD_RSIZE_4K (1<<SD_RSIZE)
- #define SD_RSIZE_8K (2<<SD_RSIZE)
- #define SD_RSIZE_16K (3<<SD_RSIZE)
+#define SD_CFG_1(tWR, tREF, tRAS, tRFC, tRP, tCL, tRCD) \
- ((tWR<<TWR)|(tREF<<TREF)|(tRAS<<TRAS)|(tRFC<<TRFC)|(tRP<<TRP)|(tCL<<TCL)|(tRCD<<TRCD))
+#define CFG_SD_0(b, c, r) \
- ((b<<SD_BIT)|(c<<SD_CSIZE)|(r<<SD_RSIZE))
+/*
- recommended values by ls1c300 user manual,
- tweat to fit your board.
nit: tweak
- */
+#define SD_CONFIG_133MHz SD_CFG_1(2, 0x818, 6, 8, 3, 3, 3) +#define SD_CONFIG_100MHz SD_CFG_1(2, 0x620, 5, 6, 2, 3, 2) +#define SD_CONFIG_75MHz SD_CFG_1(1, 0x494, 4, 5, 2, 2, 2) +#define SD_CONFIG_33MHz SD_CFG_1(1, 0x204, 2, 2, 1, 2, 1)
+#define SD_CONFIG_66MHz SD_CFG_1(1, 0x401, 4, 4, 2, 2, 2)
+#define SD_CONFIG64 (SD_CONFIG_66MHz | SD_16BIT | SD_CSIZE_1K | SD_RSIZE_8K) +#define CFG_SDCONFIGHI (SD_CONFIG64 /(1<<32)) +#define CFG_SDCONFIGLO (SD_CONFIG64 %(1<<32))
- .set noreorder
+/*
- Loongson ls1c300 SoC do not have onchip sram for initial stack,
- initialize the external sdram on reset as early as possiable.
- */
+LEAF(ls1c300_sdram_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
- li t0, SD_CONFIG
- li t1, CFG_SDCONFIGLO
- li t2, CFG_SDCONFIGHI
- sw t1, SD_CONFIGLO (t0)
- sw t2, SD_CONFIGHI (t0)
- nop
- sw t1, SD_CONFIGLO (t0)
- sw t2, SD_CONFIGHI (t0)
- nop
- ori t2, 1<<(CONFIG_VALID-32)
- sw t1, SD_CONFIGLO (t0)
- sw t2, SD_CONFIGHI (t0)
+#endif
- li v0, SZ_64M
- jr ra
nop
+END(ls1c300_sdram_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..93fd653385 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/serial.c @@ -0,0 +1,109 @@ +// 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 <mach/serial.h> +#include <linux/kernel.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) +{ +#if defined(CONFIG_SPL_SERIAL)
- int pin_rx, pin_tx;
- int afunc;
- if (CONFIG_CONS_PIN < ARRAY_SIZE(con)) {
pin_rx = con[CONFIG_CONS_PIN].rx;
pin_tx = con[CONFIG_CONS_PIN].tx;
afunc = con[CONFIG_CONS_PIN].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;
+}
This can also be pinctrl.
diff --git a/arch/mips/mach-lsmips/spl.c b/arch/mips/mach-lsmips/spl.c new file mode 100644 index 0000000000..21c49197ae --- /dev/null +++ b/arch/mips/mach-lsmips/spl.c @@ -0,0 +1,46 @@ +// 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();
+#if defined(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 Huanpengdhu@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..6809d66515 --- /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>
+#if defined(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..3e630a0c0e --- /dev/null +++ b/configs/ls1c300_defconfig @@ -0,0 +1,49 @@ +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_DEFAULT_DEVICE_TREE="ls1c300-eval" +CONFIG_SPL_SERIAL=y +CONFIG_SPL_SIZE_LIMIT=0x100000 +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x80010000 +CONFIG_ARCH_LSMIPS=y +CONFIG_SPL_PAYLOAD="u-boot.img" +CONFIG_ROM_EXCEPTION_VECTORS=y +# 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_FIT=y +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set +CONFIG_LOGLEVEL=9 +CONFIG_DISPLAY_CPUINFO=y +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_LOADS is not set +# CONFIG_PARTITIONS is not set +CONFIG_OF_EMBED=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +# CONFIG_NET is not set +CONFIG_CLK=y +CONFIG_SPL_CLK_CCF=y +# CONFIG_INPUT is not set +# CONFIG_POWER is not set +CONFIG_CONS_INDEX=2 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_WATCHDOG=y +CONFIG_SYSRESET_WATCHDOG_AUTO=y +CONFIG_WATCHDOG_TIMEOUT_MSECS=3000 +CONFIG_WDT_LSMIPS=y +CONFIG_REGEX=y +# CONFIG_GZIP is not set 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..46a94e9748 --- /dev/null +++ b/drivers/clk/lsmips/clk-ls1c300.c @@ -0,0 +1,180 @@ +// 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>
+/* PLL/SDRAM Frequency Configuration Register */ +#define START_FREQ 0 +#define CLK_DIV_PARAM 4
+/* 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},
+};
+ulong ls1c300_pll_get_rate(struct clk *clk) +{
- unsigned int mult;
- long long parent_rate;
- void *base;
- unsigned int val;
- parent_rate = clk_get_parent_rate(clk);
- base = (void *)clk->data;
- val = readl(base + START_FREQ);
- mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val);
For those following along at home:
c.f. https://lore.kernel.org/all/20220419051114.1569291-1-seanga2@gmail.com/
- return (mult * parent_rate) / 4;
+}
+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_probe(struct udevice *dev) +{
- void __iomem *base;
- void __iomem *cpu_throt;
- void __iomem *addr;
- struct clk *cl, clk;
- const char *parent_name;
- int flags;
- int ret;
- base = (void *)dev_remap_addr_index(dev, 0);
- cpu_throt = (void *)dev_remap_addr_index(dev, 1);
- ret = clk_get_by_index(dev, 0, &clk);
- if (ret)
return ret;
- ret = clk_get_rate(&clk);
- parent_name = clk.dev->name;
- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
- cl->data = (unsigned long)base;
- ret = clk_register(cl, "clk_ls1c300_pll", "pll", parent_name);
- 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);
- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
- cl->data = (unsigned long)cpu_throt;
- ret = clk_register(cl, "clk_cpu_throt", "cpu_throt_factor", "cpu_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_APB, cl);
- return 0;
+}
+static ulong cpu_throt_get_rate(struct clk *clk) +{
- void __iomem *cpu_throt;
- long long parent_rate;
- ulong ret;
- parent_rate = clk_get_parent_rate(clk);
- cpu_throt = (void *)clk->data;
- ret = readl(cpu_throt) + 1;
- ret = parent_rate * ret / 16;
- return ret;
+}
+static const struct udevice_id ls1c300_clk_ids[] = {
- { .compatible = "loongson,ls1c300-clk" },
- { }
+};
+static const struct clk_ops clk_cpu_throt_ops = {
- .get_rate = cpu_throt_get_rate,
+};
+static const struct clk_ops clk_ls1c300_pll_ops = {
- .get_rate = ls1c300_pll_get_rate,
+};
+static const struct clk_ops ls1c300_clk_ops = {
- .get_rate = ls1c300_clk_get_rate,
+};
+U_BOOT_DRIVER(clk_ls1c300_cpu_throt) = {
- .name = "clk_cpu_throt",
- .id = UCLASS_CLK,
- .ops = &clk_cpu_throt_ops,
+};
+U_BOOT_DRIVER(clk_ls1c300_pll) = {
- .name = "clk_ls1c300_pll",
- .id = UCLASS_CLK,
- .ops = &clk_ls1c300_pll_ops,
+};
+U_BOOT_DRIVER(ls1c300_clk) = {
- .name = "clk_ls1c300",
- .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 5b614cfa6e..a9af5e5eb6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -168,6 +168,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..65e60ae656 --- /dev/null +++ b/drivers/watchdog/lsmips_wdt.c @@ -0,0 +1,123 @@ +// 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 <clk.h>
+struct lsmips_wdt_priv {
- void __iomem *base;
+#define WDT_EN 0 +#define WDT_TIMER 4 +#define WDT_SET 8
- 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, priv->base + WDT_TIMER);
- writel(1, priv->base + WDT_SET);
- return 0;
+}
+static int lsmips_wdt_stop(struct udevice *dev) +{
- struct lsmips_wdt_priv *priv = dev_get_priv(dev);
- writel(0, priv->base + 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, priv->base + WDT_EN);
- writel(1, priv->base + WDT_TIMER);
- writel(1, priv->base + 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;
- const unsigned int MSEC_PER_SEC = 1000;
- timeout = U32_MAX / (priv->clock / MSEC_PER_SEC);
- if (timeout < timeout_ms)
timeout = U32_MAX;
- else
timeout = timeout_ms * (priv->clock / MSEC_PER_SEC);
- debug("WDT: reload = %08x\n", timeout);
- writel(1, priv->base + WDT_EN);
- writel(timeout, priv->base + WDT_TIMER);
- writel(1, priv->base + 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 < 45000000 || priv->clock > 133000000)
return -EAGAIN;
Please don't do this.
- debug("WDT: clock = %ld\n", priv->clock);
- writel(0, priv->base + 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..c460b4564b --- /dev/null +++ b/include/configs/ls1c300.h @@ -0,0 +1,59 @@ +/* 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_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 1 +#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..66798f40c7 --- /dev/null +++ b/include/dt-bindings/clock/ls1c300-clk.h @@ -0,0 +1,18 @@ +/* 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__
+#define CLK_XTAL 0 +#define CLK_PLL 1 +#define CLK_CPU 2 +#define CLK_APB 3 +#define CLK_CAMERA 4 +#define CLK_PIX 5 +#define CLK_AXIMUX 6 +#define CLK_CPU_THROT 7
+#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */
--Sean

sorry for the late response but I was on vacation ;)
Am Donnerstag, dem 21.04.2022 um 20:31 -0400 schrieb Sean Anderson:
On 4/18/22 4:45 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 Technical 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
Changelog for v3: - change cpu clock id from CLK_CPU to CLK_CPU_THROT - migrate all APB dev's clock id to CLK_APB - remove uarts' <reg-shift> property to use default value <0> - move /clocks/acc node to /soc/acc - call clk_request() before use a clk - make get_tbclk() return 1/2 clock of cpu - disable debug_uart by default - add ops for cpu_throt_factor clk - declare MSEC_PER_SEC for converting between sec and msec - return a error code when the wdt clock is out of range - minor format and codingstyle fixes - rebase to [9859465bfe838bc8264d45e1a1bed847bba74bad]
Changelog for v2:
dtsi: add status disabled for uart0 ~ uart11 remove bootargs from chosen make serial0 alias for uart2 oscillator remove @0 unit-address change uart2 address to kuseg
cleanup Kconfig and update defconfig
- make these options configurable, disabled by default: CMD_DM DM_ETH DM_GPIO DM_SPI DM_SPI_FLASH DM_RESET PINCONF PINCTRL PINMUX RESET_LSMIPS
- make these options configurable, enabled by default: CLK DISPLAY_CPUINFO SYSRESET ROM_EXCEPTION_VECTORS
- disabled: CONFIG_ENV_IS_IN_SPI_FLASH
- fix codingstyle drivers/watchdog/lsmips-wdt.c
- priv->base + offset
- add comment for default clock value
- remove address base definition header
- remove arch/mips/mach-lsmips/ls1c300/ls1c300.h
- clean up files uses this header
- spl and debug uart
- add comment for spl & debug uart pinmuxing
- cleanup unused registers base header
- dtsi
- add "loongson,ls1c300-uart" to all uart node
- board dts
- add memory node to board dts, start at 0x80000000, size 64MB
- Kconfig
- make ROM_EXCEPTION_VECTORS user configureable
- enable ROM_EXCEPTION_VECTORS in defconfig
- seperate sdram_init to sdram_init.S
- add macro helpers to do sdram, pll lowlevel init
- dtsi
- move clock nodes to /clocks/xxx
- define CONFIG_SKIP_LOWLEVEL_INIT to 1
- remove option PINCTRL_LS1C300 from Kconfig
- dram_init, use get_ram_size() to detect ram size.
- clk driver
- create custom clock ops for PLL
- remove debug code
- rebase to 59bffec43a657598b194b9eb30dc01eec06078c7
- remove CONFIG_SYS_MONITOR_BASE from include/configs/
commit e4d741f8abc4a92426d3a826f99390c3abe02d61 Author: Tom Rini trini@konsulko.com Date: Thu Mar 24 17:18:05 2022 -0400
Convert CONFIG_SYS_MONITOR_BASE to Kconfig
MAINTAINERS | 13 ++ arch/mips/Kconfig | 11 ++ arch/mips/Makefile | 1 + arch/mips/dts/Makefile | 1 + arch/mips/dts/loongson32-ls1c300b.dtsi | 141 ++++++++++++++ arch/mips/dts/ls1c300-eval.dts | 31 +++ arch/mips/mach-lsmips/Kconfig | 76 ++++++++ arch/mips/mach-lsmips/Makefile | 6 + arch/mips/mach-lsmips/cpu.c | 19 ++ arch/mips/mach-lsmips/include/mach/serial.h | 16 ++ arch/mips/mach-lsmips/ls1c300/Makefile | 7 + arch/mips/mach-lsmips/ls1c300/gpio.c | 66 +++++++ arch/mips/mach-lsmips/ls1c300/init.c | 63 ++++++ arch/mips/mach-lsmips/ls1c300/lowlevel_init.S | 136 +++++++++++++ arch/mips/mach-lsmips/ls1c300/sdram.S | 94 +++++++++ arch/mips/mach-lsmips/ls1c300/serial.c | 109 +++++++++++ arch/mips/mach-lsmips/spl.c | 46 +++++ 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 | 49 +++++ drivers/clk/Makefile | 1 + drivers/clk/lsmips/Makefile | 3 + drivers/clk/lsmips/clk-ls1c300.c | 180 ++++++++++++++++++ drivers/watchdog/Kconfig | 8 + drivers/watchdog/Makefile | 1 + drivers/watchdog/lsmips_wdt.c | 123 ++++++++++++ include/configs/ls1c300.h | 59 ++++++ include/dt-bindings/clock/ls1c300-clk.h | 18 ++ 30 files changed, 1320 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/sdram.S 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
Once again, please split this up into multiple patches. This makes the series much easier to review.
Sean is right. Please create separate patches for the SoC, the drivers and finally for adding the board. For each driver patch also CC the according driver subsystem maintainers.
diff --git a/MAINTAINERS b/MAINTAINERS index 34446127d4..e1714fb1fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -967,6 +967,19 @@ F: drivers/net/cortina_ni.c F: drivers/net/cortina_ni.h F: drivers/net/phy/ca_phy.c
+MIPS LOONGSON LS1C300 +M: Du Huanpeng dhu@hodcarrier.org +S: Maintained +F: arch/mips/dts/loongson32-ls1c300b.dtsi +F: arch/mips/dts/ls1c300-eval.dts +F: arch/mips/mach-lsmips/ +F: board/loongson/ls1c300-eval/ +F: configs/ls1c300_defconfig +F: drivers/clk/lsmips/ +F: drivers/watchdog/lsmips_wdt.c +F: include/configs/ls1c300.h +F: include/dt-bindings/clock/ls1c300-clk.h
- MIPS MEDIATEK M: Weijie Gao weijie.gao@mediatek.com R: GSS_MTK_Uboot_upstream <
GSS_MTK_Uboot_upstream@mediatek.com> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 06cae68ee5..461bb2a99b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -93,6 +93,16 @@ config ARCH_MTMIPS select SUPPORTS_LITTLE_ENDIAN select SUPPORT_SPL
+config ARCH_LSMIPS
- bool "Support Loongson MIPS platforms"
- select DM
- select DM_SERIAL
- select OF_CONTROL
- select SUPPORTS_CPU_MIPS32_R1
- select SUPPORTS_CPU_MIPS32_R2
- select SUPPORTS_LITTLE_ENDIAN
- select SUPPORT_SPL
- config ARCH_JZ47XX bool "Support Ingenic JZ47xx" select SUPPORT_SPL
@@ -175,6 +185,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..b13bdf189d --- /dev/null +++ b/arch/mips/dts/loongson32-ls1c300b.dtsi @@ -0,0 +1,141 @@ +// 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_THROT>;
};
- };
- clocks {
#address-cells = <1>;
#size-cells = <1>;
u-boot,dm-pre-reloc;
xtal: oscillator {
compatible = "fixed-clock";
clock-frequency = <24000000>;
#clock-cells = <0>;
};
- };
- soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
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 = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe40000 0x100>;
status = "disabled";
};
uart1: serial@1fe44000 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe44000 0x100>;
status = "disabled";
};
uart2: serial@1fe48000 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe48000 0x100>;
status = "disabled";
};
uart3: serial@1fe4c000 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c000 0x100>;
status = "disabled";
};
uart4: serial@1fe4c400 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c400 0x100>;
status = "disabled";
};
uart5: serial@1fe4c500 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c500 0x100>;
status = "disabled";
};
uart6: serial@1fe4c600 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c600 0x100>;
status = "disabled";
};
uart7: serial@1fe4c700 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c700 0x100>;
status = "disabled";
};
uart8: serial@1fe4c800 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c800 0x100>;
status = "disabled";
};
uart9: serial@1fe4c900 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4c900 0x100>;
status = "disabled";
};
uart10: serial@1fe4ca00 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4ca00 0x100>;
status = "disabled";
};
uart11: serial@1fe4cb00 {
compatible = "loongson,ls1c300-uart",
"ns16550a";
clocks = <&acc CLK_APB>;
reg = <0x1fe4cb00 0x100>;
status = "disabled";
};
wdt: watchdog@1fe5c060 {
compatible = "loongson,ls1c300-wdt";
clocks = <&acc CLK_APB>;
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..eaf65b2d96 --- /dev/null +++ b/arch/mips/dts/ls1c300-eval.dts @@ -0,0 +1,31 @@ +// 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 {
serial0 = &uart2;
- };
- memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x4000000>;
- };
- chosen {
stdout-path = "serial0:115200n8";
- };
+};
+&uart2 {
- status = "okay";
+};
diff --git a/arch/mips/mach-lsmips/Kconfig b/arch/mips/mach- lsmips/Kconfig new file mode 100644 index 0000000000..2092e6ef35 --- /dev/null +++ b/arch/mips/mach-lsmips/Kconfig @@ -0,0 +1,76 @@ +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
- default "u-boot.bin" if !SPL
+choice
- prompt "Loongson MIPS SoC select"
+config SOC_LS1C300
- bool "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
I just want to state for the record here that the size constraint on this processor is 1MiB XIP, so there is no need to use SPL AFAICT. If you insist on SPL you can enable SPL_DM. That way you can use pinctrl drivers.
I guess this is inspired from Mediatek MIPS baords, where a small SPL + LZMA compressed U-Boot decreases the boot time. But I agree with pinctrl and SPL_DM.
+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
- 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..4205d8ef83 --- /dev/null +++ b/arch/mips/mach-lsmips/cpu.c @@ -0,0 +1,19 @@ +// 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) +{
- gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
SZ_256M);
- 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..17b9d6fb9c --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0
+obj-y += lowlevel_init.o +obj-y += sdram.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..2195738b2b --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/gpio.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2022 Du Huanpeng dhu@hodcarrier.org
- */
+#include <linux/errno.h> +#include <asm/bitops.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
+/*
- pinmux for debug uart and spl only, for others, please
- use a pinctrl driver and device-tree for pin muxing.
- @gpio: gpio number
- @func: alternate function 1 to 5, 0 for GPIO.
- */
+int gpio_set_alternate(int gpio, int func) +{
- volatile void __iomem *addr;
- int i;
- if (gpio < 0 || gpio > 104)
return -ENODEV;
- if (func < 0 || func > 5)
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;
+}
So this can e.g. be in a pinctrl 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..d515bd2f86 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/init.c @@ -0,0 +1,63 @@ +// 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>
+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);
nit: no blank line here
- if (ret) {
printf("error: clock driver not found.\n");
return 0;
- }
- clk.dev = udev;
- ret = clk_request(udev, &clk);
- if (ret < 0)
return ret;
- clk.id = CLK_XTAL;
- xtal = clk_get_rate(&clk);
- clk.id = CLK_CPU_THROT;
- gd->cpu_clk = clk_get_rate(&clk);
- clk.id = CLK_APB;
- gd->mem_clk = clk_get_rate(&clk);
Again, all these clocks must be requested first.
- 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 / 2;
+} 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..a8d1359cf5 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/lowlevel_init.S @@ -0,0 +1,136 @@ +/* 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 control register */ +#define NAND_BASE 0xbfe70000 +#define START_FREQ 0x8030 +#define CLK_DIV_PARAM 0x8034 +#define CPU_THROT 0xc010
+/* START_FREQ */ +#define PLL_VALID 31 +#define Reserved_24 24 +#define FRAC_N 16 +#define M_PLL 8 +#define Reserved_4 4 +#define RST_TIME 2 +#define SDRAM_DIV 0
- #define SDRAM_DIV2 0
- #define SDRAM_DIV4 1
- #define SDRAM_DIV3 2
+/* CLK_DIV_PARAM */ +#define PIX_DIV 24 +#define CAM_DIV 16 +#define CPU_DIV 8 +#define PIX_DIV_VALID 5 +#define PIX_SEL 4 +#define CAM_DIV_VALID 3 +#define CAM_SEL 2 +#define CPU_DIV_VALID 1 +#define CPU_SEL 0
+/* Document:
- Freq_PLL = XIN *(M_PLL + FRAC_N)/4
- */
+#define XIN 24000000 +#define PLL_VALID_1 (1<<PLL_VALID) +#define PREP_M_PLL(Freq_PLL) (((Freq_PLL * 4) / XIN) << M_PLL) +#define PREP_SDRAM_DIV(div) (div<<SDRAM_DIV) +#define PREP_CPU_DIV(div1) ((0x80|div1)<<CPU_DIV | (div1&&div1)<<CPU_DIV_VALID) +#define PREP_PIX_DIV(div2) (div2<<PIX_DIV) +#define PREP_CAM_DIV(div3) (div3<<CAM_DIV)
+/* PLL @264MHz, CPU @132MHz, SDRAM @66MHz */ +#define CFG_START_FREQ (PLL_VALID_1 | PREP_M_PLL(264000000) | SDRAM_DIV2) +#define CFG_CLK_DIV_PARAM (PREP_CPU_DIV(2) | PREP_PIX_DIV(0x24) | PREP_CAM_DIV(0x24)) +#define CFG_CPU_THROT 15
+/* SPI0 control register */ +#define SPI0_BASE 0xbfe80000 +#define SPCR 0 +#define SPSR 1 +#define TxFIFO 2 +#define RxFIFO 2 +#define SPER 3 +#define SFC_PARAM 4
- #define CLK_DIV 4
- #define DUAL_IO 3
- #define FAST_READ 2
- #define BURST_EN 1
- #define MEMORY_EN 0
+#define SFC_SOFTCS 5 +#define SFC_TIMING 6
- #define T_FAST 2
- #define T_CSH 0
- .set noreorder
as a general rule for MIPS assembly: - don't use noreorder if not really required to let the assembler optimize the instructions in the branch delay slots. For your lowlevel_init code I don't see any reason for noreorder - if you use noreorder, indent all instructins in the delay slot by 1 space to make the code more readable. If there are no useful instructions, always add a nop
+LEAF(ls1c300_pll_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
- li t0, NAND_BASE
- li t1, CFG_START_FREQ
- li t2, CFG_CLK_DIV_PARAM
- li t3, CFG_CPU_THROT
- sw t3, CPU_THROT (t0)
- sw t2, CLK_DIV_PARAM (t0)
- sw t1, START_FREQ (t0)
nop
superfluous nop
- ori t2, 1<<CPU_SEL
- sw t2, CLK_DIV_PARAM (t0)
+#endif
- li v0, 264000000
- jr ra
- nop
the "li v0, 264000000" could be put in the delay slot or just don't use noreorder to let the assembler do that
+END(ls1c300_pll_init)
+LEAF(ls1c300_spi_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
- li t0, SPI0_BASE
- li t1, (1<<MEMORY_EN) | (1<<BURST_EN) | (1<<FAST_READ) |
(1<<DUAL_IO)
- sb t1, SFC_PARAM (t0)
- li t2, (1<<T_FAST) | (1<<T_CSH)
- sb t2, SFC_TIMING (t0)
+#endif
- jr ra
nop
+END(ls1c300_spi_init)
+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
the "move ra, s0" could be put in the delay slot
+END(lowlevel_init) diff --git a/arch/mips/mach-lsmips/ls1c300/sdram.S b/arch/mips/mach-lsmips/ls1c300/sdram.S new file mode 100644 index 0000000000..95d21f0093 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/sdram.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/*
- 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>
+/* sdram control 64 bit register */ +#define SD_CONFIG 0xbfd00000 +#define SD_CONFIGHI 0x414 +#define SD_CONFIGLO 0x410
+#define CONFIG_VALID 41 +#define HANG_UP 40 +#define DEF_SEL 39 +#define TWR 37 +#define TREF 25 +#define TRAS 21 +#define TRFC 17 +#define TRP 14 +#define TCL 11 +#define TRCD 8
+#define SD_BIT 6
- #define SD_8BIT (0<<SD_BIT)
- #define SD_16BIT (1<<SD_BIT)
- #define SD_32BIT (2<<SD_BIT)
+#define SD_CSIZE 3
- #define SD_CSIZE_512 (0<<SD_CSIZE)
- #define SD_CSIZE_1K (1<<SD_CSIZE)
- #define SD_CSIZE_2K (2<<SD_CSIZE)
- #define SD_CSIZE_4K (3<<SD_CSIZE)
- #define SD_CSIZE_256 (7<<SD_CSIZE)
+#define SD_RSIZE 0
- #define SD_RSIZE_2K (0<<SD_RSIZE)
- #define SD_RSIZE_4K (1<<SD_RSIZE)
- #define SD_RSIZE_8K (2<<SD_RSIZE)
- #define SD_RSIZE_16K (3<<SD_RSIZE)
+#define SD_CFG_1(tWR, tREF, tRAS, tRFC, tRP, tCL, tRCD) \
- ((tWR<<TWR)|(tREF<<TREF)|(tRAS<<TRAS)|(tRFC<<TRFC)|(tRP<<TRP)|(
tCL<<TCL)|(tRCD<<TRCD)) +#define CFG_SD_0(b, c, r) \
- ((b<<SD_BIT)|(c<<SD_CSIZE)|(r<<SD_RSIZE))
+/*
- recommended values by ls1c300 user manual,
- tweat to fit your board.
nit: tweak
- */
+#define SD_CONFIG_133MHz SD_CFG_1(2, 0x818, 6, 8, 3, 3, 3) +#define SD_CONFIG_100MHz SD_CFG_1(2, 0x620, 5, 6, 2, 3, 2) +#define SD_CONFIG_75MHz SD_CFG_1(1, 0x494, 4, 5, 2, 2, 2) +#define SD_CONFIG_33MHz SD_CFG_1(1, 0x204, 2, 2, 1, 2,
+#define SD_CONFIG_66MHz SD_CFG_1(1, 0x401, 4, 4, 2, 2, 2)
+#define SD_CONFIG64 (SD_CONFIG_66MHz | SD_16BIT | SD_CSIZE_1K | SD_RSIZE_8K) +#define CFG_SDCONFIGHI (SD_CONFIG64 /(1<<32)) +#define CFG_SDCONFIGLO (SD_CONFIG64 %(1<<32))
- .set noreorder
+/*
- Loongson ls1c300 SoC do not have onchip sram for initial stack,
- initialize the external sdram on reset as early as possiable.
- */
+LEAF(ls1c300_sdram_init) +#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
- li t0, SD_CONFIG
- li t1, CFG_SDCONFIGLO
- li t2, CFG_SDCONFIGHI
- sw t1, SD_CONFIGLO (t0)
- sw t2, SD_CONFIGHI (t0)
- nop
- sw t1, SD_CONFIGLO (t0)
- sw t2, SD_CONFIGHI (t0)
- nop
superfluous nop and why storing twice?
- ori t2, 1<<(CONFIG_VALID-32)
- sw t1, SD_CONFIGLO (t0)
- sw t2, SD_CONFIGHI (t0)
+#endif
- li v0, SZ_64M
- jr ra
nop
+END(ls1c300_sdram_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..93fd653385 --- /dev/null +++ b/arch/mips/mach-lsmips/ls1c300/serial.c @@ -0,0 +1,109 @@ +// 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 <mach/serial.h> +#include <linux/kernel.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) +{ +#if defined(CONFIG_SPL_SERIAL)
- int pin_rx, pin_tx;
- int afunc;
- if (CONFIG_CONS_PIN < ARRAY_SIZE(con)) {
pin_rx = con[CONFIG_CONS_PIN].rx;
pin_tx = con[CONFIG_CONS_PIN].tx;
afunc = con[CONFIG_CONS_PIN].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;
+}
This can also be pinctrl.
diff --git a/arch/mips/mach-lsmips/spl.c b/arch/mips/mach- lsmips/spl.c new file mode 100644 index 0000000000..21c49197ae --- /dev/null +++ b/arch/mips/mach-lsmips/spl.c @@ -0,0 +1,46 @@ +// 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();
+#if defined(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 Huanpengdhu@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..6809d66515 --- /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>
+#if defined(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..3e630a0c0e --- /dev/null +++ b/configs/ls1c300_defconfig @@ -0,0 +1,49 @@ +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_DEFAULT_DEVICE_TREE="ls1c300-eval" +CONFIG_SPL_SERIAL=y +CONFIG_SPL_SIZE_LIMIT=0x100000 +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x80010000 +CONFIG_ARCH_LSMIPS=y +CONFIG_SPL_PAYLOAD="u-boot.img" +CONFIG_ROM_EXCEPTION_VECTORS=y +# 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_FIT=y +# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set +CONFIG_LOGLEVEL=9 +CONFIG_DISPLAY_CPUINFO=y +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_LOADS is not set +# CONFIG_PARTITIONS is not set +CONFIG_OF_EMBED=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +# CONFIG_NET is not set +CONFIG_CLK=y +CONFIG_SPL_CLK_CCF=y +# CONFIG_INPUT is not set +# CONFIG_POWER is not set +CONFIG_CONS_INDEX=2 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_WATCHDOG=y +CONFIG_SYSRESET_WATCHDOG_AUTO=y +CONFIG_WATCHDOG_TIMEOUT_MSECS=3000 +CONFIG_WDT_LSMIPS=y +CONFIG_REGEX=y +# CONFIG_GZIP is not set 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..46a94e9748 --- /dev/null +++ b/drivers/clk/lsmips/clk-ls1c300.c @@ -0,0 +1,180 @@ +// 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>
+/* PLL/SDRAM Frequency Configuration Register */ +#define START_FREQ 0 +#define CLK_DIV_PARAM 4
+/* 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},
+};
+ulong ls1c300_pll_get_rate(struct clk *clk) +{
- unsigned int mult;
- long long parent_rate;
- void *base;
- unsigned int val;
- parent_rate = clk_get_parent_rate(clk);
- base = (void *)clk->data;
- val = readl(base + START_FREQ);
- mult = FIELD_GET(FRAC_N, val) + FIELD_GET(M_PLL, val);
For those following along at home:
c.f. https://lore.kernel.org/all/20220419051114.1569291-1-seanga2@gmail.com/
- return (mult * parent_rate) / 4;
+}
+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_probe(struct udevice *dev) +{
- void __iomem *base;
- void __iomem *cpu_throt;
- void __iomem *addr;
- struct clk *cl, clk;
- const char *parent_name;
- int flags;
- int ret;
- base = (void *)dev_remap_addr_index(dev, 0);
- cpu_throt = (void *)dev_remap_addr_index(dev, 1);
- ret = clk_get_by_index(dev, 0, &clk);
- if (ret)
return ret;
- ret = clk_get_rate(&clk);
- parent_name = clk.dev->name;
- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
- cl->data = (unsigned long)base;
- ret = clk_register(cl, "clk_ls1c300_pll", "pll", parent_name);
- 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);
- cl = kzalloc(sizeof(*cl), GFP_KERNEL);
- cl->data = (unsigned long)cpu_throt;
- ret = clk_register(cl, "clk_cpu_throt", "cpu_throt_factor",
"cpu_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_APB, cl);
- return 0;
+}
+static ulong cpu_throt_get_rate(struct clk *clk) +{
- void __iomem *cpu_throt;
- long long parent_rate;
- ulong ret;
- parent_rate = clk_get_parent_rate(clk);
- cpu_throt = (void *)clk->data;
- ret = readl(cpu_throt) + 1;
- ret = parent_rate * ret / 16;
- return ret;
+}
+static const struct udevice_id ls1c300_clk_ids[] = {
- { .compatible = "loongson,ls1c300-clk" },
- { }
+};
+static const struct clk_ops clk_cpu_throt_ops = {
- .get_rate = cpu_throt_get_rate,
+};
+static const struct clk_ops clk_ls1c300_pll_ops = {
- .get_rate = ls1c300_pll_get_rate,
+};
+static const struct clk_ops ls1c300_clk_ops = {
- .get_rate = ls1c300_clk_get_rate,
+};
+U_BOOT_DRIVER(clk_ls1c300_cpu_throt) = {
- .name = "clk_cpu_throt",
- .id = UCLASS_CLK,
- .ops = &clk_cpu_throt_ops,
+};
+U_BOOT_DRIVER(clk_ls1c300_pll) = {
- .name = "clk_ls1c300_pll",
- .id = UCLASS_CLK,
- .ops = &clk_ls1c300_pll_ops,
+};
+U_BOOT_DRIVER(ls1c300_clk) = {
- .name = "clk_ls1c300",
- .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 5b614cfa6e..a9af5e5eb6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -168,6 +168,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..65e60ae656 --- /dev/null +++ b/drivers/watchdog/lsmips_wdt.c @@ -0,0 +1,123 @@ +// 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 <clk.h>
+struct lsmips_wdt_priv {
- void __iomem *base;
+#define WDT_EN 0 +#define WDT_TIMER 4 +#define WDT_SET 8
- 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, priv->base + WDT_TIMER);
- writel(1, priv->base + WDT_SET);
- return 0;
+}
+static int lsmips_wdt_stop(struct udevice *dev) +{
- struct lsmips_wdt_priv *priv = dev_get_priv(dev);
- writel(0, priv->base + 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, priv->base + WDT_EN);
- writel(1, priv->base + WDT_TIMER);
- writel(1, priv->base + 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;
- const unsigned int MSEC_PER_SEC = 1000;
- timeout = U32_MAX / (priv->clock / MSEC_PER_SEC);
- if (timeout < timeout_ms)
timeout = U32_MAX;
- else
timeout = timeout_ms * (priv->clock / MSEC_PER_SEC);
- debug("WDT: reload = %08x\n", timeout);
- writel(1, priv->base + WDT_EN);
- writel(timeout, priv->base + WDT_TIMER);
- writel(1, priv->base + 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 < 45000000 || priv->clock > 133000000)
return -EAGAIN;
Please don't do this.
- debug("WDT: clock = %ld\n", priv->clock);
- writel(0, priv->base + 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..c460b4564b --- /dev/null +++ b/include/configs/ls1c300.h @@ -0,0 +1,59 @@ +/* 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_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 1 +#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..66798f40c7 --- /dev/null +++ b/include/dt-bindings/clock/ls1c300-clk.h @@ -0,0 +1,18 @@ +/* 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__
+#define CLK_XTAL 0 +#define CLK_PLL 1 +#define CLK_CPU 2 +#define CLK_APB 3 +#define CLK_CAMERA 4 +#define CLK_PIX 5 +#define CLK_AXIMUX 6 +#define CLK_CPU_THROT 7
+#endif /* __DT_BINDINGS_LS1C300_CLK_H__ */
--Sean
participants (3)
-
Daniel Schwierzeck
-
Du Huanpeng
-
Sean Anderson