mips: mtmips: add support for MediaTek MT7620 SoC
authorWeijie Gao <weijie.gao@mediatek.com>
Thu, 12 Nov 2020 08:35:52 +0000 (16:35 +0800)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Sun, 24 Jan 2021 20:39:26 +0000 (21:39 +0100)
This patch adds support for MediaTek MT7620 SoC.
All files are dedicated for u-boot.

Reviewed-by: Stefan Roese <sr@denx.de>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
14 files changed:
arch/mips/dts/mt7620-u-boot.dtsi [new file with mode: 0644]
arch/mips/dts/mt7620.dtsi [new file with mode: 0644]
arch/mips/mach-mtmips/Kconfig
arch/mips/mach-mtmips/Makefile
arch/mips/mach-mtmips/include/mach/mt7620-sysc.h [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/Kconfig [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/Makefile [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/dram.c [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/init.c [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/lowlevel_init.S [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/mt7620.h [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/serial.c [new file with mode: 0644]
arch/mips/mach-mtmips/mt7620/sysc.c [new file with mode: 0644]
include/configs/mt7620.h [new file with mode: 0644]

diff --git a/arch/mips/dts/mt7620-u-boot.dtsi b/arch/mips/dts/mt7620-u-boot.dtsi
new file mode 100644 (file)
index 0000000..ed84257
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+&uartlite {
+       u-boot,dm-pre-reloc;
+};
+
+&uartfull {
+       u-boot,dm-pre-reloc;
+};
diff --git a/arch/mips/dts/mt7620.dtsi b/arch/mips/dts/mt7620.dtsi
new file mode 100644 (file)
index 0000000..03a80b7
--- /dev/null
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/mt7620-clk.h>
+#include <dt-bindings/reset/mt7620-reset.h>
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "mediatek,mt7620-soc";
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       compatible = "mti,mips24KEc";
+                       device_type = "cpu";
+                       reg = <0>;
+               };
+       };
+
+       clk48m: clk48m@0 {
+               compatible = "fixed-clock";
+
+               clock-frequency = <48000000>;
+
+               #clock-cells = <0>;
+       };
+
+       sysc: sysc@10000000 {
+               compatible = "mediatek,mt7620-sysc";
+               reg = <0x10000000 0x100>;
+       };
+
+       clkctrl: clkctrl@10000030 {
+               compatible = "mediatek,mt7620-clk";
+               mediatek,sysc = <&sysc>;
+
+               #clock-cells = <1>;
+       };
+
+       rstctrl: rstctrl@10000034 {
+               compatible = "mediatek,mtmips-reset";
+               reg = <0x10000034 0x4>;
+               #reset-cells = <1>;
+       };
+
+       reboot: resetctl-reboot {
+               compatible = "resetctl-reboot";
+
+               resets = <&rstctrl SYS_RST>;
+               reset-names = "sysreset";
+       };
+
+       uartfull: uartfull@10000500 {
+               compatible = "mediatek,mt7620-uart";
+               reg = <10000500 0x100>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&uartf_gpio_pins>;
+
+               clocks = <&clkctrl CLK_UARTF>;
+
+               resets = <&rstctrl UARTF_RST>;
+               reset-names = "uartf";
+
+               clock-frequency = <40000000>;
+
+               status = "disabled";
+       };
+
+       uartlite: uartlite@10000c00 {
+               compatible = "mediatek,mt7620-uart";
+               reg = <0x10000c00 0x100>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&uartl_pins>;
+
+               clocks = <&clkctrl CLK_UARTL>;
+
+               resets = <&rstctrl UARTL_RST>;
+               reset-names = "uartl";
+
+               clock-frequency = <40000000>;
+       };
+
+       pinctrl: pinctrl@10000060 {
+               compatible = "mediatek,mt7620-pinctrl";
+               reg = <0x10000060 0x4>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pin_state {
+                       sutif_pins {
+                               groups = "sutif";
+                               function = "none";
+                       };
+               };
+
+               nand_pins: nand_pins {
+                       groups = "nand";
+                       function = "nand";
+               };
+
+               sd_pins: sd_pins {
+                       groups = "nand";
+                       function = "sd";
+               };
+
+               spi_single_pins: spi_single_pins {
+                       groups = "spi";
+                       function = "spi";
+               };
+
+               spi_dual_pins: spi_dual_pins {
+                       spi_master_pins {
+                               groups = "spi";
+                               function = "spi";
+                       };
+
+                       spi_cs1_pin {
+                               groups = "spi cs1";
+                               function = "spi cs1";
+                       };
+               };
+
+               uartl_pins: uartl_pins {
+                       groups = "uartl";
+                       function = "uartl";
+               };
+
+               uartf_pins: uartf_pins {
+                       groups = "uartf";
+                       function = "uartf";
+               };
+
+               uartf_pcm_pins: uartf_pcm_pins {
+                       groups = "uartf";
+                       function = "uartf pcm";
+               };
+
+               uartf_i2s_pins: uartf_i2s_pins {
+                       groups = "uartf";
+                       function = "i2s uartf";
+               };
+
+               uartf_gpio_pins: uartf_gpio_pins {
+                       groups = "uartf";
+                       function = "uartf gpio";
+               };
+       };
+
+       watchdog: watchdog@10000120 {
+               compatible = "mediatek,mt7620-wdt";
+               reg = <0x10000120 0x10>;
+
+               resets = <&rstctrl TIMER_RST>;
+               reset-names = "wdt";
+       };
+
+       gpio0: gpio0@10000600 {
+               compatible = "mediatek,mt7620-gpio";
+               reg = <0x10000600 0x34>;
+
+               resets = <&rstctrl PIO_RST>;
+               reset-names = "pio";
+
+               mediatek,bank-name = "PIOA";
+               mediatek,gpio-num = <24>;
+               mediatek,register-map = <0x20 0x24 0x2c 0x30>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       gpio1: gpio1@10000638 {
+               compatible = "mediatek,mt7620-gpio";
+               reg = <0x10000638 0x24>;
+
+               resets = <&rstctrl PIO_RST>;
+               reset-names = "pio";
+
+               mediatek,bank-name = "PIOB";
+               mediatek,gpio-num = <16>;
+               mediatek,register-map = <0x10 0x14 0x1c 0x20>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       gpio2: gpio2@10000660 {
+               compatible = "mediatek,mt7620-gpio";
+               reg = <0x10000660 0x24>;
+
+               resets = <&rstctrl PIO_RST>;
+               reset-names = "pio";
+
+               mediatek,bank-name = "PIOC";
+               mediatek,gpio-num = <32>;
+               mediatek,register-map = <0x10 0x14 0x1c 0x20>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       gpio3: gpio3@10000688 {
+               compatible = "mediatek,mt7620-gpio";
+               reg = <0x10000688 0x24>;
+
+               resets = <&rstctrl PIO_RST>;
+               reset-names = "pio";
+
+               mediatek,bank-name = "PIOD";
+               mediatek,gpio-num = <1>;
+               mediatek,register-map = <0x10 0x14 0x1c 0x20>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       spi0: spi@10000b00 {
+               compatible = "mediatek,mt7620-spi";
+               reg = <0x10000b00 0x100>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&spi_single_pins>;
+
+               resets = <&rstctrl SPI_RST>;
+               reset-names = "spi";
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clocks = <&clkctrl CLK_SPI>;
+       };
+
+       eth: eth@10100000 {
+               compatible = "mediatek,mt7620-eth";
+               reg = <0x10100000 0x10000
+                      0x10110000 0x8000>;
+               reg-names = "fe", "esw";
+
+               mediatek,sysc = <&sysc>;
+
+               resets = <&rstctrl EPHY_RST>,
+                        <&rstctrl ESW_RST>,
+                        <&rstctrl FE_RST>;
+               reset-names = "ephy", "esw", "fe";
+
+               clocks = <&clkctrl CLK_EPHY>,
+                        <&clkctrl CLK_ESW>,
+                        <&clkctrl CLK_FE>;
+               clock-names = "ephy", "esw", "fe";
+
+               status = "disabled";
+       };
+
+       usb_phy: mt7620-usb-phy {
+               compatible = "mediatek,mt7620-usbphy";
+
+               #phy-cells = <0>;
+
+               mediatek,sysc = <&sysc>;
+
+               clocks = <&clkctrl CLK_UPHY_48M>, <&clkctrl CLK_UPHY_12M>;
+               clock-names = "uphy48m", "uphy12m";
+
+               resets = <&rstctrl UHST_RST>, <&rstctrl UDEV_RST>;
+               reset-names = "uhst", "udev";
+       };
+
+       ehci@101c0000 {
+               compatible = "generic-ehci";
+               reg = <0x101c0000 0x1000>;
+
+               phys = <&usb_phy>;
+               phy-names = "usb";
+       };
+
+       mmc: mmc@10130000 {
+               compatible = "mediatek,mt7620-mmc";
+               reg = <0x10130000 0x4000>;
+               builtin-cd = <1>;
+               r_smpl = <1>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&sd_pins>;
+
+               clocks = <&clk48m>, <&clkctrl CLK_SDHC>;
+               clock-names = "source", "hclk";
+
+               resets = <&rstctrl SDHC_RST>;
+
+               status = "disabled";
+       };
+};
index c383e82..8756cad 100644 (file)
@@ -5,6 +5,7 @@ config SYS_MALLOC_F_LEN
        default 0x1000
 
 config SYS_SOC
+       default "mt7620" if SOC_MT7620
        default "mt7628" if SOC_MT7628
 
 config SYS_DCACHE_SIZE
@@ -31,10 +32,26 @@ config SPL_PAYLOAD
 
 config BUILD_TARGET
        default "u-boot-with-spl.bin" if SPL
+       default "u-boot.bin"
 
 choice
        prompt "MediaTek MIPS SoC select"
 
+config SOC_MT7620
+       bool "MT7620"
+       select MIPS_L1_CACHE_SHIFT_5
+       select SYS_MIPS_CACHE_INIT_RAM_LOAD
+       select PINCTRL_MT7620
+       select MT7620_SERIAL
+       select MISC
+       select SPL_SEPARATE_BSS if SPL
+       select SPL_LOADER_SUPPORT if SPL
+       select SPL_OF_CONTROL if SPL_DM
+       select SPL_OF_PLATDATA if SPL_DM
+       select SPL_DM_SERIAL if SPL_DM
+       help
+         This supports MediaTek MT7620.
+
 config SOC_MT7628
        bool "MT7628"
        select MIPS_L1_CACHE_SHIFT_5
@@ -59,6 +76,7 @@ config SOC_MT7628
 
 endchoice
 
+source "arch/mips/mach-mtmips/mt7620/Kconfig"
 source "arch/mips/mach-mtmips/mt7628/Kconfig"
 
 endmenu
index a7e6a66..4909b47 100644 (file)
@@ -5,4 +5,5 @@ obj-y += ddr_init.o
 obj-y += ddr_cal.o
 obj-$(CONFIG_SPL_BUILD) += spl.o
 
+obj-$(CONFIG_SOC_MT7620) += mt7620/
 obj-$(CONFIG_SOC_MT7628) += mt7628/
diff --git a/arch/mips/mach-mtmips/include/mach/mt7620-sysc.h b/arch/mips/mach-mtmips/include/mach/mt7620-sysc.h
new file mode 100644 (file)
index 0000000..743ca03
--- /dev/null
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author:  Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * Definitions of ioctl requests of MT7620 sysc driver
+ */
+
+#ifndef _MT7620_SYSC_H_
+#define _MT7620_SYSC_H_
+
+#include <linux/types.h>
+
+enum mt7620_sysc_requests {
+       MT7620_SYSC_IOCTL_GET_CLK,
+       MT7620_SYSC_IOCTL_GET_CHIP_REV,
+       MT7620_SYSC_IOCTL_SET_GE1_MODE,
+       MT7620_SYSC_IOCTL_SET_GE2_MODE,
+       MT7620_SYSC_IOCTL_SET_USB_MODE,
+       MT7620_SYSC_IOCTL_SET_PCIE_MODE
+};
+
+struct mt7620_sysc_clks {
+       u32 cpu_clk;
+       u32 sys_clk;
+       u32 xtal_clk;
+       u32 peri_clk;
+};
+
+struct mt7620_sysc_chip_rev {
+       bool bga;
+       u32 ver : 4;
+       u32 eco : 4;
+};
+
+enum mt7620_sysc_ge_mode {
+       MT7620_SYSC_GE_RGMII,
+       MT7620_SYSC_GE_MII,
+       MT7620_SYSC_GE_RMII,
+       MT7620_SYSC_GE_ESW_PHY,
+};
+
+enum mt7620_sysc_usb_mode {
+       MT7620_SYSC_USB_DEVICE_MODE,
+       MT7620_SYSC_USB_HOST_MODE
+};
+
+enum mt7620_sysc_pcie_mode {
+       MT7620_SYSC_PCIE_EP_MODE,
+       MT7620_SYSC_PCIE_RC_MODE
+};
+
+#endif /* _MT7620_SYSC_H_ */
diff --git a/arch/mips/mach-mtmips/mt7620/Kconfig b/arch/mips/mach-mtmips/mt7620/Kconfig
new file mode 100644 (file)
index 0000000..aa7cf1d
--- /dev/null
@@ -0,0 +1,54 @@
+
+if SOC_MT7620
+
+config DEBUG_UART_BOARD_INIT
+       default y
+
+choice
+       prompt "Board select"
+
+endchoice
+
+choice
+       prompt "CPU frequency select"
+       default CPU_FREQ_580MHZ
+
+config CPU_FREQ_480MHZ
+       bool "480MHz"
+
+config CPU_FREQ_500MHZ
+       bool "500MHz"
+
+config CPU_FREQ_520MHZ
+       bool "520MHz"
+
+config CPU_FREQ_540MHZ
+       bool "540MHz"
+
+config CPU_FREQ_560MHZ
+       bool "560MHz"
+
+config CPU_FREQ_580MHZ
+       bool "580MHz"
+
+config CPU_FREQ_600MHZ
+       bool "600MHz"
+
+config CPU_FREQ_620MHZ
+       bool "620MHz"
+
+endchoice
+
+config CPU_FREQ_MULTI
+       int
+       range 0 7
+       default 0 if CPU_FREQ_480MHZ
+       default 1 if CPU_FREQ_500MHZ
+       default 2 if CPU_FREQ_520MHZ
+       default 3 if CPU_FREQ_540MHZ
+       default 4 if CPU_FREQ_560MHZ
+       default 5 if CPU_FREQ_580MHZ
+       default 6 if CPU_FREQ_600MHZ
+       default 7 if CPU_FREQ_620MHZ
+
+endif
diff --git a/arch/mips/mach-mtmips/mt7620/Makefile b/arch/mips/mach-mtmips/mt7620/Makefile
new file mode 100644 (file)
index 0000000..649f6c3
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += lowlevel_init.o
+obj-y += init.o
+obj-y += dram.o
+obj-y += serial.o
+
+ifndef CONFIG_SPL_BUILD
+obj-y += sysc.o
+endif
diff --git a/arch/mips/mach-mtmips/mt7620/dram.c b/arch/mips/mach-mtmips/mt7620/dram.c
new file mode 100644 (file)
index 0000000..0f0e64b
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author:  Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <asm/addrspace.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/sizes.h>
+#include <linux/io.h>
+#include <mach/ddr.h>
+#include <mach/mc.h>
+#include "mt7620.h"
+
+/* SDR parameters */
+#define SDR_CFG0_VAL           0x51B283B3
+#define SDR_CFG1_VAL           0xC00003A9
+
+/* DDR2 DQ_DLY */
+#define DDR2_DQ_DLY            0x88888888
+
+/* DDR2 DQS_DLY */
+#define DDR2_DQS_DLY           0x88888888
+
+static const struct mc_ddr_cfg ddr1_cfgs_200mhz[] = {
+       [DRAM_8MB]   = { 0x34A1EB94, 0x20262324, 0x28000033, 0x00000002, 0x00000000 },
+       [DRAM_16MB]  = { 0x34A1EB94, 0x202A2324, 0x28000033, 0x00000002, 0x00000000 },
+       [DRAM_32MB]  = { 0x34A1E5CA, 0x202E2324, 0x28000033, 0x00000002, 0x00000000 },
+       [DRAM_64MB]  = { 0x3421E5CA, 0x20322324, 0x28000033, 0x00000002, 0x00000000 },
+       [DRAM_128MB] = { 0x241B05CA, 0x20362334, 0x28000033, 0x00000002, 0x00000000 },
+};
+
+static const struct mc_ddr_cfg ddr1_cfgs_160mhz[] = {
+       [DRAM_8MB]   = { 0x239964A1, 0x20262323, 0x00000033, 0x00000002, 0x00000000 },
+       [DRAM_16MB]  = { 0x239964A1, 0x202A2323, 0x00000033, 0x00000002, 0x00000000 },
+       [DRAM_32MB]  = { 0x239964A1, 0x202E2323, 0x00000033, 0x00000002, 0x00000000 },
+       [DRAM_64MB]  = { 0x239984A1, 0x20322323, 0x00000033, 0x00000002, 0x00000000 },
+       [DRAM_128MB] = { 0x239AB4A1, 0x20362333, 0x00000033, 0x00000002, 0x00000000 },
+};
+
+static const struct mc_ddr_cfg ddr2_cfgs_200mhz[] = {
+       [DRAM_32MB]  = { 0x2519E2E5, 0x222E2323, 0x68000C43, 0x00000416, 0x0000000A },
+       [DRAM_64MB]  = { 0x249AA2E5, 0x22322323, 0x68000C43, 0x00000416, 0x0000000A },
+       [DRAM_128MB] = { 0x249B42E5, 0x22362323, 0x68000C43, 0x00000416, 0x0000000A },
+       [DRAM_256MB] = { 0x249CE2E5, 0x223A2323, 0x68000C43, 0x00000416, 0x0000000A },
+};
+
+static const struct mc_ddr_cfg ddr2_cfgs_160mhz[] = {
+       [DRAM_32MB]  = { 0x23918250, 0x222E2322, 0x40000A43, 0x00000416, 0x00000006 },
+       [DRAM_64MB]  = { 0x239A2250, 0x22322322, 0x40000A43, 0x00000416, 0x00000008 },
+       [DRAM_128MB] = { 0x2392A250, 0x22362322, 0x40000A43, 0x00000416, 0x00000008 },
+       [DRAM_256MB] = { 0x24140250, 0x223A2322, 0x40000A43, 0x00000416, 0x00000008 },
+};
+
+static void mt7620_memc_reset(int assert)
+{
+       void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+
+       if (assert)
+               setbits_32(sysc + SYSCTL_RSTCTL_REG, MC_RST);
+       else
+               clrbits_32(sysc + SYSCTL_RSTCTL_REG, MC_RST);
+}
+
+void mt7620_dram_init(void)
+{
+       void __iomem *sysc;
+       bool lspd = false;
+       int ddr_type, aux;
+       struct mc_ddr_init_param param;
+
+       sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+       ddr_type = (readl(sysc + SYSCTL_SYSCFG0_REG) & DRAM_TYPE_M)
+                  >> DRAM_TYPE_S;
+       aux = readl(sysc + SYSCTL_CPLL_CFG1_REG) &
+             (CPU_CLK_AUX1 | CPU_CLK_AUX0);
+
+       if (aux == CPU_CLK_AUX1 || aux == CPU_CLK_AUX0)
+               lspd = true;
+
+       mt7620_memc_reset(1);
+       __udelay(200);
+
+       param.memc = ioremap_nocache(MEMCTL_BASE, MEMCTL_SIZE);
+       param.dq_dly = DDR2_DQ_DLY;
+       param.dqs_dly = DDR2_DQS_DLY;
+       param.mc_reset = mt7620_memc_reset;
+       param.memsize = 0;
+       param.bus_width = 0;
+
+       if (ddr_type == DRAM_DDR1) {
+               if (lspd)
+                       param.cfgs = ddr1_cfgs_160mhz;
+               else
+                       param.cfgs = ddr1_cfgs_200mhz;
+
+               ddr1_init(&param);
+       } else if (ddr_type == DRAM_DDR2) {
+               if (lspd)
+                       param.cfgs = ddr2_cfgs_160mhz;
+               else
+                       param.cfgs = ddr2_cfgs_200mhz;
+
+               ddr2_init(&param);
+       } else {
+               param.sdr_cfg0 = SDR_CFG0_VAL;
+               param.sdr_cfg1 = SDR_CFG1_VAL;
+
+               sdr_init(&param);
+       }
+}
diff --git a/arch/mips/mach-mtmips/mt7620/init.c b/arch/mips/mach-mtmips/mt7620/init.c
new file mode 100644 (file)
index 0000000..93abf92
--- /dev/null
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author:  Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <config.h>
+#include <asm/global_data.h>
+#include <linux/io.h>
+#include "mt7620.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char * const dram_type[] = {
+       "SDRAM", "DDR", "DDR2", "SDRAM"
+};
+
+static const char * const boot_mode[(CHIP_MODE_M >> CHIP_MODE_S) + 1] = {
+       [1] = "NAND 4-cycles 2KB-page",
+       [2] = "SPI-NOR 3-Byte Addr",
+       [3] = "SPI-NOR 4-Byte Addr",
+       [10] = "NAND 4-cycles 512B-page",
+       [11] = "NAND 5-cycles 2KB-page",
+       [12] = "NAND 3-cycles 512B-page",
+};
+
+static void cpu_pll_init(void)
+{
+       void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+       u32 pllmul = CONFIG_CPU_FREQ_MULTI;
+
+       /* Make sure the pll multiplier is valid */
+       if (pllmul > 7)
+               pllmul = 7;
+
+       /* Set init CPU clock to 480MHz */
+       clrsetbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPU_CLK_AUX1, CPU_CLK_AUX0);
+
+       /* Enable software control of CPU PLL */
+       setbits_32(sysc + SYSCTL_CPLL_CFG0_REG, CPLL_SW_CFG);
+
+       /* CPU PLL power down */
+       setbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPLL_PD);
+
+       /* PLL configuration */
+       clrsetbits_32(sysc + SYSCTL_CPLL_CFG0_REG, PLL_MULT_RATIO_M |
+                     PLL_DIV_RATIO_M | SSC_UP_BOUND_M | SSC_EN,
+                     (pllmul << PLL_MULT_RATIO_S) | SSC_SWING_M);
+
+       /* CPU PLL power up */
+       clrbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPLL_PD);
+
+       /* Wait for CPU PLL locked */
+       while (!(readl(sysc + SYSCTL_CPLL_CFG1_REG) & CPLL_LD))
+               ;
+
+       /* Set final CPU clock source */
+       clrbits_32(sysc + SYSCTL_CPLL_CFG1_REG, CPU_CLK_AUX1 | CPU_CLK_AUX0);
+
+       /* Adjust CPU clock */
+       clrsetbits_32(sysc + SYSCTL_CPU_SYS_CLKCFG_REG,
+                     CPU_FDIV_M | CPU_FFRAC_M,
+                     (1 << CPU_FDIV_S) | (1 << CPU_FFRAC_S));
+}
+
+void mt7620_init(void)
+{
+       u32 cpu_clk;
+
+       cpu_pll_init();
+
+       /*
+        * Set timer freq, which will be used during DRAM initialization
+        * Note that this function is using a temporary gd which will be
+        * destroyed after leaving this function.
+        */
+       mt7620_get_clks(&cpu_clk, NULL, NULL);
+       gd->arch.timer_freq = cpu_clk / 2;
+
+       mt7620_dram_init();
+}
+
+void mt7620_get_clks(u32 *cpu_clk, u32 *sys_clk, u32 *xtal_clk)
+{
+       void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+       u32 val, multi, div, fdiv, ffrac, dram_type, sys_div;
+       u32 cpu_freq, xtal_freq;
+
+       static const u32 div_ratio_table[] = {2, 3, 4, 8};
+
+       val = readl(sysc + SYSCTL_SYSCFG0_REG);
+
+       dram_type = (val & DRAM_TYPE_M) >> DRAM_TYPE_S;
+
+       if (val & XTAL_FREQ_SEL)
+               xtal_freq = 40000000;
+       else
+               xtal_freq = 20000000;
+
+       val = readl(sysc + SYSCTL_CPLL_CFG1_REG);
+       if (val & CPU_CLK_AUX1) {
+               cpu_freq = xtal_freq;
+       } else if (val & CPU_CLK_AUX0) {
+               cpu_freq = 480000000;
+       } else {
+               val = readl(sysc + SYSCTL_CPLL_CFG0_REG);
+               if (val & CPLL_SW_CFG) {
+                       multi = (val & PLL_MULT_RATIO_M) >> PLL_MULT_RATIO_S;
+                       div = (val & PLL_DIV_RATIO_M) >> PLL_DIV_RATIO_S;
+                       cpu_freq = (multi + 24) * 40000000 /
+                                       div_ratio_table[div];
+               } else {
+                       cpu_freq = 600000000;
+               }
+       }
+
+       val = readl(sysc + SYSCTL_CUR_CLK_STS_REG);
+       ffrac = (val & CUR_CPU_FFRAC_M) >> CUR_CPU_FFRAC_S;
+       fdiv = (val & CUR_CPU_FDIV_M) >> CUR_CPU_FDIV_S;
+       cpu_freq = (cpu_freq * ffrac) / fdiv;
+
+       switch (dram_type) {
+       case DRAM_SDRAM_E1:
+               sys_div = 4;
+               break;
+       case DRAM_DDR1:
+       case DRAM_DDR2:
+               sys_div = 3;
+               break;
+       case DRAM_SDRAM:
+               sys_div = 5;
+               break;
+       }
+
+       if (cpu_clk)
+               *cpu_clk = cpu_freq;
+
+       if (sys_clk)
+               *sys_clk = cpu_freq / sys_div;
+
+       if (xtal_clk)
+               *xtal_clk = xtal_freq;
+}
+
+int print_cpuinfo(void)
+{
+       void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+       u32 cpu_clk, bus_clk, xtal_clk;
+       u32 val, ver, eco, pkg, dram, chipmode;
+       const char *bootdev;
+
+       val = readl(sysc + SYSCTL_CHIP_REV_ID_REG);
+       ver = (val & VER_M) >> VER_S;
+       eco = (val & ECO_M) >> ECO_S;
+       pkg = !!(val & PKG_ID);
+
+       val = readl(sysc + SYSCTL_SYSCFG0_REG);
+       dram = (val & DRAM_TYPE_M) >> DRAM_TYPE_S;
+       chipmode = (val & CHIP_MODE_M) >> CHIP_MODE_S;
+
+       bootdev = boot_mode[chipmode];
+       if (!bootdev)
+               bootdev = "Unsupported boot mode";
+
+       printf("CPU:   MediaTek MT7620%c ver:%u eco:%u\n",
+              pkg ? 'A' : 'N', ver, eco);
+
+       printf("Boot:  %s, %s\n", dram_type[dram], bootdev);
+
+       mt7620_get_clks(&cpu_clk, &bus_clk, &xtal_clk);
+
+       /* Set final timer frequency */
+       gd->arch.timer_freq = cpu_clk / 2;
+
+       printf("Clock: CPU: %uMHz, Bus: %uMHz, XTAL: %uMHz\n",
+              cpu_clk / 1000000, bus_clk / 1000000, xtal_clk / 1000000);
+
+       return 0;
+}
+
+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/mt7620/lowlevel_init.S b/arch/mips/mach-mtmips/mt7620/lowlevel_init.S
new file mode 100644 (file)
index 0000000..3991746
--- /dev/null
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author:  Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <config.h>
+#include <asm-offsets.h>
+#include <asm/regdef.h>
+#include <asm/asm.h>
+
+       .set noreorder
+
+NESTED(lowlevel_init, 0, ra)
+       /* Save ra and do real lowlevel initialization */
+       move    s0, ra
+
+       /*
+       * Use SRAM from 802.11n MAC/BBP, 16KiB (0x10184000 ~ 0x10187fff)
+       * NOTE: non-word operations may fail in this SRAM.
+       * Use it as stack only for CPU/DRAM init which only has word operations.
+       */
+       PTR_LI  sp, 0xb0187f00
+
+       /* We still need a temporary gd for udelay */
+       PTR_SUBU \
+               sp, sp, GD_SIZE         # reserve space for gd
+       li      t0, -16
+       and     sp, sp, t0              # force 16 byte alignment
+       move    k0, sp                  # save gd pointer
+
+       move    fp, sp
+
+       /* Clear gd */
+       move    t0, k0
+1:
+       PTR_S   zero, 0(t0)
+       PTR_ADDIU t0, PTRSIZE
+       blt     t0, t1, 1b
+        nop
+
+       /* Do CPU & DRAM initialization */
+       PTR_LA  t9, mt7620_init
+       jalr    t9
+        nop
+
+       /* Restore ra */
+       move    ra, s0
+
+       jr      ra
+        nop
+       END(lowlevel_init)
diff --git a/arch/mips/mach-mtmips/mt7620/mt7620.h b/arch/mips/mach-mtmips/mt7620/mt7620.h
new file mode 100644 (file)
index 0000000..dd5e6d0
--- /dev/null
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author:  Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#ifndef _MT7620_H_
+#define _MT7620_H_
+
+#include <linux/bitops.h>
+
+#define SYSCTL_BASE                    0x10000000
+#define SYSCTL_SIZE                    0x100
+#define MEMCTL_BASE                    0x10000300
+#define MEMCTL_SIZE                    0x100
+#define UARTFULL_BASE                  0x10000500
+#define UARTFULL_SIZE                  0x100
+#define UARTLITE_BASE                  0x10000c00
+#define UARTLITE_SIZE                  0x100
+
+#define SYSCTL_CHIP_REV_ID_REG         0x0c
+#define PKG_ID                         BIT(16)
+#define   PKG_ID_A                     1
+#define   PKG_ID_N                     0
+#define VER_S                          8
+#define VER_M                          GENMASK(11, 8)
+#define ECO_S                          0
+#define ECO_M                          GENMASK(3, 0)
+
+#define SYSCTL_SYSCFG0_REG             0x10
+#define XTAL_FREQ_SEL                  BIT(6)
+#define   XTAL_40MHZ                   1
+#define   XTAL_20MHZ                   0
+#define DRAM_TYPE_S                    4
+#define DRAM_TYPE_M                    GENMASK(5, 4)
+#define   DRAM_SDRAM                   3
+#define   DRAM_DDR2                    2
+#define   DRAM_DDR1                    1
+#define   DRAM_SDRAM_E1                        0
+#define CHIP_MODE_S                    0
+#define CHIP_MODE_M                    GENMASK(3, 0)
+
+#define SYSCTL_SYSCFG1_REG             0x14
+#define GE2_MODE_S                     14
+#define GE2_MODE_M                     GENMASK(15, 14)
+#define GE1_MODE_S                     12
+#define GE1_MODE_M                     GENMASK(13, 12)
+#define USB0_HOST_MODE                 BIT(10)
+#define PCIE_RC_MODE                   BIT(8)
+#define GE_MODE_M                      GENMASK(1, 0)
+
+#define SYSCTL_RSTCTL_REG              0x34
+#define MC_RST                         BIT(10)
+#define SYS_RST                                BIT(0)
+
+#define SYSCTL_CLKCFG0_REG             0x2c
+#define PERI_CLK_SEL                   BIT(4)
+
+#define SYSCTL_CPU_SYS_CLKCFG_REG      0x3c
+#define CPU_OCP_RATIO_S                        16
+#define CPU_OCP_RATIO_M                        GENMASK(19, 16)
+#define CPU_FDIV_S                     8
+#define CPU_FDIV_M                     GENMASK(12, 8)
+#define CPU_FFRAC_S                    0
+#define CPU_FFRAC_M                    GENMASK(4, 0)
+
+#define SYSCTL_CUR_CLK_STS_REG         0x44
+#define CUR_CPU_OCP_RATIO_S            16
+#define CUR_CPU_OCP_RATIO_M            GENMASK(19, 16)
+#define CUR_CPU_FDIV_S                 8
+#define CUR_CPU_FDIV_M                 GENMASK(12, 8)
+#define CUR_CPU_FFRAC_S                        0
+#define CUR_CPU_FFRAC_M                        GENMASK(4, 0)
+
+#define SYSCTL_CPLL_CFG0_REG           0x54
+#define CPLL_SW_CFG                    BIT(31)
+#define PLL_MULT_RATIO_S               16
+#define PLL_MULT_RATIO_M               GENMASK(18, 16)
+#define PLL_DIV_RATIO_S                        10
+#define PLL_DIV_RATIO_M                        GENMASK(11, 10)
+#define SSC_UP_BOUND_S                 8
+#define SSC_UP_BOUND_M                 GENMASK(9, 8)
+#define SSC_EN                         BIT(7)
+#define SSC_SWING_S                    4
+#define SSC_SWING_M                    GENMASK(6, 4)
+
+#define SYSCTL_CPLL_CFG1_REG           0x58
+#define CPLL_PD                                BIT(26)
+#define CPU_CLK_AUX1                   BIT(25)
+#define CPU_CLK_AUX0                   BIT(24)
+#define CPLL_LD                                BIT(23)
+
+#define SYSCTL_GPIOMODE_REG            0x60
+#define UARTL_GPIO_MODE                        BIT(5)
+#define UARTF_SHARE_MODE_S             2
+#define UARTF_SHARE_MODE_M             GENMASK(4, 2)
+#define   UARTF_MODE_UARTF_GPIO                5
+
+void mt7620_dram_init(void);
+void mt7620_get_clks(u32 *cpu_clk, u32 *sys_clk, u32 *xtal_clk);
+
+#endif /* _MT7620_H_ */
diff --git a/arch/mips/mach-mtmips/mt7620/serial.c b/arch/mips/mach-mtmips/mt7620/serial.c
new file mode 100644 (file)
index 0000000..44f061c
--- /dev/null
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc.
+ *
+ * Author:  Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include "mt7620.h"
+
+void board_debug_uart_init(void)
+{
+       void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+
+#if CONFIG_DEBUG_UART_BASE == 0xb0000500 /* KSEG1ADDR(UARTFULL_BASE) */
+       clrsetbits_32(base + SYSCTL_GPIOMODE_REG, UARTF_SHARE_MODE_M,
+                     UARTF_MODE_UARTF_GPIO << UARTF_SHARE_MODE_S);
+#else
+       clrbits_32(base + SYSCTL_GPIOMODE_REG, UARTL_GPIO_MODE);
+#endif
+}
+
+void mtmips_spl_serial_init(void)
+{
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
+       void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE);
+
+#if CONFIG_CONS_INDEX == 1
+       clrbits_32(base + SYSCTL_GPIOMODE_REG, UARTL_GPIO_MODE);
+#elif CONFIG_CONS_INDEX == 2
+       clrsetbits_32(base + SYSCTL_GPIOMODE_REG, UARTF_SHARE_MODE_M,
+                     UARTF_MODE_UARTF_GPIO << UARTF_SHARE_MODE_S);
+#endif
+#endif /* CONFIG_SPL_SERIAL_SUPPORT */
+}
diff --git a/arch/mips/mach-mtmips/mt7620/sysc.c b/arch/mips/mach-mtmips/mt7620/sysc.c
new file mode 100644 (file)
index 0000000..296a9be
--- /dev/null
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author:  Weijie Gao <weijie.gao@mediatek.com>
+ *
+ * Misc driver for manipulating System control registers
+ */
+
+#include <dm.h>
+#include <misc.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <dm/device_compat.h>
+#include <mach/mt7620-sysc.h>
+#include "mt7620.h"
+
+struct mt7620_sysc_priv {
+       void __iomem *base;
+};
+
+static int mt7620_sysc_read(struct udevice *dev, int offset, void *buf,
+                           int size)
+{
+       struct mt7620_sysc_priv *priv = dev_get_priv(dev);
+       u32 val;
+
+       if (offset % sizeof(u32) || size != sizeof(u32) ||
+           offset >= SYSCTL_SIZE)
+               return -EINVAL;
+
+       val = readl(priv->base + offset);
+
+       if (buf)
+               *(u32 *)buf = val;
+
+       return 0;
+}
+
+static int mt7620_sysc_write(struct udevice *dev, int offset, const void *buf,
+                            int size)
+{
+       struct mt7620_sysc_priv *priv = dev_get_priv(dev);
+       u32 val;
+
+       if (offset % sizeof(u32) || size != sizeof(u32) ||
+           offset >= SYSCTL_SIZE || !buf)
+               return -EINVAL;
+
+       val = *(u32 *)buf;
+       writel(val, priv->base + offset);
+
+       return 0;
+}
+
+static int mt7620_sysc_ioctl(struct udevice *dev, unsigned long request,
+                            void *buf)
+{
+       struct mt7620_sysc_priv *priv = dev_get_priv(dev);
+       struct mt7620_sysc_chip_rev *chip_rev;
+       struct mt7620_sysc_clks *clks;
+       u32 val, shift;
+
+       if (!buf)
+               return -EINVAL;
+
+       switch (request) {
+       case MT7620_SYSC_IOCTL_GET_CLK:
+               clks = buf;
+               mt7620_get_clks(&clks->cpu_clk, &clks->sys_clk,
+                               &clks->xtal_clk);
+
+               val = readl(priv->base + SYSCTL_CLKCFG0_REG);
+               if (val & PERI_CLK_SEL)
+                       clks->peri_clk = clks->xtal_clk;
+               else
+                       clks->peri_clk = 40000000;
+
+               return 0;
+
+       case MT7620_SYSC_IOCTL_GET_CHIP_REV:
+               chip_rev = buf;
+
+               val = readl(priv->base + SYSCTL_CHIP_REV_ID_REG);
+
+               chip_rev->bga = !!(val & PKG_ID);
+               chip_rev->ver = (val & VER_M) >> VER_S;
+               chip_rev->eco = (val & ECO_M) >> ECO_S;
+
+               return 0;
+
+       case MT7620_SYSC_IOCTL_SET_GE1_MODE:
+       case MT7620_SYSC_IOCTL_SET_GE2_MODE:
+               val = *(u32 *)buf;
+
+               if (val > MT7620_SYSC_GE_ESW_PHY)
+                       return -EINVAL;
+
+               if (request == MT7620_SYSC_IOCTL_SET_GE1_MODE)
+                       shift = GE1_MODE_S;
+               else
+                       shift = GE2_MODE_S;
+
+               clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
+                             GE_MODE_M << shift, val << shift);
+
+               return 0;
+
+       case MT7620_SYSC_IOCTL_SET_USB_MODE:
+               val = *(u32 *)buf;
+
+               if (val == MT7620_SYSC_USB_DEVICE_MODE)
+                       val = 0;
+               else if (val == MT7620_SYSC_USB_HOST_MODE)
+                       val = USB0_HOST_MODE;
+
+               clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
+                             USB0_HOST_MODE, val);
+
+               return 0;
+
+       case MT7620_SYSC_IOCTL_SET_PCIE_MODE:
+               val = *(u32 *)buf;
+
+               if (val == MT7620_SYSC_PCIE_EP_MODE)
+                       val = 0;
+               else if (val == MT7620_SYSC_PCIE_RC_MODE)
+                       val = PCIE_RC_MODE;
+
+               clrsetbits_32(priv->base + SYSCTL_SYSCFG1_REG,
+                             PCIE_RC_MODE, val);
+
+               return 0;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int mt7620_sysc_probe(struct udevice *dev)
+{
+       struct mt7620_sysc_priv *priv = dev_get_priv(dev);
+
+       priv->base = dev_remap_addr_index(dev, 0);
+       if (!priv->base) {
+               dev_err(dev, "failed to map sysc registers\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct misc_ops mt7620_sysc_ops = {
+       .read = mt7620_sysc_read,
+       .write = mt7620_sysc_write,
+       .ioctl = mt7620_sysc_ioctl,
+};
+
+static const struct udevice_id mt7620_sysc_ids[] = {
+       { .compatible = "mediatek,mt7620-sysc" },
+       { }
+};
+
+U_BOOT_DRIVER(mt7620_sysc) = {
+       .name           = "mt7620_sysc",
+       .id             = UCLASS_MISC,
+       .of_match       = mt7620_sysc_ids,
+       .probe          = mt7620_sysc_probe,
+       .ops            = &mt7620_sysc_ops,
+       .priv_auto      = sizeof(struct mt7620_sysc_priv),
+       .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/configs/mt7620.h b/include/configs/mt7620.h
new file mode 100644 (file)
index 0000000..4d074a3
--- /dev/null
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#ifndef __CONFIG_MT7620_H
+#define __CONFIG_MT7620_H
+
+#define CONFIG_SYS_HZ                  1000
+#define CONFIG_SYS_MIPS_TIMER_FREQ     290000000
+
+#define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_MALLOC_LEN          0x100000
+#define CONFIG_SYS_BOOTPARAMS_LEN      0x20000
+
+#define CONFIG_SYS_SDRAM_BASE          0x80000000
+#define CONFIG_SYS_LOAD_ADDR           0x80010000
+
+#define CONFIG_SYS_INIT_SP_OFFSET      0x400000
+
+#define CONFIG_SYS_BOOTM_LEN           0x1000000
+
+#define CONFIG_SYS_MAXARGS             16
+#define CONFIG_SYS_CBSIZE              1024
+
+/* Serial common */
+#define CONFIG_SYS_BAUDRATE_TABLE      { 9600, 19200, 38400, 57600, 115200 }
+
+/* SPL */
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#endif
+
+#define CONFIG_SYS_UBOOT_START         CONFIG_SYS_TEXT_BASE
+#define CONFIG_SPL_BSS_START_ADDR      0x80010000
+#define CONFIG_SPL_BSS_MAX_SIZE                0x10000
+#define CONFIG_SPL_MAX_SIZE            0x10000
+#define CONFIG_SPL_PAD_TO              0
+
+/* Dummy value */
+#define CONFIG_SYS_UBOOT_BASE          0
+
+#endif /* __CONFIG_MT7620_H */