
2018-08-06 17:11 GMT+02:00 Stefan Roese sr@denx.de:
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
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@denx.de Cc: Daniel Schwierzeck daniel.schwierzeck@gmail.com
arch/mips/Kconfig | 15 ++ arch/mips/Makefile | 1 + arch/mips/mach-mt7620/Kconfig | 130 ++++++++++ arch/mips/mach-mt7620/Makefile | 8 + arch/mips/mach-mt7620/cpu.c | 66 +++++ arch/mips/mach-mt7620/ddr_calibrate.c | 331 +++++++++++++++++++++++++ arch/mips/mach-mt7620/lowlevel_init.S | 337 ++++++++++++++++++++++++++ arch/mips/mach-mt7620/mt76xx.h | 39 +++ 8 files changed, 927 insertions(+) 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 31b622ff51..af791c320d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -87,6 +87,20 @@ config ARCH_BMIPS select SYSRESET imply CMD_DM
+config ARCH_MT7620
bool "Support MT7620/7688 SoCs"
select SUPPORTS_LITTLE_ENDIAN
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select ROM_EXCEPTION_VECTORS
select MIPS_TUNE_4KC
MT7620 has a MIPS 24kc core, thus you could optimize for that
select OF_CONTROL
select DM
select DM_SERIAL
select DM_SPI
select DM_SPI_FLASH
select DISPLAY_CPUINFO
could you sort this in alphabetic order? There were some patches recently which did the sorting tree wide. Also drop the SPI options until you add a SPI driver.
config MACH_PIC32 bool "Support Microchip PIC32" select DM @@ -141,6 +155,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 5deec9a202..cc8ea5d7d4 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -15,6 +15,7 @@ machine-$(CONFIG_SOC_AU1X00) += au1x00 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/mach-mt7620/Kconfig b/arch/mips/mach-mt7620/Kconfig new file mode 100644 index 0000000000..40e15b8a31 --- /dev/null +++ b/arch/mips/mach-mt7620/Kconfig @@ -0,0 +1,130 @@ +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"
+config BOARD_LINKIT_SMART_7688
bool "LinkIt Smart 7688"
depends on SOC_MT7620
select SUPPORTS_BOOT_RAM
help
Seeed LinkIt Smart 7688 boards have a MT7688 SoC with 128 MiB of RAM
and 32 MiB of flash (SPI).
Between its different peripherals there's an integrated switch with 4
ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and
a MT7688 (PCIe).
could you add this part with patch 3/4?
+endchoice
+choice
prompt "Boot mode"
+config BOOT_RAM
bool "RAM boot"
depends on SUPPORTS_BOOT_RAM
select SKIP_LOWLEVEL_INIT
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
+config SKIP_LOWLEVEL_INIT
bool
this is a legacy config option, thus you have to define it in your board config header file. MIPS shouldn't add a Kconfig symbol for that. This have to be migrated to Kconfig tree-wide.
+source "board/seeed/linkit-smart-7688/Kconfig"
could you add this part with patch 3/4?
+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..0b22956499 --- /dev/null +++ b/arch/mips/mach-mt7620/cpu.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2018 Stefan Roese sr@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) +{
void (*ptr)(void);
/*
* DDR calibration routine needs to be called very early. This
* function also configures the clock to run at full speed.
*/
ptr = (void *)CKSEG0ADDR(ddr_calibrate);
(*ptr)();
what is the purpose of forcing the function symbol to KSEG0?
return 0;
+} +#endif
+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)" };
char *chr = (char *)MT76XX_CHIPID;
char buf[STR_LEN + 1];
u32 val;
snprintf(buf, STR_LEN + 1, "%s", chr);
val = readl((void *)MT76XX_CHIP_REV_ID);
printf("CPU: %-*s Rev %ld.%ld - ", STR_LEN, buf,
(val & GENMASK(11, 8)) >> 8, val & GENMASK(3, 0));
val = (readl((void *)MT76XX_SYSCFG0) & GENMASK(3, 1)) >> 1;
printf("Boot from %s\n", boot_str[val]);
could you try to create a CPU driver like on BMIPS?
return 0;
+}
+void _machine_restart(void) +{
writel(0x01, (void *)MT76XX_RSTCTL);
while (1)
; /* NOP */
could you try to create a reset controller driver? Then you could also use the generic syscon-reboot driver.
+}
+int dram_init(void) +{
gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);
shouldn't you return the real configured DRAM size here?
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..6fd136674e --- /dev/null +++ b/arch/mips/mach-mt7620/ddr_calibrate.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2018 Stefan Roese sr@denx.de
- This code is mostly based on the code extracted from this MediaTek
- github repository:
- 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)))
+#define cache_op(op, addr) \
__asm__ __volatile__( \
".set push\n" \
".set noreorder\n" \
".set mips3\n" \
"cache %0, %1\n" \
".set pop\n" \
: \
: "i" (op), "R" (*(u8 *)(addr)))
cache_op() is already available in arch/mips/include/asm/cacheops.h. Maybe you could add pref_op in the same way to that file.
+static inline void cal_invalidate_dcache_range(u32 start_addr, u32 stop) +{
u32 lsize = CONFIG_SYS_CACHELINE_SIZE;
u32 addr = start_addr & ~(lsize - 1);
u32 aend = (stop - 1) & ~(lsize - 1);
while (1) {
cache_op(HIT_INVALIDATE_D, addr);
if (addr == aend)
break;
addr += lsize;
}
+}
you should use the generic MIPS implementation instead
+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, 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),
MT76XX_MEMCTRL_BASE + 0x64);
else
writel(0x00007400 |
(((k == 1) ? coarse_dqs[dqs] : test_dqs) << 4) |
(((k == 0) ? val : test_dqs) << 0),
MT76XX_MEMCTRL_BASE + 0x64);
wmb(); /* Make sure store if finished */
cal_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(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(MT76XX_DYN_CFG0_REG);
fdiv = (val >> 8) & 0x0f;
fdiv--;
val &= ~(0x0f << 8);
val |= (fdiv << 8);
writel(val, MT76XX_DYN_CFG0_REG);
udelay(500);
val = readl(MT76XX_DYN_CFG0_REG);
fdiv = (val >> 8) & 0x0f;
}
clrbits_le32(MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
ddr_cfg2_reg = readl(MT76XX_MEMCTRL_BASE + 0x48);
clrbits_le32(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(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(MT76XX_MEMCTRL_BASE + 0x10, BIT(4));
writel(reg, MT76XX_MEMCTRL_BASE + 0x64);
writel(ddr_cfg2_reg, MT76XX_MEMCTRL_BASE + 0x48);
setbits_le32(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..92b2fcd2bb --- /dev/null +++ b/arch/mips/mach-mt7620/lowlevel_init.S @@ -0,0 +1,337 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- (c) 2018 Stefan Roese sr@denx.de
- This code is mostly based on the code extracted from this MediaTek
- github repository:
- 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/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
+LEAF(lowlevel_init)
/* 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)
j 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 */
li t1, MT76XX_RGCTRL_BASE+0x100
lw t4, 0(t1)
li t2, BIT(31)
or t4, t4, t2
sw t4, 0(t1)
li t1, MT76XX_RGCTRL_BASE+0x10c
lw t4, 0(t1)
j LDO_1P8V
nop
+LDO_1P8V:
li t2, ~BIT(6)
and t4, t4, t2
li t1, MT76XX_RGCTRL_BASE+0x10c
sw t4, 0(t1)
j DDRLDO_SOFT_START
+LDO_2P5V:
/* suppose external DDR1 LDO 2.5V */
li t2, BIT(6)
or t4, t4, t2
li t1, MT76XX_RGCTRL_BASE+0x10c
sw t4, 0(t1)
+DDRLDO_SOFT_START:
li t1, MT76XX_RGCTRL_BASE+0x10c
lw t2, 0(t1)
li t3, BIT(16)
or t2, t2, t3
sw t2, 0(t1)
li t3, DELAY_USEC(250*50)
+LDO_DELAY:
subu t3, t3, 1
bnez t3, LDO_DELAY
nop
li t1, MT76XX_RGCTRL_BASE+0x10c
lw t2, 0(t1)
li t3, BIT(18)
or t2, t2, t3
sw t2, 0(t1)
+SET_RG_BUCK_FPWM:
li t1, MT76XX_RGCTRL_BASE+0x104
lw t2, 0(t1)
ori t2, t2, BIT(10)
sw t2, 0(t1)
+DDR_PAD_CFG:
/* clean CLK PAD */
li t1, MT76XX_RGCTRL_BASE+0x704
lw t2, 0(t1)
li t8, 0xfffff0f0
and t2, t2, t8
/* clean CMD PAD */
li t1, MT76XX_RGCTRL_BASE+0x70c
lw t3, 0(t1)
li t8, 0xfffff0f0
and t3, t3, t8
/* clean DQ IPAD */
li t1, MT76XX_RGCTRL_BASE+0x710
lw t4, 0(t1)
li t8, 0xfffff8ff
and t4, t4, t8
/* clean DQ OPAD */
li t1, MT76XX_RGCTRL_BASE+0x714
lw t5, 0(t1)
li t8, 0xfffff0f0
and t5, t5, t8
/* clean DQS IPAD */
li t1, MT76XX_RGCTRL_BASE+0x718
lw t6, 0(t1)
li t8, 0xfffff8ff
and t6, t6, t8
/* clean DQS OPAD */
li t1, MT76XX_RGCTRL_BASE+0x71c
lw t7, 0(t1)
li t8, 0xfffff0f0
and t7, t7, t8
li t1, MT76XX_SYSCTL_BASE+0xC
lw t9, 0(t1)
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:
li t1, MT76XX_SYSCTL_BASE+0x10
lw t1, 0(t1)
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:
li t1, MT76XX_RGCTRL_BASE+0x704
sw t2, 0(t1)
li t1, MT76XX_RGCTRL_BASE+0x70c
sw t3, 0(t1)
li t1, MT76XX_RGCTRL_BASE+0x710
sw t4, 0(t1)
li t1, MT76XX_RGCTRL_BASE+0x714
sw t5, 0(t1)
li t1, MT76XX_RGCTRL_BASE+0x718
sw t6, 0(t1)
li t1, MT76XX_RGCTRL_BASE+0x71c
sw t7, 0(t1)
/*
* DDR initialization: reset pin to 0
*/
li t1, MT76XX_SYSCTL_BASE + 0x34
lw t2, 0(t1)
and t2, ~BIT(10)
sw t2, 0(t1)
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)
*/
li t0, MT76XX_MEMCTRL_BASE + 0x14
lw t1, 0(t0)
nop
and t1, 0xff000000
or t1, 0x01
sw t1, 0(t0)
nop
li t0, MT76XX_MEMCTRL_BASE + 0x10
lw t1, 0(t0)
nop
or t1, 0x10
sw t1, 0(t0)
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 0000000000..712d8aade0 --- /dev/null +++ b/arch/mips/mach-mt7620/mt76xx.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2018 Stefan Roese sr@denx.de
- */
+#ifndef __MT76XX_H +#define __MT76XX_H
+#ifdef __ASSEMBLY__ +#define VOID_PTR +#else +#define VOID_PTR (void *) +#endif
+#define MT76XX_SYSCTL_BASE 0xb0000000
+#define MT76XX_CHIPID (VOID_PTR(MT76XX_SYSCTL_BASE + 0x00)) +#define MT76XX_CHIP_REV_ID (VOID_PTR(MT76XX_SYSCTL_BASE + 0x0c)) +#define MT76XX_SYSCFG0 (VOID_PTR(MT76XX_SYSCTL_BASE + 0x10)) +#define MT76XX_RSTCTL (VOID_PTR(MT76XX_SYSCTL_BASE + 0x34))
+#define MT76XX_MEMCTRL_BASE (VOID_PTR(MT76XX_SYSCTL_BASE + 0x0300)) +#define MT76XX_RGCTRL_BASE (VOID_PTR(MT76XX_SYSCTL_BASE + 0x1000))
+#define MT76XX_ROM_STATUS_REG (VOID_PTR(MT76XX_SYSCTL_BASE + 0x0028)) +#define MT76XX_CLKCFG0_REG (VOID_PTR(MT76XX_SYSCTL_BASE + 0x002c)) +#define MT76XX_DYN_CFG0_REG (VOID_PTR(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
2.18.0