[U-Boot] [PATCH 1/6 v3] mips: Add basic MediaTek MT7620/88 support
Stefan
sr at denx.de
Wed Sep 5 13:05:48 UTC 2018
Hi Daniel,
On 05.09.2018 13:45, Daniel Schwierzeck wrote:
>
>
> On 16.08.2018 15:27, Stefan Roese wrote:
>> This patch adds basic support for the MediaTek MT7620/88 SoCs. Parts of
>> the code is copied from the MediaTek GitHub repository:
>>
>> https://github.com/MediaTek-Labs/linkit-smart-uboot.git
>>
>> The mt7628a.dtsi file is imported from Linux v4.17.
>>
>> Support for the LinkIt Smart 7688 module and the Gardena Smart Gateway
>> both based on the MT7688 will be added in further patches.
>>
>> Signed-off-by: Stefan Roese <sr at denx.de>
>> Cc: Daniel Schwierzeck <daniel.schwierzeck at gmail.com>
>> ---
>> v3:
>> - Added dtsi file with this platforms support as suggested by Daniel
>> - Rebased on top of Daniels I-cache startup patches -> removed magic
>> with KSEG0 call of ddr_calibrate. Its now called directly and the
>> bootup is much faster
>> - Some improvements to print_cpuinfo(), use ioremap_nocache etc
>> - Added .set noreorder to lowlevel_init.S
>> - Multiple improvements to lowlevel_init.S as suggested by Daniel
>>
>> v2:
>> - Sort Kconfig symbols alphabetically
>> - Use MIPS_TUNE_24KC
>> - Use imply for SPI support
>> - Dont' add LinkIt module support yet (is added with the board support)
>> - Move SKIP_LOWLEVEL_INIT from Kconfig to config header
>> - Use DT to get the base address of the system controller (for
>> display_cpuinfo)
>> - Remove _machine_restart - a separate driver is provided in a new patch
>> - Remove cachop_op() and cal_invalidate_dcache_range and use the
>> generic invalidate_dcache_range function instead
>>
>> arch/mips/Kconfig | 16 +
>> arch/mips/Makefile | 1 +
>> arch/mips/dts/mt7628a.dtsi | 135 +++++++++
>> arch/mips/mach-mt7620/Kconfig | 113 +++++++
>> arch/mips/mach-mt7620/Makefile | 8 +
>> arch/mips/mach-mt7620/cpu.c | 69 +++++
>> arch/mips/mach-mt7620/ddr_calibrate.c | 308 +++++++++++++++++++
>> arch/mips/mach-mt7620/lowlevel_init.S | 406 ++++++++++++++++++++++++++
>> arch/mips/mach-mt7620/mt76xx.h | 32 ++
>> 9 files changed, 1088 insertions(+)
>> create mode 100644 arch/mips/dts/mt7628a.dtsi
>> create mode 100644 arch/mips/mach-mt7620/Kconfig
>> create mode 100644 arch/mips/mach-mt7620/Makefile
>> create mode 100644 arch/mips/mach-mt7620/cpu.c
>> create mode 100644 arch/mips/mach-mt7620/ddr_calibrate.c
>> create mode 100644 arch/mips/mach-mt7620/lowlevel_init.S
>> create mode 100644 arch/mips/mach-mt7620/mt76xx.h
>>
>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> index 6e5e0ffe65..b3981ef2e6 100644
>> --- a/arch/mips/Kconfig
>> +++ b/arch/mips/Kconfig
>> @@ -68,6 +68,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
>> @@ -120,6 +135,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 a36f5f1fb6..802244a06e 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 0000000000..d00f528e1f
>> --- /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 at 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 at 10000000 {
>> + compatible = "palmbus", "simple-bus";
>> + reg = <0x10000000 0x200000>;
>> + ranges = <0x0 0x10000000 0x1FFFFF>;
>> +
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> +
>> + sysc: system-controller at 0 {
>> + compatible = "ralink,mt7620a-sysc", "syscon";
>> + reg = <0x0 0x100>;
>> + };
>> +
>> + intc: interrupt-controller at 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 at 300 {
>> + compatible = "ralink,mt7620a-memc";
>> + reg = <0x300 0x100>;
>> + };
>> +
>> + spi0: spi at b00 {
>> + compatible = "ralink,mt7621-spi";
>> + reg = <0xb00 0x40>;
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + };
>> +
>> + uart0: uartlite at c00 {
>> + compatible = "ns16550a";
>> + reg = <0xc00 0x100>;
>> +
>> + resets = <&resetc 12>;
>> + reset-names = "uart0";
>> +
>> + interrupt-parent = <&intc>;
>> + interrupts = <20>;
>> +
>> + reg-shift = <2>;
>> + };
>> +
>> + uart1: uart1 at d00 {
>> + compatible = "ns16550a";
>> + reg = <0xd00 0x100>;
>> +
>> + resets = <&resetc 19>;
>> + reset-names = "uart1";
>> +
>> + interrupt-parent = <&intc>;
>> + interrupts = <21>;
>> +
>> + reg-shift = <2>;
>> + };
>> +
>> + uart2: uart2 at e00 {
>> + compatible = "ns16550a";
>> + reg = <0xe00 0x100>;
>> +
>> + resets = <&resetc 20>;
>> + reset-names = "uart2";
>> +
>> + interrupt-parent = <&intc>;
>> + interrupts = <22>;
>> +
>> + reg-shift = <2>;
>> + };
>> + };
>> +
>> + usb_phy: usb-phy at 10120000 {
>> + compatible = "mediatek,mt7628-usbphy";
>> + reg = <0x10120000 0x1000>;
>> +
>> + #phy-cells = <0>;
>> +
>> + ralink,sysctl = <&sysc>;
>> + resets = <&resetc 22 &resetc 25>;
>> + reset-names = "host", "device";
>> + };
>> +
>> + ehci at 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 0000000000..396fbd0141
>> --- /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 0000000000..1f3e65e8a5
>> --- /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 0000000000..457f09f32c
>> --- /dev/null
>> +++ b/arch/mips/mach-mt7620/cpu.c
>> @@ -0,0 +1,69 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright (C) 2018 Stefan Roese <sr at denx.de>
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <ram.h>
>> +#include <asm/io.h>
>> +#include <linux/io.h>
>> +#include <linux/sizes.h>
>> +#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 0000000000..e178d14c76
>> --- /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 <sr at denx.de>
>> + *
>> + * 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 <common.h>
>> +#include <linux/io.h>
>> +#include <asm/cacheops.h>
>> +#include <asm/io.h>
>> +#include "mt76xx.h"
>> +
>> +#define NUM_OF_CACHELINE 64
>> +#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 0000000000..740d132f98
>> --- /dev/null
>> +++ b/arch/mips/mach-mt7620/lowlevel_init.S
>> @@ -0,0 +1,406 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * (c) 2018 Stefan Roese <sr at denx.de>
>> + *
>> + * 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 <config.h>
>> +#include <asm/regdef.h>
>> +#include <asm/mipsregs.h>
>> +#include <asm/addrspace.h>
>> +#include <asm/asm.h>
>> +#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
>
> maybe this register address could be loaded too into a sN register
> because it's used multiple times.
>
>> + 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:
>> +#if 0
>
> do you need this code in the future? Otherwise it should be removed to
> avoid adding dead code.
Ughh. This just slipped in from a debug version. I'll remove it
and will post this patch alone as v4 soon.
Thanks for spotting.
>> +#define RALINK_SYSCTL_BASE 0xB0000000
>> + // GPIO mode
>> + li t0, RALINK_SYSCTL_BASE + 0x64
>> + li t1, 0x05540551
>> + sw t1, 0(t0)
>> +
>> + // GPIO direction
>> + li t0, RALINK_SYSCTL_BASE + 0x604
>> + li t1, 0x00001000
>> + sw t1, 0(t0)
>> +
>> + // GPIO value
>> + li t0, RALINK_SYSCTL_BASE + 0x624
>> + li t1, 0x0002f5f
>> + sw t1, 0(t0)
>> +
>> + li t0, DELAY_USEC(1000000)
>> + li t1, 0x1
>> +1:
>> + sub t0, t0, t1
>> + bnez t0, 1b
>> + nop
>> +
>> + // GPIO value
>> + li t0, RALINK_SYSCTL_BASE + 0x624
>> + li t1, 0x0003f5f
>> + sw t1, 0(t0)
>> +
>> + li t0, DELAY_USEC(1000000)
>> + li t1, 0x1
>> +1:
>> + sub t0, t0, t1
>> + bnez t0, 1b
>> + nop
>> +
>> + // GPIO value
>> + li t0, RALINK_SYSCTL_BASE + 0x624
>> + li t1, 0x0002f5f
>> + sw t1, 0(t0)
>> +
>> + li t0, DELAY_USEC(1000000)
>> + li t1, 0x1
>> +1:
>> + sub t0, t0, t1
>> + bnez t0, 1b
>> + nop
>> +
>> + // GPIO value
>> + li t0, RALINK_SYSCTL_BASE + 0x624
>> + li t1, 0x0003f5f
>> + sw t1, 0(t0)
>> +
>> + li t0, DELAY_USEC(1000000)
>> + li t1, 0x1
>> +1:
>> + sub t0, t0, t1
>> + bnez t0, 1b
>> + nop
>> +
>> + // GPIO value
>> + li t0, RALINK_SYSCTL_BASE + 0x624
>> + li t1, 0x0002f5f
>> + sw t1, 0(t0)
>> +
>> +#endif
>> + /*
>> + * 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 */
>> + la t1, 0x100(s2)
>> + lw t4, 0(t1)
>
> this could be simply written as
>
> lw t4, 0x100(s2)
>
> this was the main intention of my suggested optimisation ;)
I missed this, thx.
> If you want to increase readabilty, you could add a define for this
> 0x100 offset.
Yes, that would be good. Unfortunately the documentation is not
very good and the original source code has no macros / defines
here as well. So its pretty hard to impossible for me to add such
defines.
Thanks,
Stefan
More information about the U-Boot
mailing list