mips: Add basic MediaTek MT7620/88 support
Subsystems (4)
PATCH v3 1/6 mips: Add basic MediaTek MT7620/88 support
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.
---
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
arch/mips/Kconfig +16 -0
@@ -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
arch/mips/Makefile +1 -0
@@ -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)
arch/mips/dts/mt7628a.dtsi new file +135 -0
135 lines not on this page · raw message
arch/mips/mach-mt7620/Kconfig new file +113 -0
113 lines not on this page · raw message
arch/mips/mach-mt7620/Makefile new file +8 -0
@@ -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
arch/mips/mach-mt7620/cpu.c new file +69 -0
69 lines not on this page · raw message
arch/mips/mach-mt7620/ddr_calibrate.c new file +308 -0
308 lines not on this page · raw message
arch/mips/mach-mt7620/lowlevel_init.S new file +406 -0
406 lines not on this page · raw message
arch/mips/mach-mt7620/mt76xx.h new file +32 -0
@@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +*/ + +#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
Signature · 1 line
2.18.0
PATCH v3 2/6 mips: Add arch/mips/include/asm/atomic.h
This is needed for the UBIFS support. The file is a copy of arch/xtensa/include/asm/atomic.h
---
v3:
- No change
v2:
- No change
arch/mips/include/asm/atomic.h | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 arch/mips/include/asm/atomic.h
arch/mips/include/asm/atomic.h new file +54 -0
@@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* +* Copyright (C) 2016 Cadence Design Systems Inc. +*/ + +#ifndef _MIPS_ATOMIC_H +#define _MIPS_ATOMIC_H + +#include <asm/system.h> + +typedef struct {volatile int counter; }atomic_t ; + +#define ATOMIC_INIT (i) { (i) } + +#define atomic_read (v) ((v)->counter) +#define atomic_set (v, i) ((v)->counter = (i)) + +static inline void atomic_add (int i,atomic_t *v) +{ +unsigned long flags; + +local_irq_save (flags); + v->counter += i; +local_irq_restore (flags); +} + +static inline void atomic_sub (int i,atomic_t *v) +{ +unsigned long flags; + +local_irq_save (flags); + v->counter -= i; +local_irq_restore (flags); +} + +static inline void atomic_inc (atomic_t *v) +{ +unsigned long flags; + +local_irq_save (flags); + ++v->counter; +local_irq_restore (flags); +} + +static inline void atomic_dec (atomic_t *v) +{ +unsigned long flags; + +local_irq_save (flags); + --v->counter; +local_irq_restore (flags); +} + +#endif
Signature · 1 line
2.18.0
PATCH v3 3/6 mips: Add LinkIt Smart 7688 support
In reply to Stefan RoeseThe LinkIt Smart 7688 modules have a MT7688 SoC with 128 MiB of RAM and 32 MiB of flash (SPI NOR).
This patch also includes 2 targets. One is the target that can be programmed into the SPI NOR flash and a 2nd target "xxx-ram" is added to support loading and booting via an already running U-Boot version. This allows easy development and testing without the need to flash the image each time.
---
v3:
- Removed dtsi file - its added with patch #1
- Improvements to board_debug_uart_init() as suggested by Daniel
- Added comment to board_early_init()
- Removed DEBUG_UART
v2:
- Kconfig entries added with this patch now
arch/mips/dts/linkit-smart-7688.dts | 46 +++++++++++++++++++ arch/mips/mach-mt7620/Kconfig | 13 ++++++ board/seeed/linkit-smart-7688/Kconfig | 12 +++++ board/seeed/linkit-smart-7688/MAINTAINERS | 8 ++++ board/seeed/linkit-smart-7688/Makefile | 3 ++ board/seeed/linkit-smart-7688/board.c | 26 +++++++++++ configs/linkit-smart-7688-ram_defconfig | 52 +++++++++++++++++++++ configs/linkit-smart-7688_defconfig | 56 +++++++++++++++++++++++ include/configs/linkit-smart-7688.h | 52 +++++++++++++++++++++ 9 files changed, 268 insertions(+) create mode 100644 arch/mips/dts/linkit-smart-7688.dts create mode 100644 board/seeed/linkit-smart-7688/Kconfig create mode 100644 board/seeed/linkit-smart-7688/MAINTAINERS create mode 100644 board/seeed/linkit-smart-7688/Makefile create mode 100644 board/seeed/linkit-smart-7688/board.c create mode 100644 configs/linkit-smart-7688-ram_defconfig create mode 100644 configs/linkit-smart-7688_defconfig create mode 100644 include/configs/linkit-smart-7688.h
arch/mips/dts/linkit-smart-7688.dts new file +46 -0
@@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Stefan Roese <[email protected]> + */ + +/dts-v1/; + +#include "mt7628a.dtsi" + +/ { + compatible = "seeed,linkit-smart-7688", "ralink,mt7628a-soc"; + model = "LinkIt-Smart-7688"; + + aliases { + serial0 = &uart2; + spi0 = &spi0; + }; + + memory at 0 { + device_type = "memory"; + reg = <0x0 0x08000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + stdout-path = &uart2; + }; +}; + +&uart2 { + status = "okay"; + clock-frequency = <40000000>; +}; + +&spi0 { + status = "okay"; + num-cs = <2>; + + spi-flash at 0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash", "jedec,spi-nor"; + spi-max-frequency = <25000000>; + reg = <0>; + }; +};
arch/mips/mach-mt7620/Kconfig +13 -0
@@ -21,6 +21,17 @@ 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). + endchoice choice
@@ -110,4 +121,6 @@ endchoice config SUPPORTS_BOOT_RAM bool +source "board/seeed/linkit-smart-7688/Kconfig" + endmenu
board/seeed/linkit-smart-7688/Kconfig new file +12 -0
@@ -0,0 +1,12 @@ +if BOARD_LINKIT_SMART_7688 + +config SYS_BOARD + default "linkit-smart-7688" + +config SYS_VENDOR + default "seeed" + +config SYS_CONFIG_NAME + default "linkit-smart-7688" + +endif
board/seeed/linkit-smart-7688/MAINTAINERS new file +8 -0
@@ -0,0 +1,8 @@ +LINKIT_SMART_7688 BOARD +M: Stefan Roese <[email protected]> +S: Maintained +F: board/seeed/linkit-smart-7688 +F: include/configs/linkit-smart-7688.h +F: configs/linkit-smart-7688_defconfig +F: configs/linkit-smart-7688_ram_defconfig +F: arch/mips/dts/linkit-smart-7688.dts
board/seeed/linkit-smart-7688/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += board.o
board/seeed/linkit-smart-7688/board.c new file +26 -0
@@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +*/ + +#include <common.h> +#include <asm/io.h> + +#define MT76XX_GPIO1_MODE 0xb0000060 + +void board_debug_uart_init (void ) +{ +/* Select UART2 mode instead of GPIO mode (default) */ +clrbits_le32 ((void __iomem *)MT76XX_GPIO1_MODE ,GENMASK (27 ,26 )); +} + +int board_early_init_f (void ) +{ +/* +* The pin muxing of UART2 also needs to be done, if debug uart +* is not enabled. So we need to call this function here as well. +*/ +board_debug_uart_init (); + +return 0 ; +}
configs/linkit-smart-7688-ram_defconfig new file +52 -0
52 lines not on this page · raw message
configs/linkit-smart-7688_defconfig new file +56 -0
56 lines not on this page · raw message
include/configs/linkit-smart-7688.h new file +52 -0
52 lines not on this page · raw message
Signature · 1 line
2.18.0
PATCH v3 4/6 mips: Add Gardena Smart-Gateway board support
In reply to Stefan RoeseThe Gardena Smart-Gateway boards have a MT7688 SoC with 128 MiB of RAM and 8 MiB of flash (SPI NOR) and additional 128MiB SPI NAND storage.
This patch also includes 2 targets. One is the target that can be programmed into the SPI NOR flash and a 2nd target "xxx-ram" is added to support loading and booting via an already running U-Boot version. This allows easy development and testing without the need to flash the image each time.
---
v3:
- Removed DEBUG_UART
v2:
- No change
.../mips/dts/gardena-smart-gateway-mt7688.dts | 54 ++++++++++++++++ arch/mips/mach-mt7620/Kconfig | 9 +++ board/gardena/smart-gateway-mt7688/Kconfig | 12 ++++ .../gardena/smart-gateway-mt7688/MAINTAINERS | 8 +++ board/gardena/smart-gateway-mt7688/Makefile | 3 + board/gardena/smart-gateway-mt7688/board.c | 17 ++++++ ...gardena-smart-gateway-mt7688-ram_defconfig | 58 ++++++++++++++++++ .../gardena-smart-gateway-mt7688_defconfig | 61 +++++++++++++++++++ .../configs/gardena-smart-gateway-mt7688.h | 56 +++++++++++++++++ 9 files changed, 278 insertions(+) create mode 100644 arch/mips/dts/gardena-smart-gateway-mt7688.dts create mode 100644 board/gardena/smart-gateway-mt7688/Kconfig create mode 100644 board/gardena/smart-gateway-mt7688/MAINTAINERS create mode 100644 board/gardena/smart-gateway-mt7688/Makefile create mode 100644 board/gardena/smart-gateway-mt7688/board.c create mode 100644 configs/gardena-smart-gateway-mt7688-ram_defconfig create mode 100644 configs/gardena-smart-gateway-mt7688_defconfig create mode 100644 include/configs/gardena-smart-gateway-mt7688.h
arch/mips/dts/gardena-smart-gateway-mt7688.dts new file +54 -0
@@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Stefan Roese <[email protected]> + */ + +/dts-v1/; + +#include "mt7628a.dtsi" + +/ { + compatible = "gardena,smart-gateway-mt7688", "ralink,mt7628a-soc"; + model = "Gardena smart-Gateway-MT7688"; + + aliases { + serial0 = &uart0; + spi0 = &spi0; + }; + + memory at 0 { + device_type = "memory"; + reg = <0x0 0x08000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + stdout-path = &uart0; + }; +}; + +&uart0 { + status = "okay"; + clock-frequency = <40000000>; +}; + +&spi0 { + status = "okay"; + num-cs = <2>; + + spi-flash at 0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash", "jedec,spi-nor"; + spi-max-frequency = <40000000>; + reg = <0>; + }; + + spi-nand at 1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + spi-max-frequency = <40000000>; + reg = <1>; + }; +};
arch/mips/mach-mt7620/Kconfig +9 -0
@@ -21,6 +21,14 @@ endchoice choice prompt "Board select" +config BOARD_GARDENA_SMART_GATEWAY_MT7688 + bool "Gardena Smart Gateway" + depends on SOC_MT7620 + select SUPPORTS_BOOT_RAM + help + Gardena Smart Gateway boards have a MT7688 SoC with 128 MiB of RAM + and 8 MiB of flash (SPI NOR) and additional SPI NAND storage. + config BOARD_LINKIT_SMART_7688 bool "LinkIt Smart 7688" depends on SOC_MT7620
@@ -121,6 +129,7 @@ endchoice config SUPPORTS_BOOT_RAM bool +source "board/gardena/smart-gateway-mt7688/Kconfig" source "board/seeed/linkit-smart-7688/Kconfig" endmenu
board/gardena/smart-gateway-mt7688/Kconfig new file +12 -0
@@ -0,0 +1,12 @@ +if BOARD_GARDENA_SMART_GATEWAY_MT7688 + +config SYS_BOARD + default "smart-gateway-mt7688" + +config SYS_VENDOR + default "gardena" + +config SYS_CONFIG_NAME + default "gardena-smart-gateway-mt7688" + +endif
board/gardena/smart-gateway-mt7688/MAINTAINERS new file +8 -0
@@ -0,0 +1,8 @@ +GARDENA_SMART_GATEWAY_MT7688 BOARD +M: Stefan Roese <[email protected]> +S: Maintained +F: board/gardena/smart-gateway-mt7688 +F: include/configs/gardena-smart-gateway-mt7688.h +F: configs/gardena-smart-gateway-mt7688_defconfig +F: configs/gardena-smart-gateway-mt7688-ram_defconfig +F: arch/mips/dts/gardena-smart-gateway-mt7688.dts
board/gardena/smart-gateway-mt7688/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += board.o
board/gardena/smart-gateway-mt7688/board.c new file +17 -0
@@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +*/ + +#include <common.h> +#include <asm/io.h> + +int board_early_init_f (void ) +{ +/* +* Nothing to be done here for this board (no UART setup etc) +* right now. We might need some pin muxing, so lets keep this +* function for now. +*/ +return 0 ; +}
configs/gardena-smart-gateway-mt7688-ram_defconfig new file +58 -0
58 lines not on this page · raw message
configs/gardena-smart-gateway-mt7688_defconfig new file +61 -0
61 lines not on this page · raw message
include/configs/gardena-smart-gateway-mt7688.h new file +56 -0
56 lines not on this page · raw message
Signature · 1 line
2.18.0
PATCH v3 5/6 mips: mt76xx: Add sysreset support
In reply to Stefan RoeseThis patch adds the necessary sysreset DT node and enables the required drivers via Kconfig.
---
- No change
v2:
- New patch
arch/mips/Kconfig | 1 + arch/mips/dts/mt7628a.dtsi | 7 +++++++ 2 files changed, 8 insertions(+)
arch/mips/Kconfig +1 -0
@@ -82,6 +82,7 @@ config ARCH_MT7620 select SUPPORTS_CPU_MIPS32_R1 select SUPPORTS_CPU_MIPS32_R2 select SUPPORTS_LITTLE_ENDIAN + select SYSRESET config MACH_PIC32 bool "Support Microchip PIC32"
arch/mips/dts/mt7628a.dtsi +7 -0
@@ -41,6 +41,13 @@ reg = <0x0 0x100>; }; + syscon-reboot { + compatible = "syscon-reboot"; + regmap = <&sysc>; + offset = <0x34>; + mask = <0x1>; + }; + intc: interrupt-controller at 200 { compatible = "ralink,rt2880-intc"; reg = <0x200 0x100>;
Signature · 1 line
2.18.0
PATCH v3 6/6 mips: mt7628a.dtsi: Add SPI clock-frequency property
In reply to Stefan RoeseThis patch adds the clock-frequency property to the SPI controller DT node. It will be used by the SPI driver to calculate the baud rate.
---
v3:
- New patch
arch/mips/dts/mt7628a.dtsi | 2 ++ 1 file changed, 2 insertions(+)
arch/mips/dts/mt7628a.dtsi +2 -0
@@ -76,6 +76,8 @@ reg = <0xb00 0x40>; #address-cells = <1>; #size-cells = <0>; + + clock-frequency = <200000000>; }; uart0: uartlite at c00 {
Signature · 1 line
2.18.0
PATCH v3 1/6 mips: Add basic MediaTek MT7620/88 support
In reply to Stefan RoeseQuoted 837 lines · Stefan Roese
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.dtsifile 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 <[email protected]>Cc Daniel Schwierzeck <[email protected]>---
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 ofddr_calibrate. Its now called directly and the bootup is much faster
- Some improvements toprint_cpuinfo(), useioremap_nocacheetc
- Added .set noreorder tolowlevel_init.S
- Multiple improvements tolowlevel_init.Sas suggested by Danielv2:
- SortKconfigsymbols alphabetically
- UseMIPS_TUNE_24KC
- Use imply for SPI support
- Dont' add LinkIt module support yet (is added with the board support)
- MoveSKIP_LOWLEVEL_INITfromKconfigto config header
- Use DT to get the base address of the system controller (fordisplay_cpuinfo)
- Remove_machine_restart- a separate driver is provided in a new patch
- Removecachop_op()andcal_invalidate_dcache_rangeand use the genericinvalidate_dcache_rangefunction insteadarch/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.harch/mips/Kconfig +16
-0@@ -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 MIPSarch/mips/Makefile +1
-0@@ -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)arch/mips/dts/mt7628a.dtsi new file +135
-0@@ -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>; + }; +};arch/mips/mach-mt7620/Kconfig new file +113
-0@@ -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 + +endmenuarch/mips/mach-mt7620/Makefile new file +8
-0@@ -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 +endifarch/mips/mach-mt7620/cpu.c new file +69
-0@@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +*/ + +#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 ; +}arch/mips/mach-mt7620/ddr_calibrate.c new file +308
-0@@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +* +* 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); +}arch/mips/mach-mt7620/lowlevel_init.S new file +70
-0@@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (c) 2018 Stefan Roese <[email protected]> + * + * 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 */
arch/mips/mach-mt7620/lowlevel_init.S line 80
Quoted 10 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +10
-0+ 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.
Quoted 21 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +21
-0+ 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)
arch/mips/mach-mt7620/lowlevel_init.S line 111
Quoted 10 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +10
-0+ 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.
Quoted 69 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +69
-0+#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)
arch/mips/mach-mt7620/lowlevel_init.S line 190
Quoted 10 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +10
-0+ 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 ;) If you want to increase readabilty, you could add a define for this 0x100 offset.
Quoted 255 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +216
-0+ li t2, BIT(31) + or t4, t4, t2 + sw t4, 0(t1) + la t1, 0x10c(s2) + lw t4, 0(t1) + j LDO_1P8V + nop +LDO_1P8V: + li t2, ~BIT(6) + and t4, t4, t2 + la t1, 0x10c(s2) + sw t4, 0(t1) + j DDRLDO_SOFT_START +LDO_2P5V: + /* suppose external DDR1 LDO 2.5V */ + li t2, BIT(6) + or t4, t4, t2 + la t1, 0x10c(s2) + sw t4, 0(t1) + +DDRLDO_SOFT_START: + la t1, 0x10c(s2) + 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 + + la t1, 0x10c(s2) + lw t2, 0(t1) + li t3, BIT(18) + or t2, t2, t3 + sw t2, 0(t1) + +SET_RG_BUCK_FPWM: + la t1, 0x104(s2) + lw t2, 0(t1) + ori t2, t2, BIT(10) + sw t2, 0(t1) + +DDR_PAD_CFG: + /* clean CLK PAD */ + la t1, 0x704(s2) + lw t2, 0(t1) + li t8, 0xfffff0f0 + and t2, t2, t8 + /* clean CMD PAD */ + la t1, 0x70c(s2) + lw t3, 0(t1) + li t8, 0xfffff0f0 + and t3, t3, t8 + /* clean DQ IPAD */ + la t1, 0x710(s2) + lw t4, 0(t1) + li t8, 0xfffff8ff + and t4, t4, t8 + /* clean DQ OPAD */ + la t1, 0x714(s2) + lw t5, 0(t1) + li t8, 0xfffff0f0 + and t5, t5, t8 + /* clean DQS IPAD */ + la t1, 0x718(s2) + lw t6, 0(t1) + li t8, 0xfffff8ff + and t6, t6, t8 + /* clean DQS OPAD */ + la t1, 0x71c(s2) + lw t7, 0(t1) + li t8, 0xfffff0f0 + and t7, t7, t8 + + la t1, 0xc(s0) + 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: + la t1, 0x10(s0) + 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: + 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 + */ + la t1, 0x34(s0) + 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) + */ + la t0, 0x14(s1) + lw t1, 0(t0) + nop + and t1, 0xff000000 + or t1, 0x01 + sw t1, 0(t0) + nop + la t0, 0x10(s1) + lw t1, 0(t0) + nop + or t1, 0x10 + sw t1, 0(t0) + nop + + jr ra + nop + END(lowlevel_init)arch/mips/mach-mt7620/mt76xx.h new file +32
-0@@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +*/ + +#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
Signature · 9 lines
- Daniel -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180905/c8ce0792/attachment.sig>
PATCH v3 1/6 mips: Add basic MediaTek MT7620/88 support
Hi Daniel,
Quoted 880 lines · Daniel Schwierzeck
Quoted 837 lines · Stefan Roese
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.dtsifile 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 <[email protected]>Cc Daniel Schwierzeck <[email protected]>---
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 ofddr_calibrate. Its now called directly and the bootup is much faster
- Some improvements toprint_cpuinfo(), useioremap_nocacheetc
- Added .set noreorder tolowlevel_init.S
- Multiple improvements tolowlevel_init.Sas suggested by Danielv2:
- SortKconfigsymbols alphabetically
- UseMIPS_TUNE_24KC
- Use imply for SPI support
- Dont' add LinkIt module support yet (is added with the board support)
- MoveSKIP_LOWLEVEL_INITfromKconfigto config header
- Use DT to get the base address of the system controller (fordisplay_cpuinfo)
- Remove_machine_restart- a separate driver is provided in a new patch
- Removecachop_op()andcal_invalidate_dcache_rangeand use the genericinvalidate_dcache_rangefunction insteadarch/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.dtsicreate mode 100644arch/mips/mach-mt7620/Kconfigcreate mode 100644arch/mips/mach-mt7620/Makefilecreate mode 100644arch/mips/mach-mt7620/cpu.ccreate mode 100644arch/mips/mach-mt7620/ddr_calibrate.ccreate mode 100644arch/mips/mach-mt7620/lowlevel_init.Screate mode 100644arch/mips/mach-mt7620/mt76xx.harch/mips/Kconfig +16
-0@@ -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 MIPSarch/mips/Makefile +1
-0@@ -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)arch/mips/dts/mt7628a.dtsi new file +135
-0@@ -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>; + }; +};arch/mips/mach-mt7620/Kconfig new file +113
-0@@ -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 + +endmenuarch/mips/mach-mt7620/Makefile new file +8
-0@@ -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 +endifarch/mips/mach-mt7620/cpu.c new file +69
-0@@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +*/ + +#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 ; +}arch/mips/mach-mt7620/ddr_calibrate.c new file +308
-0@@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* +* Copyright (C) 2018 Stefan Roese <[email protected]> +* +* 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); +}arch/mips/mach-mt7620/lowlevel_init.S new file +70
-0@@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (c) 2018 Stefan Roese <[email protected]> + * + * 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 */arch/mips/mach-mt7620/lowlevel_init.S line 80
Quoted 10 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +10
-0+ 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_REGmaybe this register address could be loaded too into a sN register because it's used multiple times.
Quoted 26 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +26
-0+ 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)
Quoted 8 lines
arch/mips/mach-mt7620/lowlevel_init.S line 111
Quoted 5 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +5
-0+ ori t3, t3, 0x08 + sw t3, 0(t0) + +CPLL_DONE: +#if 0do 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.
Quoted 82 lines
Quoted 69 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +69
-0+#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)arch/mips/mach-mt7620/lowlevel_init.S line 190
Quoted 10 lines
arch/mips/mach-mt7620/lowlevel_init.S new file +10
-0+ 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
Quoted 3 lines
lw t4, 0x100(s2)this was the main intention of my suggested optimisation ;)
I missed this, thx.
Quoted 2 lines
If you want to increase readabilty, you could add a define for this
0x100offset.
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