diff options
Diffstat (limited to 'package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch')
-rw-r--r-- | package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch | 2979 |
1 files changed, 2979 insertions, 0 deletions
diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..2c4c57e2d2 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,2979 @@ +From e0c82f36ad5180d9582d353407ff1bf34a2734bb Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:21 +0800 +Subject: [PATCH 05/25] mips: mtmips: add support for MediaTek MT7621 SoC + +This patch adds support for MediaTek MT7621 SoC. +All files are dedicated for u-boot. + +The default build target is u-boot-mt7621.bin. + +The specification of this chip: +https://www.mediatek.com/products/homenetworking/mt7621 + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + arch/mips/dts/mt7621-u-boot.dtsi | 111 ++++++ + arch/mips/dts/mt7621.dtsi | 349 +++++++++++++++++++ + arch/mips/mach-mtmips/Kconfig | 49 ++- + arch/mips/mach-mtmips/Makefile | 4 + + arch/mips/mach-mtmips/cpu.c | 2 +- + arch/mips/mach-mtmips/mt7621/Kconfig | 95 +++++ + arch/mips/mach-mtmips/mt7621/Makefile | 14 + + arch/mips/mach-mtmips/mt7621/init.c | 246 +++++++++++++ + arch/mips/mach-mtmips/mt7621/mt7621.h | 229 ++++++++++++ + arch/mips/mach-mtmips/mt7621/serial.c | 23 ++ + arch/mips/mach-mtmips/mt7621/spl/Makefile | 9 + + arch/mips/mach-mtmips/mt7621/spl/cps.c | 153 ++++++++ + arch/mips/mach-mtmips/mt7621/spl/dram.c | 153 ++++++++ + arch/mips/mach-mtmips/mt7621/spl/dram.h | 39 +++ + arch/mips/mach-mtmips/mt7621/spl/launch.c | 100 ++++++ + arch/mips/mach-mtmips/mt7621/spl/launch.h | 52 +++ + arch/mips/mach-mtmips/mt7621/spl/launch_ll.S | 339 ++++++++++++++++++ + arch/mips/mach-mtmips/mt7621/spl/serial.c | 24 ++ + arch/mips/mach-mtmips/mt7621/spl/spl.c | 95 +++++ + arch/mips/mach-mtmips/mt7621/spl/start.S | 226 ++++++++++++ + arch/mips/mach-mtmips/mt7621/sram_init.S | 22 ++ + arch/mips/mach-mtmips/mt7621/tpl/Makefile | 4 + + arch/mips/mach-mtmips/mt7621/tpl/start.S | 161 +++++++++ + arch/mips/mach-mtmips/mt7621/tpl/tpl.c | 144 ++++++++ + include/configs/mt7621.h | 65 ++++ + 25 files changed, 2702 insertions(+), 6 deletions(-) + create mode 100644 arch/mips/dts/mt7621-u-boot.dtsi + create mode 100644 arch/mips/dts/mt7621.dtsi + create mode 100644 arch/mips/mach-mtmips/mt7621/Kconfig + create mode 100644 arch/mips/mach-mtmips/mt7621/Makefile + create mode 100644 arch/mips/mach-mtmips/mt7621/init.c + create mode 100644 arch/mips/mach-mtmips/mt7621/mt7621.h + create mode 100644 arch/mips/mach-mtmips/mt7621/serial.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/Makefile + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/cps.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/dram.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/dram.h + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/launch.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/launch.h + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/launch_ll.S + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/serial.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/spl.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/start.S + create mode 100644 arch/mips/mach-mtmips/mt7621/sram_init.S + create mode 100644 arch/mips/mach-mtmips/mt7621/tpl/Makefile + create mode 100644 arch/mips/mach-mtmips/mt7621/tpl/start.S + create mode 100644 arch/mips/mach-mtmips/mt7621/tpl/tpl.c + create mode 100644 include/configs/mt7621.h + +diff --git a/arch/mips/dts/mt7621-u-boot.dtsi b/arch/mips/dts/mt7621-u-boot.dtsi +new file mode 100644 +index 0000000000..c5a8aa357f +--- /dev/null ++++ b/arch/mips/dts/mt7621-u-boot.dtsi +@@ -0,0 +1,111 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <linux/stringify.h> ++ ++/ { ++ binman: binman { ++ multiple-images; ++ }; ++}; ++ ++&sysc { ++ u-boot,dm-pre-reloc; ++}; ++ ++&reboot { ++ u-boot,dm-pre-reloc; ++}; ++ ++&clkctrl { ++ u-boot,dm-pre-reloc; ++}; ++ ++&rstctrl { ++ u-boot,dm-pre-reloc; ++}; ++ ++&pinctrl { ++ u-boot,dm-pre-reloc; ++}; ++ ++&uart0 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&uart1 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&uart2 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&binman { ++ u-boot-spl-ddr { ++ align = <4>; ++ align-size = <4>; ++ filename = "u-boot-spl-ddr.bin"; ++ pad-byte = <0xff>; ++ ++ u-boot-spl { ++ align-end = <4>; ++ filename = "u-boot-spl.bin"; ++ }; ++ ++ stage_bin { ++ filename = "mt7621_stage_sram.bin"; ++ type = "blob-ext"; ++ }; ++ }; ++ ++ spl-img { ++ filename = "u-boot-spl-ddr.img"; ++ ++ mkimage { ++#ifdef CONFIG_MT7621_BOOT_FROM_NAND ++ args = "-T", "mtk_image", "-n", "mt7621=1", ++ "-a", __stringify(CONFIG_SPL_TEXT_BASE), ++ "-e", __stringify(CONFIG_SPL_TEXT_BASE); ++#else ++ args = "-A", "mips", "-T", "standalone", "-O", "u-boot", ++ "-C", "none", "-n", "MT7621 U-Boot SPL", ++ "-a", __stringify(CONFIG_SPL_TEXT_BASE), ++ "-e", __stringify(CONFIG_SPL_TEXT_BASE); ++#endif ++ ++ blob { ++ filename = "u-boot-spl-ddr.bin"; ++ }; ++ }; ++ }; ++ ++ mt7621-uboot { ++ filename = "u-boot-mt7621.bin"; ++ pad-byte = <0xff>; ++ ++#ifndef CONFIG_MT7621_BOOT_FROM_NAND ++ u-boot-tpl { ++ align-end = <4>; ++ filename = "u-boot-tpl.bin"; ++ }; ++#endif ++ ++ spl { ++#ifdef CONFIG_MT7621_BOOT_FROM_NAND ++ align-end = <0x1000>; ++#endif ++ filename = "u-boot-spl-ddr.img"; ++ type = "blob"; ++ }; ++ ++ u-boot { ++ filename = "u-boot-lzma.img"; ++ type = "blob"; ++ }; ++ }; ++}; +diff --git a/arch/mips/dts/mt7621.dtsi b/arch/mips/dts/mt7621.dtsi +new file mode 100644 +index 0000000000..c32b6095e9 +--- /dev/null ++++ b/arch/mips/dts/mt7621.dtsi +@@ -0,0 +1,349 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <dt-bindings/clock/mt7621-clk.h> ++#include <dt-bindings/reset/mt7621-reset.h> ++#include <dt-bindings/phy/phy.h> ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "mediatek,mt7621-soc"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "mips,mips1004Kc"; ++ reg = <0>; ++ }; ++ ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "mips,mips1004Kc"; ++ reg = <1>; ++ }; ++ }; ++ ++ clk48m: clk48m { ++ compatible = "fixed-clock"; ++ ++ clock-frequency = <48000000>; ++ ++ #clock-cells = <0>; ++ }; ++ ++ clk50m: clk50m { ++ compatible = "fixed-clock"; ++ ++ clock-frequency = <50000000>; ++ ++ #clock-cells = <0>; ++ }; ++ ++ sysc: sysctrl@1e000000 { ++ compatible = "mediatek,mt7621-sysc", "syscon"; ++ reg = <0x1e000000 0x100>; ++ ++ clkctrl: clock-controller@1e000030 { ++ compatible = "mediatek,mt7621-clk"; ++ mediatek,memc = <&memc>; ++ ++ #clock-cells = <1>; ++ }; ++ }; ++ ++ rstctrl: reset-controller@1e000034 { ++ compatible = "mediatek,mtmips-reset"; ++ reg = <0x1e000034 0x4>; ++ #reset-cells = <1>; ++ }; ++ ++ reboot: resetctl-reboot { ++ compatible = "resetctl-reboot"; ++ ++ resets = <&rstctrl RST_SYS>; ++ reset-names = "sysreset"; ++ }; ++ ++ memc: memctrl@1e005000 { ++ compatible = "mediatek,mt7621-memc", "syscon"; ++ reg = <0x1e005000 0x1000>; ++ }; ++ ++ pinctrl: pinctrl@1e000060 { ++ compatible = "mediatek,mt7621-pinctrl"; ++ reg = <0x1e000048 0x30>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&state_default>; ++ ++ state_default: pin_state { ++ }; ++ ++ uart1_pins: uart1_pins { ++ groups = "uart1"; ++ function = "uart"; ++ }; ++ ++ uart2_pins: uart2_pins { ++ groups = "uart2"; ++ function = "uart"; ++ }; ++ ++ uart3_pins: uart3_pins { ++ groups = "uart3"; ++ function = "uart"; ++ }; ++ ++ sdxc_pins: sdxc_pins { ++ groups = "sdxc"; ++ function = "sdxc"; ++ }; ++ ++ spi_pins: spi_pins { ++ groups = "spi"; ++ function = "spi"; ++ }; ++ ++ eth_pins: eth_pins { ++ mdio_pins { ++ groups = "mdio"; ++ function = "mdio"; ++ }; ++ ++ rgmii1_pins { ++ groups = "rgmii1"; ++ function = "rgmii"; ++ }; ++ ++ esw_pins { ++ groups = "esw int"; ++ function = "esw int"; ++ }; ++ ++ mdio_pconf { ++ groups = "mdio"; ++ drive-strength = <2>; ++ }; ++ }; ++ }; ++ ++ watchdog: watchdog@1e000100 { ++ compatible = "mediatek,mt7621-wdt"; ++ reg = <0x1e000100 0x40>; ++ ++ resets = <&rstctrl RST_TIMER>; ++ reset-names = "wdt"; ++ ++ status = "disabled"; ++ }; ++ ++ gpio: gpio@1e000600 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "mtk,mt7621-gpio"; ++ reg = <0x1e000600 0x100>; ++ ++ resets = <&rstctrl RST_PIO>; ++ reset-names = "pio"; ++ ++ gpio0: bank@0 { ++ reg = <0>; ++ compatible = "mtk,mt7621-gpio-bank"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ gpio1: bank@1 { ++ reg = <1>; ++ compatible = "mtk,mt7621-gpio-bank"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ gpio2: bank@2 { ++ reg = <2>; ++ compatible = "mtk,mt7621-gpio-bank"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++ ++ spi: spi@1e000b00 { ++ compatible = "ralink,mt7621-spi"; ++ reg = <0x1e000b00 0x40>; ++ ++ status = "disabled"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_pins>; ++ ++ resets = <&rstctrl RST_SPI>; ++ reset-names = "spi"; ++ ++ clocks = <&clkctrl MT7621_CLK_SPI>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ uart0: uart1@1e000c00 { ++ compatible = "mediatek,hsuart", "ns16550a"; ++ reg = <0x1e000c00 0x100>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ ++ clocks = <&clkctrl MT7621_CLK_UART1>; ++ ++ resets = <&rstctrl RST_UART1>; ++ ++ reg-shift = <2>; ++ }; ++ ++ uart1: uart2@1e000d00 { ++ compatible = "mediatek,hsuart", "ns16550a"; ++ reg = <0x1e000d00 0x100>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart2_pins>; ++ ++ clocks = <&clkctrl MT7621_CLK_UART2>; ++ ++ resets = <&rstctrl RST_UART2>; ++ ++ reg-shift = <2>; ++ ++ status = "disabled"; ++ }; ++ ++ uart2: uart3@1e000e00 { ++ compatible = "mediatek,hsuart", "ns16550a"; ++ reg = <0x1e000e00 0x100>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins>; ++ ++ clocks = <&clkctrl MT7621_CLK_UART3>; ++ ++ resets = <&rstctrl RST_UART3>; ++ ++ reg-shift = <2>; ++ ++ status = "disabled"; ++ }; ++ ++ eth: eth@1e100000 { ++ compatible = "mediatek,mt7621-eth"; ++ reg = <0x1e100000 0x20000>; ++ mediatek,ethsys = <&sysc>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð_pins>; ++ ++ resets = <&rstctrl RST_FE>, <&rstctrl RST_GMAC>, <&rstctrl RST_MCM>; ++ reset-names = "fe", "gmac", "mcm"; ++ ++ clocks = <&clkctrl MT7621_CLK_GDMA>, ++ <&clkctrl MT7621_CLK_ETH>; ++ clock-names = "gmac", "fe"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mediatek,gmac-id = <0>; ++ phy-mode = "rgmii"; ++ mediatek,switch = "mt7530"; ++ mediatek,mcm; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ mmc: mmc@1e130000 { ++ compatible = "mediatek,mt7621-mmc"; ++ reg = <0x1e130000 0x4000>; ++ ++ status = "disabled"; ++ ++ bus-width = <4>; ++ builtin-cd = <1>; ++ r_smpl = <1>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdxc_pins>; ++ ++ clocks = <&clk50m>, <&clkctrl MT7621_CLK_SHXC>; ++ clock-names = "source", "hclk"; ++ ++ resets = <&rstctrl RST_SDXC>; ++ }; ++ ++ ssusb: usb@1e1c0000 { ++ compatible = "mediatek,mt7621-xhci", "mediatek,mtk-xhci"; ++ reg = <0x1e1c0000 0x1000>, <0x1e1d0700 0x100>; ++ reg-names = "mac", "ippc"; ++ ++ clocks = <&clk48m>, <&clk48m>; ++ clock-names = "sys_ck", "ref_ck"; ++ ++ phys = <&u2port0 PHY_TYPE_USB2>, ++ <&u3port0 PHY_TYPE_USB3>, ++ <&u2port1 PHY_TYPE_USB2>; ++ ++ status = "disabled"; ++ }; ++ ++ u3phy: usb-phy@1e1d0000 { ++ compatible = "mediatek,mt7621-u3phy", ++ "mediatek,generic-tphy-v1"; ++ reg = <0x1e1d0000 0x700>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ status = "disabled"; ++ ++ u2port0: usb-phy@1e1d0800 { ++ reg = <0x1e1d0800 0x0100>; ++ #phy-cells = <1>; ++ clocks = <&clk48m>; ++ clock-names = "ref"; ++ }; ++ ++ u3port0: usb-phy@1e1d0900 { ++ reg = <0x1e1d0900 0x0100>; ++ #phy-cells = <1>; ++ }; ++ ++ u2port1: usb-phy@1e1d1000 { ++ reg = <0x1e1d1000 0x0100>; ++ #phy-cells = <1>; ++ clocks = <&clk48m>; ++ clock-names = "ref"; ++ }; ++ }; ++ ++ i2c: i2c@1e000900 { ++ compatible = "i2c-gpio"; ++ ++ status = "disabled"; ++ ++ i2c-gpio,delay-us = <3>; ++ ++ gpios = <&gpio0 3 1>, /* PIN3 as SDA */ ++ <&gpio0 4 1>; /* PIN4 as CLK */ ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++}; +diff --git a/arch/mips/mach-mtmips/Kconfig b/arch/mips/mach-mtmips/Kconfig +index 151b004603..d46be503a2 100644 +--- a/arch/mips/mach-mtmips/Kconfig ++++ b/arch/mips/mach-mtmips/Kconfig +@@ -9,6 +9,7 @@ config SYS_MALLOC_F_LEN + + config SYS_SOC + default "mt7620" if SOC_MT7620 ++ default "mt7621" if SOC_MT7621 + default "mt7628" if SOC_MT7628 + + config SYS_DCACHE_SIZE +@@ -18,25 +19,45 @@ config SYS_DCACHE_LINE_SIZE + default 32 + + config SYS_ICACHE_SIZE +- default 65536 ++ default 65536 if SOC_MT7620 || SOC_MT7628 ++ default 32768 if SOC_MT7621 + + config SYS_ICACHE_LINE_SIZE + default 32 + ++config SYS_SCACHE_LINE_SIZE ++ default 32 if SOC_MT7621 ++ + config SYS_TEXT_BASE +- default 0x9c000000 if !SPL +- default 0x80200000 if SPL ++ default 0x9c000000 if !SPL && !SOC_MT7621 ++ default 0x80200000 if SPL || SOC_MT7621 + + config SPL_TEXT_BASE +- default 0x9c000000 ++ default 0x9c000000 if !SOC_MT7621 ++ default 0x80100000 if SOC_MT7621 ++ ++config SPL_SIZE_LIMIT ++ default 0x30000 if SOC_MT7621 ++ ++config TPL_TEXT_BASE ++ default 0xbfc00000 if SOC_MT7621 ++ ++config TPL_MAX_SIZE ++ default 4096 if SOC_MT7621 + + 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-with-spl.bin" if SPL && !SOC_MT7621 ++ default "u-boot-lzma.img" if SOC_MT7621 + default "u-boot.bin" + ++config MAX_MEM_SIZE ++ int ++ default 256 if SOC_MT7620 || SOC_MT7628 ++ default 512 if SOC_MT7621 ++ + choice + prompt "MediaTek MIPS SoC select" + +@@ -55,6 +76,23 @@ config SOC_MT7620 + help + This supports MediaTek MT7620. + ++config SOC_MT7621 ++ bool "MT7621" ++ select MIPS_CM ++ select MIPS_L2_CACHE ++ select SYS_CACHE_SHIFT_5 ++ select SYS_MIPS_CACHE_INIT_RAM_LOAD ++ select PINCTRL_MT7621 ++ select MTK_SERIAL ++ select REGMAP ++ select SYSCON ++ select BINMAN ++ select SUPPORT_TPL ++ select SPL_LOADER_SUPPORT if SPL ++ select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL ++ help ++ This supports MediaTek MT7621. ++ + config SOC_MT7628 + bool "MT7628" + select SYS_CACHE_SHIFT_5 +@@ -80,6 +118,7 @@ config SOC_MT7628 + endchoice + + source "arch/mips/mach-mtmips/mt7620/Kconfig" ++source "arch/mips/mach-mtmips/mt7621/Kconfig" + source "arch/mips/mach-mtmips/mt7628/Kconfig" + + endmenu +diff --git a/arch/mips/mach-mtmips/Makefile b/arch/mips/mach-mtmips/Makefile +index 4909b47ef2..19f1e07033 100644 +--- a/arch/mips/mach-mtmips/Makefile ++++ b/arch/mips/mach-mtmips/Makefile +@@ -1,9 +1,13 @@ + # SPDX-License-Identifier: GPL-2.0+ + + obj-y += cpu.o ++ ++ifneq ($(CONFIG_SOC_MT7621),y) + obj-y += ddr_init.o + obj-y += ddr_cal.o + obj-$(CONFIG_SPL_BUILD) += spl.o ++endif + + obj-$(CONFIG_SOC_MT7620) += mt7620/ ++obj-$(CONFIG_SOC_MT7621) += mt7621/ + obj-$(CONFIG_SOC_MT7628) += mt7628/ +diff --git a/arch/mips/mach-mtmips/cpu.c b/arch/mips/mach-mtmips/cpu.c +index a4b5cff61d..f1e9022738 100644 +--- a/arch/mips/mach-mtmips/cpu.c ++++ b/arch/mips/mach-mtmips/cpu.c +@@ -16,7 +16,7 @@ DECLARE_GLOBAL_DATA_PTR; + + int dram_init(void) + { +- gd->ram_size = get_ram_size((void *)KSEG1, SZ_256M); ++ gd->ram_size = get_ram_size((void *)KSEG1, CONFIG_MAX_MEM_SIZE << 20); + + return 0; + } +diff --git a/arch/mips/mach-mtmips/mt7621/Kconfig b/arch/mips/mach-mtmips/mt7621/Kconfig +new file mode 100644 +index 0000000000..37d512c68f +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/Kconfig +@@ -0,0 +1,95 @@ ++ ++if SOC_MT7621 ++ ++menu "CPU & DDR configuration" ++ ++config MT7621_CPU_FREQ ++ int "CPU Frequency (MHz)" ++ range 400 1200 ++ default 880 ++ ++choice ++ prompt "DRAM Frequency" ++ default MT7621_DRAM_FREQ_1200 ++ ++config MT7621_DRAM_FREQ_400 ++ bool "400MHz" ++ ++config MT7621_DRAM_FREQ_800 ++ bool "800MHz" ++ ++config MT7621_DRAM_FREQ_1066 ++ bool "1066MHz" ++ ++config MT7621_DRAM_FREQ_1200 ++ bool "1200MHz" ++ ++endchoice ++ ++choice ++ prompt "DDR2 timing parameters" ++ default MT7621_DRAM_DDR2_1024M ++ ++config MT7621_DRAM_DDR2_512M ++ bool "64MB" ++ ++config MT7621_DRAM_DDR2_1024M ++ bool "128MB" ++ ++config MT7621_DRAM_DDR2_512M_W9751G6KB_A02_1066MHZ ++ bool "W9751G6KB_A02 @ 1066MHz (64MB)" ++ ++config MT7621_DRAM_DDR2_1024M_W971GG6KB25_800MHZ ++ bool "W971GG6KB25 @ 800MHz (128MB)" ++ ++config MT7621_DRAM_DDR2_1024M_W971GG6KB18_1066MHZ ++ bool "W971GG6KB18 @ 1066MHz (128MB)" ++ ++endchoice ++ ++choice ++ prompt "DDR3 timing parameters" ++ default MT7621_DRAM_DDR3_2048M ++ ++config MT7621_DRAM_DDR3_1024M ++ bool "128MB" ++ ++config MT7621_DRAM_DDR3_1024M_KGD ++ bool "128MB KGD (MT7621DA)" ++ ++config MT7621_DRAM_DDR3_2048M ++ bool "256MB" ++ ++config MT7621_DRAM_DDR3_4096M ++ bool "512MB" ++ ++endchoice ++ ++endmenu ++ ++config DEBUG_UART_BOARD_INIT ++ default y ++ ++config MT7621_BOOT_FROM_NAND ++ bool "Boot from NAND" ++ help ++ Select this if u-boot will boot from NAND flash. When booting from ++ NAND, SPL will be loaded by bootrom directly and no TPL is needed. ++ ++choice ++ prompt "Board select" ++ ++endchoice ++ ++config SYS_CONFIG_NAME ++ string "Board configuration name" ++ default "mt7621" if BOARD_MT7621_RFB || BOARD_MT7621_NAND_RFB ++ ++config SYS_BOARD ++ string "Board name" ++ default "mt7621" if BOARD_MT7621_RFB || BOARD_MT7621_NAND_RFB ++ ++config SYS_VENDOR ++ default "mediatek" if BOARD_MT7621_RFB || BOARD_MT7621_NAND_RFB ++ ++endif +diff --git a/arch/mips/mach-mtmips/mt7621/Makefile b/arch/mips/mach-mtmips/mt7621/Makefile +new file mode 100644 +index 0000000000..bf1b0bb688 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/Makefile +@@ -0,0 +1,14 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += init.o ++obj-y += serial.o ++ ++ifeq ($(CONFIG_SPL_BUILD),y) ++ifeq ($(CONFIG_TPL_BUILD),y) ++obj-y += tpl/ ++else ++obj-y += spl/ ++endif ++ ++obj-y += sram_init.o ++endif +diff --git a/arch/mips/mach-mtmips/mt7621/init.c b/arch/mips/mach-mtmips/mt7621/init.c +new file mode 100644 +index 0000000000..d21848ad23 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/init.c +@@ -0,0 +1,246 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <clk.h> ++#include <dm.h> ++#include <dm/uclass.h> ++#include <dt-bindings/clock/mt7621-clk.h> ++#include <asm/global_data.h> ++#include <linux/io.h> ++#include <linux/bitfield.h> ++#include "mt7621.h" ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++static const char *const boot_mode[(CHIP_MODE_M >> CHIP_MODE_S) + 1] = { ++ [1] = "NAND 2K+64", ++ [2] = "SPI-NOR 3-Byte Addr", ++ [3] = "SPI-NOR 4-Byte Addr", ++ [10] = "NAND 2K+128", ++ [11] = "NAND 4K+128", ++ [12] = "NAND 4K+256", ++}; ++ ++int print_cpuinfo(void) ++{ ++ void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ u32 val, ver, eco, pkg, core, dram, chipmode; ++ u32 cpu_clk, ddr_clk, bus_clk, xtal_clk; ++ struct udevice *clkdev; ++ const char *bootdev; ++ struct clk clk; ++ int ret; ++ ++ val = readl(sysc + SYSCTL_CHIP_REV_ID_REG); ++ ver = FIELD_GET(VER_ID_M, val); ++ eco = FIELD_GET(ECO_ID_M, val); ++ pkg = FIELD_GET(PKG_ID, val); ++ core = FIELD_GET(CPU_ID, val); ++ ++ val = readl(sysc + SYSCTL_SYSCFG0_REG); ++ dram = FIELD_GET(DRAM_TYPE, val); ++ chipmode = FIELD_GET(CHIP_MODE_M, val); ++ ++ bootdev = boot_mode[chipmode]; ++ if (!bootdev) ++ bootdev = "Unsupported boot mode"; ++ ++ printf("CPU: MediaTek MT7621%c ver %u, eco %u\n", ++ core ? (pkg ? 'A' : 'N') : 'S', ver, eco); ++ ++ printf("Boot: DDR%u, %s\n", dram ? 2 : 3, bootdev); ++ ++ ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(mt7621_clk), ++ &clkdev); ++ if (ret) ++ return ret; ++ ++ clk.dev = clkdev; ++ ++ clk.id = MT7621_CLK_CPU; ++ cpu_clk = clk_get_rate(&clk); ++ ++ clk.id = MT7621_CLK_BUS; ++ bus_clk = clk_get_rate(&clk); ++ ++ clk.id = MT7621_CLK_DDR; ++ ddr_clk = clk_get_rate(&clk); ++ ++ clk.id = MT7621_CLK_XTAL; ++ xtal_clk = clk_get_rate(&clk); ++ ++ /* Set final timer frequency */ ++ if (cpu_clk) ++ gd->arch.timer_freq = cpu_clk / 2; ++ ++ printf("Clock: CPU: %uMHz, DDR: %uMT/s, Bus: %uMHz, XTAL: %uMHz\n", ++ cpu_clk / 1000000, ddr_clk / 500000, bus_clk / 1000000, ++ xtal_clk / 1000000); ++ ++ return 0; ++} ++ ++unsigned long get_xtal_mhz(void) ++{ ++ void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ u32 bs, xtal_sel; ++ ++ bs = readl(sysc + SYSCTL_SYSCFG0_REG); ++ xtal_sel = FIELD_GET(XTAL_MODE_SEL_M, bs); ++ ++ if (xtal_sel <= 2) ++ return 20; ++ else if (xtal_sel <= 5) ++ return 40; ++ else ++ return 25; ++} ++ ++static void xhci_config_40mhz(void __iomem *usbh) ++{ ++ writel(FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MODE_M, 2) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MODE_M, 2) | 0x10, ++ usbh + SSUSB_MAC_CK_CTRL_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PREDIV_PE1D_M, 2) | ++ FIELD_PREP(SSUSB_PLL_PREDIV_U3_M, 1) | ++ FIELD_PREP(SSUSB_PLL_FBKDI_M, 4), ++ usbh + DA_SSUSB_U3PHYA_10_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_FBKDIV_PE2H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1D_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_U3_M, 0x1e), ++ usbh + DA_SSUSB_PLL_FBKDIV_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PCW_NCPO_U3_M, 0x1e400000), ++ usbh + DA_SSUSB_PLL_PCW_NCPO_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE1H_M, 0x25) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_U3_M, 0x73), ++ usbh + DA_SSUSB_PLL_SSC_DELTA1_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA_U3_M, 0x71) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE2D_M, 0x4a), ++ usbh + DA_SSUSB_U3PHYA_21_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_PRD_M, 0x140), ++ usbh + SSUSB_U3PHYA_9_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_PCW_NCPO_M, 0x11c00000), ++ usbh + SSUSB_U3PHYA_3_REG); ++ ++ writel(FIELD_PREP(SSUSB_PCIE_CLKDRV_AMP_M, 4) | ++ FIELD_PREP(SSUSB_SYSPLL_FBSEL_M, 1) | ++ FIELD_PREP(SSUSB_SYSPLL_PREDIV_M, 1), ++ usbh + SSUSB_U3PHYA_1_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_FBDIV_M, 0x12) | ++ SSUSB_SYSPLL_VCO_DIV_SEL | SSUSB_SYSPLL_FPEN | ++ SSUSB_SYSPLL_MONCK_EN | SSUSB_SYSPLL_VOD_EN, ++ usbh + SSUSB_U3PHYA_2_REG); ++ ++ writel(SSUSB_EQ_CURSEL | FIELD_PREP(SSUSB_RX_DAC_MUX_M, 8) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_VTH_M, 1) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_LPF_M, 1), ++ usbh + SSUSB_U3PHYA_11_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_CNTEND_M, 0x1ff) | ++ FIELD_PREP(SSUSB_XTAL_OSC_CNTEND_M, 0x7f) | ++ SSUSB_RING_BYPASS_DET, ++ usbh + SSUSB_B2_ROSC_0_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_FRC_RECAL_M, 3) | ++ SSUSB_RING_OSC_FRC_SEL, ++ usbh + SSUSB_B2_ROSC_1_REG); ++} ++ ++static void xhci_config_25mhz(void __iomem *usbh) ++{ ++ writel(FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MODE_M, 2) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MODE_M, 2) | 0x10, ++ usbh + SSUSB_MAC_CK_CTRL_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PREDIV_PE1D_M, 2) | ++ FIELD_PREP(SSUSB_PLL_FBKDI_M, 4), ++ usbh + DA_SSUSB_U3PHYA_10_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_FBKDIV_PE2H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1D_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_U3_M, 0x19), ++ usbh + DA_SSUSB_PLL_FBKDIV_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PCW_NCPO_U3_M, 0x18000000), ++ usbh + DA_SSUSB_PLL_PCW_NCPO_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE1H_M, 0x25) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_U3_M, 0x4a), ++ usbh + DA_SSUSB_PLL_SSC_DELTA1_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA_U3_M, 0x48) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE2D_M, 0x4a), ++ usbh + DA_SSUSB_U3PHYA_21_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_PRD_M, 0x190), ++ usbh + SSUSB_U3PHYA_9_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_PCW_NCPO_M, 0xe000000), ++ usbh + SSUSB_U3PHYA_3_REG); ++ ++ writel(FIELD_PREP(SSUSB_PCIE_CLKDRV_AMP_M, 4) | ++ FIELD_PREP(SSUSB_SYSPLL_FBSEL_M, 1), ++ usbh + SSUSB_U3PHYA_1_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_FBDIV_M, 0xf) | ++ SSUSB_SYSPLL_VCO_DIV_SEL | SSUSB_SYSPLL_FPEN | ++ SSUSB_SYSPLL_MONCK_EN | SSUSB_SYSPLL_VOD_EN, ++ usbh + SSUSB_U3PHYA_2_REG); ++ ++ writel(SSUSB_EQ_CURSEL | FIELD_PREP(SSUSB_RX_DAC_MUX_M, 8) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_VTH_M, 1) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_LPF_M, 1), ++ usbh + SSUSB_U3PHYA_11_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_CNTEND_M, 0x1ff) | ++ FIELD_PREP(SSUSB_XTAL_OSC_CNTEND_M, 0x7f) | ++ SSUSB_RING_BYPASS_DET, ++ usbh + SSUSB_B2_ROSC_0_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_FRC_RECAL_M, 3) | ++ SSUSB_RING_OSC_FRC_SEL, ++ usbh + SSUSB_B2_ROSC_1_REG); ++} ++ ++void lowlevel_init(void) ++{ ++ void __iomem *usbh = ioremap_nocache(SSUSB_BASE, SSUSB_SIZE); ++ u32 xtal = get_xtal_mhz(); ++ ++ /* Setup USB xHCI */ ++ if (xtal == 40) ++ xhci_config_40mhz(usbh); ++ else if (xtal == 25) ++ xhci_config_25mhz(usbh); ++} ++ ++ulong notrace get_tbclk(void) ++{ ++ return gd->arch.timer_freq; ++} ++ ++void _machine_restart(void) ++{ ++ void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ ++ while (1) ++ writel(SYS_RST, sysc + SYSCTL_RSTCTL_REG); ++} +diff --git a/arch/mips/mach-mtmips/mt7621/mt7621.h b/arch/mips/mach-mtmips/mt7621/mt7621.h +new file mode 100644 +index 0000000000..916cc993b4 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/mt7621.h +@@ -0,0 +1,229 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _MT7621_H_ ++#define _MT7621_H_ ++ ++#define SYSCTL_BASE 0x1e000000 ++#define SYSCTL_SIZE 0x100 ++#define TIMER_BASE 0x1e000100 ++#define TIMER_SIZE 0x100 ++#define RBUS_BASE 0x1e000400 ++#define RBUS_SIZE 0x100 ++#define GPIO_BASE 0x1e000600 ++#define GPIO_SIZE 0x100 ++#define DMA_CFG_ARB_BASE 0x1e000800 ++#define DMA_CFG_ARB_SIZE 0x100 ++#define SPI_BASE 0x1e000b00 ++#define SPI_SIZE 0x100 ++#define UART1_BASE 0x1e000c00 ++#define UART1_SIZE 0x100 ++#define UART2_BASE 0x1e000d00 ++#define UART2_SIZE 0x100 ++#define UART3_BASE 0x1e000e00 ++#define UART3_SIZE 0x100 ++#define NFI_BASE 0x1e003000 ++#define NFI_SIZE 0x800 ++#define NFI_ECC_BASE 0x1e003800 ++#define NFI_ECC_SIZE 0x800 ++#define DRAMC_BASE 0x1e005000 ++#define DRAMC_SIZE 0x1000 ++#define FE_BASE 0x1e100000 ++#define FE_SIZE 0xe000 ++#define GMAC_BASE 0x1e110000 ++#define GMAC_SIZE 0x8000 ++#define SSUSB_BASE 0x1e1c0000 ++#define SSUSB_SIZE 0x40000 ++ ++ /* GIC Base Address */ ++#define MIPS_GIC_BASE 0x1fbc0000 ++ ++ /* CPC Base Address */ ++#define MIPS_CPC_BASE 0x1fbf0000 ++ ++ /* Flash Memory-mapped Base Address */ ++#define FLASH_MMAP_BASE 0x1fc00000 ++#define TPL_INFO_OFFSET 0x40 ++#define TPL_INFO_MAGIC 0x31323637 /* Magic "7621" */ ++ ++/* SRAM */ ++#define FE_SRAM_BASE1 0x8000 ++#define FE_SRAM_BASE2 0xa000 ++ ++/* SYSCTL_BASE */ ++#define SYSCTL_CHIP_REV_ID_REG 0x0c ++#define CPU_ID 0x20000 ++#define PKG_ID 0x10000 ++#define VER_ID_S 8 ++#define VER_ID_M 0xf00 ++#define ECO_ID_S 0 ++#define ECO_ID_M 0x0f ++ ++#define SYSCTL_SYSCFG0_REG 0x10 ++#define XTAL_MODE_SEL_S 6 ++#define XTAL_MODE_SEL_M 0x1c0 ++#define DRAM_TYPE 0x10 ++#define CHIP_MODE_S 0 ++#define CHIP_MODE_M 0x0f ++ ++#define BOOT_SRAM_BASE_REG 0x20 ++ ++#define SYSCTL_CLKCFG0_REG 0x2c ++#define CPU_CLK_SEL_S 30 ++#define CPU_CLK_SEL_M 0xc0000000 ++#define MPLL_CFG_SEL_S 23 ++#define MPLL_CFG_SEL_M 0x800000 ++ ++#define SYSCTL_RSTCTL_REG 0x34 ++#define MCM_RST 0x04 ++#define SYS_RST 0x01 ++ ++#define SYSCTL_CUR_CLK_STS_REG 0x44 ++#define CUR_CPU_FDIV_S 8 ++#define CUR_CPU_FDIV_M 0x1f00 ++#define CUR_CPU_FFRAC_S 0 ++#define CUR_CPU_FFRAC_M 0x1f ++ ++#define SYSCTL_GPIOMODE_REG 0x60 ++#define UART2_MODE_S 5 ++#define UART2_MODE_M 0x60 ++#define UART3_MODE_S 3 ++#define UART3_MODE_M 0x18 ++#define UART1_MODE 0x02 ++ ++/* RBUS_BASE */ ++#define RBUS_DYN_CFG0_REG 0x0010 ++#define CPU_FDIV_S 8 ++#define CPU_FDIV_M 0x1f00 ++#define CPU_FFRAC_S 0 ++#define CPU_FFRAC_M 0x1f ++ ++/* DMA_CFG_ARB_BASE */ ++#define DMA_ROUTE_REG 0x000c ++ ++/* SPI_BASE */ ++#define SPI_SPACE_REG 0x003c ++#define FS_SLAVE_SEL_S 12 ++#define FS_SLAVE_SEL_M 0x70000 ++#define FS_CLK_SEL_S 0 ++#define FS_CLK_SEL_M 0xfff ++ ++/* FE_BASE */ ++#define FE_RST_GLO_REG 0x0004 ++#define FE_PSE_RAM 0x04 ++#define FE_PSE_MEM_EN 0x02 ++#define FE_PSE_RESET 0x01 ++ ++/* SSUSB_BASE */ ++#define SSUSB_MAC_CK_CTRL_REG 0x10784 ++#define SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_S 16 ++#define SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_M 0xff0000 ++#define SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_S 8 ++#define SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_M 0xff00 ++#define SSUSB_MAC3_SYS_CK_GATE_MODE_S 2 ++#define SSUSB_MAC3_SYS_CK_GATE_MODE_M 0x0c ++#define SSUSB_MAC2_SYS_CK_GATE_MODE_S 0 ++#define SSUSB_MAC2_SYS_CK_GATE_MODE_M 0x03 ++ ++#define SSUSB_B2_ROSC_0_REG 0x10a40 ++#define SSUSB_RING_OSC_CNTEND_S 23 ++#define SSUSB_RING_OSC_CNTEND_M 0xff800000 ++#define SSUSB_XTAL_OSC_CNTEND_S 16 ++#define SSUSB_XTAL_OSC_CNTEND_M 0x7f0000 ++#define SSUSB_RING_BYPASS_DET 0x01 ++ ++#define SSUSB_B2_ROSC_1_REG 0x10a44 ++#define SSUSB_RING_OSC_FRC_RECAL_S 17 ++#define SSUSB_RING_OSC_FRC_RECAL_M 0x60000 ++#define SSUSB_RING_OSC_FRC_SEL 0x01 ++ ++#define SSUSB_U3PHYA_1_REG 0x10b04 ++#define SSUSB_PCIE_CLKDRV_AMP_S 27 ++#define SSUSB_PCIE_CLKDRV_AMP_M 0x38000000 ++#define SSUSB_SYSPLL_FBSEL_S 2 ++#define SSUSB_SYSPLL_FBSEL_M 0x0c ++#define SSUSB_SYSPLL_PREDIV_S 0 ++#define SSUSB_SYSPLL_PREDIV_M 0x03 ++ ++#define SSUSB_U3PHYA_2_REG 0x10b08 ++#define SSUSB_SYSPLL_FBDIV_S 24 ++#define SSUSB_SYSPLL_FBDIV_M 0x7f000000 ++#define SSUSB_SYSPLL_VCO_DIV_SEL 0x200000 ++#define SSUSB_SYSPLL_FPEN 0x2000 ++#define SSUSB_SYSPLL_MONCK_EN 0x1000 ++#define SSUSB_SYSPLL_VOD_EN 0x200 ++ ++#define SSUSB_U3PHYA_3_REG 0x10b10 ++#define SSUSB_SYSPLL_PCW_NCPO_S 1 ++#define SSUSB_SYSPLL_PCW_NCPO_M 0xfffffffe ++ ++#define SSUSB_U3PHYA_9_REG 0x10b24 ++#define SSUSB_PLL_SSC_PRD_S 0 ++#define SSUSB_PLL_SSC_PRD_M 0xffff ++ ++#define SSUSB_U3PHYA_11_REG 0x10b2c ++#define SSUSB_EQ_CURSEL 0x1000000 ++#define SSUSB_RX_DAC_MUX_S 19 ++#define SSUSB_RX_DAC_MUX_M 0xf80000 ++#define SSUSB_PCIE_SIGDET_VTH_S 5 ++#define SSUSB_PCIE_SIGDET_VTH_M 0x60 ++#define SSUSB_PCIE_SIGDET_LPF_S 3 ++#define SSUSB_PCIE_SIGDET_LPF_M 0x18 ++ ++#define DA_SSUSB_PLL_FBKDIV_REG 0x10c1c ++#define SSUSB_PLL_FBKDIV_PE2H_S 24 ++#define SSUSB_PLL_FBKDIV_PE2H_M 0x7f000000 ++#define SSUSB_PLL_FBKDIV_PE1D_S 16 ++#define SSUSB_PLL_FBKDIV_PE1D_M 0x7f0000 ++#define SSUSB_PLL_FBKDIV_PE1H_S 8 ++#define SSUSB_PLL_FBKDIV_PE1H_M 0x7f00 ++#define SSUSB_PLL_FBKDIV_U3_S 0 ++#define SSUSB_PLL_FBKDIV_U3_M 0x7f ++ ++#define DA_SSUSB_U3PHYA_10_REG 0x10c20 ++#define SSUSB_PLL_PREDIV_PE1D_S 18 ++#define SSUSB_PLL_PREDIV_PE1D_M 0xc0000 ++#define SSUSB_PLL_PREDIV_U3_S 8 ++#define SSUSB_PLL_PREDIV_U3_M 0x300 ++#define SSUSB_PLL_FBKDI_S 0 ++#define SSUSB_PLL_FBKDI_M 0x07 ++ ++#define DA_SSUSB_PLL_PCW_NCPO_REG 0x10c24 ++#define SSUSB_PLL_PCW_NCPO_U3_S 0 ++#define SSUSB_PLL_PCW_NCPO_U3_M 0x7fffffff ++ ++#define DA_SSUSB_PLL_SSC_DELTA1_REG 0x10c38 ++#define SSUSB_PLL_SSC_DELTA1_PE1H_S 16 ++#define SSUSB_PLL_SSC_DELTA1_PE1H_M 0xffff0000 ++#define SSUSB_PLL_SSC_DELTA1_U3_S 0 ++#define SSUSB_PLL_SSC_DELTA1_U3_M 0xffff ++ ++#define DA_SSUSB_U3PHYA_21_REG 0x10c40 ++#define SSUSB_PLL_SSC_DELTA_U3_S 16 ++#define SSUSB_PLL_SSC_DELTA_U3_M 0xffff0000 ++#define SSUSB_PLL_SSC_DELTA1_PE2D_S 0 ++#define SSUSB_PLL_SSC_DELTA1_PE2D_M 0xffff ++ ++/* MT7621 specific CM values */ ++ ++/* GCR_REGx_BASE */ ++#define GCR_REG0_BASE_VALUE 0x1c000000 ++#define GCR_REG1_BASE_VALUE 0x60000000 ++#define GCR_REG2_BASE_VALUE 0x1c000000 ++#define GCR_REG3_BASE_VALUE 0x1c000000 ++ ++/* GCR_REGx_MASK */ ++#define GCR_REG0_MASK_VALUE 0x0000fc00 /* 64M Bus */ ++#define GCR_REG1_MASK_VALUE 0x0000f000 /* 256M PCI Mem */ ++#define GCR_REG2_MASK_VALUE 0x0000fc00 /* unused */ ++#define GCR_REG3_MASK_VALUE 0x0000fc00 /* unused */ ++ ++#ifndef __ASSEMBLY__ ++unsigned long get_xtal_mhz(void); ++#endif ++ ++#endif /* _MT7621_H_ */ +diff --git a/arch/mips/mach-mtmips/mt7621/serial.c b/arch/mips/mach-mtmips/mt7621/serial.c +new file mode 100644 +index 0000000000..0ccc71dc75 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/serial.c +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include <asm/addrspace.h> ++#include "mt7621.h" ++ ++void board_debug_uart_init(void) ++{ ++ void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ ++#if CONFIG_DEBUG_UART_BASE == 0xbe000c00 /* KSEG1ADDR(UART1_BASE) */ ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART1_MODE); ++#elif CONFIG_DEBUG_UART_BASE == 0xbe000d00 /* KSEG1ADDR(UART2_BASE) */ ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART2_MODE_M); ++#elif CONFIG_DEBUG_UART_BASE == 0xbe000e00 /* KSEG1ADDR(UART3_BASE) */ ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART3_MODE_M); ++#endif ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/Makefile b/arch/mips/mach-mtmips/mt7621/spl/Makefile +new file mode 100644 +index 0000000000..ebe54e79b9 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/Makefile +@@ -0,0 +1,9 @@ ++ ++extra-y += start.o ++ ++obj-y += spl.o ++obj-y += cps.o ++obj-y += dram.o ++obj-y += serial.o ++obj-y += launch.o ++obj-y += launch_ll.o +diff --git a/arch/mips/mach-mtmips/mt7621/spl/cps.c b/arch/mips/mach-mtmips/mt7621/spl/cps.c +new file mode 100644 +index 0000000000..779e646c12 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/cps.c +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include <asm/addrspace.h> ++#include <asm/mipsregs.h> ++#include <asm/cm.h> ++#include <linux/bitfield.h> ++#include "../mt7621.h" ++ ++/* GIC Shared Register Bases */ ++#define GIC_SH_POL_BASE 0x100 ++#define GIC_SH_TRIG_BASE 0x180 ++#define GIC_SH_RMASK_BASE 0x300 ++#define GIC_SH_SMASK_BASE 0x380 ++#define GIC_SH_MASK_BASE 0x400 ++#define GIC_SH_PEND_BASE 0x480 ++#define GIC_SH_MAP_PIN_BASE 0x500 ++#define GIC_SH_MAP_VPE_BASE 0x2000 ++ ++/* GIC Registers */ ++#define GIC_SH_POL31_0 (GIC_SH_POL_BASE + 0x00) ++#define GIC_SH_POL63_32 (GIC_SH_POL_BASE + 0x04) ++ ++#define GIC_SH_TRIG31_0 (GIC_SH_TRIG_BASE + 0x00) ++#define GIC_SH_TRIG63_32 (GIC_SH_TRIG_BASE + 0x04) ++ ++#define GIC_SH_RMASK31_0 (GIC_SH_RMASK_BASE + 0x00) ++#define GIC_SH_RMASK63_32 (GIC_SH_RMASK_BASE + 0x04) ++ ++#define GIC_SH_SMASK31_0 (GIC_SH_SMASK_BASE + 0x00) ++#define GIC_SH_SMASK63_32 (GIC_SH_SMASK_BASE + 0x04) ++ ++#define GIC_SH_MAP_PIN(n) (GIC_SH_MAP_PIN_BASE + (n) * 4) ++ ++#define GIC_SH_MAP_VPE(n, v) (GIC_SH_MAP_VPE_BASE + (n) * 0x20 + ((v) / 32) * 4) ++#define GIC_SH_MAP_VPE31_0(n) GIC_SH_MAP_VPE(n, 0) ++ ++/* GIC_SH_MAP_PIN fields */ ++#define GIC_MAP_TO_PIN BIT(31) ++#define GIC_MAP_TO_NMI BIT(30) ++#define GIC_MAP GENMASK(5, 0) ++#define GIC_MAP_SHIFT 0 ++ ++static void cm_init(void __iomem *cm_base) ++{ ++ u32 gcrcfg, num_cores; ++ ++ gcrcfg = readl(cm_base + GCR_CONFIG); ++ num_cores = FIELD_GET(GCR_CONFIG_PCORES, gcrcfg) + 1; ++ ++ writel((1 << num_cores) - 1, cm_base + GCR_ACCESS); ++ ++ writel(GCR_REG0_BASE_VALUE, cm_base + GCR_REG0_BASE); ++ writel(GCR_REG1_BASE_VALUE, cm_base + GCR_REG1_BASE); ++ writel(GCR_REG2_BASE_VALUE, cm_base + GCR_REG2_BASE); ++ writel(GCR_REG3_BASE_VALUE, cm_base + GCR_REG3_BASE); ++ ++ clrsetbits_32(cm_base + GCR_REG0_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG0_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrsetbits_32(cm_base + GCR_REG1_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG1_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrsetbits_32(cm_base + GCR_REG2_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG2_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrsetbits_32(cm_base + GCR_REG3_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG3_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrbits_32(cm_base + GCR_BASE, CM_DEFAULT_TARGET_MASK); ++ setbits_32(cm_base + GCR_CONTROL, GCR_CONTROL_SYNCCTL); ++} ++ ++static void gic_init(void) ++{ ++ void __iomem *gic_base = (void *)KSEG1ADDR(MIPS_GIC_BASE); ++ int i; ++ ++ /* Interrupt 0..5: Level Trigger, Active High */ ++ writel(0, gic_base + GIC_SH_TRIG31_0); ++ writel(0x3f, gic_base + GIC_SH_RMASK31_0); ++ writel(0x3f, gic_base + GIC_SH_POL31_0); ++ writel(0x3f, gic_base + GIC_SH_SMASK31_0); ++ ++ /* Interrupt 56..63: Edge Trigger, Rising Edge */ ++ /* Hardcoded to set up the last 8 external interrupts for IPI. */ ++ writel(0xff000000, gic_base + GIC_SH_TRIG63_32); ++ writel(0xff000000, gic_base + GIC_SH_RMASK63_32); ++ writel(0xff000000, gic_base + GIC_SH_POL63_32); ++ writel(0xff000000, gic_base + GIC_SH_SMASK63_32); ++ ++ /* Map interrupt source to particular hardware interrupt pin */ ++ /* source {0,1,2,3,4,5} -> pin {0,0,4,3,0,5} */ ++ writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(0)); ++ writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(1)); ++ writel(GIC_MAP_TO_PIN | 4, gic_base + GIC_SH_MAP_PIN(2)); ++ writel(GIC_MAP_TO_PIN | 3, gic_base + GIC_SH_MAP_PIN(3)); ++ writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(4)); ++ writel(GIC_MAP_TO_PIN | 5, gic_base + GIC_SH_MAP_PIN(5)); ++ ++ /* source 56~59 -> pin 1, 60~63 -> pin 2 */ ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(56)); ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(57)); ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(58)); ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(59)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(60)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(61)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(62)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(63)); ++ ++ /* Interrupt map to VPE (bit mask) */ ++ for (i = 0; i < 32; i++) ++ writel(BIT(0), gic_base + GIC_SH_MAP_VPE31_0(i)); ++ ++ /* ++ * Direct GIC_int 56..63 to vpe 0..3 ++ * MIPS Linux convention that last 16 interrupts implemented be set ++ * aside for IPI signaling. ++ * The actual interrupts are tied low and software sends interrupts ++ * via GIC_SH_WEDGE writes. ++ */ ++ for (i = 0; i < 4; i++) { ++ writel(BIT(i), gic_base + GIC_SH_MAP_VPE31_0(i + 56)); ++ writel(BIT(i), gic_base + GIC_SH_MAP_VPE31_0(i + 60)); ++ } ++} ++ ++void mt7621_cps_init(void) ++{ ++ void __iomem *cm_base = (void *)KSEG1ADDR(CONFIG_MIPS_CM_BASE); ++ ++ /* Enable GIC */ ++ writel(MIPS_GIC_BASE | GCR_GIC_EN, cm_base + GCR_GIC_BASE); ++ ++ /* Enable CPC */ ++ writel(MIPS_CPC_BASE | GCR_CPC_EN, cm_base + GCR_CPC_BASE); ++ ++ gic_init(); ++ cm_init(cm_base); ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/dram.c b/arch/mips/mach-mtmips/mt7621/spl/dram.c +new file mode 100644 +index 0000000000..100adfb93a +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/dram.c +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <vsprintf.h> ++#include <asm/io.h> ++#include <asm/sections.h> ++#include <asm/byteorder.h> ++#include <asm/addrspace.h> ++#include <linux/string.h> ++#include "../mt7621.h" ++#include "dram.h" ++ ++static const u32 ddr2_act[DDR_PARAM_SIZE] = { ++#if defined(CONFIG_MT7621_DRAM_DDR2_512M) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x22174441, ++ 0x00000000, 0xF0748661, 0x40001273, 0x9F0A0481, ++ 0x0304692F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000000, 0x07100000, ++ 0x00001B63, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR2_512M_W9751G6KB_A02_1066MHZ) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x33484584, ++ 0x00000000, 0xF07486A1, 0x50001273, 0x9F010481, ++ 0x0304693F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000010, 0x07100000, ++ 0x00001F73, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR2_1024M_W971GG6KB25_800MHZ) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x22174430, ++ 0x01000000, 0xF0748661, 0x40001273, 0x9F0F0481, ++ 0x0304692F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000000, 0x07100000, ++ 0x00001B63, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR2_1024M_W971GG6KB18_1066MHZ) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x33484584, ++ 0x01000000, 0xF07486A1, 0x50001273, 0x9F070481, ++ 0x0304693F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000010, 0x07100000, ++ 0x00001F73, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#else /* CONFIG_MT7621_DRAM_DDR2_1024M */ ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x22174441, ++ 0x01000000, 0xF0748661, 0x40001273, 0x9F0F0481, ++ 0x0304692F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000000, 0x07100000, ++ 0x00001B63, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#endif ++}; ++ ++static const u32 ddr3_act[DDR_PARAM_SIZE] = { ++#if defined(CONFIG_MT7621_DRAM_DDR3_1024M) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x44694683, ++ 0x01000000, 0xF07486A1, 0xC287221D, 0x9F060481, ++ 0x03046948, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000210, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR3_4096M) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x44694683, ++ 0x01000000, 0xF07486A1, 0xC287221D, 0x9F0F0481, ++ 0x03046948, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000240, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR3_1024M_KGD) ++ 0xFF00FF00, 0xFF00FF00, 0x00000007, 0x44694683, ++ 0x01000000, 0xF07406A1, 0xC287221D, 0x9F060481, ++ 0x03046923, 0x152f2842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000210, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x000C0000, 0x00000000, ++#else /* CONFIG_MT7621_DRAM_DDR3_2048M */ ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x44694673, ++ 0x01000000, 0xF07486A1, 0xC287221D, 0x9F050481, ++ 0x03046948, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000220, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x00000000, 0x00000000, ++#endif ++}; ++ ++#if defined(CONFIG_MT7621_DRAM_FREQ_400) ++#define DDR_FREQ_PARAM 0x41000000 ++#elif defined(CONFIG_MT7621_DRAM_FREQ_1066) ++#define DDR_FREQ_PARAM 0x21000000 ++#elif defined(CONFIG_MT7621_DRAM_FREQ_1200) ++#define DDR_FREQ_PARAM 0x11000000 ++#else /* CONFIG_MT7621_DRAM_FREQ_800 */ ++#define DDR_FREQ_PARAM 0x31000000 ++#endif ++ ++#define RG_MEPL_FBDIV_S 4 ++#define RG_MEPL_FBDIV_M 0x7f ++ ++static inline void word_copy(u32 *dest, const u32 *src, u32 count) ++{ ++ u32 i; ++ ++ for (i = 0; i < count; i++) ++ dest[i] = src[i]; ++} ++ ++static u32 calc_cpu_pll_val(void) ++{ ++ u32 div, baseval, fb; ++ ++ div = get_xtal_mhz(); ++ ++ if (div == 40) { ++ div /= 2; ++ baseval = 0xc0005802; ++ } else { ++ baseval = 0xc0004802; ++ } ++ ++ fb = CONFIG_MT7621_CPU_FREQ / div - 1; ++ if (fb > RG_MEPL_FBDIV_M) ++ fb = RG_MEPL_FBDIV_M; ++ ++ return baseval | (fb << RG_MEPL_FBDIV_S); ++} ++ ++void prepare_stage_bin(void) ++{ ++ u32 stage_size; ++ ++ const struct stage_header *stock_stage_bin = ++ (const struct stage_header *)__image_copy_end; ++ ++ struct stage_header *new_stage_bin = ++ (struct stage_header *)STAGE_LOAD_ADDR; ++ ++ if (be32_to_cpu(stock_stage_bin->ep) != STAGE_LOAD_ADDR) ++ panic("Invalid DDR stage binary blob\n"); ++ ++ stage_size = be32_to_cpu(stock_stage_bin->stage_size); ++ ++ word_copy((u32 *)new_stage_bin, (const u32 *)stock_stage_bin, ++ (stage_size + sizeof(u32) - 1) / sizeof(u32)); ++ ++ word_copy(new_stage_bin->ddr2_act, ddr2_act, DDR_PARAM_SIZE); ++ word_copy(new_stage_bin->ddr3_act, ddr3_act, DDR_PARAM_SIZE); ++ ++ new_stage_bin->cpu_pll_cfg = calc_cpu_pll_val(); ++ new_stage_bin->ddr_pll_cfg = DDR_FREQ_PARAM; ++ new_stage_bin->baudrate = CONFIG_BAUDRATE; ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/dram.h b/arch/mips/mach-mtmips/mt7621/spl/dram.h +new file mode 100644 +index 0000000000..7322c58276 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/dram.h +@@ -0,0 +1,39 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _MT7621_DRAM_H_ ++#define _MT7621_DRAM_H_ ++ ++#define STAGE_LOAD_ADDR 0xBE108800 ++ ++#ifndef __ASSEMBLY__ ++#include <linux/types.h> ++ ++#define DDR_PARAM_SIZE 24 ++ ++struct stage_header { ++ u32 jump_insn[2]; ++ u32 ep; ++ u32 stage_size; ++ u32 has_stage2; ++ u32 next_ep; ++ u32 next_size; ++ u32 next_offset; ++ u32 cpu_pll_cfg; ++ u32 ddr_pll_cfg; ++ u32 reserved2[6]; ++ char build_tag[32]; ++ u32 ddr3_act[DDR_PARAM_SIZE]; ++ u32 padding1[2]; ++ u32 ddr2_act[DDR_PARAM_SIZE]; ++ u32 padding2[2]; ++ u32 baudrate; ++ u32 padding3; ++}; ++#endif ++ ++#endif /* _MT7621_DRAM_H_ */ +diff --git a/arch/mips/mach-mtmips/mt7621/spl/launch.c b/arch/mips/mach-mtmips/mt7621/spl/launch.c +new file mode 100644 +index 0000000000..37c20a5f56 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/launch.c +@@ -0,0 +1,100 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include <asm/cm.h> ++#include <asm/sections.h> ++#include <asm/addrspace.h> ++#include <asm/mipsmtregs.h> ++#include <linux/sizes.h> ++#include <time.h> ++#include <cpu_func.h> ++#include "launch.h" ++#include "../mt7621.h" ++ ++/* Cluster Power Controller (CPC) offsets */ ++#define CPC_CL_OTHER 0x2010 ++#define CPC_CO_CMD 0x4000 ++ ++/* CPC_CL_OTHER fields */ ++#define CPC_CL_OTHER_CORENUM_SHIFT 16 ++#define CPC_CL_OTHER_CORENUM GENMASK(23, 16) ++ ++/* CPC_CO_CMD */ ++#define PWR_UP 3 ++ ++#define NUM_CORES 2 ++#define NUM_CPUS 4 ++#define WAIT_CPUS_TIMEOUT 4000 ++ ++static void copy_launch_wait_code(void) ++{ ++ memset((void *)KSEG1, 0, SZ_4K); ++ ++ memcpy((void *)KSEG1ADDR(LAUNCH_WAITCODE), ++ &launch_wait_code_start, ++ &launch_wait_code_end - &launch_wait_code_start); ++ ++ invalidate_dcache_range(KSEG0, SZ_4K); ++} ++ ++static void bootup_secondary_core(void) ++{ ++ void __iomem *cpcbase = (void __iomem *)KSEG1ADDR(MIPS_CPC_BASE); ++ int i; ++ ++ for (i = 1; i < NUM_CORES; i++) { ++ writel(i << CPC_CL_OTHER_CORENUM_SHIFT, cpcbase + CPC_CL_OTHER); ++ writel(PWR_UP, cpcbase + CPC_CO_CMD); ++ } ++} ++ ++void secondary_cpu_init(void) ++{ ++ void __iomem *sysc = (void __iomem *)KSEG1ADDR(SYSCTL_BASE); ++ u32 i, dual_core = 0, cpuready = 1, cpumask = 0x03; ++ ulong wait_tick; ++ struct cpulaunch_t *c; ++ ++ /* Copy LAUNCH wait code used by other VPEs */ ++ copy_launch_wait_code(); ++ ++ dual_core = readl(sysc + SYSCTL_CHIP_REV_ID_REG) & CPU_ID; ++ ++ if (dual_core) { ++ /* Bootup secondary core for MT7621A */ ++ cpumask = 0x0f; ++ ++ /* Make BootROM/TPL redirect Core1's bootup flow to our entry point */ ++ writel((uintptr_t)&_start, sysc + BOOT_SRAM_BASE_REG); ++ ++ bootup_secondary_core(); ++ } ++ ++ /* Join the coherent domain */ ++ join_coherent_domain(dual_core ? 2 : 1); ++ ++ /* Bootup Core0/VPE1 */ ++ boot_vpe1(); ++ ++ /* Wait for all CPU ready */ ++ wait_tick = get_timer(0) + WAIT_CPUS_TIMEOUT; ++ ++ while (time_before(get_timer(0), wait_tick)) { ++ /* CPU0 is obviously ready */ ++ for (i = 1; i < NUM_CPUS; i++) { ++ c = (struct cpulaunch_t *)(KSEG0ADDR(CPULAUNCH) + ++ (i << LOG2CPULAUNCH)); ++ ++ if (c->flags & LAUNCH_FREADY) ++ cpuready |= BIT(i); ++ } ++ ++ if ((cpuready & cpumask) == cpumask) ++ break; ++ } ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/launch.h b/arch/mips/mach-mtmips/mt7621/spl/launch.h +new file mode 100644 +index 0000000000..f34250d605 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/launch.h +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _LAUNCH_H_ ++#define _LAUNCH_H_ ++ ++#ifndef __ASSEMBLY__ ++ ++struct cpulaunch_t { ++ unsigned long pc; ++ unsigned long gp; ++ unsigned long sp; ++ unsigned long a0; ++ unsigned long _pad[3]; /* pad to cache line size to avoid thrashing */ ++ unsigned long flags; ++}; ++ ++extern char launch_wait_code_start; ++extern char launch_wait_code_end; ++ ++void join_coherent_domain(int ncores); ++void boot_vpe1(void); ++ ++#else ++ ++#define LAUNCH_PC 0 ++#define LAUNCH_GP 4 ++#define LAUNCH_SP 8 ++#define LAUNCH_A0 12 ++#define LAUNCH_FLAGS 28 ++ ++#endif ++ ++#define LOG2CPULAUNCH 5 ++ ++#define LAUNCH_FREADY 1 ++#define LAUNCH_FGO 2 ++#define LAUNCH_FGONE 4 ++ ++#define LAUNCH_WAITCODE 0x00000d00 ++#define SCRLAUNCH 0x00000e00 ++#define CPULAUNCH 0x00000f00 ++#define NCPULAUNCH 8 ++ ++/* Polling period in count cycles for secondary CPU's */ ++#define LAUNCHPERIOD 10000 ++ ++#endif /* _LAUNCH_H_ */ +diff --git a/arch/mips/mach-mtmips/mt7621/spl/launch_ll.S b/arch/mips/mach-mtmips/mt7621/spl/launch_ll.S +new file mode 100644 +index 0000000000..32d28c7539 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/launch_ll.S +@@ -0,0 +1,339 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/cm.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include <asm/cacheops.h> ++#include <asm/mipsregs.h> ++#include <asm/addrspace.h> ++#include <asm/mipsmtregs.h> ++#include "launch.h" ++ ++ .macro cache_loop curr, end, line_sz, op ++10: cache \op, 0(\curr) ++ PTR_ADDU \curr, \curr, \line_sz ++ bne \curr, \end, 10b ++ .endm ++ ++ .set mt ++ ++/* ++ * Join the coherent domain ++ * a0 = number of cores ++ */ ++LEAF(join_coherent_domain) ++ /* ++ * Enable coherence and allow interventions from all other cores. ++ * (Write access enabled via GCR_ACCESS by core 0.) ++ */ ++ li t1, 1 ++ sll t1, a0 ++ addiu t1, -1 ++ ++ li t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) ++ sw t1, GCR_Cx_COHERENCE(t0) ++ ehb ++ ++ move t2, zero ++ ++_next_coherent_core: ++ sll t1, t2, GCR_Cx_OTHER_CORENUM_SHIFT ++ sw t1, GCR_Cx_OTHER(t0) ++ ++_busy_wait_coherent_core: ++ lw t1, GCR_CO_COHERENCE(t0) ++ beqz t1, _busy_wait_coherent_core ++ ++ addiu t2, 1 ++ bne t2, a0, _next_coherent_core ++ ++ jr ra ++ END(join_coherent_domain) ++ ++/* ++ * All VPEs other than VPE0 will go here. ++ */ ++LEAF(launch_vpe_entry) ++ mfc0 t0, CP0_EBASE ++ and t0, t0, MIPS_EBASE_CPUNUM ++ ++ /* per-VPE cpulaunch_t */ ++ li a0, KSEG0ADDR(CPULAUNCH) ++ sll t1, t0, LOG2CPULAUNCH ++ addu a0, t1 ++ ++ /* Set CPU online flag */ ++ li t0, LAUNCH_FREADY ++ sw t0, LAUNCH_FLAGS(a0) ++ ++ /* Enable count interrupt in mask, but do not enable interrupts */ ++ mfc0 t0, CP0_STATUS ++ ori t0, STATUSF_IP7 ++ mtc0 t0, CP0_STATUS ++ ++ /* VPEs executing in wait code do not need a stack */ ++ li t9, KSEG0ADDR(LAUNCH_WAITCODE) ++ jr t9 ++ END(launch_vpe_entry) ++ ++/* ++ * This function will not be executed in place. ++ * It will be copied into memory, and VPEs other than VPE0 will be ++ * started to run into this in-memory function. ++ */ ++LEAF(launch_wait_code) ++ .globl launch_wait_code_start ++launch_wait_code_start: ++ ++ move t0, a0 ++ ++start_poll: ++ /* Poll CPU go flag */ ++ mtc0 zero, CP0_COUNT ++ li t1, LAUNCHPERIOD ++ mtc0 t1, CP0_COMPARE ++ ++time_wait: ++ /* Software wait */ ++ mfc0 t2, CP0_COUNT ++ subu t2, t1 ++ bltz t2, time_wait ++ ++ /* Check the launch flag */ ++ lw t3, LAUNCH_FLAGS(t0) ++ and t3, LAUNCH_FGO ++ beqz t3, start_poll ++ ++ /* Reset the counter and interrupts to give naive clients a chance */ ++ mfc0 t1, CP0_STATUS ++ ins t1, zero, STATUSB_IP7, 1 ++ mtc0 t1, CP0_STATUS ++ ++ mfc0 t1, CP0_COUNT ++ subu t1, 1 ++ mtc0 t1, CP0_COMPARE ++ ++ /* Jump to kernel */ ++ lw t9, LAUNCH_PC(t0) ++ lw gp, LAUNCH_GP(t0) ++ lw sp, LAUNCH_SP(t0) ++ lw a0, LAUNCH_A0(t0) ++ move a1, zero ++ move a2, zero ++ move a3, zero ++ ori t3, LAUNCH_FGONE ++ sw t3, LAUNCH_FLAGS(t0) ++ ++ jr t9 ++ ++ .globl launch_wait_code_end ++launch_wait_code_end: ++ END(launch_wait_code) ++ ++/* ++ * Core1 will go here. ++ */ ++LEAF(launch_core_entry) ++ /* Disable caches */ ++ bal mips_cache_disable ++ ++ /* Initialize L1 cache only */ ++ li a0, CONFIG_SYS_ICACHE_SIZE ++ li a1, CONFIG_SYS_ICACHE_LINE_SIZE ++ li a2, CONFIG_SYS_DCACHE_SIZE ++ li a3, CONFIG_SYS_DCACHE_LINE_SIZE ++ ++ mtc0 zero, CP0_TAGLO ++ mtc0 zero, CP0_TAGLO, 2 ++ ehb ++ ++ /* ++ * Initialize the I-cache first, ++ */ ++ li t0, KSEG0 ++ addu t1, t0, a0 ++ /* clear tag to invalidate */ ++ cache_loop t0, t1, a1, INDEX_STORE_TAG_I ++#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD ++ /* fill once, so data field parity is correct */ ++ PTR_LI t0, KSEG0 ++ cache_loop t0, t1, a1, FILL ++ /* invalidate again - prudent but not strictly necessary */ ++ PTR_LI t0, KSEG0 ++ cache_loop t0, t1, a1, INDEX_STORE_TAG_I ++#endif ++ ++ /* ++ * then initialize D-cache. ++ */ ++ PTR_LI t0, KSEG0 ++ PTR_ADDU t1, t0, a2 ++ /* clear all tags */ ++ cache_loop t0, t1, a3, INDEX_STORE_TAG_D ++#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD ++ /* load from each line (in cached space) */ ++ PTR_LI t0, KSEG0 ++2: LONG_L zero, 0(t0) ++ PTR_ADDU t0, a3 ++ bne t0, t1, 2b ++ /* clear all tags */ ++ PTR_LI t0, KSEG0 ++ cache_loop t0, t1, a3, INDEX_STORE_TAG_D ++#endif ++ ++ /* Set Cache Mode */ ++ mfc0 t0, CP0_CONFIG ++ li t1, CONF_CM_CACHABLE_COW ++ ins t0, t1, 0, 3 ++ mtc0 t0, CP0_CONFIG ++ ++ /* Join the coherent domain */ ++ li a0, 2 ++ bal join_coherent_domain ++ ++ /* Bootup Core0/VPE1 */ ++ bal boot_vpe1 ++ ++ b launch_vpe_entry ++ END(launch_core_entry) ++ ++/* ++ * Bootup VPE1. ++ * This subroutine must be executed from VPE0 with VPECONF0[MVP] already set. ++ */ ++LEAF(boot_vpe1) ++ mfc0 t0, CP0_MVPCONF0 ++ ++ /* a0 = number of TCs - 1 */ ++ ext a0, t0, MVPCONF0_PTC_SHIFT, 8 ++ beqz a0, _vpe1_init_done ++ ++ /* a1 = number of VPEs - 1 */ ++ ext a1, t0, MVPCONF0_PVPE_SHIFT, 4 ++ beqz a1, _vpe1_init_done ++ ++ /* a2 = current TC No. */ ++ move a2, zero ++ ++ /* Enter VPE Configuration State */ ++ mfc0 t0, CP0_MVPCONTROL ++ or t0, MVPCONTROL_VPC ++ mtc0 t0, CP0_MVPCONTROL ++ ehb ++ ++_next_tc: ++ /* Set the TC number to be used on MTTR and MFTR instructions */ ++ mfc0 t0, CP0_VPECONTROL ++ ins t0, a2, 0, 8 ++ mtc0 t0, CP0_VPECONTROL ++ ehb ++ ++ /* TC0 is already bound */ ++ beqz a2, _next_vpe ++ ++ /* Halt current TC */ ++ li t0, TCHALT_H ++ mttc0 t0, CP0_TCHALT ++ ehb ++ ++ /* If there is spare TC, bind it to the last VPE (VPE[a1]) */ ++ slt t1, a1, a2 ++ bnez t1, _vpe_bind_tc ++ move t1, a1 ++ ++ /* Set Exclusive TC for active TC */ ++ mftc0 t0, CP0_VPECONF0 ++ ins t0, a2, VPECONF0_XTC_SHIFT, 8 ++ mttc0 t0, CP0_VPECONF0 ++ ++ move t1, a2 ++_vpe_bind_tc: ++ /* Bind TC to a VPE */ ++ mftc0 t0, CP0_TCBIND ++ ins t0, t1, TCBIND_CURVPE_SHIFT, 4 ++ mttc0 t0, CP0_TCBIND ++ ++ /* ++ * Set up CP0_TCSTATUS register: ++ * Disable Coprocessor Usable bits ++ * Disable MDMX/DSP ASE ++ * Clear Dirty TC ++ * not dynamically allocatable ++ * not allocated ++ * Kernel mode ++ * interrupt exempt ++ * ASID 0 ++ */ ++ li t0, TCSTATUS_IXMT ++ mttc0 t0, CP0_TCSTATUS ++ ++_next_vpe: ++ slt t1, a1, a2 ++ bnez t1, _done_vpe # No more VPEs ++ ++ /* Disable TC multi-threading */ ++ mftc0 t0, CP0_VPECONTROL ++ ins t0, zero, VPECONTROL_TE_SHIFT, 1 ++ mttc0 t0, CP0_VPECONTROL ++ ++ /* Skip following configuration for TC0 */ ++ beqz a2, _done_vpe ++ ++ /* Deactivate VPE, set Master VPE */ ++ mftc0 t0, CP0_VPECONF0 ++ ins t0, zero, VPECONF0_VPA_SHIFT, 1 ++ or t0, VPECONF0_MVP ++ mttc0 t0, CP0_VPECONF0 ++ ++ mfc0 t0, CP0_STATUS ++ mttc0 t0, CP0_STATUS ++ ++ mttc0 zero, CP0_EPC ++ mttc0 zero, CP0_CAUSE ++ ++ mfc0 t0, CP0_CONFIG ++ mttc0 t0, CP0_CONFIG ++ ++ /* ++ * VPE1 of each core can execute cached as its L1 I$ has already ++ * been initialized. ++ * and the L2$ has been initialized or "disabled" via CCA override. ++ */ ++ PTR_LA t0, _start ++ mttc0 t0, CP0_TCRESTART ++ ++ /* Unset Interrupt Exempt, set Activate Thread */ ++ mftc0 t0, CP0_TCSTATUS ++ ins t0, zero, TCSTATUS_IXMT_SHIFT, 1 ++ ori t0, TCSTATUS_A ++ mttc0 t0, CP0_TCSTATUS ++ ++ /* Resume TC */ ++ mttc0 zero, CP0_TCHALT ++ ++ /* Activate VPE */ ++ mftc0 t0, CP0_VPECONF0 ++ ori t0, VPECONF0_VPA ++ mttc0 t0, CP0_VPECONF0 ++ ++_done_vpe: ++ addu a2, 1 ++ sltu t0, a0, a2 ++ beqz t0, _next_tc ++ ++ mfc0 t0, CP0_MVPCONTROL ++ /* Enable all activated VPE to execute */ ++ ori t0, MVPCONTROL_EVP ++ /* Exit VPE Configuration State */ ++ ins t0, zero, MVPCONTROL_VPC_SHIFT, 1 ++ mtc0 t0, CP0_MVPCONTROL ++ ehb ++ ++_vpe1_init_done: ++ jr ra ++ END(boot_vpe1) +diff --git a/arch/mips/mach-mtmips/mt7621/spl/serial.c b/arch/mips/mach-mtmips/mt7621/spl/serial.c +new file mode 100644 +index 0000000000..5cf093a078 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/serial.c +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include "../mt7621.h" ++ ++void mtmips_spl_serial_init(void) ++{ ++#ifdef CONFIG_SPL_SERIAL ++ void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ ++#if CONFIG_CONS_INDEX == 1 ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART1_MODE); ++#elif CONFIG_CONS_INDEX == 2 ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART2_MODE_M); ++#elif CONFIG_CONS_INDEX == 3 ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART3_MODE_M); ++#endif /* CONFIG_CONS_INDEX */ ++#endif /* CONFIG_SPL_SERIAL */ ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/spl.c b/arch/mips/mach-mtmips/mt7621/spl/spl.c +new file mode 100644 +index 0000000000..71d01aa7f5 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/spl.c +@@ -0,0 +1,95 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <spl.h> ++#include <init.h> ++#include <image.h> ++#include <vsprintf.h> ++#include <malloc.h> ++#include <asm/io.h> ++#include <asm/sections.h> ++#include <asm/addrspace.h> ++#include <asm/byteorder.h> ++#include <asm/global_data.h> ++#include <linux/sizes.h> ++#include <mach/serial.h> ++#include "../mt7621.h" ++#include "dram.h" ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++struct tpl_info { ++ u32 magic; ++ u32 size; ++}; ++ ++void set_timer_freq_simple(void) ++{ ++ u32 div = get_xtal_mhz(); ++ ++ /* Round down cpu freq */ ++ gd->arch.timer_freq = rounddown(CONFIG_MT7621_CPU_FREQ, div) * 500000; ++} ++ ++void __noreturn board_init_f(ulong dummy) ++{ ++ spl_init(); ++ ++#ifdef CONFIG_SPL_SERIAL ++ /* ++ * mtmips_spl_serial_init() is useful if debug uart is enabled, ++ * or DM based serial is not enabled. ++ */ ++ mtmips_spl_serial_init(); ++ preloader_console_init(); ++#endif ++ ++ board_init_r(NULL, 0); ++} ++ ++void board_boot_order(u32 *spl_boot_list) ++{ ++#ifdef CONFIG_MT7621_BOOT_FROM_NAND ++ spl_boot_list[0] = BOOT_DEVICE_NAND; ++#else ++ spl_boot_list[0] = BOOT_DEVICE_NOR; ++#endif ++} ++ ++unsigned long spl_nor_get_uboot_base(void) ++{ ++ const struct tpl_info *tpli; ++ const image_header_t *hdr; ++ u32 addr; ++ ++ addr = FLASH_MMAP_BASE + TPL_INFO_OFFSET; ++ tpli = (const struct tpl_info *)KSEG1ADDR(addr); ++ ++ if (tpli->magic == TPL_INFO_MAGIC) { ++ addr = FLASH_MMAP_BASE + tpli->size; ++ hdr = (const image_header_t *)KSEG1ADDR(addr); ++ ++ if (image_get_magic(hdr) == IH_MAGIC) { ++ addr += sizeof(*hdr) + image_get_size(hdr); ++ return KSEG1ADDR(addr); ++ } ++ } ++ ++ panic("Unable to locate SPL payload\n"); ++ return 0; ++} ++ ++uint32_t spl_nand_get_uboot_raw_page(void) ++{ ++ const struct stage_header *sh = (const struct stage_header *)&_start; ++ u32 addr; ++ ++ addr = image_get_header_size() + be32_to_cpu(sh->stage_size); ++ addr = ALIGN(addr, SZ_4K); ++ ++ return addr; ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/start.S b/arch/mips/mach-mtmips/mt7621/spl/start.S +new file mode 100644 +index 0000000000..3cad3567e7 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/start.S +@@ -0,0 +1,226 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm-offsets.h> ++#include <config.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include <asm/mipsregs.h> ++#include <asm/cacheops.h> ++#include <asm/addrspace.h> ++#include <asm/mipsmtregs.h> ++#include <asm/cm.h> ++#include "../mt7621.h" ++#include "dram.h" ++ ++#ifndef CONFIG_SYS_INIT_SP_ADDR ++#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + \ ++ CONFIG_SYS_INIT_SP_OFFSET) ++#endif ++ ++#define SP_ADDR_TEMP 0xbe10dff0 ++ ++ .macro init_wr sel ++ MTC0 zero, CP0_WATCHLO,\sel ++ mtc0 t1, CP0_WATCHHI,\sel ++ .endm ++ ++ .macro setup_stack_gd ++ li t0, -16 ++ PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR ++ and sp, t1, t0 # force 16 byte alignment ++ PTR_SUBU \ ++ sp, sp, GD_SIZE # reserve space for gd ++ and sp, sp, t0 # force 16 byte alignment ++ move k0, sp # save gd pointer ++#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ ++ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) ++ li t2, CONFIG_VAL(SYS_MALLOC_F_LEN) ++ PTR_SUBU \ ++ sp, sp, t2 # reserve space for early malloc ++ and sp, sp, t0 # force 16 byte alignment ++#endif ++ move fp, sp ++ ++ /* Clear gd */ ++ move t0, k0 ++1: ++ PTR_S zero, 0(t0) ++ PTR_ADDIU t0, PTRSIZE ++ blt t0, t1, 1b ++ nop ++ ++#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ ++ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) ++ PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset ++#endif ++ .endm ++ ++ .set noreorder ++ ++ENTRY(_start) ++ b 1f ++ mtc0 zero, CP0_COUNT ++ ++ /* Stage header required by BootROM */ ++ .org 0x8 ++ .word 0 # ep, filled by mkimage ++ .word 0 # stage_size, filled by mkimage ++ .word 0 # has_stage2 ++ .word 0 # next_ep ++ .word 0 # next_size ++ .word 0 # next_offset ++ ++1: ++ /* Init CP0 Status */ ++ mfc0 t0, CP0_STATUS ++ and t0, ST0_IMPL ++ or t0, ST0_BEV | ST0_ERL ++ mtc0 t0, CP0_STATUS ++ ehb ++ ++ /* Clear Watch Status bits and disable watch exceptions */ ++ li t1, 0x7 # Clear I, R and W conditions ++ init_wr 0 ++ init_wr 1 ++ init_wr 2 ++ init_wr 3 ++ ++ /* Clear WP, IV and SW interrupts */ ++ mtc0 zero, CP0_CAUSE ++ ++ /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */ ++ mtc0 zero, CP0_COMPARE ++ ++ /* VPE1 goes to wait code directly */ ++ mfc0 t0, CP0_TCBIND ++ andi t0, TCBIND_CURVPE ++ bnez t0, launch_vpe_entry ++ nop ++ ++ /* Core1 goes to specific launch entry */ ++ PTR_LI t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) ++ lw t1, GCR_Cx_ID(t0) ++ bnez t1, launch_core_entry ++ nop ++ ++ /* MT7530 reset */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_RSTCTL_REG(t0) ++ ori t1, MCM_RST ++ sw t1, SYSCTL_RSTCTL_REG(t0) ++ ++ /* Disable DMA route for PSE SRAM set by BootROM */ ++ PTR_LI t0, KSEG1ADDR(DMA_CFG_ARB_BASE) ++ sw zero, DMA_ROUTE_REG(t0) ++ ++ /* Set CPU clock to 500MHz (Required if boot from NAND) */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_CLKCFG0_REG(t0) ++ ins t1, zero, 30, 2 # CPU_CLK_SEL ++ sw t1, SYSCTL_CLKCFG0_REG(t0) ++ ++ /* Set CPU clock divider to 1/1 */ ++ li t0, KSEG1ADDR(RBUS_BASE) ++ li t1, 0x101 ++ sw t1, RBUS_DYN_CFG0_REG(t0) ++ ++ /* (Re-)initialize the SRAM */ ++ bal mips_sram_init ++ nop ++ ++ /* Set up temporary stack */ ++ li sp, SP_ADDR_TEMP ++ ++ /* Setup full CPS */ ++ bal mips_cm_map ++ nop ++ ++ bal mt7621_cps_init ++ nop ++ ++ /* Prepare for CPU/DDR initialization binary blob */ ++ bal prepare_stage_bin ++ nop ++ ++ /* Call CPU/DDR initialization binary blob */ ++ li t9, STAGE_LOAD_ADDR ++ jalr t9 ++ nop ++ ++ /* Switch CPU PLL source */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_CLKCFG0_REG(t0) ++ li t2, 1 ++ ins t1, t2, CPU_CLK_SEL_S, 2 ++ sw t1, SYSCTL_CLKCFG0_REG(t0) ++ ++ /* ++ * Currently SPL is running on locked L2 cache (on KSEG0). ++ * To reset the entire cache, we have to writeback SPL to DRAM first. ++ * Cache flush won't work here. Use memcpy instead. ++ */ ++ ++ la a0, __text_start ++ move a1, a0 ++ la a2, __image_copy_end ++ sub a2, a2, a1 ++ li a3, 5 ++ ins a0, a3, 29, 3 # convert to KSEG1 ++ ++ bal memcpy ++ nop ++ ++ /* Disable caches */ ++ bal mips_cache_disable ++ nop ++ ++ /* Reset caches */ ++ bal mips_cache_reset ++ nop ++ ++ /* Disable SRAM */ ++ li t0, KSEG1ADDR(FE_BASE) ++ li t1, FE_PSE_RESET ++ sw t1, FE_RST_GLO_REG(t0) ++ ++ /* Clear the .bss section */ ++ la a0, __bss_start ++ la a1, __bss_end ++1: sw zero, 0(a0) ++ addiu a0, 4 ++ ble a0, a1, 1b ++ nop ++ ++ /* Set up initial stack and global data */ ++ setup_stack_gd ++ ++#if CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) ++ /* Set malloc base */ ++ li t0, (CONFIG_SYS_INIT_SP_ADDR + 15) & (~15) ++ PTR_S t0, GD_MALLOC_BASE(k0) # gd->malloc_base offset ++#endif ++ ++#if defined(CONFIG_DEBUG_UART) && defined(CONFIG_SPL_SERIAL) ++ /* Earliest point to set up debug uart */ ++ bal debug_uart_init ++ nop ++#endif ++ ++ /* Setup timer */ ++ bal set_timer_freq_simple ++ nop ++ ++ /* Bootup secondary CPUs */ ++ bal secondary_cpu_init ++ nop ++ ++ move a0, zero # a0 <-- boot_flags = 0 ++ bal board_init_f ++ move ra, zero ++ ++ END(_start) +diff --git a/arch/mips/mach-mtmips/mt7621/sram_init.S b/arch/mips/mach-mtmips/mt7621/sram_init.S +new file mode 100644 +index 0000000000..03b9eab10b +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/sram_init.S +@@ -0,0 +1,22 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/addrspace.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include "mt7621.h" ++ ++LEAF(mips_sram_init) ++ li t0, KSEG1ADDR(FE_BASE) ++ li t1, FE_PSE_RESET ++ sw t1, FE_RST_GLO_REG(t0) ++ ++ li t1, (FE_PSE_RAM | FE_PSE_MEM_EN) ++ sw t1, FE_RST_GLO_REG(t0) ++ ++ jr ra ++ END(mips_sram_init) +diff --git a/arch/mips/mach-mtmips/mt7621/tpl/Makefile b/arch/mips/mach-mtmips/mt7621/tpl/Makefile +new file mode 100644 +index 0000000000..471ad74249 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/tpl/Makefile +@@ -0,0 +1,4 @@ ++ ++extra-y += start.o ++ ++obj-y += tpl.o +diff --git a/arch/mips/mach-mtmips/mt7621/tpl/start.S b/arch/mips/mach-mtmips/mt7621/tpl/start.S +new file mode 100644 +index 0000000000..19b09f7251 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/tpl/start.S +@@ -0,0 +1,161 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm-offsets.h> ++#include <config.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include <asm/addrspace.h> ++#include <asm/mipsregs.h> ++#include <asm/cm.h> ++#include "../mt7621.h" ++ ++#define SP_ADDR_TEMP 0xbe10dff0 ++ ++ .set noreorder ++ ++ .macro init_wr sel ++ MTC0 zero, CP0_WATCHLO,\sel ++ mtc0 t1, CP0_WATCHHI,\sel ++ .endm ++ ++ .macro uhi_mips_exception ++ move k0, t9 # preserve t9 in k0 ++ move k1, a0 # preserve a0 in k1 ++ li t9, 15 # UHI exception operation ++ li a0, 0 # Use hard register context ++ sdbbp 1 # Invoke UHI operation ++ .endm ++ ++ENTRY(_start) ++ b reset ++ mtc0 zero, CP0_COUNT ++ ++ /* ++ * Store TPL size here. ++ * This will be used by SPL to locate u-boot payload. ++ */ ++ .org TPL_INFO_OFFSET ++ .word TPL_INFO_MAGIC ++ .word __image_copy_len ++ ++ /* Exception vector */ ++ .org 0x200 ++ /* TLB refill, 32 bit task */ ++ uhi_mips_exception ++ ++ .org 0x280 ++ /* XTLB refill, 64 bit task */ ++ uhi_mips_exception ++ ++ .org 0x300 ++ /* Cache error exception */ ++ uhi_mips_exception ++ ++ .org 0x380 ++ /* General exception */ ++ uhi_mips_exception ++ ++ .org 0x400 ++ /* Catch interrupt exceptions */ ++ uhi_mips_exception ++ ++ .org 0x480 ++ /* EJTAG debug exception */ ++1: b 1b ++ nop ++ ++ .org 0x500 ++ ++reset: ++ /* Set KSEG0 to Uncached */ ++ mfc0 t0, CP0_CONFIG ++ ins t0, zero, 0, 3 ++ ori t0, t0, CONF_CM_UNCACHED ++ mtc0 t0, CP0_CONFIG ++ ehb ++ ++ /* Check for CPU number */ ++ mfc0 t0, CP0_EBASE ++ and t0, t0, MIPS_EBASE_CPUNUM ++ beqz t0, 1f ++ nop ++ ++ /* Secondary core goes to specified SPL entry address */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t0, BOOT_SRAM_BASE_REG(t0) ++ jr t0 ++ nop ++ ++ /* Init CP0 Status */ ++1: mfc0 t0, CP0_STATUS ++ and t0, ST0_IMPL ++ or t0, ST0_BEV | ST0_ERL ++ mtc0 t0, CP0_STATUS ++ nop ++ ++ /* Clear Watch Status bits and disable watch exceptions */ ++ li t1, 0x7 # Clear I, R and W conditions ++ init_wr 0 ++ init_wr 1 ++ init_wr 2 ++ init_wr 3 ++ ++ /* Clear WP, IV and SW interrupts */ ++ mtc0 zero, CP0_CAUSE ++ ++ /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */ ++ mtc0 zero, CP0_COMPARE ++ ++ /* Setup basic CPS */ ++ bal mips_cm_map ++ nop ++ ++ li t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) ++ li t1, GCR_REG0_BASE_VALUE ++ sw t1, GCR_REG0_BASE(t0) ++ ++ li t1, ((GCR_REG0_MASK_VALUE << GCR_REGn_MASK_ADDRMASK_SHIFT) | \ ++ GCR_REGn_MASK_CMTGT_IOCU0) ++ sw t1, GCR_REG0_MASK(t0) ++ ++ lw t1, GCR_BASE(t0) ++ ins t1, zero, 0, 2 # CM_DEFAULT_TARGET ++ sw t1, GCR_BASE(t0) ++ ++ lw t1, GCR_CONTROL(t0) ++ li t2, GCR_CONTROL_SYNCCTL ++ or t1, t1, t2 ++ sw t1, GCR_CONTROL(t0) ++ ++ /* Increase SPI frequency */ ++ li t0, KSEG1ADDR(SPI_BASE) ++ li t1, 5 ++ sw t1, SPI_SPACE_REG(t0) ++ ++ /* Set CPU clock to 500MHz */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_CLKCFG0_REG(t0) ++ ins t1, zero, 30, 2 # CPU_CLK_SEL ++ sw t1, SYSCTL_CLKCFG0_REG(t0) ++ ++ /* Set CPU clock divider to 1/1 */ ++ li t0, KSEG1ADDR(RBUS_BASE) ++ li t1, 0x101 ++ sw t1, RBUS_DYN_CFG0_REG(t0) ++ ++ /* Initialize the SRAM */ ++ bal mips_sram_init ++ nop ++ ++ /* Set up initial stack */ ++ li sp, SP_ADDR_TEMP ++ ++ bal tpl_main ++ nop ++ ++ END(_start) +diff --git a/arch/mips/mach-mtmips/mt7621/tpl/tpl.c b/arch/mips/mach-mtmips/mt7621/tpl/tpl.c +new file mode 100644 +index 0000000000..2a828907a3 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/tpl/tpl.c +@@ -0,0 +1,144 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <image.h> ++#include <asm/system.h> ++#include <asm/sections.h> ++#include <asm/cacheops.h> ++#include <asm/mipsregs.h> ++#include <asm/cm.h> ++ ++#define INDEX_STORE_DATA_SD 0x0f ++ ++typedef void __noreturn (*image_entry_noargs_t)(void); ++ ++/* ++ * Lock L2 cache and fill data ++ * Assume that data is 4-byte aligned and start_addr/size is 32-byte aligned ++ */ ++static void fill_lock_l2cache(uintptr_t dataptr, ulong start_addr, ulong size) ++{ ++ ulong slsize = CONFIG_SYS_DCACHE_LINE_SIZE; ++ ulong end_addr = start_addr + size; ++ const u32 *data = (u32 *)dataptr; ++ ulong i, addr; ++ u32 val; ++ ++ /* Clear WSC & SPR bit in ErrCtl */ ++ val = read_c0_ecc(); ++ val &= 0xcfffffff; ++ write_c0_ecc(val); ++ execution_hazard_barrier(); ++ ++ for (addr = start_addr; addr < end_addr; addr += slsize) { ++ /* Set STagLo to lock cache line */ ++ write_c0_staglo((addr & 0x1ffff800) | 0xa0); ++ mips_cache(INDEX_STORE_TAG_SD, (void *)addr); ++ ++ /* Fill data */ ++ for (i = 0; i < slsize; i += 8) { ++ val = *data++; ++ __write_32bit_c0_register($28, 5, val); /* sdtaglo */ ++ val = *data++; ++ __write_32bit_c0_register($29, 5, val); /* sdtaghi */ ++ mips_cache(INDEX_STORE_DATA_SD, (void *)(addr + i)); ++ } ++ } ++ ++ sync(); ++} ++ ++/* A simple function to initialize MT7621's cache */ ++static void mt7621_cache_init(void) ++{ ++ void __iomem *cm_base = (void *)KSEG1ADDR(CONFIG_MIPS_CM_BASE); ++ ulong lsize = CONFIG_SYS_DCACHE_LINE_SIZE; ++ ulong addr; ++ u32 val; ++ ++ /* Enable CCA override. Set to uncached */ ++ val = readl(cm_base + GCR_BASE); ++ val &= ~CCA_DEFAULT_OVR_MASK; ++ val |= CCA_DEFAULT_OVREN | (2 << CCA_DEFAULT_OVR_SHIFT); ++ writel(val, cm_base + GCR_BASE); ++ ++ /* Initialize L1 I-Cache */ ++ write_c0_taglo(0); ++ write_c0_taghi(0); ++ ++ for (addr = 0; addr < CONFIG_SYS_ICACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_STORE_TAG_I, (void *)addr); ++ ++ /* Initialize L1 D-Cache */ ++ write_c0_dtaglo(0); ++ __write_32bit_c0_register($29, 2, 0); /* dtaghi */ ++ ++ for (addr = 0; addr < CONFIG_SYS_DCACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_STORE_TAG_D, (void *)addr); ++ ++ /* Initialize L2 Cache */ ++ write_c0_staglo(0); ++ __write_32bit_c0_register($29, 4, 0); /* staghi */ ++ ++ for (addr = 0; addr < (256 << 10); addr += lsize) ++ mips_cache(INDEX_STORE_TAG_SD, (void *)addr); ++ ++ /* Dsiable CCA override */ ++ val = readl(cm_base + GCR_BASE); ++ val &= ~(CCA_DEFAULT_OVR_MASK | CCA_DEFAULT_OVREN); ++ writel(val, cm_base + GCR_BASE); ++ ++ /* Set KSEG0 to non-coherent cached (important!) */ ++ val = read_c0_config(); ++ val &= ~CONF_CM_CMASK; ++ val |= CONF_CM_CACHABLE_NONCOHERENT; ++ write_c0_config(val); ++ execution_hazard_barrier(); ++ ++ /* Again, invalidate L1 D-Cache */ ++ for (addr = 0; addr < CONFIG_SYS_DCACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_WRITEBACK_INV_D, (void *)addr); ++ ++ /* Invalidate L1 I-Cache */ ++ for (addr = 0; addr < CONFIG_SYS_ICACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_INVALIDATE_I, (void *)addr); ++ ++ /* Disable L2 cache bypass */ ++ val = read_c0_config2(); ++ val &= ~MIPS_CONF_IMPL; ++ write_c0_config2(val); ++ execution_hazard_barrier(); ++} ++ ++void __noreturn tpl_main(void) ++{ ++ const image_header_t *hdr = (const image_header_t *)__image_copy_end; ++ image_entry_noargs_t image_entry; ++ u32 loadaddr, size; ++ uintptr_t data; ++ ++ /* Initialize the cache first */ ++ mt7621_cache_init(); ++ ++ if (image_get_magic(hdr) != IH_MAGIC) ++ goto failed; ++ ++ loadaddr = image_get_load(hdr); ++ size = image_get_size(hdr); ++ image_entry = (image_entry_noargs_t)image_get_ep(hdr); ++ ++ /* Load TPL image to L2 cache */ ++ data = (uintptr_t)__image_copy_end + sizeof(struct image_header); ++ fill_lock_l2cache(data, loadaddr, size); ++ ++ /* Jump to SPL */ ++ image_entry(); ++ ++failed: ++ for (;;) ++ ; ++} +diff --git a/include/configs/mt7621.h b/include/configs/mt7621.h +new file mode 100644 +index 0000000000..dac6aa4afb +--- /dev/null ++++ b/include/configs/mt7621.h +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef __CONFIG_MT7621_H ++#define __CONFIG_MT7621_H ++ ++#define CONFIG_SYS_MIPS_TIMER_FREQ 440000000 ++ ++#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000 ++ ++#define CONFIG_SYS_SDRAM_BASE 0x80000000 ++ ++#define CONFIG_VERY_BIG_RAM ++#define CONFIG_MAX_MEM_MAPPED 0x1c000000 ++ ++#define CONFIG_SYS_INIT_SP_OFFSET 0x800000 ++ ++#define CONFIG_SYS_BOOTM_LEN 0x2000000 ++ ++#define CONFIG_SYS_MAXARGS 16 ++#define CONFIG_SYS_CBSIZE 1024 ++ ++#define CONFIG_SYS_NONCACHED_MEMORY 0x100000 ++ ++/* MMC */ ++#define MMC_SUPPORTS_TUNING ++ ++/* NAND */ ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 ++ ++/* Serial SPL */ ++#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL) ++#define CONFIG_SYS_NS16550_MEM32 ++#define CONFIG_SYS_NS16550_CLK 50000000 ++#define CONFIG_SYS_NS16550_REG_SIZE -4 ++#define CONFIG_SYS_NS16550_COM1 0xbe000c00 ++#endif ++ ++/* Serial common */ ++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, \ ++ 230400, 460800, 921600 } ++ ++/* SPL */ ++#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE ++ ++#ifdef CONFIG_TPL_BUILD ++#define CONFIG_SPL_START_S_PATH "arch/mips/mach-mtmips/mt7621/tpl" ++/* .bss will not be used by TPL */ ++#define CONFIG_SPL_BSS_START_ADDR 0x80000000 ++#define CONFIG_SPL_BSS_MAX_SIZE 0 ++#else ++#define CONFIG_SPL_START_S_PATH "arch/mips/mach-mtmips/mt7621/spl" ++#define CONFIG_SPL_BSS_START_ADDR 0x80140000 ++#define CONFIG_SPL_BSS_MAX_SIZE 0x80000 ++#define CONFIG_SPL_MAX_SIZE 0x30000 ++#endif ++ ++/* Dummy value */ ++#define CONFIG_SYS_UBOOT_BASE 0 ++ ++#endif /* __CONFIG_MT7621_H */ +-- +2.36.1 + |