diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 30fb9bf..10b55c9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -69,6 +69,21 @@ config ARCH_BMIPS select SYSRESET imply CMD_DM +config ARCH_MT7620 + bool "Support MT7620/7688 SoCs" + imply CMD_DM + select DISPLAY_CPUINFO + select DM + select DM_SERIAL + imply DM_SPI + imply DM_SPI_FLASH + select MIPS_TUNE_24KC + select OF_CONTROL + select ROM_EXCEPTION_VECTORS + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + select SUPPORTS_LITTLE_ENDIAN + config MACH_PIC32 bool "Support Microchip PIC32" select DM @@ -121,6 +136,7 @@ source "board/qemu-mips/Kconfig" source "arch/mips/mach-ath79/Kconfig" source "arch/mips/mach-bmips/Kconfig" source "arch/mips/mach-pic32/Kconfig" +source "arch/mips/mach-mt7620/Kconfig" if MIPS diff --git a/arch/mips/Makefile b/arch/mips/Makefile index a36f5f1..802244a 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -14,6 +14,7 @@ libs-y += arch/mips/lib/ machine-$(CONFIG_ARCH_ATH79) += ath79 machine-$(CONFIG_ARCH_BMIPS) += bmips machine-$(CONFIG_MACH_PIC32) += pic32 +machine-$(CONFIG_ARCH_MT7620) += mt7620 machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y)) libs-y += $(machdirs) diff --git a/arch/mips/dts/mt7628a.dtsi b/arch/mips/dts/mt7628a.dtsi new file mode 100644 index 0000000..d00f528 --- /dev/null +++ b/arch/mips/dts/mt7628a.dtsi @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0 + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,mt7628a-soc"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "mti,mips24KEc"; + device_type = "cpu"; + reg = <0>; + }; + }; + + resetc: reset-controller { + compatible = "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + cpuintc: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus", "simple-bus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc: system-controller@0 { + compatible = "ralink,mt7620a-sysc", "syscon"; + reg = <0x0 0x100>; + }; + + intc: interrupt-controller@200 { + compatible = "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + interrupt-controller; + #interrupt-cells = <1>; + + resets = <&resetc 9>; + reset-names = "intc"; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + + ralink,intc-registers = <0x9c 0xa0 + 0x6c 0xa4 + 0x80 0x78>; + }; + + memory-controller@300 { + compatible = "ralink,mt7620a-memc"; + reg = <0x300 0x100>; + }; + + spi0: spi@b00 { + compatible = "ralink,mt7621-spi"; + reg = <0xb00 0x40>; + #address-cells = <1>; + #size-cells = <0>; + }; + + uart0: uartlite@c00 { + compatible = "ns16550a"; + reg = <0xc00 0x100>; + + resets = <&resetc 12>; + reset-names = "uart0"; + + interrupt-parent = <&intc>; + interrupts = <20>; + + reg-shift = <2>; + }; + + uart1: uart1@d00 { + compatible = "ns16550a"; + reg = <0xd00 0x100>; + + resets = <&resetc 19>; + reset-names = "uart1"; + + interrupt-parent = <&intc>; + interrupts = <21>; + + reg-shift = <2>; + }; + + uart2: uart2@e00 { + compatible = "ns16550a"; + reg = <0xe00 0x100>; + + resets = <&resetc 20>; + reset-names = "uart2"; + + interrupt-parent = <&intc>; + interrupts = <22>; + + reg-shift = <2>; + }; + }; + + usb_phy: usb-phy@10120000 { + compatible = "mediatek,mt7628-usbphy"; + reg = <0x10120000 0x1000>; + + #phy-cells = <0>; + + ralink,sysctl = <&sysc>; + resets = <&resetc 22 &resetc 25>; + reset-names = "host", "device"; + }; + + ehci@101c0000 { + compatible = "generic-ehci"; + reg = <0x101c0000 0x1000>; + + phys = <&usb_phy>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + }; +}; diff --git a/arch/mips/mach-mt7620/Kconfig b/arch/mips/mach-mt7620/Kconfig new file mode 100644 index 0000000..396fbd0 --- /dev/null +++ b/arch/mips/mach-mt7620/Kconfig @@ -0,0 +1,113 @@ +menu "MediaTek MIPS platforms" + depends on ARCH_MT7620 + +config SYS_MALLOC_F_LEN + default 0x1000 + +config SYS_SOC + default "mt7620" if SOC_MT7620 + +choice + prompt "MediaTek MIPS SoC select" + +config SOC_MT7620 + bool "MT7620/8" + select MIPS_L1_CACHE_SHIFT_5 + help + This supports MediaTek MIPS MT7620 family. + +endchoice + +choice + prompt "Board select" + +endchoice + +choice + prompt "Boot mode" + +config BOOT_RAM + bool "RAM boot" + depends on SUPPORTS_BOOT_RAM + help + This builds an image that is linked to a RAM address. It can be used + for booting from CFE via TFTP using an ELF image, but it can also be + booted from RAM by other bootloaders using a BIN image. + +config BOOT_ROM + bool "ROM boot" + depends on SUPPORTS_BOOT_RAM + help + This builds an image that is linked to a ROM address. It can be + used as main bootloader image which is programmed onto the onboard + flash storage (SPI NOR). + +endchoice + +choice + prompt "DDR2 size" + +config ONBOARD_DDR2_SIZE_256MBIT + bool "256MBit (32MByte) total size" + depends on BOOT_ROM + help + Use 256MBit (32MByte) of DDR total size + +config ONBOARD_DDR2_SIZE_512MBIT + bool "512MBit (64MByte) total size" + depends on BOOT_ROM + help + Use 512MBit (64MByte) of DDR total size + +config ONBOARD_DDR2_SIZE_1024MBIT + bool "1024MBit (128MByte) total size" + depends on BOOT_ROM + help + Use 1024MBit (128MByte) of DDR total size + +config ONBOARD_DDR2_SIZE_2048MBIT + bool "2048MBit (256MByte) total size" + depends on BOOT_ROM + help + Use 2048MBit (256MByte) of DDR total size + +endchoice + +choice + prompt "DDR2 chip width" + +config ONBOARD_DDR2_CHIP_WIDTH_8BIT + bool "8bit DDR chip width" + depends on BOOT_ROM + help + Use DDR chips with 8bit width + +config ONBOARD_DDR2_CHIP_WIDTH_16BIT + bool "16bit DDR chip width" + depends on BOOT_ROM + help + Use DDR chips with 16bit width + +endchoice + +choice + prompt "DDR2 bus width" + +config ONBOARD_DDR2_BUS_WIDTH_16BIT + bool "16bit DDR bus width" + depends on BOOT_ROM + help + Use 16bit DDR bus width + +config ONBOARD_DDR2_BUS_WIDTH_32BIT + bool "32bit DDR bus width" + depends on BOOT_ROM + help + Use 32bit DDR bus width + +endchoice + +config SUPPORTS_BOOT_RAM + bool + +endmenu diff --git a/arch/mips/mach-mt7620/Makefile b/arch/mips/mach-mt7620/Makefile new file mode 100644 index 0000000..1f3e65e --- /dev/null +++ b/arch/mips/mach-mt7620/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += cpu.o + +ifndef CONFIG_SKIP_LOWLEVEL_INIT +obj-y += ddr_calibrate.o +obj-y += lowlevel_init.o +endif diff --git a/arch/mips/mach-mt7620/cpu.c b/arch/mips/mach-mt7620/cpu.c new file mode 100644 index 0000000..457f09f --- /dev/null +++ b/arch/mips/mach-mt7620/cpu.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Stefan Roese + */ + +#include +#include +#include +#include +#include +#include +#include "mt76xx.h" + +#define STR_LEN 6 + +#ifdef CONFIG_BOOT_ROM +int mach_cpu_init(void) +{ + ddr_calibrate(); + + return 0; +} +#endif + +int dram_init(void) +{ + gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M); + + return 0; +} + +int print_cpuinfo(void) +{ + static const char * const boot_str[] = { "PLL (3-Byte SPI Addr)", + "PLL (4-Byte SPI Addr)", + "XTAL (3-Byte SPI Addr)", + "XTAL (4-Byte SPI Addr)" }; + const void *blob = gd->fdt_blob; + void __iomem *sysc_base; + char buf[STR_LEN + 1]; + fdt_addr_t base; + fdt_size_t size; + char *str; + int node; + u32 val; + + /* Get system controller base address */ + node = fdt_node_offset_by_compatible(blob, -1, "ralink,mt7620a-sysc"); + if (node < 0) + return -FDT_ERR_NOTFOUND; + + base = fdtdec_get_addr_size_auto_noparent(blob, node, "reg", + 0, &size, true); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + sysc_base = ioremap_nocache(base, size); + + str = (char *)sysc_base + MT76XX_CHIPID_OFFS; + snprintf(buf, STR_LEN + 1, "%s", str); + val = readl(sysc_base + MT76XX_CHIP_REV_ID_OFFS); + printf("CPU: %-*s Rev %ld.%ld - ", STR_LEN, buf, + (val & GENMASK(11, 8)) >> 8, val & GENMASK(3, 0)); + + val = (readl(sysc_base + MT76XX_SYSCFG0_OFFS) & GENMASK(3, 1)) >> 1; + printf("Boot from %s\n", boot_str[val]); + + return 0; +} diff --git a/arch/mips/mach-mt7620/ddr_calibrate.c b/arch/mips/mach-mt7620/ddr_calibrate.c new file mode 100644 index 0000000..75763c4 --- /dev/null +++ b/arch/mips/mach-mt7620/ddr_calibrate.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Stefan Roese + * + * This code is mostly based on the code extracted from this MediaTek + * github repository: + * + * https://github.com/MediaTek-Labs/linkit-smart-uboot.git + * + * I was not able to find a specific license or other developers + * copyrights here, so I can't add them here. + * + * Most functions in this file are copied from the MediaTek U-Boot + * repository. Without any documentation, it was impossible to really + * implement this differently. So its mostly a cleaned-up version of + * the original code, with only support for the MT7628 / MT7688 SoC. + */ + +#include +#include +#include +#include +#include "mt76xx.h" + +#define NUM_OF_CACHELINE 128 +#define MIN_START 6 +#define MIN_FINE_START 0xf +#define MAX_START 7 +#define MAX_FINE_START 0x0 + +#define CPU_FRAC_DIV 1 + +#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT) +#define DRAM_BUTTOM 0x02000000 +#endif +#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT) +#define DRAM_BUTTOM 0x04000000 +#endif +#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT) +#define DRAM_BUTTOM 0x08000000 +#endif +#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT) +#define DRAM_BUTTOM 0x10000000 +#endif + +static inline void cal_memcpy(void *src, void *dst, u32 size) +{ + u8 *psrc = (u8 *)src; + u8 *pdst = (u8 *)dst; + int i; + + for (i = 0; i < size; i++, psrc++, pdst++) + *pdst = *psrc; +} + +static inline void cal_memset(void *src, u8 pat, u32 size) +{ + u8 *psrc = (u8 *)src; + int i; + + for (i = 0; i < size; i++, psrc++) + *psrc = pat; +} + +#define pref_op(hint, addr) \ + __asm__ __volatile__( \ + ".set push\n" \ + ".set noreorder\n" \ + "pref %0, %1\n" \ + ".set pop\n" \ + : \ + : "i" (hint), "R" (*(u8 *)(addr))) + +static inline void cal_patgen(u32 start_addr, u32 size, u32 bias) +{ + u32 *addr = (u32 *)start_addr; + int i; + + for (i = 0; i < size; i++) + addr[i] = start_addr + i + bias; +} + +static inline int test_loop(int k, int dqs, u32 test_dqs, u32 *coarse_dqs, + u32 offs, u32 pat, u32 val) +{ + u32 nc_addr; + u32 *c_addr; + int i; + + for (nc_addr = 0xa0000000; + nc_addr < (0xa0000000 + DRAM_BUTTOM - NUM_OF_CACHELINE * 32); + nc_addr += (DRAM_BUTTOM >> 6) + offs) { + writel(0x00007474, (void *)MT76XX_MEMCTRL_BASE + 0x64); + wmb(); /* Make sure store if finished */ + + c_addr = (u32 *)(nc_addr & 0xdfffffff); + cal_memset(((u8 *)c_addr), 0x1F, NUM_OF_CACHELINE * 32); + cal_patgen(nc_addr, NUM_OF_CACHELINE * 8, pat); + + if (dqs > 0) + writel(0x00000074 | + (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 12) | + (((k == 0) ? val : test_dqs) << 8), + (void *)MT76XX_MEMCTRL_BASE + 0x64); + else + writel(0x00007400 | + (((k == 1) ? coarse_dqs[dqs] : test_dqs) << 4) | + (((k == 0) ? val : test_dqs) << 0), + (void *)MT76XX_MEMCTRL_BASE + 0x64); + wmb(); /* Make sure store if finished */ + + invalidate_dcache_range((u32)c_addr, + (u32)c_addr + + NUM_OF_CACHELINE * 32); + wmb(); /* Make sure store if finished */ + + for (i = 0; i < NUM_OF_CACHELINE * 8; i++) { + if (i % 8 == 0) + pref_op(0, &c_addr[i]); + } + + for (i = 0; i < NUM_OF_CACHELINE * 8; i++) { + if (c_addr[i] != nc_addr + i + pat) + return -1; + } + } + + return 0; +} + +void ddr_calibrate(void) +{ + u32 min_coarse_dqs[2]; + u32 max_coarse_dqs[2]; + u32 min_fine_dqs[2]; + u32 max_fine_dqs[2]; + u32 coarse_dqs[2]; + u32 fine_dqs[2]; + int reg = 0, ddr_cfg2_reg; + int flag; + int i, k; + int dqs = 0; + u32 min_coarse_dqs_bnd, min_fine_dqs_bnd, coarse_dqs_dll, fine_dqs_dll; + u32 val; + u32 fdiv = 0, frac = 0; + + /* Setup clock to run at full speed */ + val = readl((void *)MT76XX_DYN_CFG0_REG); + fdiv = (u32)((val >> 8) & 0x0F); + if (CPU_FRAC_DIV < 1 || CPU_FRAC_DIV > 10) + frac = val & 0x0f; + else + frac = CPU_FRAC_DIV; + + while (frac < fdiv) { + val = readl((void *)MT76XX_DYN_CFG0_REG); + fdiv = (val >> 8) & 0x0f; + fdiv--; + val &= ~(0x0f << 8); + val |= (fdiv << 8); + writel(val, (void *)MT76XX_DYN_CFG0_REG); + udelay(500); + val = readl((void *)MT76XX_DYN_CFG0_REG); + fdiv = (val >> 8) & 0x0f; + } + + clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4)); + ddr_cfg2_reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x48); + clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x48, + (0x3 << 28) | (0x3 << 26)); + + min_coarse_dqs[0] = MIN_START; + min_coarse_dqs[1] = MIN_START; + min_fine_dqs[0] = MIN_FINE_START; + min_fine_dqs[1] = MIN_FINE_START; + max_coarse_dqs[0] = MAX_START; + max_coarse_dqs[1] = MAX_START; + max_fine_dqs[0] = MAX_FINE_START; + max_fine_dqs[1] = MAX_FINE_START; + dqs = 0; + + /* Add by KP, DQS MIN boundary */ + reg = readl((void *)MT76XX_MEMCTRL_BASE + 0x20); + coarse_dqs_dll = (reg & 0xf00) >> 8; + fine_dqs_dll = (reg & 0xf0) >> 4; + if (coarse_dqs_dll <= 8) + min_coarse_dqs_bnd = 8 - coarse_dqs_dll; + else + min_coarse_dqs_bnd = 0; + + if (fine_dqs_dll <= 8) + min_fine_dqs_bnd = 8 - fine_dqs_dll; + else + min_fine_dqs_bnd = 0; + /* DQS MIN boundary */ + +DQS_CAL: + + for (k = 0; k < 2; k++) { + u32 test_dqs; + + if (k == 0) + test_dqs = MAX_START; + else + test_dqs = MAX_FINE_START; + + do { + flag = test_loop(k, dqs, test_dqs, max_coarse_dqs, + 0x400, 0x3, 0xf); + if (flag == -1) + break; + + test_dqs++; + } while (test_dqs <= 0xf); + + if (k == 0) { + max_coarse_dqs[dqs] = test_dqs; + } else { + test_dqs--; + + if (test_dqs == MAX_FINE_START - 1) { + max_coarse_dqs[dqs]--; + max_fine_dqs[dqs] = 0xf; + } else { + max_fine_dqs[dqs] = test_dqs; + } + } + } + + for (k = 0; k < 2; k++) { + u32 test_dqs; + + if (k == 0) + test_dqs = MIN_START; + else + test_dqs = MIN_FINE_START; + + do { + flag = test_loop(k, dqs, test_dqs, min_coarse_dqs, + 0x480, 0x1, 0x0); + if (k == 0) { + if (flag == -1 || + test_dqs == min_coarse_dqs_bnd) + break; + + test_dqs--; + + if (test_dqs < min_coarse_dqs_bnd) + break; + } else { + if (flag == -1) { + test_dqs++; + break; + } else if (test_dqs == min_fine_dqs_bnd) { + break; + } + + test_dqs--; + + if (test_dqs < min_fine_dqs_bnd) + break; + } + } while (test_dqs >= 0); + + if (k == 0) { + min_coarse_dqs[dqs] = test_dqs; + } else { + if (test_dqs == MIN_FINE_START + 1) { + min_coarse_dqs[dqs]++; + min_fine_dqs[dqs] = 0x0; + } else { + min_fine_dqs[dqs] = test_dqs; + } + } + } + + if (dqs == 0) { + dqs = 1; + goto DQS_CAL; + } + + for (i = 0; i < 2; i++) { + u32 temp; + + coarse_dqs[i] = (max_coarse_dqs[i] + min_coarse_dqs[i]) >> 1; + temp = + (((max_coarse_dqs[i] + min_coarse_dqs[i]) % 2) * 4) + + ((max_fine_dqs[i] + min_fine_dqs[i]) >> 1); + if (temp >= 0x10) { + coarse_dqs[i]++; + fine_dqs[i] = (temp - 0x10) + 0x8; + } else { + fine_dqs[i] = temp; + } + } + reg = (coarse_dqs[1] << 12) | (fine_dqs[1] << 8) | + (coarse_dqs[0] << 4) | fine_dqs[0]; + + clrbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4)); + writel(reg, (void *)MT76XX_MEMCTRL_BASE + 0x64); + writel(ddr_cfg2_reg, (void *)MT76XX_MEMCTRL_BASE + 0x48); + setbits_le32((void *)MT76XX_MEMCTRL_BASE + 0x10, BIT(4)); + + for (i = 0; i < 2; i++) + debug("[%02X%02X%02X%02X]", min_coarse_dqs[i], + min_fine_dqs[i], max_coarse_dqs[i], max_fine_dqs[i]); + debug("\nDDR Calibration DQS reg = %08X\n", reg); +} diff --git a/arch/mips/mach-mt7620/lowlevel_init.S b/arch/mips/mach-mt7620/lowlevel_init.S new file mode 100644 index 0000000..1a50f160 --- /dev/null +++ b/arch/mips/mach-mt7620/lowlevel_init.S @@ -0,0 +1,322 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (c) 2018 Stefan Roese + * + * This code is mostly based on the code extracted from this MediaTek + * github repository: + * + * https://github.com/MediaTek-Labs/linkit-smart-uboot.git + * + * I was not able to find a specific license or other developers + * copyrights here, so I can't add them here. + */ + +#include +#include +#include +#include +#include +#include "mt76xx.h" + +#ifndef BIT +#define BIT(nr) (1 << (nr)) +#endif + +#define DELAY_USEC(us) ((us) / 100) + +#define DDR_CFG1_CHIP_WIDTH_MASK (0x3 << 16) +#define DDR_CFG1_BUS_WIDTH_MASK (0x3 << 12) + +#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT) +#define DDR_CFG1_SIZE_VAL 0x222e2323 +#define DDR_CFG4_SIZE_VAL 7 +#endif +#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT) +#define DDR_CFG1_SIZE_VAL 0x22322323 +#define DDR_CFG4_SIZE_VAL 9 +#endif +#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT) +#define DDR_CFG1_SIZE_VAL 0x22362323 +#define DDR_CFG4_SIZE_VAL 9 +#endif +#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT) +#define DDR_CFG1_SIZE_VAL 0x223a2323 +#define DDR_CFG4_SIZE_VAL 9 +#endif + +#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_8BIT) +#define DDR_CFG1_CHIP_WIDTH_VAL (0x1 << 16) +#endif +#if defined(CONFIG_ONBOARD_DDR2_CHIP_WIDTH_16BIT) +#define DDR_CFG1_CHIP_WIDTH_VAL (0x2 << 16) +#endif + +#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_16BIT) +#define DDR_CFG1_BUS_WIDTH_VAL (0x2 << 12) +#endif +#if defined(CONFIG_ONBOARD_DDR2_BUS_WIDTH_32BIT) +#define DDR_CFG1_BUS_WIDTH_VAL (0x3 << 12) +#endif + + .set noreorder + +LEAF(lowlevel_init) + + /* Load base addresses as physical addresses for later usage */ + li s0, CKSEG1ADDR(MT76XX_SYSCTL_BASE) + li s1, CKSEG1ADDR(MT76XX_MEMCTRL_BASE) + li s2, CKSEG1ADDR(MT76XX_RGCTRL_BASE) + + /* polling CPLL is ready */ + li t1, DELAY_USEC(1000000) + la t5, MT76XX_ROM_STATUS_REG +1: + lw t2, 0(t5) + andi t2, t2, 0x1 + bnez t2, CPLL_READY + subu t1, t1, 1 + bgtz t1, 1b + nop + la t0, MT76XX_CLKCFG0_REG + lw t3, 0(t0) + ori t3, t3, 0x1 + sw t3, 0(t0) + b CPLL_DONE + nop +CPLL_READY: + la t0, MT76XX_CLKCFG0_REG + lw t1, 0(t0) + li t2, ~0x0c + and t1, t1, t2 + ori t1, t1, 0xc + sw t1, 0(t0) + la t0, MT76XX_DYN_CFG0_REG + lw t3, 0(t0) + li t5, ~((0x0f << 8) | (0x0f << 0)) + and t3, t3, t5 + li t5, (10 << 8) | (1 << 0) + or t3, t3, t5 + sw t3, 0(t0) + la t0, MT76XX_CLKCFG0_REG + lw t3, 0(t0) + li t4, ~0x0F + and t3, t3, t4 + ori t3, t3, 0xc + sw t3, 0(t0) + lw t3, 0(t0) + ori t3, t3, 0x08 + sw t3, 0(t0) + +CPLL_DONE: + /* + * SDR and DDR initialization: delay 200us + */ + li t0, DELAY_USEC(200 + 40) + li t1, 0x1 +1: + sub t0, t0, t1 + bnez t0, 1b + nop + + /* set DRAM IO PAD for MT7628IC */ + /* DDR LDO Enable */ + lw t4, 0x100(s2) + li t2, BIT(31) + or t4, t4, t2 + sw t4, 0x100(s2) + lw t4, 0x10c(s2) + j LDO_1P8V + nop +LDO_1P8V: + li t2, ~BIT(6) + and t4, t4, t2 + sw t4, 0x10c(s2) + j DDRLDO_SOFT_START +LDO_2P5V: + /* suppose external DDR1 LDO 2.5V */ + li t2, BIT(6) + or t4, t4, t2 + sw t4, 0x10c(s2) + +DDRLDO_SOFT_START: + lw t2, 0x10c(s2) + li t3, BIT(16) + or t2, t2, t3 + sw t2, 0x10c(s2) + li t3, DELAY_USEC(250*50) +LDO_DELAY: + subu t3, t3, 1 + bnez t3, LDO_DELAY + nop + + lw t2, 0x10c(s2) + li t3, BIT(18) + or t2, t2, t3 + sw t2, 0x10c(s2) + +SET_RG_BUCK_FPWM: + lw t2, 0x104(s2) + ori t2, t2, BIT(10) + sw t2, 0x104(s2) + +DDR_PAD_CFG: + /* clean CLK PAD */ + lw t2, 0x704(s2) + li t8, 0xfffff0f0 + and t2, t2, t8 + /* clean CMD PAD */ + lw t3, 0x70c(s2) + li t8, 0xfffff0f0 + and t3, t3, t8 + /* clean DQ IPAD */ + lw t4, 0x710(s2) + li t8, 0xfffff8ff + and t4, t4, t8 + /* clean DQ OPAD */ + lw t5, 0x714(s2) + li t8, 0xfffff0f0 + and t5, t5, t8 + /* clean DQS IPAD */ + lw t6, 0x718(s2) + li t8, 0xfffff8ff + and t6, t6, t8 + /* clean DQS OPAD */ + lw t7, 0x71c(s2) + li t8, 0xfffff0f0 + and t7, t7, t8 + + lw t9, 0xc(s0) + srl t9, t9, 16 + andi t9, t9, 0x1 + bnez t9, MT7628_AN_DDR1_PAD +MT7628_KN_PAD: + li t8, 0x00000303 + or t2, t2, t8 + or t3, t3, t8 + or t5, t5, t8 + or t7, t7, t8 + li t8, 0x00000000 + or t4, t4, t8 + or t6, t6, t8 + j SET_PAD_CFG +MT7628_AN_DDR1_PAD: + lw t1, 0x10(s0) + andi t1, t1, 0x1 + beqz t1, MT7628_AN_DDR2_PAD + li t8, 0x00000c0c + or t2, t2, t8 + li t8, 0x00000202 + or t3, t3, t8 + li t8, 0x00000707 + or t5, t5, t8 + li t8, 0x00000c0c + or t7, t7, t8 + li t8, 0x00000000 + or t4, t4, t8 + or t6, t6, t8 + j SET_PAD_CFG +MT7628_AN_DDR2_PAD: + li t8, 0x00000c0c + or t2, t2, t8 + li t8, 0x00000202 + or t3, t3, t8 + li t8, 0x00000404 + or t5, t5, t8 + li t8, 0x00000c0c + or t7, t7, t8 + li t8, 0x00000000 /* ODT off */ + or t4, t4, t8 + or t6, t6, t8 + +SET_PAD_CFG: + sw t2, 0x704(s2) + sw t3, 0x70c(s2) + sw t4, 0x710(s2) + sw t5, 0x714(s2) + sw t6, 0x718(s2) + sw t7, 0x71c(s2) + + /* + * DDR initialization: reset pin to 0 + */ + lw t2, 0x34(s0) + and t2, ~BIT(10) + sw t2, 0x34(s0) + nop + + /* + * DDR initialization: wait til reg DDR_CFG1 bit 21 equal to 1 (ready) + */ +DDR_READY: + li t1, DDR_CFG1_REG + lw t0, 0(t1) + nop + and t2, t0, BIT(21) + beqz t2, DDR_READY + nop + + /* + * DDR initialization + * + * Only DDR2 supported right now. DDR2 support can be added, once + * boards using it will get added to mainline U-Boot. + */ + li t1, DDR_CFG2_REG + lw t0, 0(t1) + nop + and t0, ~BIT(30) + and t0, ~(7 << 4) + or t0, (4 << 4) + or t0, BIT(30) + or t0, BIT(11) + sw t0, 0(t1) + nop + + li t1, DDR_CFG3_REG + lw t2, 0(t1) + /* Disable ODT; reference board ok, ev board fail */ + and t2, ~BIT(6) + or t2, BIT(2) + li t0, DDR_CFG4_REG + lw t1, 0(t0) + li t2, ~(0x01f | 0x0f0) + and t1, t1, t2 + ori t1, t1, DDR_CFG4_SIZE_VAL + sw t1, 0(t0) + nop + + /* + * DDR initialization: config size and width on reg DDR_CFG1 + */ + li t6, DDR_CFG1_SIZE_VAL + + and t6, ~DDR_CFG1_CHIP_WIDTH_MASK + or t6, DDR_CFG1_CHIP_WIDTH_VAL + + /* CONFIG DDR_CFG1[13:12] about TOTAL WIDTH */ + and t6, ~DDR_CFG1_BUS_WIDTH_MASK + or t6, DDR_CFG1_BUS_WIDTH_VAL + + li t5, DDR_CFG1_REG + sw t6, 0(t5) + nop + + /* + * DDR: enable self auto refresh for power saving + * enable it by default for both RAM and ROM version (for CoC) + */ + lw t1, 0x14(s1) + nop + and t1, 0xff000000 + or t1, 0x01 + sw t1, 0x14(s1) + nop + lw t1, 0x10(s1) + nop + or t1, 0x10 + sw t1, 0x10(s1) + nop + + jr ra + nop + END(lowlevel_init) diff --git a/arch/mips/mach-mt7620/mt76xx.h b/arch/mips/mach-mt7620/mt76xx.h new file mode 100644 index 0000000..17473ea --- /dev/null +++ b/arch/mips/mach-mt7620/mt76xx.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Stefan Roese + */ + +#ifndef __MT76XX_H +#define __MT76XX_H + +#define MT76XX_SYSCTL_BASE 0x10000000 + +#define MT76XX_CHIPID_OFFS 0x00 +#define MT76XX_CHIP_REV_ID_OFFS 0x0c +#define MT76XX_SYSCFG0_OFFS 0x10 + +#define MT76XX_MEMCTRL_BASE (MT76XX_SYSCTL_BASE + 0x0300) +#define MT76XX_RGCTRL_BASE (MT76XX_SYSCTL_BASE + 0x1000) + +#define MT76XX_ROM_STATUS_REG (MT76XX_SYSCTL_BASE + 0x0028) +#define MT76XX_CLKCFG0_REG (MT76XX_SYSCTL_BASE + 0x002c) +#define MT76XX_DYN_CFG0_REG (MT76XX_SYSCTL_BASE + 0x0440) + +#define DDR_CFG1_REG (MT76XX_MEMCTRL_BASE + 0x44) +#define DDR_CFG2_REG (MT76XX_MEMCTRL_BASE + 0x48) +#define DDR_CFG3_REG (MT76XX_MEMCTRL_BASE + 0x4c) +#define DDR_CFG4_REG (MT76XX_MEMCTRL_BASE + 0x50) + +#ifndef __ASSEMBLY__ +/* Prototypes */ +void ddr_calibrate(void); +#endif + +#endif