diff options
author | Daniel Golle <daniel@makrotopia.org> | 2022-07-11 21:15:32 +0100 |
---|---|---|
committer | Daniel Golle <daniel@makrotopia.org> | 2022-07-11 21:27:24 +0100 |
commit | 2f7fb57c12d7afe5be7747611bceec92a4c0c834 (patch) | |
tree | 8766380a7feeb1350a6b78aa01014a8cb43c4e05 | |
parent | fa75a3a935b26378630498ba7d3f6a0b5b11f86e (diff) | |
download | upstream-2f7fb57c12d7afe5be7747611bceec92a4c0c834.tar.gz upstream-2f7fb57c12d7afe5be7747611bceec92a4c0c834.tar.bz2 upstream-2f7fb57c12d7afe5be7747611bceec92a4c0c834.zip |
uboot-ramips: add support for MT7621, merge into uboot-mediatek
* Merge uboot-ramips into uboot-mediatek.
* Port support for the RAVPower RP WD009 to U-Boot 2022.07.
* Add support for MT7621 and add builds for the reference boards.
* Add builds for MT7620 and MT7628 reference boards.
This should help to make development of U-Boot-level board support for
all MediaTek targets much easier.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
29 files changed, 7440 insertions, 110 deletions
diff --git a/package/boot/uboot-mediatek/Makefile b/package/boot/uboot-mediatek/Makefile index aeaf8bc14b..a994b8be4d 100644 --- a/package/boot/uboot-mediatek/Makefile +++ b/package/boot/uboot-mediatek/Makefile @@ -9,11 +9,59 @@ include $(INCLUDE_DIR)/u-boot.mk include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/host-build.mk +MT7621_LOWLEVEL_PRELOADER_URL:=https://raw.githubusercontent.com/mtk-openwrt/mt7621-lowlevel-preloader/master/ + +define Download/mt7621-stage-sram + FILE:=mt7621_stage_sram.bin + URL:=$(MT7621_LOWLEVEL_PRELOADER_URL) + HASH:=1dda68aa089f0ff262e01539b990dea478952e9fb68bcc0a8cd6f76f0135c62e +endef + +ifdef CONFIG_TARGET_ramips_mt7621 +$(eval $(call Download,mt7621-stage-sram)) +endif + define U-Boot/Default BUILD_TARGET:=mediatek UBOOT_IMAGE:=u-boot-mtk.bin endef +define U-Boot/mt7620_rfb + NAME:=MT7620 Reference Board + UBOOT_CONFIG:=mt7620_rfb + BUILD_DEVICES:=ralink_mt7620a-evb + BUILD_TARGET:=ramips + BUILD_SUBTARGET:=mt7620 + UBOOT_IMAGE:=u-boot-with-spl.bin +endef + +define U-Boot/mt7620_mt7530_rfb + NAME:=MT7620+MT7530 Reference Board + UBOOT_CONFIG:=mt7620_mt7530_rfb + BUILD_DEVICES:=ralink_mt7620a-mt7530-evb + BUILD_TARGET:=ramips + BUILD_SUBTARGET:=mt7620 + UBOOT_IMAGE:=u-boot-with-spl.bin +endef + +define U-Boot/mt7621_rfb + NAME:=MT7621 Reference Board + UBOOT_CONFIG:=mt7621_rfb + BUILD_DEVICES:=mediatek_mt7621-eval-board + BUILD_TARGET:=ramips + BUILD_SUBTARGET:=mt7621 + UBOOT_IMAGE:=u-boot-mt7621.bin +endef + +define U-Boot/mt7621_nand_rfb + NAME:=MT7621 Reference Board (NAND) + UBOOT_CONFIG:=mt7621_nand_rfb + BUILD_DEVICES:=mediatek_mt7621-eval-board + BUILD_TARGET:=ramips + BUILD_SUBTARGET:=mt7621 + UBOOT_IMAGE:=u-boot-mt7621.bin +endef + define U-Boot/mt7622_rfb1 NAME:=MT7622 Reference Board 1 UBOOT_CONFIG:=mt7622_rfb @@ -91,6 +139,24 @@ define U-Boot/mt7623n_bpir2 UBOOT_CONFIG:=mt7623n_bpir2 endef +define U-Boot/mt7628_rfb + NAME:=MT7628 Reference Board + BUILD_DEVICES:=mediatek_mt7628an-eval-board + BUILD_TARGET:=ramips + BUILD_SUBTARGET:=mt76x8 + UBOOT_CONFIG:=mt7628_rfb + UBOOT_IMAGE:=u-boot-with-spl.bin +endef + +define U-Boot/ravpower_rp-wd009 + NAME:=RAVPower RP-WD009 + BUILD_TARGET:=ramips + BUILD_DEVICES:=ravpower_rp-wd009 + BUILD_SUBTARGET:=mt76x8 + UBOOT_CONFIG:=ravpower-rp-wd009-ram + UBOOT_IMAGE:=u-boot.bin +endef + define U-Boot/mt7629_rfb NAME:=MT7629 Reference Board BUILD_SUBTARGET:=mt7629 @@ -99,6 +165,10 @@ define U-Boot/mt7629_rfb endef UBOOT_TARGETS := \ + mt7620_mt7530_rfb \ + mt7620_rfb \ + mt7621_nand_rfb \ + mt7621_rfb \ mt7622_bananapi_bpi-r64-emmc \ mt7622_bananapi_bpi-r64-sdmmc \ mt7622_bananapi_bpi-r64-snand \ @@ -107,9 +177,13 @@ UBOOT_TARGETS := \ mt7622_ubnt_unifi-6-lr \ mt7623n_bpir2 \ mt7623a_unielec_u7623 \ + mt7628_rfb \ + ravpower_rp-wd009 \ mt7629_rfb +ifdef CONFIG_TARGET_mediatek UBOOT_MAKE_FLAGS += $(UBOOT_IMAGE:.fip=.bin) +endif define Build/fip-image $(STAGING_DIR_HOST)/bin/fiptool create \ @@ -118,6 +192,13 @@ define Build/fip-image $(PKG_BUILD_DIR)/u-boot.fip endef +ifdef CONFIG_TARGET_ramips_mt7621 +define Build/Prepare + $(call Build/Prepare/Default) + $(CP) $(DL_DIR)/mt7621_stage_sram.bin $(PKG_BUILD_DIR)/ +endef +endif + define Build/Configure $(call Build/Configure/U-Boot) sed -i 's/CONFIG_TOOLS_LIBCRYPTO=y/# CONFIG_TOOLS_LIBCRYPTO is not set/' $(PKG_BUILD_DIR)/.config @@ -131,8 +212,10 @@ endif endef # don't stage files to bindir, let target/linux/mediatek/image/*.mk do that +ifdef CONFIG_TARGET_mediatek define Package/u-boot/install endef +endif define Build/InstallDev $(INSTALL_DIR) $(STAGING_DIR_IMAGE) diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0001-mips-add-asm-mipsmtregs.h-for-MIPS-multi-threading.patch b/package/boot/uboot-mediatek/patches/001-mtk-0001-mips-add-asm-mipsmtregs.h-for-MIPS-multi-threading.patch new file mode 100644 index 0000000000..1a054c110f --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0001-mips-add-asm-mipsmtregs.h-for-MIPS-multi-threading.patch @@ -0,0 +1,169 @@ +From 65a4a80157bacde3cf86ce8cbc9a08f5f05ad9bb Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:21:34 +0800 +Subject: [PATCH 01/25] mips: add asm/mipsmtregs.h for MIPS multi-threading + +To be compatible with old u-boot used by lots of MT7621 devices, the u-boot +needs to boot-up MT7621's all cores, and all VPES of each core. + +This patch adds asm/mipsmtregs.h from linux kernel which is need for +boot-up VPEs. + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + arch/mips/include/asm/mipsmtregs.h | 142 +++++++++++++++++++++++++++++ + 1 file changed, 142 insertions(+) + create mode 100644 arch/mips/include/asm/mipsmtregs.h + +diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h +new file mode 100644 +index 0000000000..ba82e2bd97 +--- /dev/null ++++ b/arch/mips/include/asm/mipsmtregs.h +@@ -0,0 +1,142 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * MT regs definitions, follows on from mipsregs.h ++ * Copyright (C) 2004 - 2005 MIPS Technologies, Inc. All rights reserved. ++ * Elizabeth Clarke et. al. ++ * ++ */ ++#ifndef _ASM_MIPSMTREGS_H ++#define _ASM_MIPSMTREGS_H ++ ++#include <asm/mipsregs.h> ++ ++/* ++ * Macros for use in assembly language code ++ */ ++ ++#define CP0_MVPCONTROL $0, 1 ++#define CP0_MVPCONF0 $0, 2 ++#define CP0_MVPCONF1 $0, 3 ++#define CP0_VPECONTROL $1, 1 ++#define CP0_VPECONF0 $1, 2 ++#define CP0_VPECONF1 $1, 3 ++#define CP0_YQMASK $1, 4 ++#define CP0_VPESCHEDULE $1, 5 ++#define CP0_VPESCHEFBK $1, 6 ++#define CP0_TCSTATUS $2, 1 ++#define CP0_TCBIND $2, 2 ++#define CP0_TCRESTART $2, 3 ++#define CP0_TCHALT $2, 4 ++#define CP0_TCCONTEXT $2, 5 ++#define CP0_TCSCHEDULE $2, 6 ++#define CP0_TCSCHEFBK $2, 7 ++#define CP0_SRSCONF0 $6, 1 ++#define CP0_SRSCONF1 $6, 2 ++#define CP0_SRSCONF2 $6, 3 ++#define CP0_SRSCONF3 $6, 4 ++#define CP0_SRSCONF4 $6, 5 ++ ++/* MVPControl fields */ ++#define MVPCONTROL_EVP (_ULCAST_(1)) ++ ++#define MVPCONTROL_VPC_SHIFT 1 ++#define MVPCONTROL_VPC (_ULCAST_(1) << MVPCONTROL_VPC_SHIFT) ++ ++#define MVPCONTROL_STLB_SHIFT 2 ++#define MVPCONTROL_STLB (_ULCAST_(1) << MVPCONTROL_STLB_SHIFT) ++ ++/* MVPConf0 fields */ ++#define MVPCONF0_PTC_SHIFT 0 ++#define MVPCONF0_PTC (_ULCAST_(0xff)) ++#define MVPCONF0_PVPE_SHIFT 10 ++#define MVPCONF0_PVPE (_ULCAST_(0xf) << MVPCONF0_PVPE_SHIFT) ++#define MVPCONF0_TCA_SHIFT 15 ++#define MVPCONF0_TCA (_ULCAST_(1) << MVPCONF0_TCA_SHIFT) ++#define MVPCONF0_PTLBE_SHIFT 16 ++#define MVPCONF0_PTLBE (_ULCAST_(0x3ff) << MVPCONF0_PTLBE_SHIFT) ++#define MVPCONF0_TLBS_SHIFT 29 ++#define MVPCONF0_TLBS (_ULCAST_(1) << MVPCONF0_TLBS_SHIFT) ++#define MVPCONF0_M_SHIFT 31 ++#define MVPCONF0_M (_ULCAST_(0x1) << MVPCONF0_M_SHIFT) ++ ++/* config3 fields */ ++#define CONFIG3_MT_SHIFT 2 ++#define CONFIG3_MT (_ULCAST_(1) << CONFIG3_MT_SHIFT) ++ ++/* VPEControl fields (per VPE) */ ++#define VPECONTROL_TARGTC (_ULCAST_(0xff)) ++ ++#define VPECONTROL_TE_SHIFT 15 ++#define VPECONTROL_TE (_ULCAST_(1) << VPECONTROL_TE_SHIFT) ++#define VPECONTROL_EXCPT_SHIFT 16 ++#define VPECONTROL_EXCPT (_ULCAST_(0x7) << VPECONTROL_EXCPT_SHIFT) ++ ++/* Thread Exception Codes for EXCPT field */ ++#define THREX_TU 0 ++#define THREX_TO 1 ++#define THREX_IYQ 2 ++#define THREX_GSX 3 ++#define THREX_YSCH 4 ++#define THREX_GSSCH 5 ++ ++#define VPECONTROL_GSI_SHIFT 20 ++#define VPECONTROL_GSI (_ULCAST_(1) << VPECONTROL_GSI_SHIFT) ++#define VPECONTROL_YSI_SHIFT 21 ++#define VPECONTROL_YSI (_ULCAST_(1) << VPECONTROL_YSI_SHIFT) ++ ++/* VPEConf0 fields (per VPE) */ ++#define VPECONF0_VPA_SHIFT 0 ++#define VPECONF0_VPA (_ULCAST_(1) << VPECONF0_VPA_SHIFT) ++#define VPECONF0_MVP_SHIFT 1 ++#define VPECONF0_MVP (_ULCAST_(1) << VPECONF0_MVP_SHIFT) ++#define VPECONF0_XTC_SHIFT 21 ++#define VPECONF0_XTC (_ULCAST_(0xff) << VPECONF0_XTC_SHIFT) ++ ++/* VPEConf1 fields (per VPE) */ ++#define VPECONF1_NCP1_SHIFT 0 ++#define VPECONF1_NCP1 (_ULCAST_(0xff) << VPECONF1_NCP1_SHIFT) ++#define VPECONF1_NCP2_SHIFT 10 ++#define VPECONF1_NCP2 (_ULCAST_(0xff) << VPECONF1_NCP2_SHIFT) ++#define VPECONF1_NCX_SHIFT 20 ++#define VPECONF1_NCX (_ULCAST_(0xff) << VPECONF1_NCX_SHIFT) ++ ++/* TCStatus fields (per TC) */ ++#define TCSTATUS_TASID (_ULCAST_(0xff)) ++#define TCSTATUS_IXMT_SHIFT 10 ++#define TCSTATUS_IXMT (_ULCAST_(1) << TCSTATUS_IXMT_SHIFT) ++#define TCSTATUS_TKSU_SHIFT 11 ++#define TCSTATUS_TKSU (_ULCAST_(3) << TCSTATUS_TKSU_SHIFT) ++#define TCSTATUS_A_SHIFT 13 ++#define TCSTATUS_A (_ULCAST_(1) << TCSTATUS_A_SHIFT) ++#define TCSTATUS_DA_SHIFT 15 ++#define TCSTATUS_DA (_ULCAST_(1) << TCSTATUS_DA_SHIFT) ++#define TCSTATUS_DT_SHIFT 20 ++#define TCSTATUS_DT (_ULCAST_(1) << TCSTATUS_DT_SHIFT) ++#define TCSTATUS_TDS_SHIFT 21 ++#define TCSTATUS_TDS (_ULCAST_(1) << TCSTATUS_TDS_SHIFT) ++#define TCSTATUS_TSST_SHIFT 22 ++#define TCSTATUS_TSST (_ULCAST_(1) << TCSTATUS_TSST_SHIFT) ++#define TCSTATUS_RNST_SHIFT 23 ++#define TCSTATUS_RNST (_ULCAST_(3) << TCSTATUS_RNST_SHIFT) ++/* Codes for RNST */ ++#define TC_RUNNING 0 ++#define TC_WAITING 1 ++#define TC_YIELDING 2 ++#define TC_GATED 3 ++ ++#define TCSTATUS_TMX_SHIFT 27 ++#define TCSTATUS_TMX (_ULCAST_(1) << TCSTATUS_TMX_SHIFT) ++/* TCStatus TCU bits can use same definitions/offsets as CU bits in Status */ ++ ++/* TCBind */ ++#define TCBIND_CURVPE_SHIFT 0 ++#define TCBIND_CURVPE (_ULCAST_(0xf)) ++ ++#define TCBIND_CURTC_SHIFT 21 ++ ++#define TCBIND_CURTC (_ULCAST_(0xff) << TCBIND_CURTC_SHIFT) ++ ++/* TCHalt */ ++#define TCHALT_H (_ULCAST_(1)) ++ ++#endif +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0002-mips-add-more-definitions-for-asm-cm.h.patch b/package/boot/uboot-mediatek/patches/001-mtk-0002-mips-add-more-definitions-for-asm-cm.h.patch new file mode 100644 index 0000000000..0a3a0a18b6 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0002-mips-add-more-definitions-for-asm-cm.h.patch @@ -0,0 +1,116 @@ +From be570e7b0ce004127a7cc97bfae30037fc42a340 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:21:39 +0800 +Subject: [PATCH 02/25] mips: add more definitions for asm/cm.h + +This patch add more definitions needed for MT7621 initialization. +MT7621 needs to initialize GIC/CPC and other related parts. + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + arch/mips/include/asm/cm.h | 67 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + +diff --git a/arch/mips/include/asm/cm.h b/arch/mips/include/asm/cm.h +index 99ddbccd80..5cc8c09621 100644 +--- a/arch/mips/include/asm/cm.h ++++ b/arch/mips/include/asm/cm.h +@@ -8,9 +8,23 @@ + #define __MIPS_ASM_CM_H__ + + /* Global Control Register (GCR) offsets */ ++#define GCR_CONFIG 0x0000 + #define GCR_BASE 0x0008 + #define GCR_BASE_UPPER 0x000c ++#define GCR_CONTROL 0x0010 ++#define GCR_ACCESS 0x0020 + #define GCR_REV 0x0030 ++#define GCR_GIC_BASE 0x0080 ++#define GCR_CPC_BASE 0x0088 ++#define GCR_REG0_BASE 0x0090 ++#define GCR_REG0_MASK 0x0098 ++#define GCR_REG1_BASE 0x00a0 ++#define GCR_REG1_MASK 0x00a8 ++#define GCR_REG2_BASE 0x00b0 ++#define GCR_REG2_MASK 0x00b8 ++#define GCR_REG3_BASE 0x00c0 ++#define GCR_REG3_MASK 0x00c8 ++#define GCR_CPC_STATUS 0x00f0 + #define GCR_L2_CONFIG 0x0130 + #define GCR_L2_TAG_ADDR 0x0600 + #define GCR_L2_TAG_ADDR_UPPER 0x0604 +@@ -19,10 +33,59 @@ + #define GCR_L2_DATA 0x0610 + #define GCR_L2_DATA_UPPER 0x0614 + #define GCR_Cx_COHERENCE 0x2008 ++#define GCR_Cx_OTHER 0x2018 ++#define GCR_Cx_ID 0x2028 ++#define GCR_CO_COHERENCE 0x4008 ++ ++/* GCR_CONFIG fields */ ++#define GCR_CONFIG_NUM_CLUSTERS_SHIFT 23 ++#define GCR_CONFIG_NUM_CLUSTERS (0x7f << 23) ++#define GCR_CONFIG_NUMIOCU_SHIFT 8 ++#define GCR_CONFIG_NUMIOCU (0xff << 8) ++#define GCR_CONFIG_PCORES_SHIFT 0 ++#define GCR_CONFIG_PCORES (0xff << 0) ++ ++/* GCR_BASE fields */ ++#define GCR_BASE_SHIFT 15 ++#define CCA_DEFAULT_OVR_SHIFT 5 ++#define CCA_DEFAULT_OVR_MASK (0x7 << 5) ++#define CCA_DEFAULT_OVREN (0x1 << 4) ++#define CM_DEFAULT_TARGET_SHIFT 0 ++#define CM_DEFAULT_TARGET_MASK (0x3 << 0) ++ ++/* GCR_CONTROL fields */ ++#define GCR_CONTROL_SYNCCTL (0x1 << 16) + + /* GCR_REV CM versions */ + #define GCR_REV_CM3 0x0800 + ++/* GCR_GIC_BASE fields */ ++#define GCR_GIC_BASE_ADDRMASK_SHIFT 7 ++#define GCR_GIC_BASE_ADDRMASK (0x1ffffff << 7) ++#define GCR_GIC_EN (0x1 << 0) ++ ++/* GCR_CPC_BASE fields */ ++#define GCR_CPC_BASE_ADDRMASK_SHIFT 15 ++#define GCR_CPC_BASE_ADDRMASK (0x1ffff << 15) ++#define GCR_CPC_EN (0x1 << 0) ++ ++/* GCR_REGn_MASK fields */ ++#define GCR_REGn_MASK_ADDRMASK_SHIFT 16 ++#define GCR_REGn_MASK_ADDRMASK (0xffff << 16) ++#define GCR_REGn_MASK_CCAOVR_SHIFT 5 ++#define GCR_REGn_MASK_CCAOVR (0x7 << 5) ++#define GCR_REGn_MASK_CCAOVREN (1 << 4) ++#define GCR_REGn_MASK_DROPL2 (1 << 2) ++#define GCR_REGn_MASK_CMTGT_SHIFT 0 ++#define GCR_REGn_MASK_CMTGT (0x3 << 0) ++#define GCR_REGn_MASK_CMTGT_DISABLED 0x0 ++#define GCR_REGn_MASK_CMTGT_MEM 0x1 ++#define GCR_REGn_MASK_CMTGT_IOCU0 0x2 ++#define GCR_REGn_MASK_CMTGT_IOCU1 0x3 ++ ++/* GCR_CPC_STATUS fields */ ++#define GCR_CPC_EX (0x1 << 0) ++ + /* GCR_L2_CONFIG fields */ + #define GCR_L2_CONFIG_ASSOC_SHIFT 0 + #define GCR_L2_CONFIG_ASSOC_BITS 8 +@@ -36,6 +99,10 @@ + #define GCR_Cx_COHERENCE_DOM_EN (0xff << 0) + #define GCR_Cx_COHERENCE_EN (0x1 << 0) + ++/* GCR_Cx_OTHER fields */ ++#define GCR_Cx_OTHER_CORENUM_SHIFT 16 ++#define GCR_Cx_OTHER_CORENUM (0xffff << 16) ++ + #ifndef __ASSEMBLY__ + + #include <asm/io.h> +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0003-mips-add-__image_copy_len-for-SPL-linker-script.patch b/package/boot/uboot-mediatek/patches/001-mtk-0003-mips-add-__image_copy_len-for-SPL-linker-script.patch new file mode 100644 index 0000000000..42339bdebf --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0003-mips-add-__image_copy_len-for-SPL-linker-script.patch @@ -0,0 +1,40 @@ +From 71ebc3d25147172e219ea87bec061f751257395b Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:21:45 +0800 +Subject: [PATCH 03/25] mips: add __image_copy_len for SPL linker script + +This patch adds __image_copy_len needed by TPL of MT7621 SoC. +The __image_copy_len represents the binary blob size of both SPL/TPL +binaries. To achieve this, __text_start/end are added for calculation. + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + arch/mips/cpu/u-boot-spl.lds | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/mips/cpu/u-boot-spl.lds b/arch/mips/cpu/u-boot-spl.lds +index 28ea4f2a48..f88754ab56 100644 +--- a/arch/mips/cpu/u-boot-spl.lds ++++ b/arch/mips/cpu/u-boot-spl.lds +@@ -13,7 +13,9 @@ SECTIONS + + . = ALIGN(4); + .text : { ++ __text_start = .; + *(.text*) ++ __text_end = .; + } > .spl_mem + + . = ALIGN(4); +@@ -36,6 +38,7 @@ SECTIONS + + . = ALIGN(4); + __image_copy_end = .; ++ __image_copy_len = __image_copy_end - __text_start; + + _image_binary_end = .; + +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0004-mips-add-support-for-noncached_alloc.patch b/package/boot/uboot-mediatek/patches/001-mtk-0004-mips-add-support-for-noncached_alloc.patch new file mode 100644 index 0000000000..ef46beea06 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0004-mips-add-support-for-noncached_alloc.patch @@ -0,0 +1,111 @@ +From d7cfa1cb5602a1d936df36ee70869753835de28e Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:21:51 +0800 +Subject: [PATCH 04/25] mips: add support for noncached_alloc() + +This patch adds support for noncached_alloc() which was only supported by +ARM platform. + +Unlike the ARM platform, MMU is not used in u-boot for MIPS. Instead, KSEG +is provided to access uncached memory. So most code of this patch is copied +from cache.c of ARM platform, with only two differences: +1. MMU is untouched in noncached_set_region() +2. Address returned by noncached_alloc() is converted using KSEG1ADDR() + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + arch/mips/include/asm/system.h | 20 ++++++++++++++++ + arch/mips/lib/cache.c | 43 ++++++++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + +diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h +index 79e638844b..89a2ac209f 100644 +--- a/arch/mips/include/asm/system.h ++++ b/arch/mips/include/asm/system.h +@@ -282,4 +282,24 @@ static inline void instruction_hazard_barrier(void) + : "=&r"(tmp)); + } + ++#ifdef CONFIG_SYS_NONCACHED_MEMORY ++/* 1MB granularity */ ++#define MMU_SECTION_SHIFT 20 ++#define MMU_SECTION_SIZE (1 << MMU_SECTION_SHIFT) ++ ++/** ++ * noncached_init() - Initialize non-cached memory region ++ * ++ * Initialize non-cached memory area. This memory region will be typically ++ * located right below the malloc() area and be accessed from KSEG1. ++ * ++ * It is called during the generic post-relocation init sequence. ++ * ++ * Return: 0 if OK ++ */ ++int noncached_init(void); ++ ++phys_addr_t noncached_alloc(size_t size, size_t align); ++#endif /* CONFIG_SYS_NONCACHED_MEMORY */ ++ + #endif /* _ASM_SYSTEM_H */ +diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c +index ec652f0fba..d23b38d6b9 100644 +--- a/arch/mips/lib/cache.c ++++ b/arch/mips/lib/cache.c +@@ -6,6 +6,7 @@ + + #include <common.h> + #include <cpu_func.h> ++#include <malloc.h> + #include <asm/cache.h> + #include <asm/cacheops.h> + #include <asm/cm.h> +@@ -197,3 +198,45 @@ void dcache_disable(void) + /* ensure the pipeline doesn't contain now-invalid instructions */ + instruction_hazard_barrier(); + } ++ ++#ifdef CONFIG_SYS_NONCACHED_MEMORY ++static unsigned long noncached_start; ++static unsigned long noncached_end; ++static unsigned long noncached_next; ++ ++void noncached_set_region(void) ++{ ++} ++ ++int noncached_init(void) ++{ ++ phys_addr_t start, end; ++ size_t size; ++ ++ /* If this calculation changes, update board_f.c:reserve_noncached() */ ++ end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE; ++ size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE); ++ start = end - size; ++ ++ debug("mapping memory %pa-%pa non-cached\n", &start, &end); ++ ++ noncached_start = start; ++ noncached_end = end; ++ noncached_next = start; ++ ++ return 0; ++} ++ ++phys_addr_t noncached_alloc(size_t size, size_t align) ++{ ++ phys_addr_t next = ALIGN(noncached_next, align); ++ ++ if (next >= noncached_end || (noncached_end - next) < size) ++ return 0; ++ ++ debug("allocated %zu bytes of uncached memory @%pa\n", size, &next); ++ noncached_next = next + size; ++ ++ return CKSEG1ADDR(next); ++} ++#endif /* CONFIG_SYS_NONCACHED_MEMORY */ +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..2c4c57e2d2 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0005-mips-mtmips-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,2979 @@ +From e0c82f36ad5180d9582d353407ff1bf34a2734bb Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:21 +0800 +Subject: [PATCH 05/25] mips: mtmips: add support for MediaTek MT7621 SoC + +This patch adds support for MediaTek MT7621 SoC. +All files are dedicated for u-boot. + +The default build target is u-boot-mt7621.bin. + +The specification of this chip: +https://www.mediatek.com/products/homenetworking/mt7621 + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + arch/mips/dts/mt7621-u-boot.dtsi | 111 ++++++ + arch/mips/dts/mt7621.dtsi | 349 +++++++++++++++++++ + arch/mips/mach-mtmips/Kconfig | 49 ++- + arch/mips/mach-mtmips/Makefile | 4 + + arch/mips/mach-mtmips/cpu.c | 2 +- + arch/mips/mach-mtmips/mt7621/Kconfig | 95 +++++ + arch/mips/mach-mtmips/mt7621/Makefile | 14 + + arch/mips/mach-mtmips/mt7621/init.c | 246 +++++++++++++ + arch/mips/mach-mtmips/mt7621/mt7621.h | 229 ++++++++++++ + arch/mips/mach-mtmips/mt7621/serial.c | 23 ++ + arch/mips/mach-mtmips/mt7621/spl/Makefile | 9 + + arch/mips/mach-mtmips/mt7621/spl/cps.c | 153 ++++++++ + arch/mips/mach-mtmips/mt7621/spl/dram.c | 153 ++++++++ + arch/mips/mach-mtmips/mt7621/spl/dram.h | 39 +++ + arch/mips/mach-mtmips/mt7621/spl/launch.c | 100 ++++++ + arch/mips/mach-mtmips/mt7621/spl/launch.h | 52 +++ + arch/mips/mach-mtmips/mt7621/spl/launch_ll.S | 339 ++++++++++++++++++ + arch/mips/mach-mtmips/mt7621/spl/serial.c | 24 ++ + arch/mips/mach-mtmips/mt7621/spl/spl.c | 95 +++++ + arch/mips/mach-mtmips/mt7621/spl/start.S | 226 ++++++++++++ + arch/mips/mach-mtmips/mt7621/sram_init.S | 22 ++ + arch/mips/mach-mtmips/mt7621/tpl/Makefile | 4 + + arch/mips/mach-mtmips/mt7621/tpl/start.S | 161 +++++++++ + arch/mips/mach-mtmips/mt7621/tpl/tpl.c | 144 ++++++++ + include/configs/mt7621.h | 65 ++++ + 25 files changed, 2702 insertions(+), 6 deletions(-) + create mode 100644 arch/mips/dts/mt7621-u-boot.dtsi + create mode 100644 arch/mips/dts/mt7621.dtsi + create mode 100644 arch/mips/mach-mtmips/mt7621/Kconfig + create mode 100644 arch/mips/mach-mtmips/mt7621/Makefile + create mode 100644 arch/mips/mach-mtmips/mt7621/init.c + create mode 100644 arch/mips/mach-mtmips/mt7621/mt7621.h + create mode 100644 arch/mips/mach-mtmips/mt7621/serial.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/Makefile + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/cps.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/dram.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/dram.h + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/launch.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/launch.h + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/launch_ll.S + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/serial.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/spl.c + create mode 100644 arch/mips/mach-mtmips/mt7621/spl/start.S + create mode 100644 arch/mips/mach-mtmips/mt7621/sram_init.S + create mode 100644 arch/mips/mach-mtmips/mt7621/tpl/Makefile + create mode 100644 arch/mips/mach-mtmips/mt7621/tpl/start.S + create mode 100644 arch/mips/mach-mtmips/mt7621/tpl/tpl.c + create mode 100644 include/configs/mt7621.h + +diff --git a/arch/mips/dts/mt7621-u-boot.dtsi b/arch/mips/dts/mt7621-u-boot.dtsi +new file mode 100644 +index 0000000000..c5a8aa357f +--- /dev/null ++++ b/arch/mips/dts/mt7621-u-boot.dtsi +@@ -0,0 +1,111 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <linux/stringify.h> ++ ++/ { ++ binman: binman { ++ multiple-images; ++ }; ++}; ++ ++&sysc { ++ u-boot,dm-pre-reloc; ++}; ++ ++&reboot { ++ u-boot,dm-pre-reloc; ++}; ++ ++&clkctrl { ++ u-boot,dm-pre-reloc; ++}; ++ ++&rstctrl { ++ u-boot,dm-pre-reloc; ++}; ++ ++&pinctrl { ++ u-boot,dm-pre-reloc; ++}; ++ ++&uart0 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&uart1 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&uart2 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&binman { ++ u-boot-spl-ddr { ++ align = <4>; ++ align-size = <4>; ++ filename = "u-boot-spl-ddr.bin"; ++ pad-byte = <0xff>; ++ ++ u-boot-spl { ++ align-end = <4>; ++ filename = "u-boot-spl.bin"; ++ }; ++ ++ stage_bin { ++ filename = "mt7621_stage_sram.bin"; ++ type = "blob-ext"; ++ }; ++ }; ++ ++ spl-img { ++ filename = "u-boot-spl-ddr.img"; ++ ++ mkimage { ++#ifdef CONFIG_MT7621_BOOT_FROM_NAND ++ args = "-T", "mtk_image", "-n", "mt7621=1", ++ "-a", __stringify(CONFIG_SPL_TEXT_BASE), ++ "-e", __stringify(CONFIG_SPL_TEXT_BASE); ++#else ++ args = "-A", "mips", "-T", "standalone", "-O", "u-boot", ++ "-C", "none", "-n", "MT7621 U-Boot SPL", ++ "-a", __stringify(CONFIG_SPL_TEXT_BASE), ++ "-e", __stringify(CONFIG_SPL_TEXT_BASE); ++#endif ++ ++ blob { ++ filename = "u-boot-spl-ddr.bin"; ++ }; ++ }; ++ }; ++ ++ mt7621-uboot { ++ filename = "u-boot-mt7621.bin"; ++ pad-byte = <0xff>; ++ ++#ifndef CONFIG_MT7621_BOOT_FROM_NAND ++ u-boot-tpl { ++ align-end = <4>; ++ filename = "u-boot-tpl.bin"; ++ }; ++#endif ++ ++ spl { ++#ifdef CONFIG_MT7621_BOOT_FROM_NAND ++ align-end = <0x1000>; ++#endif ++ filename = "u-boot-spl-ddr.img"; ++ type = "blob"; ++ }; ++ ++ u-boot { ++ filename = "u-boot-lzma.img"; ++ type = "blob"; ++ }; ++ }; ++}; +diff --git a/arch/mips/dts/mt7621.dtsi b/arch/mips/dts/mt7621.dtsi +new file mode 100644 +index 0000000000..c32b6095e9 +--- /dev/null ++++ b/arch/mips/dts/mt7621.dtsi +@@ -0,0 +1,349 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <dt-bindings/clock/mt7621-clk.h> ++#include <dt-bindings/reset/mt7621-reset.h> ++#include <dt-bindings/phy/phy.h> ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "mediatek,mt7621-soc"; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "mips,mips1004Kc"; ++ reg = <0>; ++ }; ++ ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "mips,mips1004Kc"; ++ reg = <1>; ++ }; ++ }; ++ ++ clk48m: clk48m { ++ compatible = "fixed-clock"; ++ ++ clock-frequency = <48000000>; ++ ++ #clock-cells = <0>; ++ }; ++ ++ clk50m: clk50m { ++ compatible = "fixed-clock"; ++ ++ clock-frequency = <50000000>; ++ ++ #clock-cells = <0>; ++ }; ++ ++ sysc: sysctrl@1e000000 { ++ compatible = "mediatek,mt7621-sysc", "syscon"; ++ reg = <0x1e000000 0x100>; ++ ++ clkctrl: clock-controller@1e000030 { ++ compatible = "mediatek,mt7621-clk"; ++ mediatek,memc = <&memc>; ++ ++ #clock-cells = <1>; ++ }; ++ }; ++ ++ rstctrl: reset-controller@1e000034 { ++ compatible = "mediatek,mtmips-reset"; ++ reg = <0x1e000034 0x4>; ++ #reset-cells = <1>; ++ }; ++ ++ reboot: resetctl-reboot { ++ compatible = "resetctl-reboot"; ++ ++ resets = <&rstctrl RST_SYS>; ++ reset-names = "sysreset"; ++ }; ++ ++ memc: memctrl@1e005000 { ++ compatible = "mediatek,mt7621-memc", "syscon"; ++ reg = <0x1e005000 0x1000>; ++ }; ++ ++ pinctrl: pinctrl@1e000060 { ++ compatible = "mediatek,mt7621-pinctrl"; ++ reg = <0x1e000048 0x30>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&state_default>; ++ ++ state_default: pin_state { ++ }; ++ ++ uart1_pins: uart1_pins { ++ groups = "uart1"; ++ function = "uart"; ++ }; ++ ++ uart2_pins: uart2_pins { ++ groups = "uart2"; ++ function = "uart"; ++ }; ++ ++ uart3_pins: uart3_pins { ++ groups = "uart3"; ++ function = "uart"; ++ }; ++ ++ sdxc_pins: sdxc_pins { ++ groups = "sdxc"; ++ function = "sdxc"; ++ }; ++ ++ spi_pins: spi_pins { ++ groups = "spi"; ++ function = "spi"; ++ }; ++ ++ eth_pins: eth_pins { ++ mdio_pins { ++ groups = "mdio"; ++ function = "mdio"; ++ }; ++ ++ rgmii1_pins { ++ groups = "rgmii1"; ++ function = "rgmii"; ++ }; ++ ++ esw_pins { ++ groups = "esw int"; ++ function = "esw int"; ++ }; ++ ++ mdio_pconf { ++ groups = "mdio"; ++ drive-strength = <2>; ++ }; ++ }; ++ }; ++ ++ watchdog: watchdog@1e000100 { ++ compatible = "mediatek,mt7621-wdt"; ++ reg = <0x1e000100 0x40>; ++ ++ resets = <&rstctrl RST_TIMER>; ++ reset-names = "wdt"; ++ ++ status = "disabled"; ++ }; ++ ++ gpio: gpio@1e000600 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "mtk,mt7621-gpio"; ++ reg = <0x1e000600 0x100>; ++ ++ resets = <&rstctrl RST_PIO>; ++ reset-names = "pio"; ++ ++ gpio0: bank@0 { ++ reg = <0>; ++ compatible = "mtk,mt7621-gpio-bank"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ gpio1: bank@1 { ++ reg = <1>; ++ compatible = "mtk,mt7621-gpio-bank"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ gpio2: bank@2 { ++ reg = <2>; ++ compatible = "mtk,mt7621-gpio-bank"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++ ++ spi: spi@1e000b00 { ++ compatible = "ralink,mt7621-spi"; ++ reg = <0x1e000b00 0x40>; ++ ++ status = "disabled"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_pins>; ++ ++ resets = <&rstctrl RST_SPI>; ++ reset-names = "spi"; ++ ++ clocks = <&clkctrl MT7621_CLK_SPI>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ uart0: uart1@1e000c00 { ++ compatible = "mediatek,hsuart", "ns16550a"; ++ reg = <0x1e000c00 0x100>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ ++ clocks = <&clkctrl MT7621_CLK_UART1>; ++ ++ resets = <&rstctrl RST_UART1>; ++ ++ reg-shift = <2>; ++ }; ++ ++ uart1: uart2@1e000d00 { ++ compatible = "mediatek,hsuart", "ns16550a"; ++ reg = <0x1e000d00 0x100>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart2_pins>; ++ ++ clocks = <&clkctrl MT7621_CLK_UART2>; ++ ++ resets = <&rstctrl RST_UART2>; ++ ++ reg-shift = <2>; ++ ++ status = "disabled"; ++ }; ++ ++ uart2: uart3@1e000e00 { ++ compatible = "mediatek,hsuart", "ns16550a"; ++ reg = <0x1e000e00 0x100>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins>; ++ ++ clocks = <&clkctrl MT7621_CLK_UART3>; ++ ++ resets = <&rstctrl RST_UART3>; ++ ++ reg-shift = <2>; ++ ++ status = "disabled"; ++ }; ++ ++ eth: eth@1e100000 { ++ compatible = "mediatek,mt7621-eth"; ++ reg = <0x1e100000 0x20000>; ++ mediatek,ethsys = <&sysc>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð_pins>; ++ ++ resets = <&rstctrl RST_FE>, <&rstctrl RST_GMAC>, <&rstctrl RST_MCM>; ++ reset-names = "fe", "gmac", "mcm"; ++ ++ clocks = <&clkctrl MT7621_CLK_GDMA>, ++ <&clkctrl MT7621_CLK_ETH>; ++ clock-names = "gmac", "fe"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mediatek,gmac-id = <0>; ++ phy-mode = "rgmii"; ++ mediatek,switch = "mt7530"; ++ mediatek,mcm; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ mmc: mmc@1e130000 { ++ compatible = "mediatek,mt7621-mmc"; ++ reg = <0x1e130000 0x4000>; ++ ++ status = "disabled"; ++ ++ bus-width = <4>; ++ builtin-cd = <1>; ++ r_smpl = <1>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdxc_pins>; ++ ++ clocks = <&clk50m>, <&clkctrl MT7621_CLK_SHXC>; ++ clock-names = "source", "hclk"; ++ ++ resets = <&rstctrl RST_SDXC>; ++ }; ++ ++ ssusb: usb@1e1c0000 { ++ compatible = "mediatek,mt7621-xhci", "mediatek,mtk-xhci"; ++ reg = <0x1e1c0000 0x1000>, <0x1e1d0700 0x100>; ++ reg-names = "mac", "ippc"; ++ ++ clocks = <&clk48m>, <&clk48m>; ++ clock-names = "sys_ck", "ref_ck"; ++ ++ phys = <&u2port0 PHY_TYPE_USB2>, ++ <&u3port0 PHY_TYPE_USB3>, ++ <&u2port1 PHY_TYPE_USB2>; ++ ++ status = "disabled"; ++ }; ++ ++ u3phy: usb-phy@1e1d0000 { ++ compatible = "mediatek,mt7621-u3phy", ++ "mediatek,generic-tphy-v1"; ++ reg = <0x1e1d0000 0x700>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ status = "disabled"; ++ ++ u2port0: usb-phy@1e1d0800 { ++ reg = <0x1e1d0800 0x0100>; ++ #phy-cells = <1>; ++ clocks = <&clk48m>; ++ clock-names = "ref"; ++ }; ++ ++ u3port0: usb-phy@1e1d0900 { ++ reg = <0x1e1d0900 0x0100>; ++ #phy-cells = <1>; ++ }; ++ ++ u2port1: usb-phy@1e1d1000 { ++ reg = <0x1e1d1000 0x0100>; ++ #phy-cells = <1>; ++ clocks = <&clk48m>; ++ clock-names = "ref"; ++ }; ++ }; ++ ++ i2c: i2c@1e000900 { ++ compatible = "i2c-gpio"; ++ ++ status = "disabled"; ++ ++ i2c-gpio,delay-us = <3>; ++ ++ gpios = <&gpio0 3 1>, /* PIN3 as SDA */ ++ <&gpio0 4 1>; /* PIN4 as CLK */ ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++}; +diff --git a/arch/mips/mach-mtmips/Kconfig b/arch/mips/mach-mtmips/Kconfig +index 151b004603..d46be503a2 100644 +--- a/arch/mips/mach-mtmips/Kconfig ++++ b/arch/mips/mach-mtmips/Kconfig +@@ -9,6 +9,7 @@ config SYS_MALLOC_F_LEN + + config SYS_SOC + default "mt7620" if SOC_MT7620 ++ default "mt7621" if SOC_MT7621 + default "mt7628" if SOC_MT7628 + + config SYS_DCACHE_SIZE +@@ -18,25 +19,45 @@ config SYS_DCACHE_LINE_SIZE + default 32 + + config SYS_ICACHE_SIZE +- default 65536 ++ default 65536 if SOC_MT7620 || SOC_MT7628 ++ default 32768 if SOC_MT7621 + + config SYS_ICACHE_LINE_SIZE + default 32 + ++config SYS_SCACHE_LINE_SIZE ++ default 32 if SOC_MT7621 ++ + config SYS_TEXT_BASE +- default 0x9c000000 if !SPL +- default 0x80200000 if SPL ++ default 0x9c000000 if !SPL && !SOC_MT7621 ++ default 0x80200000 if SPL || SOC_MT7621 + + config SPL_TEXT_BASE +- default 0x9c000000 ++ default 0x9c000000 if !SOC_MT7621 ++ default 0x80100000 if SOC_MT7621 ++ ++config SPL_SIZE_LIMIT ++ default 0x30000 if SOC_MT7621 ++ ++config TPL_TEXT_BASE ++ default 0xbfc00000 if SOC_MT7621 ++ ++config TPL_MAX_SIZE ++ default 4096 if SOC_MT7621 + + config SPL_PAYLOAD + default "u-boot-lzma.img" if SPL_LZMA + + config BUILD_TARGET +- default "u-boot-with-spl.bin" if SPL ++ default "u-boot-with-spl.bin" if SPL && !SOC_MT7621 ++ default "u-boot-lzma.img" if SOC_MT7621 + default "u-boot.bin" + ++config MAX_MEM_SIZE ++ int ++ default 256 if SOC_MT7620 || SOC_MT7628 ++ default 512 if SOC_MT7621 ++ + choice + prompt "MediaTek MIPS SoC select" + +@@ -55,6 +76,23 @@ config SOC_MT7620 + help + This supports MediaTek MT7620. + ++config SOC_MT7621 ++ bool "MT7621" ++ select MIPS_CM ++ select MIPS_L2_CACHE ++ select SYS_CACHE_SHIFT_5 ++ select SYS_MIPS_CACHE_INIT_RAM_LOAD ++ select PINCTRL_MT7621 ++ select MTK_SERIAL ++ select REGMAP ++ select SYSCON ++ select BINMAN ++ select SUPPORT_TPL ++ select SPL_LOADER_SUPPORT if SPL ++ select SPL_INIT_STACK_WITHOUT_MALLOC_F if SPL ++ help ++ This supports MediaTek MT7621. ++ + config SOC_MT7628 + bool "MT7628" + select SYS_CACHE_SHIFT_5 +@@ -80,6 +118,7 @@ config SOC_MT7628 + endchoice + + source "arch/mips/mach-mtmips/mt7620/Kconfig" ++source "arch/mips/mach-mtmips/mt7621/Kconfig" + source "arch/mips/mach-mtmips/mt7628/Kconfig" + + endmenu +diff --git a/arch/mips/mach-mtmips/Makefile b/arch/mips/mach-mtmips/Makefile +index 4909b47ef2..19f1e07033 100644 +--- a/arch/mips/mach-mtmips/Makefile ++++ b/arch/mips/mach-mtmips/Makefile +@@ -1,9 +1,13 @@ + # SPDX-License-Identifier: GPL-2.0+ + + obj-y += cpu.o ++ ++ifneq ($(CONFIG_SOC_MT7621),y) + obj-y += ddr_init.o + obj-y += ddr_cal.o + obj-$(CONFIG_SPL_BUILD) += spl.o ++endif + + obj-$(CONFIG_SOC_MT7620) += mt7620/ ++obj-$(CONFIG_SOC_MT7621) += mt7621/ + obj-$(CONFIG_SOC_MT7628) += mt7628/ +diff --git a/arch/mips/mach-mtmips/cpu.c b/arch/mips/mach-mtmips/cpu.c +index a4b5cff61d..f1e9022738 100644 +--- a/arch/mips/mach-mtmips/cpu.c ++++ b/arch/mips/mach-mtmips/cpu.c +@@ -16,7 +16,7 @@ DECLARE_GLOBAL_DATA_PTR; + + int dram_init(void) + { +- gd->ram_size = get_ram_size((void *)KSEG1, SZ_256M); ++ gd->ram_size = get_ram_size((void *)KSEG1, CONFIG_MAX_MEM_SIZE << 20); + + return 0; + } +diff --git a/arch/mips/mach-mtmips/mt7621/Kconfig b/arch/mips/mach-mtmips/mt7621/Kconfig +new file mode 100644 +index 0000000000..37d512c68f +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/Kconfig +@@ -0,0 +1,95 @@ ++ ++if SOC_MT7621 ++ ++menu "CPU & DDR configuration" ++ ++config MT7621_CPU_FREQ ++ int "CPU Frequency (MHz)" ++ range 400 1200 ++ default 880 ++ ++choice ++ prompt "DRAM Frequency" ++ default MT7621_DRAM_FREQ_1200 ++ ++config MT7621_DRAM_FREQ_400 ++ bool "400MHz" ++ ++config MT7621_DRAM_FREQ_800 ++ bool "800MHz" ++ ++config MT7621_DRAM_FREQ_1066 ++ bool "1066MHz" ++ ++config MT7621_DRAM_FREQ_1200 ++ bool "1200MHz" ++ ++endchoice ++ ++choice ++ prompt "DDR2 timing parameters" ++ default MT7621_DRAM_DDR2_1024M ++ ++config MT7621_DRAM_DDR2_512M ++ bool "64MB" ++ ++config MT7621_DRAM_DDR2_1024M ++ bool "128MB" ++ ++config MT7621_DRAM_DDR2_512M_W9751G6KB_A02_1066MHZ ++ bool "W9751G6KB_A02 @ 1066MHz (64MB)" ++ ++config MT7621_DRAM_DDR2_1024M_W971GG6KB25_800MHZ ++ bool "W971GG6KB25 @ 800MHz (128MB)" ++ ++config MT7621_DRAM_DDR2_1024M_W971GG6KB18_1066MHZ ++ bool "W971GG6KB18 @ 1066MHz (128MB)" ++ ++endchoice ++ ++choice ++ prompt "DDR3 timing parameters" ++ default MT7621_DRAM_DDR3_2048M ++ ++config MT7621_DRAM_DDR3_1024M ++ bool "128MB" ++ ++config MT7621_DRAM_DDR3_1024M_KGD ++ bool "128MB KGD (MT7621DA)" ++ ++config MT7621_DRAM_DDR3_2048M ++ bool "256MB" ++ ++config MT7621_DRAM_DDR3_4096M ++ bool "512MB" ++ ++endchoice ++ ++endmenu ++ ++config DEBUG_UART_BOARD_INIT ++ default y ++ ++config MT7621_BOOT_FROM_NAND ++ bool "Boot from NAND" ++ help ++ Select this if u-boot will boot from NAND flash. When booting from ++ NAND, SPL will be loaded by bootrom directly and no TPL is needed. ++ ++choice ++ prompt "Board select" ++ ++endchoice ++ ++config SYS_CONFIG_NAME ++ string "Board configuration name" ++ default "mt7621" if BOARD_MT7621_RFB || BOARD_MT7621_NAND_RFB ++ ++config SYS_BOARD ++ string "Board name" ++ default "mt7621" if BOARD_MT7621_RFB || BOARD_MT7621_NAND_RFB ++ ++config SYS_VENDOR ++ default "mediatek" if BOARD_MT7621_RFB || BOARD_MT7621_NAND_RFB ++ ++endif +diff --git a/arch/mips/mach-mtmips/mt7621/Makefile b/arch/mips/mach-mtmips/mt7621/Makefile +new file mode 100644 +index 0000000000..bf1b0bb688 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/Makefile +@@ -0,0 +1,14 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += init.o ++obj-y += serial.o ++ ++ifeq ($(CONFIG_SPL_BUILD),y) ++ifeq ($(CONFIG_TPL_BUILD),y) ++obj-y += tpl/ ++else ++obj-y += spl/ ++endif ++ ++obj-y += sram_init.o ++endif +diff --git a/arch/mips/mach-mtmips/mt7621/init.c b/arch/mips/mach-mtmips/mt7621/init.c +new file mode 100644 +index 0000000000..d21848ad23 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/init.c +@@ -0,0 +1,246 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <clk.h> ++#include <dm.h> ++#include <dm/uclass.h> ++#include <dt-bindings/clock/mt7621-clk.h> ++#include <asm/global_data.h> ++#include <linux/io.h> ++#include <linux/bitfield.h> ++#include "mt7621.h" ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++static const char *const boot_mode[(CHIP_MODE_M >> CHIP_MODE_S) + 1] = { ++ [1] = "NAND 2K+64", ++ [2] = "SPI-NOR 3-Byte Addr", ++ [3] = "SPI-NOR 4-Byte Addr", ++ [10] = "NAND 2K+128", ++ [11] = "NAND 4K+128", ++ [12] = "NAND 4K+256", ++}; ++ ++int print_cpuinfo(void) ++{ ++ void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ u32 val, ver, eco, pkg, core, dram, chipmode; ++ u32 cpu_clk, ddr_clk, bus_clk, xtal_clk; ++ struct udevice *clkdev; ++ const char *bootdev; ++ struct clk clk; ++ int ret; ++ ++ val = readl(sysc + SYSCTL_CHIP_REV_ID_REG); ++ ver = FIELD_GET(VER_ID_M, val); ++ eco = FIELD_GET(ECO_ID_M, val); ++ pkg = FIELD_GET(PKG_ID, val); ++ core = FIELD_GET(CPU_ID, val); ++ ++ val = readl(sysc + SYSCTL_SYSCFG0_REG); ++ dram = FIELD_GET(DRAM_TYPE, val); ++ chipmode = FIELD_GET(CHIP_MODE_M, val); ++ ++ bootdev = boot_mode[chipmode]; ++ if (!bootdev) ++ bootdev = "Unsupported boot mode"; ++ ++ printf("CPU: MediaTek MT7621%c ver %u, eco %u\n", ++ core ? (pkg ? 'A' : 'N') : 'S', ver, eco); ++ ++ printf("Boot: DDR%u, %s\n", dram ? 2 : 3, bootdev); ++ ++ ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(mt7621_clk), ++ &clkdev); ++ if (ret) ++ return ret; ++ ++ clk.dev = clkdev; ++ ++ clk.id = MT7621_CLK_CPU; ++ cpu_clk = clk_get_rate(&clk); ++ ++ clk.id = MT7621_CLK_BUS; ++ bus_clk = clk_get_rate(&clk); ++ ++ clk.id = MT7621_CLK_DDR; ++ ddr_clk = clk_get_rate(&clk); ++ ++ clk.id = MT7621_CLK_XTAL; ++ xtal_clk = clk_get_rate(&clk); ++ ++ /* Set final timer frequency */ ++ if (cpu_clk) ++ gd->arch.timer_freq = cpu_clk / 2; ++ ++ printf("Clock: CPU: %uMHz, DDR: %uMT/s, Bus: %uMHz, XTAL: %uMHz\n", ++ cpu_clk / 1000000, ddr_clk / 500000, bus_clk / 1000000, ++ xtal_clk / 1000000); ++ ++ return 0; ++} ++ ++unsigned long get_xtal_mhz(void) ++{ ++ void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ u32 bs, xtal_sel; ++ ++ bs = readl(sysc + SYSCTL_SYSCFG0_REG); ++ xtal_sel = FIELD_GET(XTAL_MODE_SEL_M, bs); ++ ++ if (xtal_sel <= 2) ++ return 20; ++ else if (xtal_sel <= 5) ++ return 40; ++ else ++ return 25; ++} ++ ++static void xhci_config_40mhz(void __iomem *usbh) ++{ ++ writel(FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MODE_M, 2) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MODE_M, 2) | 0x10, ++ usbh + SSUSB_MAC_CK_CTRL_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PREDIV_PE1D_M, 2) | ++ FIELD_PREP(SSUSB_PLL_PREDIV_U3_M, 1) | ++ FIELD_PREP(SSUSB_PLL_FBKDI_M, 4), ++ usbh + DA_SSUSB_U3PHYA_10_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_FBKDIV_PE2H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1D_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_U3_M, 0x1e), ++ usbh + DA_SSUSB_PLL_FBKDIV_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PCW_NCPO_U3_M, 0x1e400000), ++ usbh + DA_SSUSB_PLL_PCW_NCPO_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE1H_M, 0x25) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_U3_M, 0x73), ++ usbh + DA_SSUSB_PLL_SSC_DELTA1_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA_U3_M, 0x71) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE2D_M, 0x4a), ++ usbh + DA_SSUSB_U3PHYA_21_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_PRD_M, 0x140), ++ usbh + SSUSB_U3PHYA_9_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_PCW_NCPO_M, 0x11c00000), ++ usbh + SSUSB_U3PHYA_3_REG); ++ ++ writel(FIELD_PREP(SSUSB_PCIE_CLKDRV_AMP_M, 4) | ++ FIELD_PREP(SSUSB_SYSPLL_FBSEL_M, 1) | ++ FIELD_PREP(SSUSB_SYSPLL_PREDIV_M, 1), ++ usbh + SSUSB_U3PHYA_1_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_FBDIV_M, 0x12) | ++ SSUSB_SYSPLL_VCO_DIV_SEL | SSUSB_SYSPLL_FPEN | ++ SSUSB_SYSPLL_MONCK_EN | SSUSB_SYSPLL_VOD_EN, ++ usbh + SSUSB_U3PHYA_2_REG); ++ ++ writel(SSUSB_EQ_CURSEL | FIELD_PREP(SSUSB_RX_DAC_MUX_M, 8) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_VTH_M, 1) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_LPF_M, 1), ++ usbh + SSUSB_U3PHYA_11_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_CNTEND_M, 0x1ff) | ++ FIELD_PREP(SSUSB_XTAL_OSC_CNTEND_M, 0x7f) | ++ SSUSB_RING_BYPASS_DET, ++ usbh + SSUSB_B2_ROSC_0_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_FRC_RECAL_M, 3) | ++ SSUSB_RING_OSC_FRC_SEL, ++ usbh + SSUSB_B2_ROSC_1_REG); ++} ++ ++static void xhci_config_25mhz(void __iomem *usbh) ++{ ++ writel(FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_M, 0x20) | ++ FIELD_PREP(SSUSB_MAC3_SYS_CK_GATE_MODE_M, 2) | ++ FIELD_PREP(SSUSB_MAC2_SYS_CK_GATE_MODE_M, 2) | 0x10, ++ usbh + SSUSB_MAC_CK_CTRL_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PREDIV_PE1D_M, 2) | ++ FIELD_PREP(SSUSB_PLL_FBKDI_M, 4), ++ usbh + DA_SSUSB_U3PHYA_10_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_FBKDIV_PE2H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1D_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_PE1H_M, 0x18) | ++ FIELD_PREP(SSUSB_PLL_FBKDIV_U3_M, 0x19), ++ usbh + DA_SSUSB_PLL_FBKDIV_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_PCW_NCPO_U3_M, 0x18000000), ++ usbh + DA_SSUSB_PLL_PCW_NCPO_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE1H_M, 0x25) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_U3_M, 0x4a), ++ usbh + DA_SSUSB_PLL_SSC_DELTA1_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_DELTA_U3_M, 0x48) | ++ FIELD_PREP(SSUSB_PLL_SSC_DELTA1_PE2D_M, 0x4a), ++ usbh + DA_SSUSB_U3PHYA_21_REG); ++ ++ writel(FIELD_PREP(SSUSB_PLL_SSC_PRD_M, 0x190), ++ usbh + SSUSB_U3PHYA_9_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_PCW_NCPO_M, 0xe000000), ++ usbh + SSUSB_U3PHYA_3_REG); ++ ++ writel(FIELD_PREP(SSUSB_PCIE_CLKDRV_AMP_M, 4) | ++ FIELD_PREP(SSUSB_SYSPLL_FBSEL_M, 1), ++ usbh + SSUSB_U3PHYA_1_REG); ++ ++ writel(FIELD_PREP(SSUSB_SYSPLL_FBDIV_M, 0xf) | ++ SSUSB_SYSPLL_VCO_DIV_SEL | SSUSB_SYSPLL_FPEN | ++ SSUSB_SYSPLL_MONCK_EN | SSUSB_SYSPLL_VOD_EN, ++ usbh + SSUSB_U3PHYA_2_REG); ++ ++ writel(SSUSB_EQ_CURSEL | FIELD_PREP(SSUSB_RX_DAC_MUX_M, 8) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_VTH_M, 1) | ++ FIELD_PREP(SSUSB_PCIE_SIGDET_LPF_M, 1), ++ usbh + SSUSB_U3PHYA_11_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_CNTEND_M, 0x1ff) | ++ FIELD_PREP(SSUSB_XTAL_OSC_CNTEND_M, 0x7f) | ++ SSUSB_RING_BYPASS_DET, ++ usbh + SSUSB_B2_ROSC_0_REG); ++ ++ writel(FIELD_PREP(SSUSB_RING_OSC_FRC_RECAL_M, 3) | ++ SSUSB_RING_OSC_FRC_SEL, ++ usbh + SSUSB_B2_ROSC_1_REG); ++} ++ ++void lowlevel_init(void) ++{ ++ void __iomem *usbh = ioremap_nocache(SSUSB_BASE, SSUSB_SIZE); ++ u32 xtal = get_xtal_mhz(); ++ ++ /* Setup USB xHCI */ ++ if (xtal == 40) ++ xhci_config_40mhz(usbh); ++ else if (xtal == 25) ++ xhci_config_25mhz(usbh); ++} ++ ++ulong notrace get_tbclk(void) ++{ ++ return gd->arch.timer_freq; ++} ++ ++void _machine_restart(void) ++{ ++ void __iomem *sysc = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ ++ while (1) ++ writel(SYS_RST, sysc + SYSCTL_RSTCTL_REG); ++} +diff --git a/arch/mips/mach-mtmips/mt7621/mt7621.h b/arch/mips/mach-mtmips/mt7621/mt7621.h +new file mode 100644 +index 0000000000..916cc993b4 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/mt7621.h +@@ -0,0 +1,229 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _MT7621_H_ ++#define _MT7621_H_ ++ ++#define SYSCTL_BASE 0x1e000000 ++#define SYSCTL_SIZE 0x100 ++#define TIMER_BASE 0x1e000100 ++#define TIMER_SIZE 0x100 ++#define RBUS_BASE 0x1e000400 ++#define RBUS_SIZE 0x100 ++#define GPIO_BASE 0x1e000600 ++#define GPIO_SIZE 0x100 ++#define DMA_CFG_ARB_BASE 0x1e000800 ++#define DMA_CFG_ARB_SIZE 0x100 ++#define SPI_BASE 0x1e000b00 ++#define SPI_SIZE 0x100 ++#define UART1_BASE 0x1e000c00 ++#define UART1_SIZE 0x100 ++#define UART2_BASE 0x1e000d00 ++#define UART2_SIZE 0x100 ++#define UART3_BASE 0x1e000e00 ++#define UART3_SIZE 0x100 ++#define NFI_BASE 0x1e003000 ++#define NFI_SIZE 0x800 ++#define NFI_ECC_BASE 0x1e003800 ++#define NFI_ECC_SIZE 0x800 ++#define DRAMC_BASE 0x1e005000 ++#define DRAMC_SIZE 0x1000 ++#define FE_BASE 0x1e100000 ++#define FE_SIZE 0xe000 ++#define GMAC_BASE 0x1e110000 ++#define GMAC_SIZE 0x8000 ++#define SSUSB_BASE 0x1e1c0000 ++#define SSUSB_SIZE 0x40000 ++ ++ /* GIC Base Address */ ++#define MIPS_GIC_BASE 0x1fbc0000 ++ ++ /* CPC Base Address */ ++#define MIPS_CPC_BASE 0x1fbf0000 ++ ++ /* Flash Memory-mapped Base Address */ ++#define FLASH_MMAP_BASE 0x1fc00000 ++#define TPL_INFO_OFFSET 0x40 ++#define TPL_INFO_MAGIC 0x31323637 /* Magic "7621" */ ++ ++/* SRAM */ ++#define FE_SRAM_BASE1 0x8000 ++#define FE_SRAM_BASE2 0xa000 ++ ++/* SYSCTL_BASE */ ++#define SYSCTL_CHIP_REV_ID_REG 0x0c ++#define CPU_ID 0x20000 ++#define PKG_ID 0x10000 ++#define VER_ID_S 8 ++#define VER_ID_M 0xf00 ++#define ECO_ID_S 0 ++#define ECO_ID_M 0x0f ++ ++#define SYSCTL_SYSCFG0_REG 0x10 ++#define XTAL_MODE_SEL_S 6 ++#define XTAL_MODE_SEL_M 0x1c0 ++#define DRAM_TYPE 0x10 ++#define CHIP_MODE_S 0 ++#define CHIP_MODE_M 0x0f ++ ++#define BOOT_SRAM_BASE_REG 0x20 ++ ++#define SYSCTL_CLKCFG0_REG 0x2c ++#define CPU_CLK_SEL_S 30 ++#define CPU_CLK_SEL_M 0xc0000000 ++#define MPLL_CFG_SEL_S 23 ++#define MPLL_CFG_SEL_M 0x800000 ++ ++#define SYSCTL_RSTCTL_REG 0x34 ++#define MCM_RST 0x04 ++#define SYS_RST 0x01 ++ ++#define SYSCTL_CUR_CLK_STS_REG 0x44 ++#define CUR_CPU_FDIV_S 8 ++#define CUR_CPU_FDIV_M 0x1f00 ++#define CUR_CPU_FFRAC_S 0 ++#define CUR_CPU_FFRAC_M 0x1f ++ ++#define SYSCTL_GPIOMODE_REG 0x60 ++#define UART2_MODE_S 5 ++#define UART2_MODE_M 0x60 ++#define UART3_MODE_S 3 ++#define UART3_MODE_M 0x18 ++#define UART1_MODE 0x02 ++ ++/* RBUS_BASE */ ++#define RBUS_DYN_CFG0_REG 0x0010 ++#define CPU_FDIV_S 8 ++#define CPU_FDIV_M 0x1f00 ++#define CPU_FFRAC_S 0 ++#define CPU_FFRAC_M 0x1f ++ ++/* DMA_CFG_ARB_BASE */ ++#define DMA_ROUTE_REG 0x000c ++ ++/* SPI_BASE */ ++#define SPI_SPACE_REG 0x003c ++#define FS_SLAVE_SEL_S 12 ++#define FS_SLAVE_SEL_M 0x70000 ++#define FS_CLK_SEL_S 0 ++#define FS_CLK_SEL_M 0xfff ++ ++/* FE_BASE */ ++#define FE_RST_GLO_REG 0x0004 ++#define FE_PSE_RAM 0x04 ++#define FE_PSE_MEM_EN 0x02 ++#define FE_PSE_RESET 0x01 ++ ++/* SSUSB_BASE */ ++#define SSUSB_MAC_CK_CTRL_REG 0x10784 ++#define SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_S 16 ++#define SSUSB_MAC3_SYS_CK_GATE_MASK_TIME_M 0xff0000 ++#define SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_S 8 ++#define SSUSB_MAC2_SYS_CK_GATE_MASK_TIME_M 0xff00 ++#define SSUSB_MAC3_SYS_CK_GATE_MODE_S 2 ++#define SSUSB_MAC3_SYS_CK_GATE_MODE_M 0x0c ++#define SSUSB_MAC2_SYS_CK_GATE_MODE_S 0 ++#define SSUSB_MAC2_SYS_CK_GATE_MODE_M 0x03 ++ ++#define SSUSB_B2_ROSC_0_REG 0x10a40 ++#define SSUSB_RING_OSC_CNTEND_S 23 ++#define SSUSB_RING_OSC_CNTEND_M 0xff800000 ++#define SSUSB_XTAL_OSC_CNTEND_S 16 ++#define SSUSB_XTAL_OSC_CNTEND_M 0x7f0000 ++#define SSUSB_RING_BYPASS_DET 0x01 ++ ++#define SSUSB_B2_ROSC_1_REG 0x10a44 ++#define SSUSB_RING_OSC_FRC_RECAL_S 17 ++#define SSUSB_RING_OSC_FRC_RECAL_M 0x60000 ++#define SSUSB_RING_OSC_FRC_SEL 0x01 ++ ++#define SSUSB_U3PHYA_1_REG 0x10b04 ++#define SSUSB_PCIE_CLKDRV_AMP_S 27 ++#define SSUSB_PCIE_CLKDRV_AMP_M 0x38000000 ++#define SSUSB_SYSPLL_FBSEL_S 2 ++#define SSUSB_SYSPLL_FBSEL_M 0x0c ++#define SSUSB_SYSPLL_PREDIV_S 0 ++#define SSUSB_SYSPLL_PREDIV_M 0x03 ++ ++#define SSUSB_U3PHYA_2_REG 0x10b08 ++#define SSUSB_SYSPLL_FBDIV_S 24 ++#define SSUSB_SYSPLL_FBDIV_M 0x7f000000 ++#define SSUSB_SYSPLL_VCO_DIV_SEL 0x200000 ++#define SSUSB_SYSPLL_FPEN 0x2000 ++#define SSUSB_SYSPLL_MONCK_EN 0x1000 ++#define SSUSB_SYSPLL_VOD_EN 0x200 ++ ++#define SSUSB_U3PHYA_3_REG 0x10b10 ++#define SSUSB_SYSPLL_PCW_NCPO_S 1 ++#define SSUSB_SYSPLL_PCW_NCPO_M 0xfffffffe ++ ++#define SSUSB_U3PHYA_9_REG 0x10b24 ++#define SSUSB_PLL_SSC_PRD_S 0 ++#define SSUSB_PLL_SSC_PRD_M 0xffff ++ ++#define SSUSB_U3PHYA_11_REG 0x10b2c ++#define SSUSB_EQ_CURSEL 0x1000000 ++#define SSUSB_RX_DAC_MUX_S 19 ++#define SSUSB_RX_DAC_MUX_M 0xf80000 ++#define SSUSB_PCIE_SIGDET_VTH_S 5 ++#define SSUSB_PCIE_SIGDET_VTH_M 0x60 ++#define SSUSB_PCIE_SIGDET_LPF_S 3 ++#define SSUSB_PCIE_SIGDET_LPF_M 0x18 ++ ++#define DA_SSUSB_PLL_FBKDIV_REG 0x10c1c ++#define SSUSB_PLL_FBKDIV_PE2H_S 24 ++#define SSUSB_PLL_FBKDIV_PE2H_M 0x7f000000 ++#define SSUSB_PLL_FBKDIV_PE1D_S 16 ++#define SSUSB_PLL_FBKDIV_PE1D_M 0x7f0000 ++#define SSUSB_PLL_FBKDIV_PE1H_S 8 ++#define SSUSB_PLL_FBKDIV_PE1H_M 0x7f00 ++#define SSUSB_PLL_FBKDIV_U3_S 0 ++#define SSUSB_PLL_FBKDIV_U3_M 0x7f ++ ++#define DA_SSUSB_U3PHYA_10_REG 0x10c20 ++#define SSUSB_PLL_PREDIV_PE1D_S 18 ++#define SSUSB_PLL_PREDIV_PE1D_M 0xc0000 ++#define SSUSB_PLL_PREDIV_U3_S 8 ++#define SSUSB_PLL_PREDIV_U3_M 0x300 ++#define SSUSB_PLL_FBKDI_S 0 ++#define SSUSB_PLL_FBKDI_M 0x07 ++ ++#define DA_SSUSB_PLL_PCW_NCPO_REG 0x10c24 ++#define SSUSB_PLL_PCW_NCPO_U3_S 0 ++#define SSUSB_PLL_PCW_NCPO_U3_M 0x7fffffff ++ ++#define DA_SSUSB_PLL_SSC_DELTA1_REG 0x10c38 ++#define SSUSB_PLL_SSC_DELTA1_PE1H_S 16 ++#define SSUSB_PLL_SSC_DELTA1_PE1H_M 0xffff0000 ++#define SSUSB_PLL_SSC_DELTA1_U3_S 0 ++#define SSUSB_PLL_SSC_DELTA1_U3_M 0xffff ++ ++#define DA_SSUSB_U3PHYA_21_REG 0x10c40 ++#define SSUSB_PLL_SSC_DELTA_U3_S 16 ++#define SSUSB_PLL_SSC_DELTA_U3_M 0xffff0000 ++#define SSUSB_PLL_SSC_DELTA1_PE2D_S 0 ++#define SSUSB_PLL_SSC_DELTA1_PE2D_M 0xffff ++ ++/* MT7621 specific CM values */ ++ ++/* GCR_REGx_BASE */ ++#define GCR_REG0_BASE_VALUE 0x1c000000 ++#define GCR_REG1_BASE_VALUE 0x60000000 ++#define GCR_REG2_BASE_VALUE 0x1c000000 ++#define GCR_REG3_BASE_VALUE 0x1c000000 ++ ++/* GCR_REGx_MASK */ ++#define GCR_REG0_MASK_VALUE 0x0000fc00 /* 64M Bus */ ++#define GCR_REG1_MASK_VALUE 0x0000f000 /* 256M PCI Mem */ ++#define GCR_REG2_MASK_VALUE 0x0000fc00 /* unused */ ++#define GCR_REG3_MASK_VALUE 0x0000fc00 /* unused */ ++ ++#ifndef __ASSEMBLY__ ++unsigned long get_xtal_mhz(void); ++#endif ++ ++#endif /* _MT7621_H_ */ +diff --git a/arch/mips/mach-mtmips/mt7621/serial.c b/arch/mips/mach-mtmips/mt7621/serial.c +new file mode 100644 +index 0000000000..0ccc71dc75 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/serial.c +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include <asm/addrspace.h> ++#include "mt7621.h" ++ ++void board_debug_uart_init(void) ++{ ++ void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ ++#if CONFIG_DEBUG_UART_BASE == 0xbe000c00 /* KSEG1ADDR(UART1_BASE) */ ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART1_MODE); ++#elif CONFIG_DEBUG_UART_BASE == 0xbe000d00 /* KSEG1ADDR(UART2_BASE) */ ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART2_MODE_M); ++#elif CONFIG_DEBUG_UART_BASE == 0xbe000e00 /* KSEG1ADDR(UART3_BASE) */ ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART3_MODE_M); ++#endif ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/Makefile b/arch/mips/mach-mtmips/mt7621/spl/Makefile +new file mode 100644 +index 0000000000..ebe54e79b9 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/Makefile +@@ -0,0 +1,9 @@ ++ ++extra-y += start.o ++ ++obj-y += spl.o ++obj-y += cps.o ++obj-y += dram.o ++obj-y += serial.o ++obj-y += launch.o ++obj-y += launch_ll.o +diff --git a/arch/mips/mach-mtmips/mt7621/spl/cps.c b/arch/mips/mach-mtmips/mt7621/spl/cps.c +new file mode 100644 +index 0000000000..779e646c12 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/cps.c +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include <asm/addrspace.h> ++#include <asm/mipsregs.h> ++#include <asm/cm.h> ++#include <linux/bitfield.h> ++#include "../mt7621.h" ++ ++/* GIC Shared Register Bases */ ++#define GIC_SH_POL_BASE 0x100 ++#define GIC_SH_TRIG_BASE 0x180 ++#define GIC_SH_RMASK_BASE 0x300 ++#define GIC_SH_SMASK_BASE 0x380 ++#define GIC_SH_MASK_BASE 0x400 ++#define GIC_SH_PEND_BASE 0x480 ++#define GIC_SH_MAP_PIN_BASE 0x500 ++#define GIC_SH_MAP_VPE_BASE 0x2000 ++ ++/* GIC Registers */ ++#define GIC_SH_POL31_0 (GIC_SH_POL_BASE + 0x00) ++#define GIC_SH_POL63_32 (GIC_SH_POL_BASE + 0x04) ++ ++#define GIC_SH_TRIG31_0 (GIC_SH_TRIG_BASE + 0x00) ++#define GIC_SH_TRIG63_32 (GIC_SH_TRIG_BASE + 0x04) ++ ++#define GIC_SH_RMASK31_0 (GIC_SH_RMASK_BASE + 0x00) ++#define GIC_SH_RMASK63_32 (GIC_SH_RMASK_BASE + 0x04) ++ ++#define GIC_SH_SMASK31_0 (GIC_SH_SMASK_BASE + 0x00) ++#define GIC_SH_SMASK63_32 (GIC_SH_SMASK_BASE + 0x04) ++ ++#define GIC_SH_MAP_PIN(n) (GIC_SH_MAP_PIN_BASE + (n) * 4) ++ ++#define GIC_SH_MAP_VPE(n, v) (GIC_SH_MAP_VPE_BASE + (n) * 0x20 + ((v) / 32) * 4) ++#define GIC_SH_MAP_VPE31_0(n) GIC_SH_MAP_VPE(n, 0) ++ ++/* GIC_SH_MAP_PIN fields */ ++#define GIC_MAP_TO_PIN BIT(31) ++#define GIC_MAP_TO_NMI BIT(30) ++#define GIC_MAP GENMASK(5, 0) ++#define GIC_MAP_SHIFT 0 ++ ++static void cm_init(void __iomem *cm_base) ++{ ++ u32 gcrcfg, num_cores; ++ ++ gcrcfg = readl(cm_base + GCR_CONFIG); ++ num_cores = FIELD_GET(GCR_CONFIG_PCORES, gcrcfg) + 1; ++ ++ writel((1 << num_cores) - 1, cm_base + GCR_ACCESS); ++ ++ writel(GCR_REG0_BASE_VALUE, cm_base + GCR_REG0_BASE); ++ writel(GCR_REG1_BASE_VALUE, cm_base + GCR_REG1_BASE); ++ writel(GCR_REG2_BASE_VALUE, cm_base + GCR_REG2_BASE); ++ writel(GCR_REG3_BASE_VALUE, cm_base + GCR_REG3_BASE); ++ ++ clrsetbits_32(cm_base + GCR_REG0_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG0_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrsetbits_32(cm_base + GCR_REG1_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG1_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrsetbits_32(cm_base + GCR_REG2_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG2_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrsetbits_32(cm_base + GCR_REG3_MASK, ++ GCR_REGn_MASK_ADDRMASK | GCR_REGn_MASK_CMTGT, ++ FIELD_PREP(GCR_REGn_MASK_ADDRMASK, GCR_REG3_MASK_VALUE) | ++ GCR_REGn_MASK_CMTGT_IOCU0); ++ ++ clrbits_32(cm_base + GCR_BASE, CM_DEFAULT_TARGET_MASK); ++ setbits_32(cm_base + GCR_CONTROL, GCR_CONTROL_SYNCCTL); ++} ++ ++static void gic_init(void) ++{ ++ void __iomem *gic_base = (void *)KSEG1ADDR(MIPS_GIC_BASE); ++ int i; ++ ++ /* Interrupt 0..5: Level Trigger, Active High */ ++ writel(0, gic_base + GIC_SH_TRIG31_0); ++ writel(0x3f, gic_base + GIC_SH_RMASK31_0); ++ writel(0x3f, gic_base + GIC_SH_POL31_0); ++ writel(0x3f, gic_base + GIC_SH_SMASK31_0); ++ ++ /* Interrupt 56..63: Edge Trigger, Rising Edge */ ++ /* Hardcoded to set up the last 8 external interrupts for IPI. */ ++ writel(0xff000000, gic_base + GIC_SH_TRIG63_32); ++ writel(0xff000000, gic_base + GIC_SH_RMASK63_32); ++ writel(0xff000000, gic_base + GIC_SH_POL63_32); ++ writel(0xff000000, gic_base + GIC_SH_SMASK63_32); ++ ++ /* Map interrupt source to particular hardware interrupt pin */ ++ /* source {0,1,2,3,4,5} -> pin {0,0,4,3,0,5} */ ++ writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(0)); ++ writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(1)); ++ writel(GIC_MAP_TO_PIN | 4, gic_base + GIC_SH_MAP_PIN(2)); ++ writel(GIC_MAP_TO_PIN | 3, gic_base + GIC_SH_MAP_PIN(3)); ++ writel(GIC_MAP_TO_PIN | 0, gic_base + GIC_SH_MAP_PIN(4)); ++ writel(GIC_MAP_TO_PIN | 5, gic_base + GIC_SH_MAP_PIN(5)); ++ ++ /* source 56~59 -> pin 1, 60~63 -> pin 2 */ ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(56)); ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(57)); ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(58)); ++ writel(GIC_MAP_TO_PIN | 1, gic_base + GIC_SH_MAP_PIN(59)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(60)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(61)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(62)); ++ writel(GIC_MAP_TO_PIN | 2, gic_base + GIC_SH_MAP_PIN(63)); ++ ++ /* Interrupt map to VPE (bit mask) */ ++ for (i = 0; i < 32; i++) ++ writel(BIT(0), gic_base + GIC_SH_MAP_VPE31_0(i)); ++ ++ /* ++ * Direct GIC_int 56..63 to vpe 0..3 ++ * MIPS Linux convention that last 16 interrupts implemented be set ++ * aside for IPI signaling. ++ * The actual interrupts are tied low and software sends interrupts ++ * via GIC_SH_WEDGE writes. ++ */ ++ for (i = 0; i < 4; i++) { ++ writel(BIT(i), gic_base + GIC_SH_MAP_VPE31_0(i + 56)); ++ writel(BIT(i), gic_base + GIC_SH_MAP_VPE31_0(i + 60)); ++ } ++} ++ ++void mt7621_cps_init(void) ++{ ++ void __iomem *cm_base = (void *)KSEG1ADDR(CONFIG_MIPS_CM_BASE); ++ ++ /* Enable GIC */ ++ writel(MIPS_GIC_BASE | GCR_GIC_EN, cm_base + GCR_GIC_BASE); ++ ++ /* Enable CPC */ ++ writel(MIPS_CPC_BASE | GCR_CPC_EN, cm_base + GCR_CPC_BASE); ++ ++ gic_init(); ++ cm_init(cm_base); ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/dram.c b/arch/mips/mach-mtmips/mt7621/spl/dram.c +new file mode 100644 +index 0000000000..100adfb93a +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/dram.c +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <vsprintf.h> ++#include <asm/io.h> ++#include <asm/sections.h> ++#include <asm/byteorder.h> ++#include <asm/addrspace.h> ++#include <linux/string.h> ++#include "../mt7621.h" ++#include "dram.h" ++ ++static const u32 ddr2_act[DDR_PARAM_SIZE] = { ++#if defined(CONFIG_MT7621_DRAM_DDR2_512M) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x22174441, ++ 0x00000000, 0xF0748661, 0x40001273, 0x9F0A0481, ++ 0x0304692F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000000, 0x07100000, ++ 0x00001B63, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR2_512M_W9751G6KB_A02_1066MHZ) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x33484584, ++ 0x00000000, 0xF07486A1, 0x50001273, 0x9F010481, ++ 0x0304693F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000010, 0x07100000, ++ 0x00001F73, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR2_1024M_W971GG6KB25_800MHZ) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x22174430, ++ 0x01000000, 0xF0748661, 0x40001273, 0x9F0F0481, ++ 0x0304692F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000000, 0x07100000, ++ 0x00001B63, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR2_1024M_W971GG6KB18_1066MHZ) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x33484584, ++ 0x01000000, 0xF07486A1, 0x50001273, 0x9F070481, ++ 0x0304693F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000010, 0x07100000, ++ 0x00001F73, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#else /* CONFIG_MT7621_DRAM_DDR2_1024M */ ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x22174441, ++ 0x01000000, 0xF0748661, 0x40001273, 0x9F0F0481, ++ 0x0304692F, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000000, 0x07100000, ++ 0x00001B63, 0x00002000, 0x00004000, 0x00006000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++#endif ++}; ++ ++static const u32 ddr3_act[DDR_PARAM_SIZE] = { ++#if defined(CONFIG_MT7621_DRAM_DDR3_1024M) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x44694683, ++ 0x01000000, 0xF07486A1, 0xC287221D, 0x9F060481, ++ 0x03046948, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000210, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR3_4096M) ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x44694683, ++ 0x01000000, 0xF07486A1, 0xC287221D, 0x9F0F0481, ++ 0x03046948, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000240, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x00000000, 0x00000000, ++#elif defined(CONFIG_MT7621_DRAM_DDR3_1024M_KGD) ++ 0xFF00FF00, 0xFF00FF00, 0x00000007, 0x44694683, ++ 0x01000000, 0xF07406A1, 0xC287221D, 0x9F060481, ++ 0x03046923, 0x152f2842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000210, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x000C0000, 0x00000000, ++#else /* CONFIG_MT7621_DRAM_DDR3_2048M */ ++ 0xAA00AA00, 0xAA00AA00, 0x00000007, 0x44694673, ++ 0x01000000, 0xF07486A1, 0xC287221D, 0x9F050481, ++ 0x03046948, 0x15602842, 0x00008888, 0x88888888, ++ 0x00000000, 0x00000000, 0x00000220, 0x07100000, ++ 0x00001B61, 0x00002040, 0x00004010, 0x00006000, ++ 0x0C000000, 0x07070000, 0x00000000, 0x00000000, ++#endif ++}; ++ ++#if defined(CONFIG_MT7621_DRAM_FREQ_400) ++#define DDR_FREQ_PARAM 0x41000000 ++#elif defined(CONFIG_MT7621_DRAM_FREQ_1066) ++#define DDR_FREQ_PARAM 0x21000000 ++#elif defined(CONFIG_MT7621_DRAM_FREQ_1200) ++#define DDR_FREQ_PARAM 0x11000000 ++#else /* CONFIG_MT7621_DRAM_FREQ_800 */ ++#define DDR_FREQ_PARAM 0x31000000 ++#endif ++ ++#define RG_MEPL_FBDIV_S 4 ++#define RG_MEPL_FBDIV_M 0x7f ++ ++static inline void word_copy(u32 *dest, const u32 *src, u32 count) ++{ ++ u32 i; ++ ++ for (i = 0; i < count; i++) ++ dest[i] = src[i]; ++} ++ ++static u32 calc_cpu_pll_val(void) ++{ ++ u32 div, baseval, fb; ++ ++ div = get_xtal_mhz(); ++ ++ if (div == 40) { ++ div /= 2; ++ baseval = 0xc0005802; ++ } else { ++ baseval = 0xc0004802; ++ } ++ ++ fb = CONFIG_MT7621_CPU_FREQ / div - 1; ++ if (fb > RG_MEPL_FBDIV_M) ++ fb = RG_MEPL_FBDIV_M; ++ ++ return baseval | (fb << RG_MEPL_FBDIV_S); ++} ++ ++void prepare_stage_bin(void) ++{ ++ u32 stage_size; ++ ++ const struct stage_header *stock_stage_bin = ++ (const struct stage_header *)__image_copy_end; ++ ++ struct stage_header *new_stage_bin = ++ (struct stage_header *)STAGE_LOAD_ADDR; ++ ++ if (be32_to_cpu(stock_stage_bin->ep) != STAGE_LOAD_ADDR) ++ panic("Invalid DDR stage binary blob\n"); ++ ++ stage_size = be32_to_cpu(stock_stage_bin->stage_size); ++ ++ word_copy((u32 *)new_stage_bin, (const u32 *)stock_stage_bin, ++ (stage_size + sizeof(u32) - 1) / sizeof(u32)); ++ ++ word_copy(new_stage_bin->ddr2_act, ddr2_act, DDR_PARAM_SIZE); ++ word_copy(new_stage_bin->ddr3_act, ddr3_act, DDR_PARAM_SIZE); ++ ++ new_stage_bin->cpu_pll_cfg = calc_cpu_pll_val(); ++ new_stage_bin->ddr_pll_cfg = DDR_FREQ_PARAM; ++ new_stage_bin->baudrate = CONFIG_BAUDRATE; ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/dram.h b/arch/mips/mach-mtmips/mt7621/spl/dram.h +new file mode 100644 +index 0000000000..7322c58276 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/dram.h +@@ -0,0 +1,39 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _MT7621_DRAM_H_ ++#define _MT7621_DRAM_H_ ++ ++#define STAGE_LOAD_ADDR 0xBE108800 ++ ++#ifndef __ASSEMBLY__ ++#include <linux/types.h> ++ ++#define DDR_PARAM_SIZE 24 ++ ++struct stage_header { ++ u32 jump_insn[2]; ++ u32 ep; ++ u32 stage_size; ++ u32 has_stage2; ++ u32 next_ep; ++ u32 next_size; ++ u32 next_offset; ++ u32 cpu_pll_cfg; ++ u32 ddr_pll_cfg; ++ u32 reserved2[6]; ++ char build_tag[32]; ++ u32 ddr3_act[DDR_PARAM_SIZE]; ++ u32 padding1[2]; ++ u32 ddr2_act[DDR_PARAM_SIZE]; ++ u32 padding2[2]; ++ u32 baudrate; ++ u32 padding3; ++}; ++#endif ++ ++#endif /* _MT7621_DRAM_H_ */ +diff --git a/arch/mips/mach-mtmips/mt7621/spl/launch.c b/arch/mips/mach-mtmips/mt7621/spl/launch.c +new file mode 100644 +index 0000000000..37c20a5f56 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/launch.c +@@ -0,0 +1,100 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include <asm/cm.h> ++#include <asm/sections.h> ++#include <asm/addrspace.h> ++#include <asm/mipsmtregs.h> ++#include <linux/sizes.h> ++#include <time.h> ++#include <cpu_func.h> ++#include "launch.h" ++#include "../mt7621.h" ++ ++/* Cluster Power Controller (CPC) offsets */ ++#define CPC_CL_OTHER 0x2010 ++#define CPC_CO_CMD 0x4000 ++ ++/* CPC_CL_OTHER fields */ ++#define CPC_CL_OTHER_CORENUM_SHIFT 16 ++#define CPC_CL_OTHER_CORENUM GENMASK(23, 16) ++ ++/* CPC_CO_CMD */ ++#define PWR_UP 3 ++ ++#define NUM_CORES 2 ++#define NUM_CPUS 4 ++#define WAIT_CPUS_TIMEOUT 4000 ++ ++static void copy_launch_wait_code(void) ++{ ++ memset((void *)KSEG1, 0, SZ_4K); ++ ++ memcpy((void *)KSEG1ADDR(LAUNCH_WAITCODE), ++ &launch_wait_code_start, ++ &launch_wait_code_end - &launch_wait_code_start); ++ ++ invalidate_dcache_range(KSEG0, SZ_4K); ++} ++ ++static void bootup_secondary_core(void) ++{ ++ void __iomem *cpcbase = (void __iomem *)KSEG1ADDR(MIPS_CPC_BASE); ++ int i; ++ ++ for (i = 1; i < NUM_CORES; i++) { ++ writel(i << CPC_CL_OTHER_CORENUM_SHIFT, cpcbase + CPC_CL_OTHER); ++ writel(PWR_UP, cpcbase + CPC_CO_CMD); ++ } ++} ++ ++void secondary_cpu_init(void) ++{ ++ void __iomem *sysc = (void __iomem *)KSEG1ADDR(SYSCTL_BASE); ++ u32 i, dual_core = 0, cpuready = 1, cpumask = 0x03; ++ ulong wait_tick; ++ struct cpulaunch_t *c; ++ ++ /* Copy LAUNCH wait code used by other VPEs */ ++ copy_launch_wait_code(); ++ ++ dual_core = readl(sysc + SYSCTL_CHIP_REV_ID_REG) & CPU_ID; ++ ++ if (dual_core) { ++ /* Bootup secondary core for MT7621A */ ++ cpumask = 0x0f; ++ ++ /* Make BootROM/TPL redirect Core1's bootup flow to our entry point */ ++ writel((uintptr_t)&_start, sysc + BOOT_SRAM_BASE_REG); ++ ++ bootup_secondary_core(); ++ } ++ ++ /* Join the coherent domain */ ++ join_coherent_domain(dual_core ? 2 : 1); ++ ++ /* Bootup Core0/VPE1 */ ++ boot_vpe1(); ++ ++ /* Wait for all CPU ready */ ++ wait_tick = get_timer(0) + WAIT_CPUS_TIMEOUT; ++ ++ while (time_before(get_timer(0), wait_tick)) { ++ /* CPU0 is obviously ready */ ++ for (i = 1; i < NUM_CPUS; i++) { ++ c = (struct cpulaunch_t *)(KSEG0ADDR(CPULAUNCH) + ++ (i << LOG2CPULAUNCH)); ++ ++ if (c->flags & LAUNCH_FREADY) ++ cpuready |= BIT(i); ++ } ++ ++ if ((cpuready & cpumask) == cpumask) ++ break; ++ } ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/launch.h b/arch/mips/mach-mtmips/mt7621/spl/launch.h +new file mode 100644 +index 0000000000..f34250d605 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/launch.h +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _LAUNCH_H_ ++#define _LAUNCH_H_ ++ ++#ifndef __ASSEMBLY__ ++ ++struct cpulaunch_t { ++ unsigned long pc; ++ unsigned long gp; ++ unsigned long sp; ++ unsigned long a0; ++ unsigned long _pad[3]; /* pad to cache line size to avoid thrashing */ ++ unsigned long flags; ++}; ++ ++extern char launch_wait_code_start; ++extern char launch_wait_code_end; ++ ++void join_coherent_domain(int ncores); ++void boot_vpe1(void); ++ ++#else ++ ++#define LAUNCH_PC 0 ++#define LAUNCH_GP 4 ++#define LAUNCH_SP 8 ++#define LAUNCH_A0 12 ++#define LAUNCH_FLAGS 28 ++ ++#endif ++ ++#define LOG2CPULAUNCH 5 ++ ++#define LAUNCH_FREADY 1 ++#define LAUNCH_FGO 2 ++#define LAUNCH_FGONE 4 ++ ++#define LAUNCH_WAITCODE 0x00000d00 ++#define SCRLAUNCH 0x00000e00 ++#define CPULAUNCH 0x00000f00 ++#define NCPULAUNCH 8 ++ ++/* Polling period in count cycles for secondary CPU's */ ++#define LAUNCHPERIOD 10000 ++ ++#endif /* _LAUNCH_H_ */ +diff --git a/arch/mips/mach-mtmips/mt7621/spl/launch_ll.S b/arch/mips/mach-mtmips/mt7621/spl/launch_ll.S +new file mode 100644 +index 0000000000..32d28c7539 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/launch_ll.S +@@ -0,0 +1,339 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/cm.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include <asm/cacheops.h> ++#include <asm/mipsregs.h> ++#include <asm/addrspace.h> ++#include <asm/mipsmtregs.h> ++#include "launch.h" ++ ++ .macro cache_loop curr, end, line_sz, op ++10: cache \op, 0(\curr) ++ PTR_ADDU \curr, \curr, \line_sz ++ bne \curr, \end, 10b ++ .endm ++ ++ .set mt ++ ++/* ++ * Join the coherent domain ++ * a0 = number of cores ++ */ ++LEAF(join_coherent_domain) ++ /* ++ * Enable coherence and allow interventions from all other cores. ++ * (Write access enabled via GCR_ACCESS by core 0.) ++ */ ++ li t1, 1 ++ sll t1, a0 ++ addiu t1, -1 ++ ++ li t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) ++ sw t1, GCR_Cx_COHERENCE(t0) ++ ehb ++ ++ move t2, zero ++ ++_next_coherent_core: ++ sll t1, t2, GCR_Cx_OTHER_CORENUM_SHIFT ++ sw t1, GCR_Cx_OTHER(t0) ++ ++_busy_wait_coherent_core: ++ lw t1, GCR_CO_COHERENCE(t0) ++ beqz t1, _busy_wait_coherent_core ++ ++ addiu t2, 1 ++ bne t2, a0, _next_coherent_core ++ ++ jr ra ++ END(join_coherent_domain) ++ ++/* ++ * All VPEs other than VPE0 will go here. ++ */ ++LEAF(launch_vpe_entry) ++ mfc0 t0, CP0_EBASE ++ and t0, t0, MIPS_EBASE_CPUNUM ++ ++ /* per-VPE cpulaunch_t */ ++ li a0, KSEG0ADDR(CPULAUNCH) ++ sll t1, t0, LOG2CPULAUNCH ++ addu a0, t1 ++ ++ /* Set CPU online flag */ ++ li t0, LAUNCH_FREADY ++ sw t0, LAUNCH_FLAGS(a0) ++ ++ /* Enable count interrupt in mask, but do not enable interrupts */ ++ mfc0 t0, CP0_STATUS ++ ori t0, STATUSF_IP7 ++ mtc0 t0, CP0_STATUS ++ ++ /* VPEs executing in wait code do not need a stack */ ++ li t9, KSEG0ADDR(LAUNCH_WAITCODE) ++ jr t9 ++ END(launch_vpe_entry) ++ ++/* ++ * This function will not be executed in place. ++ * It will be copied into memory, and VPEs other than VPE0 will be ++ * started to run into this in-memory function. ++ */ ++LEAF(launch_wait_code) ++ .globl launch_wait_code_start ++launch_wait_code_start: ++ ++ move t0, a0 ++ ++start_poll: ++ /* Poll CPU go flag */ ++ mtc0 zero, CP0_COUNT ++ li t1, LAUNCHPERIOD ++ mtc0 t1, CP0_COMPARE ++ ++time_wait: ++ /* Software wait */ ++ mfc0 t2, CP0_COUNT ++ subu t2, t1 ++ bltz t2, time_wait ++ ++ /* Check the launch flag */ ++ lw t3, LAUNCH_FLAGS(t0) ++ and t3, LAUNCH_FGO ++ beqz t3, start_poll ++ ++ /* Reset the counter and interrupts to give naive clients a chance */ ++ mfc0 t1, CP0_STATUS ++ ins t1, zero, STATUSB_IP7, 1 ++ mtc0 t1, CP0_STATUS ++ ++ mfc0 t1, CP0_COUNT ++ subu t1, 1 ++ mtc0 t1, CP0_COMPARE ++ ++ /* Jump to kernel */ ++ lw t9, LAUNCH_PC(t0) ++ lw gp, LAUNCH_GP(t0) ++ lw sp, LAUNCH_SP(t0) ++ lw a0, LAUNCH_A0(t0) ++ move a1, zero ++ move a2, zero ++ move a3, zero ++ ori t3, LAUNCH_FGONE ++ sw t3, LAUNCH_FLAGS(t0) ++ ++ jr t9 ++ ++ .globl launch_wait_code_end ++launch_wait_code_end: ++ END(launch_wait_code) ++ ++/* ++ * Core1 will go here. ++ */ ++LEAF(launch_core_entry) ++ /* Disable caches */ ++ bal mips_cache_disable ++ ++ /* Initialize L1 cache only */ ++ li a0, CONFIG_SYS_ICACHE_SIZE ++ li a1, CONFIG_SYS_ICACHE_LINE_SIZE ++ li a2, CONFIG_SYS_DCACHE_SIZE ++ li a3, CONFIG_SYS_DCACHE_LINE_SIZE ++ ++ mtc0 zero, CP0_TAGLO ++ mtc0 zero, CP0_TAGLO, 2 ++ ehb ++ ++ /* ++ * Initialize the I-cache first, ++ */ ++ li t0, KSEG0 ++ addu t1, t0, a0 ++ /* clear tag to invalidate */ ++ cache_loop t0, t1, a1, INDEX_STORE_TAG_I ++#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD ++ /* fill once, so data field parity is correct */ ++ PTR_LI t0, KSEG0 ++ cache_loop t0, t1, a1, FILL ++ /* invalidate again - prudent but not strictly necessary */ ++ PTR_LI t0, KSEG0 ++ cache_loop t0, t1, a1, INDEX_STORE_TAG_I ++#endif ++ ++ /* ++ * then initialize D-cache. ++ */ ++ PTR_LI t0, KSEG0 ++ PTR_ADDU t1, t0, a2 ++ /* clear all tags */ ++ cache_loop t0, t1, a3, INDEX_STORE_TAG_D ++#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD ++ /* load from each line (in cached space) */ ++ PTR_LI t0, KSEG0 ++2: LONG_L zero, 0(t0) ++ PTR_ADDU t0, a3 ++ bne t0, t1, 2b ++ /* clear all tags */ ++ PTR_LI t0, KSEG0 ++ cache_loop t0, t1, a3, INDEX_STORE_TAG_D ++#endif ++ ++ /* Set Cache Mode */ ++ mfc0 t0, CP0_CONFIG ++ li t1, CONF_CM_CACHABLE_COW ++ ins t0, t1, 0, 3 ++ mtc0 t0, CP0_CONFIG ++ ++ /* Join the coherent domain */ ++ li a0, 2 ++ bal join_coherent_domain ++ ++ /* Bootup Core0/VPE1 */ ++ bal boot_vpe1 ++ ++ b launch_vpe_entry ++ END(launch_core_entry) ++ ++/* ++ * Bootup VPE1. ++ * This subroutine must be executed from VPE0 with VPECONF0[MVP] already set. ++ */ ++LEAF(boot_vpe1) ++ mfc0 t0, CP0_MVPCONF0 ++ ++ /* a0 = number of TCs - 1 */ ++ ext a0, t0, MVPCONF0_PTC_SHIFT, 8 ++ beqz a0, _vpe1_init_done ++ ++ /* a1 = number of VPEs - 1 */ ++ ext a1, t0, MVPCONF0_PVPE_SHIFT, 4 ++ beqz a1, _vpe1_init_done ++ ++ /* a2 = current TC No. */ ++ move a2, zero ++ ++ /* Enter VPE Configuration State */ ++ mfc0 t0, CP0_MVPCONTROL ++ or t0, MVPCONTROL_VPC ++ mtc0 t0, CP0_MVPCONTROL ++ ehb ++ ++_next_tc: ++ /* Set the TC number to be used on MTTR and MFTR instructions */ ++ mfc0 t0, CP0_VPECONTROL ++ ins t0, a2, 0, 8 ++ mtc0 t0, CP0_VPECONTROL ++ ehb ++ ++ /* TC0 is already bound */ ++ beqz a2, _next_vpe ++ ++ /* Halt current TC */ ++ li t0, TCHALT_H ++ mttc0 t0, CP0_TCHALT ++ ehb ++ ++ /* If there is spare TC, bind it to the last VPE (VPE[a1]) */ ++ slt t1, a1, a2 ++ bnez t1, _vpe_bind_tc ++ move t1, a1 ++ ++ /* Set Exclusive TC for active TC */ ++ mftc0 t0, CP0_VPECONF0 ++ ins t0, a2, VPECONF0_XTC_SHIFT, 8 ++ mttc0 t0, CP0_VPECONF0 ++ ++ move t1, a2 ++_vpe_bind_tc: ++ /* Bind TC to a VPE */ ++ mftc0 t0, CP0_TCBIND ++ ins t0, t1, TCBIND_CURVPE_SHIFT, 4 ++ mttc0 t0, CP0_TCBIND ++ ++ /* ++ * Set up CP0_TCSTATUS register: ++ * Disable Coprocessor Usable bits ++ * Disable MDMX/DSP ASE ++ * Clear Dirty TC ++ * not dynamically allocatable ++ * not allocated ++ * Kernel mode ++ * interrupt exempt ++ * ASID 0 ++ */ ++ li t0, TCSTATUS_IXMT ++ mttc0 t0, CP0_TCSTATUS ++ ++_next_vpe: ++ slt t1, a1, a2 ++ bnez t1, _done_vpe # No more VPEs ++ ++ /* Disable TC multi-threading */ ++ mftc0 t0, CP0_VPECONTROL ++ ins t0, zero, VPECONTROL_TE_SHIFT, 1 ++ mttc0 t0, CP0_VPECONTROL ++ ++ /* Skip following configuration for TC0 */ ++ beqz a2, _done_vpe ++ ++ /* Deactivate VPE, set Master VPE */ ++ mftc0 t0, CP0_VPECONF0 ++ ins t0, zero, VPECONF0_VPA_SHIFT, 1 ++ or t0, VPECONF0_MVP ++ mttc0 t0, CP0_VPECONF0 ++ ++ mfc0 t0, CP0_STATUS ++ mttc0 t0, CP0_STATUS ++ ++ mttc0 zero, CP0_EPC ++ mttc0 zero, CP0_CAUSE ++ ++ mfc0 t0, CP0_CONFIG ++ mttc0 t0, CP0_CONFIG ++ ++ /* ++ * VPE1 of each core can execute cached as its L1 I$ has already ++ * been initialized. ++ * and the L2$ has been initialized or "disabled" via CCA override. ++ */ ++ PTR_LA t0, _start ++ mttc0 t0, CP0_TCRESTART ++ ++ /* Unset Interrupt Exempt, set Activate Thread */ ++ mftc0 t0, CP0_TCSTATUS ++ ins t0, zero, TCSTATUS_IXMT_SHIFT, 1 ++ ori t0, TCSTATUS_A ++ mttc0 t0, CP0_TCSTATUS ++ ++ /* Resume TC */ ++ mttc0 zero, CP0_TCHALT ++ ++ /* Activate VPE */ ++ mftc0 t0, CP0_VPECONF0 ++ ori t0, VPECONF0_VPA ++ mttc0 t0, CP0_VPECONF0 ++ ++_done_vpe: ++ addu a2, 1 ++ sltu t0, a0, a2 ++ beqz t0, _next_tc ++ ++ mfc0 t0, CP0_MVPCONTROL ++ /* Enable all activated VPE to execute */ ++ ori t0, MVPCONTROL_EVP ++ /* Exit VPE Configuration State */ ++ ins t0, zero, MVPCONTROL_VPC_SHIFT, 1 ++ mtc0 t0, CP0_MVPCONTROL ++ ehb ++ ++_vpe1_init_done: ++ jr ra ++ END(boot_vpe1) +diff --git a/arch/mips/mach-mtmips/mt7621/spl/serial.c b/arch/mips/mach-mtmips/mt7621/spl/serial.c +new file mode 100644 +index 0000000000..5cf093a078 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/serial.c +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/io.h> ++#include "../mt7621.h" ++ ++void mtmips_spl_serial_init(void) ++{ ++#ifdef CONFIG_SPL_SERIAL ++ void __iomem *base = ioremap_nocache(SYSCTL_BASE, SYSCTL_SIZE); ++ ++#if CONFIG_CONS_INDEX == 1 ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART1_MODE); ++#elif CONFIG_CONS_INDEX == 2 ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART2_MODE_M); ++#elif CONFIG_CONS_INDEX == 3 ++ clrbits_32(base + SYSCTL_GPIOMODE_REG, UART3_MODE_M); ++#endif /* CONFIG_CONS_INDEX */ ++#endif /* CONFIG_SPL_SERIAL */ ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/spl.c b/arch/mips/mach-mtmips/mt7621/spl/spl.c +new file mode 100644 +index 0000000000..71d01aa7f5 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/spl.c +@@ -0,0 +1,95 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <spl.h> ++#include <init.h> ++#include <image.h> ++#include <vsprintf.h> ++#include <malloc.h> ++#include <asm/io.h> ++#include <asm/sections.h> ++#include <asm/addrspace.h> ++#include <asm/byteorder.h> ++#include <asm/global_data.h> ++#include <linux/sizes.h> ++#include <mach/serial.h> ++#include "../mt7621.h" ++#include "dram.h" ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++struct tpl_info { ++ u32 magic; ++ u32 size; ++}; ++ ++void set_timer_freq_simple(void) ++{ ++ u32 div = get_xtal_mhz(); ++ ++ /* Round down cpu freq */ ++ gd->arch.timer_freq = rounddown(CONFIG_MT7621_CPU_FREQ, div) * 500000; ++} ++ ++void __noreturn board_init_f(ulong dummy) ++{ ++ spl_init(); ++ ++#ifdef CONFIG_SPL_SERIAL ++ /* ++ * mtmips_spl_serial_init() is useful if debug uart is enabled, ++ * or DM based serial is not enabled. ++ */ ++ mtmips_spl_serial_init(); ++ preloader_console_init(); ++#endif ++ ++ board_init_r(NULL, 0); ++} ++ ++void board_boot_order(u32 *spl_boot_list) ++{ ++#ifdef CONFIG_MT7621_BOOT_FROM_NAND ++ spl_boot_list[0] = BOOT_DEVICE_NAND; ++#else ++ spl_boot_list[0] = BOOT_DEVICE_NOR; ++#endif ++} ++ ++unsigned long spl_nor_get_uboot_base(void) ++{ ++ const struct tpl_info *tpli; ++ const image_header_t *hdr; ++ u32 addr; ++ ++ addr = FLASH_MMAP_BASE + TPL_INFO_OFFSET; ++ tpli = (const struct tpl_info *)KSEG1ADDR(addr); ++ ++ if (tpli->magic == TPL_INFO_MAGIC) { ++ addr = FLASH_MMAP_BASE + tpli->size; ++ hdr = (const image_header_t *)KSEG1ADDR(addr); ++ ++ if (image_get_magic(hdr) == IH_MAGIC) { ++ addr += sizeof(*hdr) + image_get_size(hdr); ++ return KSEG1ADDR(addr); ++ } ++ } ++ ++ panic("Unable to locate SPL payload\n"); ++ return 0; ++} ++ ++uint32_t spl_nand_get_uboot_raw_page(void) ++{ ++ const struct stage_header *sh = (const struct stage_header *)&_start; ++ u32 addr; ++ ++ addr = image_get_header_size() + be32_to_cpu(sh->stage_size); ++ addr = ALIGN(addr, SZ_4K); ++ ++ return addr; ++} +diff --git a/arch/mips/mach-mtmips/mt7621/spl/start.S b/arch/mips/mach-mtmips/mt7621/spl/start.S +new file mode 100644 +index 0000000000..3cad3567e7 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/spl/start.S +@@ -0,0 +1,226 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm-offsets.h> ++#include <config.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include <asm/mipsregs.h> ++#include <asm/cacheops.h> ++#include <asm/addrspace.h> ++#include <asm/mipsmtregs.h> ++#include <asm/cm.h> ++#include "../mt7621.h" ++#include "dram.h" ++ ++#ifndef CONFIG_SYS_INIT_SP_ADDR ++#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + \ ++ CONFIG_SYS_INIT_SP_OFFSET) ++#endif ++ ++#define SP_ADDR_TEMP 0xbe10dff0 ++ ++ .macro init_wr sel ++ MTC0 zero, CP0_WATCHLO,\sel ++ mtc0 t1, CP0_WATCHHI,\sel ++ .endm ++ ++ .macro setup_stack_gd ++ li t0, -16 ++ PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR ++ and sp, t1, t0 # force 16 byte alignment ++ PTR_SUBU \ ++ sp, sp, GD_SIZE # reserve space for gd ++ and sp, sp, t0 # force 16 byte alignment ++ move k0, sp # save gd pointer ++#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ ++ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) ++ li t2, CONFIG_VAL(SYS_MALLOC_F_LEN) ++ PTR_SUBU \ ++ sp, sp, t2 # reserve space for early malloc ++ and sp, sp, t0 # force 16 byte alignment ++#endif ++ move fp, sp ++ ++ /* Clear gd */ ++ move t0, k0 ++1: ++ PTR_S zero, 0(t0) ++ PTR_ADDIU t0, PTRSIZE ++ blt t0, t1, 1b ++ nop ++ ++#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \ ++ !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) ++ PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset ++#endif ++ .endm ++ ++ .set noreorder ++ ++ENTRY(_start) ++ b 1f ++ mtc0 zero, CP0_COUNT ++ ++ /* Stage header required by BootROM */ ++ .org 0x8 ++ .word 0 # ep, filled by mkimage ++ .word 0 # stage_size, filled by mkimage ++ .word 0 # has_stage2 ++ .word 0 # next_ep ++ .word 0 # next_size ++ .word 0 # next_offset ++ ++1: ++ /* Init CP0 Status */ ++ mfc0 t0, CP0_STATUS ++ and t0, ST0_IMPL ++ or t0, ST0_BEV | ST0_ERL ++ mtc0 t0, CP0_STATUS ++ ehb ++ ++ /* Clear Watch Status bits and disable watch exceptions */ ++ li t1, 0x7 # Clear I, R and W conditions ++ init_wr 0 ++ init_wr 1 ++ init_wr 2 ++ init_wr 3 ++ ++ /* Clear WP, IV and SW interrupts */ ++ mtc0 zero, CP0_CAUSE ++ ++ /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */ ++ mtc0 zero, CP0_COMPARE ++ ++ /* VPE1 goes to wait code directly */ ++ mfc0 t0, CP0_TCBIND ++ andi t0, TCBIND_CURVPE ++ bnez t0, launch_vpe_entry ++ nop ++ ++ /* Core1 goes to specific launch entry */ ++ PTR_LI t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) ++ lw t1, GCR_Cx_ID(t0) ++ bnez t1, launch_core_entry ++ nop ++ ++ /* MT7530 reset */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_RSTCTL_REG(t0) ++ ori t1, MCM_RST ++ sw t1, SYSCTL_RSTCTL_REG(t0) ++ ++ /* Disable DMA route for PSE SRAM set by BootROM */ ++ PTR_LI t0, KSEG1ADDR(DMA_CFG_ARB_BASE) ++ sw zero, DMA_ROUTE_REG(t0) ++ ++ /* Set CPU clock to 500MHz (Required if boot from NAND) */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_CLKCFG0_REG(t0) ++ ins t1, zero, 30, 2 # CPU_CLK_SEL ++ sw t1, SYSCTL_CLKCFG0_REG(t0) ++ ++ /* Set CPU clock divider to 1/1 */ ++ li t0, KSEG1ADDR(RBUS_BASE) ++ li t1, 0x101 ++ sw t1, RBUS_DYN_CFG0_REG(t0) ++ ++ /* (Re-)initialize the SRAM */ ++ bal mips_sram_init ++ nop ++ ++ /* Set up temporary stack */ ++ li sp, SP_ADDR_TEMP ++ ++ /* Setup full CPS */ ++ bal mips_cm_map ++ nop ++ ++ bal mt7621_cps_init ++ nop ++ ++ /* Prepare for CPU/DDR initialization binary blob */ ++ bal prepare_stage_bin ++ nop ++ ++ /* Call CPU/DDR initialization binary blob */ ++ li t9, STAGE_LOAD_ADDR ++ jalr t9 ++ nop ++ ++ /* Switch CPU PLL source */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_CLKCFG0_REG(t0) ++ li t2, 1 ++ ins t1, t2, CPU_CLK_SEL_S, 2 ++ sw t1, SYSCTL_CLKCFG0_REG(t0) ++ ++ /* ++ * Currently SPL is running on locked L2 cache (on KSEG0). ++ * To reset the entire cache, we have to writeback SPL to DRAM first. ++ * Cache flush won't work here. Use memcpy instead. ++ */ ++ ++ la a0, __text_start ++ move a1, a0 ++ la a2, __image_copy_end ++ sub a2, a2, a1 ++ li a3, 5 ++ ins a0, a3, 29, 3 # convert to KSEG1 ++ ++ bal memcpy ++ nop ++ ++ /* Disable caches */ ++ bal mips_cache_disable ++ nop ++ ++ /* Reset caches */ ++ bal mips_cache_reset ++ nop ++ ++ /* Disable SRAM */ ++ li t0, KSEG1ADDR(FE_BASE) ++ li t1, FE_PSE_RESET ++ sw t1, FE_RST_GLO_REG(t0) ++ ++ /* Clear the .bss section */ ++ la a0, __bss_start ++ la a1, __bss_end ++1: sw zero, 0(a0) ++ addiu a0, 4 ++ ble a0, a1, 1b ++ nop ++ ++ /* Set up initial stack and global data */ ++ setup_stack_gd ++ ++#if CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) ++ /* Set malloc base */ ++ li t0, (CONFIG_SYS_INIT_SP_ADDR + 15) & (~15) ++ PTR_S t0, GD_MALLOC_BASE(k0) # gd->malloc_base offset ++#endif ++ ++#if defined(CONFIG_DEBUG_UART) && defined(CONFIG_SPL_SERIAL) ++ /* Earliest point to set up debug uart */ ++ bal debug_uart_init ++ nop ++#endif ++ ++ /* Setup timer */ ++ bal set_timer_freq_simple ++ nop ++ ++ /* Bootup secondary CPUs */ ++ bal secondary_cpu_init ++ nop ++ ++ move a0, zero # a0 <-- boot_flags = 0 ++ bal board_init_f ++ move ra, zero ++ ++ END(_start) +diff --git a/arch/mips/mach-mtmips/mt7621/sram_init.S b/arch/mips/mach-mtmips/mt7621/sram_init.S +new file mode 100644 +index 0000000000..03b9eab10b +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/sram_init.S +@@ -0,0 +1,22 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm/addrspace.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include "mt7621.h" ++ ++LEAF(mips_sram_init) ++ li t0, KSEG1ADDR(FE_BASE) ++ li t1, FE_PSE_RESET ++ sw t1, FE_RST_GLO_REG(t0) ++ ++ li t1, (FE_PSE_RAM | FE_PSE_MEM_EN) ++ sw t1, FE_RST_GLO_REG(t0) ++ ++ jr ra ++ END(mips_sram_init) +diff --git a/arch/mips/mach-mtmips/mt7621/tpl/Makefile b/arch/mips/mach-mtmips/mt7621/tpl/Makefile +new file mode 100644 +index 0000000000..471ad74249 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/tpl/Makefile +@@ -0,0 +1,4 @@ ++ ++extra-y += start.o ++ ++obj-y += tpl.o +diff --git a/arch/mips/mach-mtmips/mt7621/tpl/start.S b/arch/mips/mach-mtmips/mt7621/tpl/start.S +new file mode 100644 +index 0000000000..19b09f7251 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/tpl/start.S +@@ -0,0 +1,161 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <asm-offsets.h> ++#include <config.h> ++#include <asm/asm.h> ++#include <asm/regdef.h> ++#include <asm/addrspace.h> ++#include <asm/mipsregs.h> ++#include <asm/cm.h> ++#include "../mt7621.h" ++ ++#define SP_ADDR_TEMP 0xbe10dff0 ++ ++ .set noreorder ++ ++ .macro init_wr sel ++ MTC0 zero, CP0_WATCHLO,\sel ++ mtc0 t1, CP0_WATCHHI,\sel ++ .endm ++ ++ .macro uhi_mips_exception ++ move k0, t9 # preserve t9 in k0 ++ move k1, a0 # preserve a0 in k1 ++ li t9, 15 # UHI exception operation ++ li a0, 0 # Use hard register context ++ sdbbp 1 # Invoke UHI operation ++ .endm ++ ++ENTRY(_start) ++ b reset ++ mtc0 zero, CP0_COUNT ++ ++ /* ++ * Store TPL size here. ++ * This will be used by SPL to locate u-boot payload. ++ */ ++ .org TPL_INFO_OFFSET ++ .word TPL_INFO_MAGIC ++ .word __image_copy_len ++ ++ /* Exception vector */ ++ .org 0x200 ++ /* TLB refill, 32 bit task */ ++ uhi_mips_exception ++ ++ .org 0x280 ++ /* XTLB refill, 64 bit task */ ++ uhi_mips_exception ++ ++ .org 0x300 ++ /* Cache error exception */ ++ uhi_mips_exception ++ ++ .org 0x380 ++ /* General exception */ ++ uhi_mips_exception ++ ++ .org 0x400 ++ /* Catch interrupt exceptions */ ++ uhi_mips_exception ++ ++ .org 0x480 ++ /* EJTAG debug exception */ ++1: b 1b ++ nop ++ ++ .org 0x500 ++ ++reset: ++ /* Set KSEG0 to Uncached */ ++ mfc0 t0, CP0_CONFIG ++ ins t0, zero, 0, 3 ++ ori t0, t0, CONF_CM_UNCACHED ++ mtc0 t0, CP0_CONFIG ++ ehb ++ ++ /* Check for CPU number */ ++ mfc0 t0, CP0_EBASE ++ and t0, t0, MIPS_EBASE_CPUNUM ++ beqz t0, 1f ++ nop ++ ++ /* Secondary core goes to specified SPL entry address */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t0, BOOT_SRAM_BASE_REG(t0) ++ jr t0 ++ nop ++ ++ /* Init CP0 Status */ ++1: mfc0 t0, CP0_STATUS ++ and t0, ST0_IMPL ++ or t0, ST0_BEV | ST0_ERL ++ mtc0 t0, CP0_STATUS ++ nop ++ ++ /* Clear Watch Status bits and disable watch exceptions */ ++ li t1, 0x7 # Clear I, R and W conditions ++ init_wr 0 ++ init_wr 1 ++ init_wr 2 ++ init_wr 3 ++ ++ /* Clear WP, IV and SW interrupts */ ++ mtc0 zero, CP0_CAUSE ++ ++ /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */ ++ mtc0 zero, CP0_COMPARE ++ ++ /* Setup basic CPS */ ++ bal mips_cm_map ++ nop ++ ++ li t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) ++ li t1, GCR_REG0_BASE_VALUE ++ sw t1, GCR_REG0_BASE(t0) ++ ++ li t1, ((GCR_REG0_MASK_VALUE << GCR_REGn_MASK_ADDRMASK_SHIFT) | \ ++ GCR_REGn_MASK_CMTGT_IOCU0) ++ sw t1, GCR_REG0_MASK(t0) ++ ++ lw t1, GCR_BASE(t0) ++ ins t1, zero, 0, 2 # CM_DEFAULT_TARGET ++ sw t1, GCR_BASE(t0) ++ ++ lw t1, GCR_CONTROL(t0) ++ li t2, GCR_CONTROL_SYNCCTL ++ or t1, t1, t2 ++ sw t1, GCR_CONTROL(t0) ++ ++ /* Increase SPI frequency */ ++ li t0, KSEG1ADDR(SPI_BASE) ++ li t1, 5 ++ sw t1, SPI_SPACE_REG(t0) ++ ++ /* Set CPU clock to 500MHz */ ++ li t0, KSEG1ADDR(SYSCTL_BASE) ++ lw t1, SYSCTL_CLKCFG0_REG(t0) ++ ins t1, zero, 30, 2 # CPU_CLK_SEL ++ sw t1, SYSCTL_CLKCFG0_REG(t0) ++ ++ /* Set CPU clock divider to 1/1 */ ++ li t0, KSEG1ADDR(RBUS_BASE) ++ li t1, 0x101 ++ sw t1, RBUS_DYN_CFG0_REG(t0) ++ ++ /* Initialize the SRAM */ ++ bal mips_sram_init ++ nop ++ ++ /* Set up initial stack */ ++ li sp, SP_ADDR_TEMP ++ ++ bal tpl_main ++ nop ++ ++ END(_start) +diff --git a/arch/mips/mach-mtmips/mt7621/tpl/tpl.c b/arch/mips/mach-mtmips/mt7621/tpl/tpl.c +new file mode 100644 +index 0000000000..2a828907a3 +--- /dev/null ++++ b/arch/mips/mach-mtmips/mt7621/tpl/tpl.c +@@ -0,0 +1,144 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <image.h> ++#include <asm/system.h> ++#include <asm/sections.h> ++#include <asm/cacheops.h> ++#include <asm/mipsregs.h> ++#include <asm/cm.h> ++ ++#define INDEX_STORE_DATA_SD 0x0f ++ ++typedef void __noreturn (*image_entry_noargs_t)(void); ++ ++/* ++ * Lock L2 cache and fill data ++ * Assume that data is 4-byte aligned and start_addr/size is 32-byte aligned ++ */ ++static void fill_lock_l2cache(uintptr_t dataptr, ulong start_addr, ulong size) ++{ ++ ulong slsize = CONFIG_SYS_DCACHE_LINE_SIZE; ++ ulong end_addr = start_addr + size; ++ const u32 *data = (u32 *)dataptr; ++ ulong i, addr; ++ u32 val; ++ ++ /* Clear WSC & SPR bit in ErrCtl */ ++ val = read_c0_ecc(); ++ val &= 0xcfffffff; ++ write_c0_ecc(val); ++ execution_hazard_barrier(); ++ ++ for (addr = start_addr; addr < end_addr; addr += slsize) { ++ /* Set STagLo to lock cache line */ ++ write_c0_staglo((addr & 0x1ffff800) | 0xa0); ++ mips_cache(INDEX_STORE_TAG_SD, (void *)addr); ++ ++ /* Fill data */ ++ for (i = 0; i < slsize; i += 8) { ++ val = *data++; ++ __write_32bit_c0_register($28, 5, val); /* sdtaglo */ ++ val = *data++; ++ __write_32bit_c0_register($29, 5, val); /* sdtaghi */ ++ mips_cache(INDEX_STORE_DATA_SD, (void *)(addr + i)); ++ } ++ } ++ ++ sync(); ++} ++ ++/* A simple function to initialize MT7621's cache */ ++static void mt7621_cache_init(void) ++{ ++ void __iomem *cm_base = (void *)KSEG1ADDR(CONFIG_MIPS_CM_BASE); ++ ulong lsize = CONFIG_SYS_DCACHE_LINE_SIZE; ++ ulong addr; ++ u32 val; ++ ++ /* Enable CCA override. Set to uncached */ ++ val = readl(cm_base + GCR_BASE); ++ val &= ~CCA_DEFAULT_OVR_MASK; ++ val |= CCA_DEFAULT_OVREN | (2 << CCA_DEFAULT_OVR_SHIFT); ++ writel(val, cm_base + GCR_BASE); ++ ++ /* Initialize L1 I-Cache */ ++ write_c0_taglo(0); ++ write_c0_taghi(0); ++ ++ for (addr = 0; addr < CONFIG_SYS_ICACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_STORE_TAG_I, (void *)addr); ++ ++ /* Initialize L1 D-Cache */ ++ write_c0_dtaglo(0); ++ __write_32bit_c0_register($29, 2, 0); /* dtaghi */ ++ ++ for (addr = 0; addr < CONFIG_SYS_DCACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_STORE_TAG_D, (void *)addr); ++ ++ /* Initialize L2 Cache */ ++ write_c0_staglo(0); ++ __write_32bit_c0_register($29, 4, 0); /* staghi */ ++ ++ for (addr = 0; addr < (256 << 10); addr += lsize) ++ mips_cache(INDEX_STORE_TAG_SD, (void *)addr); ++ ++ /* Dsiable CCA override */ ++ val = readl(cm_base + GCR_BASE); ++ val &= ~(CCA_DEFAULT_OVR_MASK | CCA_DEFAULT_OVREN); ++ writel(val, cm_base + GCR_BASE); ++ ++ /* Set KSEG0 to non-coherent cached (important!) */ ++ val = read_c0_config(); ++ val &= ~CONF_CM_CMASK; ++ val |= CONF_CM_CACHABLE_NONCOHERENT; ++ write_c0_config(val); ++ execution_hazard_barrier(); ++ ++ /* Again, invalidate L1 D-Cache */ ++ for (addr = 0; addr < CONFIG_SYS_DCACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_WRITEBACK_INV_D, (void *)addr); ++ ++ /* Invalidate L1 I-Cache */ ++ for (addr = 0; addr < CONFIG_SYS_ICACHE_SIZE; addr += lsize) ++ mips_cache(INDEX_INVALIDATE_I, (void *)addr); ++ ++ /* Disable L2 cache bypass */ ++ val = read_c0_config2(); ++ val &= ~MIPS_CONF_IMPL; ++ write_c0_config2(val); ++ execution_hazard_barrier(); ++} ++ ++void __noreturn tpl_main(void) ++{ ++ const image_header_t *hdr = (const image_header_t *)__image_copy_end; ++ image_entry_noargs_t image_entry; ++ u32 loadaddr, size; ++ uintptr_t data; ++ ++ /* Initialize the cache first */ ++ mt7621_cache_init(); ++ ++ if (image_get_magic(hdr) != IH_MAGIC) ++ goto failed; ++ ++ loadaddr = image_get_load(hdr); ++ size = image_get_size(hdr); ++ image_entry = (image_entry_noargs_t)image_get_ep(hdr); ++ ++ /* Load TPL image to L2 cache */ ++ data = (uintptr_t)__image_copy_end + sizeof(struct image_header); ++ fill_lock_l2cache(data, loadaddr, size); ++ ++ /* Jump to SPL */ ++ image_entry(); ++ ++failed: ++ for (;;) ++ ; ++} +diff --git a/include/configs/mt7621.h b/include/configs/mt7621.h +new file mode 100644 +index 0000000000..dac6aa4afb +--- /dev/null ++++ b/include/configs/mt7621.h +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef __CONFIG_MT7621_H ++#define __CONFIG_MT7621_H ++ ++#define CONFIG_SYS_MIPS_TIMER_FREQ 440000000 ++ ++#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000 ++ ++#define CONFIG_SYS_SDRAM_BASE 0x80000000 ++ ++#define CONFIG_VERY_BIG_RAM ++#define CONFIG_MAX_MEM_MAPPED 0x1c000000 ++ ++#define CONFIG_SYS_INIT_SP_OFFSET 0x800000 ++ ++#define CONFIG_SYS_BOOTM_LEN 0x2000000 ++ ++#define CONFIG_SYS_MAXARGS 16 ++#define CONFIG_SYS_CBSIZE 1024 ++ ++#define CONFIG_SYS_NONCACHED_MEMORY 0x100000 ++ ++/* MMC */ ++#define MMC_SUPPORTS_TUNING ++ ++/* NAND */ ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 ++ ++/* Serial SPL */ ++#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SERIAL) ++#define CONFIG_SYS_NS16550_MEM32 ++#define CONFIG_SYS_NS16550_CLK 50000000 ++#define CONFIG_SYS_NS16550_REG_SIZE -4 ++#define CONFIG_SYS_NS16550_COM1 0xbe000c00 ++#endif ++ ++/* Serial common */ ++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, \ ++ 230400, 460800, 921600 } ++ ++/* SPL */ ++#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE ++ ++#ifdef CONFIG_TPL_BUILD ++#define CONFIG_SPL_START_S_PATH "arch/mips/mach-mtmips/mt7621/tpl" ++/* .bss will not be used by TPL */ ++#define CONFIG_SPL_BSS_START_ADDR 0x80000000 ++#define CONFIG_SPL_BSS_MAX_SIZE 0 ++#else ++#define CONFIG_SPL_START_S_PATH "arch/mips/mach-mtmips/mt7621/spl" ++#define CONFIG_SPL_BSS_START_ADDR 0x80140000 ++#define CONFIG_SPL_BSS_MAX_SIZE 0x80000 ++#define CONFIG_SPL_MAX_SIZE 0x30000 ++#endif ++ ++/* Dummy value */ ++#define CONFIG_SYS_UBOOT_BASE 0 ++ ++#endif /* __CONFIG_MT7621_H */ +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0006-mips-mtmips-add-two-reference-boards-for-mt7621.patch b/package/boot/uboot-mediatek/patches/001-mtk-0006-mips-mtmips-add-two-reference-boards-for-mt7621.patch new file mode 100644 index 0000000000..d45670f3aa --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0006-mips-mtmips-add-two-reference-boards-for-mt7621.patch @@ -0,0 +1,456 @@ +From b1549087ecd1eb53f6173b17b473134fd6cca157 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:26 +0800 +Subject: [PATCH 06/25] mips: mtmips: add two reference boards for mt7621 + +The mt7621_rfb board supports integrated giga PHYs plus one external +giga PHYs. It also has up to 512MiB DDR3, 16MB SPI-NOR, 3 mini PCI-e x1 +slots, SDXC and USB. + +The mt7621_nand_rfb board is almost the same as mt7621_rfb board, but it +uses NAND flash and SDXC is not available. + +Reviewed-by: Stefan Roese <sr@denx.de> +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + arch/mips/dts/Makefile | 2 + + arch/mips/dts/mediatek,mt7621-nand-rfb.dts | 67 +++++++++++++++++ + arch/mips/dts/mediatek,mt7621-rfb.dts | 82 +++++++++++++++++++++ + arch/mips/mach-mtmips/mt7621/Kconfig | 20 +++++ + board/mediatek/mt7621/MAINTAINERS | 8 ++ + board/mediatek/mt7621/Makefile | 3 + + board/mediatek/mt7621/board.c | 6 ++ + configs/mt7621_nand_rfb_defconfig | 85 ++++++++++++++++++++++ + configs/mt7621_rfb_defconfig | 82 +++++++++++++++++++++ + 9 files changed, 355 insertions(+) + create mode 100644 arch/mips/dts/mediatek,mt7621-nand-rfb.dts + create mode 100644 arch/mips/dts/mediatek,mt7621-rfb.dts + create mode 100644 board/mediatek/mt7621/MAINTAINERS + create mode 100644 board/mediatek/mt7621/Makefile + create mode 100644 board/mediatek/mt7621/board.c + create mode 100644 configs/mt7621_nand_rfb_defconfig + create mode 100644 configs/mt7621_rfb_defconfig + +diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile +index 95144b24dc..1b179116c9 100644 +--- a/arch/mips/dts/Makefile ++++ b/arch/mips/dts/Makefile +@@ -16,6 +16,8 @@ dtb-$(CONFIG_BOARD_COMTREND_WAP5813N) += comtrend,wap-5813n.dtb + dtb-$(CONFIG_BOARD_HUAWEI_HG556A) += huawei,hg556a.dtb + dtb-$(CONFIG_BOARD_MT7620_RFB) += mediatek,mt7620-rfb.dtb + dtb-$(CONFIG_BOARD_MT7620_MT7530_RFB) += mediatek,mt7620-mt7530-rfb.dtb ++dtb-$(CONFIG_BOARD_MT7621_RFB) += mediatek,mt7621-rfb.dtb ++dtb-$(CONFIG_BOARD_MT7621_NAND_RFB) += mediatek,mt7621-nand-rfb.dtb + dtb-$(CONFIG_BOARD_MT7628_RFB) += mediatek,mt7628-rfb.dtb + dtb-$(CONFIG_BOARD_GARDENA_SMART_GATEWAY_MT7688) += gardena-smart-gateway-mt7688.dtb + dtb-$(CONFIG_BOARD_LINKIT_SMART_7688) += linkit-smart-7688.dtb +diff --git a/arch/mips/dts/mediatek,mt7621-nand-rfb.dts b/arch/mips/dts/mediatek,mt7621-nand-rfb.dts +new file mode 100644 +index 0000000000..67ba298b0a +--- /dev/null ++++ b/arch/mips/dts/mediatek,mt7621-nand-rfb.dts +@@ -0,0 +1,67 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++/dts-v1/; ++ ++#include "mt7621.dtsi" ++ ++/ { ++ compatible = "mediatek,mt7621-nand-rfb", "mediatek,mt7621-soc"; ++ model = "MediaTek MT7621 RFB (NAND)"; ++ ++ aliases { ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = &uart0; ++ }; ++}; ++ ++&pinctrl { ++ state_default: pin_state { ++ nand { ++ groups = "spi", "sdxc"; ++ function = "nand"; ++ }; ++ ++ gpios { ++ groups = "i2c", "uart3", "pcie reset"; ++ function = "gpio"; ++ }; ++ ++ wdt { ++ groups = "wdt"; ++ function = "wdt rst"; ++ }; ++ ++ jtag { ++ groups = "jtag"; ++ function = "jtag"; ++ }; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&gpio { ++ status = "okay"; ++}; ++ ++ð { ++ status = "okay"; ++}; ++ ++&ssusb { ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; +diff --git a/arch/mips/dts/mediatek,mt7621-rfb.dts b/arch/mips/dts/mediatek,mt7621-rfb.dts +new file mode 100644 +index 0000000000..ff7eaf0f20 +--- /dev/null ++++ b/arch/mips/dts/mediatek,mt7621-rfb.dts +@@ -0,0 +1,82 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++/dts-v1/; ++ ++#include "mt7621.dtsi" ++ ++/ { ++ compatible = "mediatek,mt7621-rfb", "mediatek,mt7621-soc"; ++ model = "MediaTek MT7621 RFB (SPI-NOR)"; ++ ++ aliases { ++ serial0 = &uart0; ++ spi0 = &spi; ++ }; ++ ++ chosen { ++ stdout-path = &uart0; ++ }; ++}; ++ ++&pinctrl { ++ state_default: pin_state { ++ gpios { ++ groups = "i2c", "uart3", "pcie reset"; ++ function = "gpio"; ++ }; ++ ++ wdt { ++ groups = "wdt"; ++ function = "wdt rst"; ++ }; ++ ++ jtag { ++ groups = "jtag"; ++ function = "jtag"; ++ }; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&gpio { ++ status = "okay"; ++}; ++ ++&spi { ++ status = "okay"; ++ num-cs = <2>; ++ ++ spi-flash@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec,spi-nor"; ++ spi-max-frequency = <25000000>; ++ reg = <0>; ++ }; ++}; ++ ++ð { ++ status = "okay"; ++}; ++ ++&mmc { ++ cap-sd-highspeed; ++ ++ status = "okay"; ++}; ++ ++&ssusb { ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; +diff --git a/arch/mips/mach-mtmips/mt7621/Kconfig b/arch/mips/mach-mtmips/mt7621/Kconfig +index 37d512c68f..008a28f991 100644 +--- a/arch/mips/mach-mtmips/mt7621/Kconfig ++++ b/arch/mips/mach-mtmips/mt7621/Kconfig +@@ -79,6 +79,26 @@ config MT7621_BOOT_FROM_NAND + choice + prompt "Board select" + ++config BOARD_MT7621_RFB ++ bool "MediaTek MT7621 RFB (SPI-NOR)" ++ help ++ The reference design of MT7621A (WS3010) booting from SPI-NOR flash. ++ The board can be configured with DDR2 (64MiB~256MiB) or DDR3 ++ (128MiB~512MiB). The board has 16 MiB SPI-NOR flash, built-in MT7530 ++ GbE switch, 1 UART, 1 USB 2.0 host, 1 USB 3.0 host, 1 SDXC, 3 PCIe ++ sockets, 1 RGMII to external GbE PHY, 2 audio jacks (in/out), ++ JTAG pins and expansion GPIO pins. ++ ++config BOARD_MT7621_NAND_RFB ++ bool "MediaTek MT7621 RFB (NAND)" ++ help ++ The reference design of MT7621A (WS3010) booting from NAND flash. ++ The board can be configured with DDR2 (64MiB~256MiB) or DDR3 ++ (128MiB~512MiB). The board has 128 MiB parallel NAND flash, built-in ++ MT7530 GbE switch, 1 UART, 1 USB 2.0 host, 1 USB 3.0 host, 3 PCIe ++ sockets, 1 RGMII to external GbE PHY, 2 audio jacks (in/out), ++ JTAG pins and expansion GPIO pins. ++ + endchoice + + config SYS_CONFIG_NAME +diff --git a/board/mediatek/mt7621/MAINTAINERS b/board/mediatek/mt7621/MAINTAINERS +new file mode 100644 +index 0000000000..f83141cea1 +--- /dev/null ++++ b/board/mediatek/mt7621/MAINTAINERS +@@ -0,0 +1,8 @@ ++MT7621_RFB BOARD ++M: Weijie Gao <weijie.gao@mediatek.com> ++S: Maintained ++F: board/mediatek/mt7621 ++F: configs/mt7621_rfb_defconfig ++F: configs/mt7621_nand_rfb_defconfig ++F: arch/mips/dts/mediatek,mt7621-rfb.dts ++F: arch/mips/dts/mediatek,mt7621-nand-rfb.dts +diff --git a/board/mediatek/mt7621/Makefile b/board/mediatek/mt7621/Makefile +new file mode 100644 +index 0000000000..db129c5aba +--- /dev/null ++++ b/board/mediatek/mt7621/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += board.o +diff --git a/board/mediatek/mt7621/board.c b/board/mediatek/mt7621/board.c +new file mode 100644 +index 0000000000..0496f3f806 +--- /dev/null ++++ b/board/mediatek/mt7621/board.c +@@ -0,0 +1,6 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ +diff --git a/configs/mt7621_nand_rfb_defconfig b/configs/mt7621_nand_rfb_defconfig +new file mode 100644 +index 0000000000..fe8543df49 +--- /dev/null ++++ b/configs/mt7621_nand_rfb_defconfig +@@ -0,0 +1,85 @@ ++CONFIG_MIPS=y ++CONFIG_SYS_MALLOC_LEN=0x100000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x1000 ++CONFIG_DEFAULT_DEVICE_TREE="mediatek,mt7621-nand-rfb" ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_SYS_MALLOC_F_LEN=0x100000 ++CONFIG_SPL=y ++CONFIG_DEBUG_UART_BASE=0xbe000c00 ++CONFIG_DEBUG_UART_CLOCK=50000000 ++CONFIG_SYS_LOAD_ADDR=0x83000000 ++CONFIG_ARCH_MTMIPS=y ++CONFIG_SOC_MT7621=y ++CONFIG_MT7621_BOOT_FROM_NAND=y ++CONFIG_BOARD_MT7621_NAND_RFB=y ++# CONFIG_MIPS_CACHE_SETUP is not set ++# CONFIG_MIPS_CACHE_DISABLE is not set ++CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y ++CONFIG_MIPS_BOOT_FDT=y ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set ++CONFIG_SYS_CONSOLE_INFO_QUIET=y ++CONFIG_SPL_SYS_MALLOC_SIMPLE=y ++CONFIG_SPL_NAND_SUPPORT=y ++CONFIG_SPL_NAND_BASE=y ++CONFIG_SPL_NAND_IDENT=y ++# CONFIG_BOOTM_NETBSD is not set ++# CONFIG_BOOTM_PLAN9 is not set ++# CONFIG_BOOTM_RTEMS is not set ++# CONFIG_BOOTM_VXWORKS is not set ++# CONFIG_CMD_ELF is not set ++# CONFIG_CMD_XIMG is not set ++# CONFIG_CMD_CRC32 is not set ++# CONFIG_CMD_DM is not set ++# CONFIG_CMD_FLASH is not set ++CONFIG_CMD_GPIO=y ++# CONFIG_CMD_LOADS is not set ++CONFIG_CMD_MMC=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PART=y ++# CONFIG_CMD_PINMUX is not set ++CONFIG_CMD_USB=y ++# CONFIG_CMD_NFS is not set ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FS_GENERIC=y ++# CONFIG_SPL_DOS_PARTITION is not set ++# CONFIG_ISO_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SPL_EFI_PARTITION is not set ++CONFIG_PARTITION_TYPE_GUID=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_NET_RANDOM_ETHADDR=y ++# CONFIG_I2C is not set ++# CONFIG_INPUT is not set ++CONFIG_MMC=y ++# CONFIG_MMC_QUIRKS is not set ++# CONFIG_MMC_HW_PARTITIONING is not set ++CONFIG_MMC_MTK=y ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTD_RAW_NAND=y ++CONFIG_NAND_MT7621=y ++CONFIG_SYS_NAND_ONFI_DETECTION=y ++CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y ++CONFIG_SYS_NAND_U_BOOT_OFFS=0x0 ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_RESETCTL=y ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_WDT=y ++CONFIG_WDT_MT7621=y ++CONFIG_FAT_WRITE=y ++# CONFIG_BINMAN_FDT is not set ++CONFIG_LZMA=y ++# CONFIG_GZIP is not set ++CONFIG_SPL_LZMA=y +diff --git a/configs/mt7621_rfb_defconfig b/configs/mt7621_rfb_defconfig +new file mode 100644 +index 0000000000..ae62360e63 +--- /dev/null ++++ b/configs/mt7621_rfb_defconfig +@@ -0,0 +1,82 @@ ++CONFIG_MIPS=y ++CONFIG_SYS_MALLOC_LEN=0x100000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x1000 ++CONFIG_DEFAULT_DEVICE_TREE="mediatek,mt7621-rfb" ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_SYS_MALLOC_F_LEN=0x40000 ++CONFIG_SPL=y ++CONFIG_DEBUG_UART_BASE=0xbe000c00 ++CONFIG_DEBUG_UART_CLOCK=50000000 ++CONFIG_SYS_LOAD_ADDR=0x83000000 ++CONFIG_ARCH_MTMIPS=y ++CONFIG_SOC_MT7621=y ++# CONFIG_MIPS_CACHE_SETUP is not set ++# CONFIG_MIPS_CACHE_DISABLE is not set ++CONFIG_RESTORE_EXCEPTION_VECTOR_BASE=y ++CONFIG_MIPS_BOOT_FDT=y ++CONFIG_DEBUG_UART=y ++CONFIG_TPL_SYS_MALLOC_F_LEN=0x1000 ++CONFIG_FIT=y ++# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set ++CONFIG_SYS_CONSOLE_INFO_QUIET=y ++CONFIG_SPL_SYS_MALLOC_SIMPLE=y ++CONFIG_SPL_NOR_SUPPORT=y ++CONFIG_TPL=y ++# CONFIG_TPL_FRAMEWORK is not set ++# CONFIG_BOOTM_NETBSD is not set ++# CONFIG_BOOTM_PLAN9 is not set ++# CONFIG_BOOTM_RTEMS is not set ++# CONFIG_BOOTM_VXWORKS is not set ++# CONFIG_CMD_ELF is not set ++# CONFIG_CMD_XIMG is not set ++# CONFIG_CMD_CRC32 is not set ++# CONFIG_CMD_DM is not set ++CONFIG_CMD_GPIO=y ++# CONFIG_CMD_LOADS is not set ++CONFIG_CMD_MMC=y ++CONFIG_CMD_PART=y ++# CONFIG_CMD_PINMUX is not set ++CONFIG_CMD_SPI=y ++# CONFIG_CMD_NFS is not set ++CONFIG_DOS_PARTITION=y ++# CONFIG_SPL_DOS_PARTITION is not set ++# CONFIG_ISO_PARTITION is not set ++CONFIG_EFI_PARTITION=y ++# CONFIG_SPL_EFI_PARTITION is not set ++CONFIG_PARTITION_TYPE_GUID=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_NET_RANDOM_ETHADDR=y ++# CONFIG_I2C is not set ++# CONFIG_INPUT is not set ++CONFIG_MMC=y ++# CONFIG_MMC_QUIRKS is not set ++# CONFIG_MMC_HW_PARTITIONING is not set ++CONFIG_MMC_MTK=y ++CONFIG_SF_DEFAULT_SPEED=20000000 ++CONFIG_SPI_FLASH_BAR=y ++CONFIG_SPI_FLASH_EON=y ++CONFIG_SPI_FLASH_GIGADEVICE=y ++CONFIG_SPI_FLASH_ISSI=y ++CONFIG_SPI_FLASH_MACRONIX=y ++CONFIG_SPI_FLASH_SPANSION=y ++CONFIG_SPI_FLASH_STMICRO=y ++CONFIG_SPI_FLASH_WINBOND=y ++CONFIG_SPI_FLASH_XMC=y ++CONFIG_SPI_FLASH_XTX=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_DEBUG_UART_SHIFT=2 ++CONFIG_SPI=y ++CONFIG_MT7621_SPI=y ++CONFIG_SYSRESET=y ++CONFIG_SYSRESET_RESETCTL=y ++CONFIG_WDT=y ++CONFIG_WDT_MT7621=y ++# CONFIG_BINMAN_FDT is not set ++CONFIG_LZMA=y ++# CONFIG_GZIP is not set ++CONFIG_SPL_LZMA=y +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0007-doc-mediatek-add-documentation-for-mt7621-reference-.patch b/package/boot/uboot-mediatek/patches/001-mtk-0007-doc-mediatek-add-documentation-for-mt7621-reference-.patch new file mode 100644 index 0000000000..294740ae70 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0007-doc-mediatek-add-documentation-for-mt7621-reference-.patch @@ -0,0 +1,104 @@ +From 3fed02d930597c53f1c8500aff14581bb87a1e3d Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:31 +0800 +Subject: [PATCH 07/25] doc: mediatek: add documentation for mt7621 reference + boards + +The MT7621 requires external binary blob being executed during u-boot's +boot-up flow. It's necessary to provide a guide here for users to correctly +build the u-boot. + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + doc/board/index.rst | 1 + + doc/board/mediatek/index.rst | 9 +++++++ + doc/board/mediatek/mt7621.rst | 48 +++++++++++++++++++++++++++++++++++ + 3 files changed, 58 insertions(+) + create mode 100644 doc/board/mediatek/index.rst + create mode 100644 doc/board/mediatek/mt7621.rst + +diff --git a/doc/board/index.rst b/doc/board/index.rst +index f90a9cad45..01b99f9cf5 100644 +--- a/doc/board/index.rst ++++ b/doc/board/index.rst +@@ -23,6 +23,7 @@ Board-specific doc + highbank/index + intel/index + kontron/index ++ mediatek/index + microchip/index + nokia/index + nxp/index +diff --git a/doc/board/mediatek/index.rst b/doc/board/mediatek/index.rst +new file mode 100644 +index 0000000000..38cd8cb5b2 +--- /dev/null ++++ b/doc/board/mediatek/index.rst +@@ -0,0 +1,9 @@ ++.. SPDX-License-Identifier: GPL-2.0+ ++ ++Mediatek ++========= ++ ++.. toctree:: ++ :maxdepth: 2 ++ ++ mt7621 +diff --git a/doc/board/mediatek/mt7621.rst b/doc/board/mediatek/mt7621.rst +new file mode 100644 +index 0000000000..1662255546 +--- /dev/null ++++ b/doc/board/mediatek/mt7621.rst +@@ -0,0 +1,48 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++mt7621_rfb/mt7621_nand_rfb ++========================== ++ ++U-Boot for the MediaTek MT7621 boards ++ ++Quick Start ++----------- ++ ++- Get the DDR initialization binary blob ++- Configure CPU and DDR parameters ++- Build U-Boot ++ ++Get the DDR initialization binary blob ++-------------------------------------- ++ ++Download one from: ++ - https://raw.githubusercontent.com/mtk-openwrt/mt7621-lowlevel-preloader/master/mt7621_stage_sram.bin ++ - https://raw.githubusercontent.com/mtk-openwrt/mt7621-lowlevel-preloader/master/mt7621_stage_sram_noprint.bin ++ ++mt7621_stage_sram_noprint.bin has removed all output logs. To use this one, ++download and rename it to mt7621_stage_sram.bin ++ ++Put the binary blob to the u-boot build directory. ++ ++Configure CPU and DDR parameters ++-------------------------------- ++ ++menuconfig > MIPS architecture > MediaTek MIPS platforms > CPU & DDR configuration ++ ++Select the correct DDR timing parameters for your board. The size shown here ++must match the DDR size of you board. ++ ++The frequency of CPU and DDR can also be adjusted. ++ ++Build U-Boot ++------------ ++ ++.. code-block:: bash ++ ++ $ export CROSS_COMPILE=mipsel-linux- ++ $ make O=build mt7621_rfb_defconfig # or mt7621_nand_rfb_defconfig ++ $ cp mt7621_stage_sram.bin ./build/mt7621_stage_sram.bin ++ $ # or cp mt7621_stage_sram_noprint.bin ./build/mt7621_stage_sram.bin ++ $ make O=build ++ ++Burn the u-boot-mt7621.bin to the SPI-NOR or NAND flash. +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0008-clk-mtmips-add-clock-driver-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0008-clk-mtmips-add-clock-driver-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..02d97e9a85 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0008-clk-mtmips-add-clock-driver-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,378 @@ +From c2e579662748cb5d3bf3e31f58d99c4db4d102c1 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:36 +0800 +Subject: [PATCH 08/25] clk: mtmips: add clock driver for MediaTek MT7621 SoC + +This patch adds a clock driver for MediaTek MT7621 SoC. +This driver provides clock gate control as well as getting clock frequency +for CPU/SYS/XTAL and some peripherals. + +Reviewed-by: Sean Anderson <seanga2@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/clk/mtmips/Makefile | 1 + + drivers/clk/mtmips/clk-mt7621.c | 288 +++++++++++++++++++++++++ + include/dt-bindings/clock/mt7621-clk.h | 46 ++++ + 3 files changed, 335 insertions(+) + create mode 100644 drivers/clk/mtmips/clk-mt7621.c + create mode 100644 include/dt-bindings/clock/mt7621-clk.h + +diff --git a/drivers/clk/mtmips/Makefile b/drivers/clk/mtmips/Makefile +index 732e7f2545..ee8b5afe87 100644 +--- a/drivers/clk/mtmips/Makefile ++++ b/drivers/clk/mtmips/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 + + obj-$(CONFIG_SOC_MT7620) += clk-mt7620.o ++obj-$(CONFIG_SOC_MT7621) += clk-mt7621.o + obj-$(CONFIG_SOC_MT7628) += clk-mt7628.o +diff --git a/drivers/clk/mtmips/clk-mt7621.c b/drivers/clk/mtmips/clk-mt7621.c +new file mode 100644 +index 0000000000..03363b70d7 +--- /dev/null ++++ b/drivers/clk/mtmips/clk-mt7621.c +@@ -0,0 +1,288 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <clk-uclass.h> ++#include <dm.h> ++#include <dm/device_compat.h> ++#include <regmap.h> ++#include <syscon.h> ++#include <dt-bindings/clock/mt7621-clk.h> ++#include <linux/io.h> ++#include <linux/bitops.h> ++#include <linux/bitfield.h> ++ ++#define SYSC_MAP_SIZE 0x100 ++#define MEMC_MAP_SIZE 0x1000 ++ ++/* SYSC */ ++#define SYSCFG0_REG 0x10 ++#define XTAL_MODE_SEL GENMASK(8, 6) ++ ++#define CLKCFG0_REG 0x2c ++#define CPU_CLK_SEL GENMASK(31, 30) ++#define PERI_CLK_SEL BIT(4) ++ ++#define CLKCFG1_REG 0x30 ++ ++#define CUR_CLK_STS_REG 0x44 ++#define CUR_CPU_FDIV GENMASK(12, 8) ++#define CUR_CPU_FFRAC GENMASK(4, 0) ++ ++/* MEMC */ ++#define MEMPLL1_REG 0x0604 ++#define RG_MEPL_DIV2_SEL GENMASK(2, 1) ++ ++#define MEMPLL6_REG 0x0618 ++#define MEMPLL18_REG 0x0648 ++#define RG_MEPL_PREDIV GENMASK(13, 12) ++#define RG_MEPL_FBDIV GENMASK(10, 4) ++ ++/* Fixed 500M clock */ ++#define GMPLL_CLK 500000000 ++ ++struct mt7621_clk_priv { ++ void __iomem *sysc_base; ++ int cpu_clk; ++ int ddr_clk; ++ int sys_clk; ++ int xtal_clk; ++}; ++ ++enum mt7621_clk_src { ++ CLK_SRC_CPU, ++ CLK_SRC_DDR, ++ CLK_SRC_SYS, ++ CLK_SRC_XTAL, ++ CLK_SRC_PERI, ++ CLK_SRC_125M, ++ CLK_SRC_150M, ++ CLK_SRC_250M, ++ CLK_SRC_270M, ++ ++ __CLK_SRC_MAX ++}; ++ ++struct mt7621_clk_map { ++ u32 cgbit; ++ enum mt7621_clk_src clksrc; ++}; ++ ++#define CLK_MAP(_id, _cg, _src) \ ++ [_id] = { .cgbit = (_cg), .clksrc = (_src) } ++ ++#define CLK_MAP_SRC(_id, _src) \ ++ [_id] = { .cgbit = UINT32_MAX, .clksrc = (_src) } ++ ++static const struct mt7621_clk_map mt7621_clk_mappings[] = { ++ CLK_MAP_SRC(MT7621_CLK_XTAL, CLK_SRC_XTAL), ++ CLK_MAP_SRC(MT7621_CLK_CPU, CLK_SRC_CPU), ++ CLK_MAP_SRC(MT7621_CLK_BUS, CLK_SRC_SYS), ++ CLK_MAP_SRC(MT7621_CLK_50M, CLK_SRC_PERI), ++ CLK_MAP_SRC(MT7621_CLK_125M, CLK_SRC_125M), ++ CLK_MAP_SRC(MT7621_CLK_150M, CLK_SRC_150M), ++ CLK_MAP_SRC(MT7621_CLK_250M, CLK_SRC_250M), ++ CLK_MAP_SRC(MT7621_CLK_270M, CLK_SRC_270M), ++ ++ CLK_MAP(MT7621_CLK_HSDMA, 5, CLK_SRC_150M), ++ CLK_MAP(MT7621_CLK_FE, 6, CLK_SRC_250M), ++ CLK_MAP(MT7621_CLK_SP_DIVTX, 7, CLK_SRC_270M), ++ CLK_MAP(MT7621_CLK_TIMER, 8, CLK_SRC_PERI), ++ CLK_MAP(MT7621_CLK_PCM, 11, CLK_SRC_270M), ++ CLK_MAP(MT7621_CLK_PIO, 13, CLK_SRC_PERI), ++ CLK_MAP(MT7621_CLK_GDMA, 14, CLK_SRC_SYS), ++ CLK_MAP(MT7621_CLK_NAND, 15, CLK_SRC_125M), ++ CLK_MAP(MT7621_CLK_I2C, 16, CLK_SRC_PERI), ++ CLK_MAP(MT7621_CLK_I2S, 17, CLK_SRC_270M), ++ CLK_MAP(MT7621_CLK_SPI, 18, CLK_SRC_SYS), ++ CLK_MAP(MT7621_CLK_UART1, 19, CLK_SRC_PERI), ++ CLK_MAP(MT7621_CLK_UART2, 20, CLK_SRC_PERI), ++ CLK_MAP(MT7621_CLK_UART3, 21, CLK_SRC_PERI), ++ CLK_MAP(MT7621_CLK_ETH, 23, CLK_SRC_PERI), ++ CLK_MAP(MT7621_CLK_PCIE0, 24, CLK_SRC_125M), ++ CLK_MAP(MT7621_CLK_PCIE1, 25, CLK_SRC_125M), ++ CLK_MAP(MT7621_CLK_PCIE2, 26, CLK_SRC_125M), ++ CLK_MAP(MT7621_CLK_CRYPTO, 29, CLK_SRC_250M), ++ CLK_MAP(MT7621_CLK_SHXC, 30, CLK_SRC_PERI), ++ ++ CLK_MAP_SRC(MT7621_CLK_MAX, __CLK_SRC_MAX), ++ ++ CLK_MAP_SRC(MT7621_CLK_DDR, CLK_SRC_DDR), ++}; ++ ++static ulong mt7621_clk_get_rate(struct clk *clk) ++{ ++ struct mt7621_clk_priv *priv = dev_get_priv(clk->dev); ++ u32 val; ++ ++ switch (mt7621_clk_mappings[clk->id].clksrc) { ++ case CLK_SRC_CPU: ++ return priv->cpu_clk; ++ case CLK_SRC_DDR: ++ return priv->ddr_clk; ++ case CLK_SRC_SYS: ++ return priv->sys_clk; ++ case CLK_SRC_XTAL: ++ return priv->xtal_clk; ++ case CLK_SRC_PERI: ++ val = readl(priv->sysc_base + CLKCFG0_REG); ++ if (val & PERI_CLK_SEL) ++ return priv->xtal_clk; ++ else ++ return GMPLL_CLK / 10; ++ case CLK_SRC_125M: ++ return 125000000; ++ case CLK_SRC_150M: ++ return 150000000; ++ case CLK_SRC_250M: ++ return 250000000; ++ case CLK_SRC_270M: ++ return 270000000; ++ default: ++ return 0; ++ } ++} ++ ++static int mt7621_clk_enable(struct clk *clk) ++{ ++ struct mt7621_clk_priv *priv = dev_get_priv(clk->dev); ++ u32 cgbit; ++ ++ cgbit = mt7621_clk_mappings[clk->id].cgbit; ++ if (cgbit == UINT32_MAX) ++ return -ENOSYS; ++ ++ setbits_32(priv->sysc_base + CLKCFG1_REG, BIT(cgbit)); ++ ++ return 0; ++} ++ ++static int mt7621_clk_disable(struct clk *clk) ++{ ++ struct mt7621_clk_priv *priv = dev_get_priv(clk->dev); ++ u32 cgbit; ++ ++ cgbit = mt7621_clk_mappings[clk->id].cgbit; ++ if (cgbit == UINT32_MAX) ++ return -ENOSYS; ++ ++ clrbits_32(priv->sysc_base + CLKCFG1_REG, BIT(cgbit)); ++ ++ return 0; ++} ++ ++static int mt7621_clk_request(struct clk *clk) ++{ ++ if (clk->id >= ARRAY_SIZE(mt7621_clk_mappings)) ++ return -EINVAL; ++ return 0; ++} ++ ++const struct clk_ops mt7621_clk_ops = { ++ .request = mt7621_clk_request, ++ .enable = mt7621_clk_enable, ++ .disable = mt7621_clk_disable, ++ .get_rate = mt7621_clk_get_rate, ++}; ++ ++static void mt7621_get_clocks(struct mt7621_clk_priv *priv, struct regmap *memc) ++{ ++ u32 bs, xtal_sel, clkcfg0, cur_clk, mempll, dividx, fb; ++ u32 xtal_clk, xtal_div, ffiv, ffrac, cpu_clk, ddr_clk; ++ static const u32 xtal_div_tbl[] = {0, 1, 2, 2}; ++ ++ bs = readl(priv->sysc_base + SYSCFG0_REG); ++ clkcfg0 = readl(priv->sysc_base + CLKCFG0_REG); ++ cur_clk = readl(priv->sysc_base + CUR_CLK_STS_REG); ++ ++ xtal_sel = FIELD_GET(XTAL_MODE_SEL, bs); ++ ++ if (xtal_sel <= 2) ++ xtal_clk = 20 * 1000 * 1000; ++ else if (xtal_sel <= 5) ++ xtal_clk = 40 * 1000 * 1000; ++ else ++ xtal_clk = 25 * 1000 * 1000; ++ ++ switch (FIELD_GET(CPU_CLK_SEL, clkcfg0)) { ++ case 0: ++ cpu_clk = GMPLL_CLK; ++ break; ++ case 1: ++ regmap_read(memc, MEMPLL18_REG, &mempll); ++ dividx = FIELD_GET(RG_MEPL_PREDIV, mempll); ++ fb = FIELD_GET(RG_MEPL_FBDIV, mempll); ++ xtal_div = 1 << xtal_div_tbl[dividx]; ++ cpu_clk = (fb + 1) * xtal_clk / xtal_div; ++ break; ++ default: ++ cpu_clk = xtal_clk; ++ } ++ ++ ffiv = FIELD_GET(CUR_CPU_FDIV, cur_clk); ++ ffrac = FIELD_GET(CUR_CPU_FFRAC, cur_clk); ++ cpu_clk = cpu_clk / ffiv * ffrac; ++ ++ regmap_read(memc, MEMPLL6_REG, &mempll); ++ dividx = FIELD_GET(RG_MEPL_PREDIV, mempll); ++ fb = FIELD_GET(RG_MEPL_FBDIV, mempll); ++ xtal_div = 1 << xtal_div_tbl[dividx]; ++ ddr_clk = fb * xtal_clk / xtal_div; ++ ++ regmap_read(memc, MEMPLL1_REG, &bs); ++ if (!FIELD_GET(RG_MEPL_DIV2_SEL, bs)) ++ ddr_clk *= 2; ++ ++ priv->cpu_clk = cpu_clk; ++ priv->sys_clk = cpu_clk / 4; ++ priv->ddr_clk = ddr_clk; ++ priv->xtal_clk = xtal_clk; ++} ++ ++static int mt7621_clk_probe(struct udevice *dev) ++{ ++ struct mt7621_clk_priv *priv = dev_get_priv(dev); ++ struct ofnode_phandle_args args; ++ struct udevice *pdev; ++ struct regmap *memc; ++ int ret; ++ ++ pdev = dev_get_parent(dev); ++ if (!pdev) ++ return -ENODEV; ++ ++ priv->sysc_base = dev_remap_addr(pdev); ++ if (!priv->sysc_base) ++ return -EINVAL; ++ ++ /* get corresponding memc phandle */ ++ ret = dev_read_phandle_with_args(dev, "mediatek,memc", NULL, 0, 0, ++ &args); ++ if (ret) ++ return ret; ++ ++ memc = syscon_node_to_regmap(args.node); ++ if (IS_ERR(memc)) ++ return PTR_ERR(memc); ++ ++ mt7621_get_clocks(priv, memc); ++ ++ return 0; ++} ++ ++static const struct udevice_id mt7621_clk_ids[] = { ++ { .compatible = "mediatek,mt7621-clk" }, ++ { } ++}; ++ ++U_BOOT_DRIVER(mt7621_clk) = { ++ .name = "mt7621-clk", ++ .id = UCLASS_CLK, ++ .of_match = mt7621_clk_ids, ++ .probe = mt7621_clk_probe, ++ .priv_auto = sizeof(struct mt7621_clk_priv), ++ .ops = &mt7621_clk_ops, ++}; +diff --git a/include/dt-bindings/clock/mt7621-clk.h b/include/dt-bindings/clock/mt7621-clk.h +new file mode 100644 +index 0000000000..978c67951b +--- /dev/null ++++ b/include/dt-bindings/clock/mt7621-clk.h +@@ -0,0 +1,46 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _DT_BINDINGS_MT7621_CLK_H_ ++#define _DT_BINDINGS_MT7621_CLK_H_ ++ ++#define MT7621_CLK_XTAL 0 ++#define MT7621_CLK_CPU 1 ++#define MT7621_CLK_BUS 2 ++#define MT7621_CLK_50M 3 ++#define MT7621_CLK_125M 4 ++#define MT7621_CLK_150M 5 ++#define MT7621_CLK_250M 6 ++#define MT7621_CLK_270M 7 ++ ++#define MT7621_CLK_HSDMA 8 ++#define MT7621_CLK_FE 9 ++#define MT7621_CLK_SP_DIVTX 10 ++#define MT7621_CLK_TIMER 11 ++#define MT7621_CLK_PCM 12 ++#define MT7621_CLK_PIO 13 ++#define MT7621_CLK_GDMA 14 ++#define MT7621_CLK_NAND 15 ++#define MT7621_CLK_I2C 16 ++#define MT7621_CLK_I2S 17 ++#define MT7621_CLK_SPI 18 ++#define MT7621_CLK_UART1 19 ++#define MT7621_CLK_UART2 20 ++#define MT7621_CLK_UART3 21 ++#define MT7621_CLK_ETH 22 ++#define MT7621_CLK_PCIE0 23 ++#define MT7621_CLK_PCIE1 24 ++#define MT7621_CLK_PCIE2 25 ++#define MT7621_CLK_CRYPTO 26 ++#define MT7621_CLK_SHXC 27 ++ ++#define MT7621_CLK_MAX 28 ++ ++/* for u-boot only */ ++#define MT7621_CLK_DDR 29 ++ ++#endif /* _DT_BINDINGS_MT7621_CLK_H_ */ +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0009-reset-mtmips-add-reset-controller-support-for-MediaT.patch b/package/boot/uboot-mediatek/patches/001-mtk-0009-reset-mtmips-add-reset-controller-support-for-MediaT.patch new file mode 100644 index 0000000000..a6f61a6b8d --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0009-reset-mtmips-add-reset-controller-support-for-MediaT.patch @@ -0,0 +1,62 @@ +From 03035a6566300808c8845799b2f9ceca471aa61a Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:41 +0800 +Subject: [PATCH 09/25] reset: mtmips: add reset controller support for + MediaTek MT7621 SoC + +This patch adds reset controller bits definition header file for MediaTek +MT7621 SoC + +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + include/dt-bindings/reset/mt7621-reset.h | 38 ++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + create mode 100644 include/dt-bindings/reset/mt7621-reset.h + +diff --git a/include/dt-bindings/reset/mt7621-reset.h b/include/dt-bindings/reset/mt7621-reset.h +new file mode 100644 +index 0000000000..8e4341f040 +--- /dev/null ++++ b/include/dt-bindings/reset/mt7621-reset.h +@@ -0,0 +1,38 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _DT_BINDINGS_MT7621_RESET_H_ ++#define _DT_BINDINGS_MT7621_RESET_H_ ++ ++#define RST_PPE 31 ++#define RST_SDXC 30 ++#define RST_CRYPTO 29 ++#define RST_AUX_STCK 28 ++#define RST_PCIE2 26 ++#define RST_PCIE1 25 ++#define RST_PCIE0 24 ++#define RST_GMAC 23 ++#define RST_UART3 21 ++#define RST_UART2 20 ++#define RST_UART1 19 ++#define RST_SPI 18 ++#define RST_I2S 17 ++#define RST_I2C 16 ++#define RST_NFI 15 ++#define RST_GDMA 14 ++#define RST_PIO 13 ++#define RST_PCM 11 ++#define RST_MC 10 ++#define RST_INTC 9 ++#define RST_TIMER 8 ++#define RST_SPDIFTX 7 ++#define RST_FE 6 ++#define RST_HSDMA 5 ++#define RST_MCM 2 ++#define RST_SYS 0 ++ ++#endif /* _DT_BINDINGS_MT7621_RESET_H_ */ +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0010-pinctrl-mtmips-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0010-pinctrl-mtmips-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..8bafc869ff --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0010-pinctrl-mtmips-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,409 @@ +From 3cf9e2daca330a0ba89d3793ceb09037c788db46 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:49 +0800 +Subject: [PATCH 10/25] pinctrl: mtmips: add support for MediaTek MT7621 SoC + +This patch adds pinctrl support for MediaTek MT7621 SoC. +The MT7621 SoC supports pinconf, but it is not the same as mt7628. + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/pinctrl/mtmips/Kconfig | 9 + + drivers/pinctrl/mtmips/Makefile | 1 + + drivers/pinctrl/mtmips/pinctrl-mt7621.c | 306 ++++++++++++++++++ + .../pinctrl/mtmips/pinctrl-mtmips-common.c | 4 +- + .../pinctrl/mtmips/pinctrl-mtmips-common.h | 12 + + 5 files changed, 330 insertions(+), 2 deletions(-) + create mode 100644 drivers/pinctrl/mtmips/pinctrl-mt7621.c + +diff --git a/drivers/pinctrl/mtmips/Kconfig b/drivers/pinctrl/mtmips/Kconfig +index 844d5b743f..456f3ea25d 100644 +--- a/drivers/pinctrl/mtmips/Kconfig ++++ b/drivers/pinctrl/mtmips/Kconfig +@@ -12,6 +12,15 @@ config PINCTRL_MT7620 + The driver is controlled by a device tree node which contains + the pin mux functions for each available pin groups. + ++config PINCTRL_MT7621 ++ bool "MediaTek MT7621 pin control driver" ++ select PINCTRL_MTMIPS ++ depends on SOC_MT7621 && PINCTRL_GENERIC ++ help ++ Support pin multiplexing control on MediaTek MT7621. ++ The driver is controlled by a device tree node which contains ++ the pin mux functions for each available pin groups. ++ + config PINCTRL_MT7628 + bool "MediaTek MT7628 pin control driver" + select PINCTRL_MTMIPS +diff --git a/drivers/pinctrl/mtmips/Makefile b/drivers/pinctrl/mtmips/Makefile +index ba945a89a7..8fece4f5fa 100644 +--- a/drivers/pinctrl/mtmips/Makefile ++++ b/drivers/pinctrl/mtmips/Makefile +@@ -5,4 +5,5 @@ obj-$(CONFIG_PINCTRL_MTMIPS) += pinctrl-mtmips-common.o + + # SoC Drivers + obj-$(CONFIG_PINCTRL_MT7620) += pinctrl-mt7620.o ++obj-$(CONFIG_PINCTRL_MT7621) += pinctrl-mt7621.o + obj-$(CONFIG_PINCTRL_MT7628) += pinctrl-mt7628.o +diff --git a/drivers/pinctrl/mtmips/pinctrl-mt7621.c b/drivers/pinctrl/mtmips/pinctrl-mt7621.c +new file mode 100644 +index 0000000000..3e98a01bad +--- /dev/null ++++ b/drivers/pinctrl/mtmips/pinctrl-mt7621.c +@@ -0,0 +1,306 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <dm.h> ++#include <dm/pinctrl.h> ++#include <dm/device_compat.h> ++#include <linux/bitops.h> ++#include <linux/io.h> ++ ++#include "pinctrl-mtmips-common.h" ++ ++#define SYSC_MAP_SIZE 0x100 ++ ++#define PAD_UART1_GPIO0_OFS 0x00 ++#define PAD_UART3_I2C_OFS 0x04 ++#define PAD_UART2_JTAG_OFS 0x08 ++#define PAD_PERST_WDT_OFS 0x0c ++#define PAD_RGMII2_MDIO_OFS 0x10 ++#define PAD_SDXC_SPI_OFS 0x14 ++#define GPIOMODE_OFS 0x18 ++#define PAD_BOPT_ESWINT_OFS 0x28 ++ ++#define ESWINT_SHIFT 20 ++#define SDXC_SHIFT 18 ++#define SPI_SHIFT 16 ++#define RGMII2_SHIFT 15 ++#define RGMII1_SHIFT 14 ++#define MDIO_SHIFT 12 ++#define PERST_SHIFT 10 ++#define WDT_SHIFT 8 ++#define JTAG_SHIFT 7 ++#define UART2_SHIFT 5 ++#define UART3_SHIFT 3 ++#define I2C_SHIFT 2 ++#define UART1_SHIFT 1 ++#define GPIO0_SHIFT 0 /* Dummy */ ++ ++#define GM4_MASK 3 ++ ++#define E4_E2_M 0x03 ++#define E4_E2_S 4 ++#define PULL_UP BIT(3) ++#define PULL_DOWN BIT(2) ++#define SMT BIT(1) ++#define SR BIT(0) ++ ++struct mt7621_pinctrl_priv { ++ struct mtmips_pinctrl_priv mp; ++}; ++ ++#if CONFIG_IS_ENABLED(PINMUX) ++static const struct mtmips_pmx_func esw_int_grp[] = { ++ FUNC("gpio", 1), ++ FUNC("esw int", 0), ++}; ++ ++static const struct mtmips_pmx_func sdxc_grp[] = { ++ FUNC("nand", 2), ++ FUNC("gpio", 1), ++ FUNC("sdxc", 0), ++}; ++ ++static const struct mtmips_pmx_func spi_grp[] = { ++ FUNC("nand", 2), ++ FUNC("gpio", 1), ++ FUNC("spi", 0), ++}; ++ ++static const struct mtmips_pmx_func rgmii2_grp[] = { ++ FUNC("gpio", 1), ++ FUNC("rgmii", 0), ++}; ++ ++static const struct mtmips_pmx_func rgmii1_grp[] = { ++ FUNC("gpio", 1), ++ FUNC("rgmii", 0), ++}; ++ ++static const struct mtmips_pmx_func mdio_grp[] = { ++ FUNC("gpio", 1), ++ FUNC("mdio", 0), ++}; ++ ++static const struct mtmips_pmx_func perst_grp[] = { ++ FUNC("refclk", 2), ++ FUNC("gpio", 1), ++ FUNC("pcie reset", 0), ++}; ++ ++static const struct mtmips_pmx_func wdt_grp[] = { ++ FUNC("refclk", 2), ++ FUNC("gpio", 1), ++ FUNC("wdt rst", 0), ++}; ++ ++static const struct mtmips_pmx_func jtag_grp[] = { ++ FUNC("gpio", 1), ++ FUNC("jtag", 0), ++}; ++ ++static const struct mtmips_pmx_func uart2_grp[] = { ++ FUNC("spdif", 3), ++ FUNC("pcm", 2), ++ FUNC("gpio", 1), ++ FUNC("uart", 0), ++}; ++ ++static const struct mtmips_pmx_func uart3_grp[] = { ++ FUNC("spdif", 3), ++ FUNC("i2s", 2), ++ FUNC("gpio", 1), ++ FUNC("uart", 0), ++}; ++ ++static const struct mtmips_pmx_func i2c_grp[] = { ++ FUNC("gpio", 1), ++ FUNC("i2c", 0), ++}; ++ ++static const struct mtmips_pmx_func uart1_grp[] = { ++ FUNC("gpio", 1), ++ FUNC("uart", 0), ++}; ++ ++static const struct mtmips_pmx_func gpio0_grp[] = { ++ FUNC("gpio", 0), ++}; ++ ++static const struct mtmips_pmx_group mt7621_pmx_data[] = { ++ GRP_PCONF("esw int", esw_int_grp, GPIOMODE_OFS, ESWINT_SHIFT, 1, ++ PAD_BOPT_ESWINT_OFS, 0), ++ GRP_PCONF("sdxc", sdxc_grp, GPIOMODE_OFS, SDXC_SHIFT, GM4_MASK, ++ PAD_SDXC_SPI_OFS, 16), ++ GRP_PCONF("spi", spi_grp, GPIOMODE_OFS, SPI_SHIFT, GM4_MASK, ++ PAD_SDXC_SPI_OFS, 0), ++ GRP_PCONF("rgmii2", rgmii2_grp, GPIOMODE_OFS, RGMII2_SHIFT, 1, ++ PAD_RGMII2_MDIO_OFS, 16), ++ GRP("rgmii1", rgmii1_grp, GPIOMODE_OFS, RGMII1_SHIFT, 1), ++ GRP_PCONF("mdio", mdio_grp, GPIOMODE_OFS, MDIO_SHIFT, GM4_MASK, ++ PAD_RGMII2_MDIO_OFS, 0), ++ GRP_PCONF("pcie reset", perst_grp, GPIOMODE_OFS, PERST_SHIFT, GM4_MASK, ++ PAD_PERST_WDT_OFS, 16), ++ GRP_PCONF("wdt", wdt_grp, GPIOMODE_OFS, WDT_SHIFT, GM4_MASK, ++ PAD_PERST_WDT_OFS, 0), ++ GRP_PCONF("jtag", jtag_grp, GPIOMODE_OFS, JTAG_SHIFT, 1, ++ PAD_UART2_JTAG_OFS, 16), ++ GRP_PCONF("uart2", uart2_grp, GPIOMODE_OFS, UART2_SHIFT, GM4_MASK, ++ PAD_UART2_JTAG_OFS, 0), ++ GRP_PCONF("uart3", uart3_grp, GPIOMODE_OFS, UART3_SHIFT, GM4_MASK, ++ PAD_UART3_I2C_OFS, 16), ++ GRP_PCONF("i2c", i2c_grp, GPIOMODE_OFS, I2C_SHIFT, 1, ++ PAD_UART3_I2C_OFS, 0), ++ GRP_PCONF("uart1", uart1_grp, GPIOMODE_OFS, UART1_SHIFT, 1, ++ PAD_UART1_GPIO0_OFS, 16), ++ GRP_PCONF("gpio0", gpio0_grp, GPIOMODE_OFS, GPIO0_SHIFT, 1, ++ PAD_UART1_GPIO0_OFS, 0), ++}; ++ ++static int mt7621_get_groups_count(struct udevice *dev) ++{ ++ return ARRAY_SIZE(mt7621_pmx_data); ++} ++ ++static const char *mt7621_get_group_name(struct udevice *dev, ++ unsigned int selector) ++{ ++ return mt7621_pmx_data[selector].name; ++} ++#endif /* CONFIG_IS_ENABLED(PINMUX) */ ++ ++#if CONFIG_IS_ENABLED(PINCONF) ++static const struct pinconf_param mt7621_conf_params[] = { ++ { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, ++ { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, ++ { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, ++ { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 }, ++ { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 }, ++ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, ++ { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 }, ++}; ++ ++static const u32 mt7621_pconf_drv_strength_tbl[] = {2, 4, 6, 8}; ++ ++static int mt7621_pinconf_group_set(struct udevice *dev, ++ unsigned int group_selector, ++ unsigned int param, unsigned int arg) ++{ ++ struct mt7621_pinctrl_priv *priv = dev_get_priv(dev); ++ const struct mtmips_pmx_group *grp = &mt7621_pmx_data[group_selector]; ++ u32 clr = 0, set = 0; ++ int i; ++ ++ if (!grp->pconf_avail) ++ return 0; ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ clr = PULL_UP | PULL_DOWN; ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_UP: ++ clr = PULL_DOWN; ++ set = PULL_UP; ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ clr = PULL_UP; ++ set = PULL_DOWN; ++ break; ++ ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ if (arg) ++ set = SMT; ++ else ++ clr = SMT; ++ break; ++ ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ for (i = 0; i < ARRAY_SIZE(mt7621_pconf_drv_strength_tbl); i++) ++ if (mt7621_pconf_drv_strength_tbl[i] == arg) ++ break; ++ ++ if (i >= ARRAY_SIZE(mt7621_pconf_drv_strength_tbl)) ++ return -EINVAL; ++ ++ clr = E4_E2_M << E4_E2_S; ++ set = i << E4_E2_S; ++ break; ++ ++ case PIN_CONFIG_SLEW_RATE: ++ if (arg) ++ set = SR; ++ else ++ clr = SR; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ mtmips_pinctrl_reg_set(&priv->mp, grp->pconf_reg, grp->pconf_shift, ++ clr, set); ++ ++ return 0; ++} ++#endif ++ ++static int mt7621_pinctrl_probe(struct udevice *dev) ++{ ++ struct mt7621_pinctrl_priv *priv = dev_get_priv(dev); ++ int ret = 0; ++ ++#if CONFIG_IS_ENABLED(PINMUX) ++ ret = mtmips_pinctrl_probe(&priv->mp, ARRAY_SIZE(mt7621_pmx_data), ++ mt7621_pmx_data); ++#endif /* CONFIG_IS_ENABLED(PINMUX) */ ++ ++ return ret; ++} ++ ++static int mt7621_pinctrl_of_to_plat(struct udevice *dev) ++{ ++ struct mt7621_pinctrl_priv *priv = dev_get_priv(dev); ++ ++ priv->mp.base = (void __iomem *)dev_remap_addr_index(dev, 0); ++ ++ if (!priv->mp.base) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct pinctrl_ops mt7621_pinctrl_ops = { ++#if CONFIG_IS_ENABLED(PINMUX) ++ .get_groups_count = mt7621_get_groups_count, ++ .get_group_name = mt7621_get_group_name, ++ .get_functions_count = mtmips_get_functions_count, ++ .get_function_name = mtmips_get_function_name, ++ .pinmux_group_set = mtmips_pinmux_group_set, ++#endif /* CONFIG_IS_ENABLED(PINMUX) */ ++#if CONFIG_IS_ENABLED(PINCONF) ++ .pinconf_num_params = ARRAY_SIZE(mt7621_conf_params), ++ .pinconf_params = mt7621_conf_params, ++ .pinconf_group_set = mt7621_pinconf_group_set, ++#endif /* CONFIG_IS_ENABLED(PINCONF) */ ++ .set_state = pinctrl_generic_set_state, ++}; ++ ++static const struct udevice_id mt7621_pinctrl_ids[] = { ++ { .compatible = "mediatek,mt7621-pinctrl" }, ++ { } ++}; ++ ++U_BOOT_DRIVER(mt7621_pinctrl) = { ++ .name = "mt7621-pinctrl", ++ .id = UCLASS_PINCTRL, ++ .of_match = mt7621_pinctrl_ids, ++ .of_to_plat = mt7621_pinctrl_of_to_plat, ++ .ops = &mt7621_pinctrl_ops, ++ .probe = mt7621_pinctrl_probe, ++ .priv_auto = sizeof(struct mt7621_pinctrl_priv), ++}; +diff --git a/drivers/pinctrl/mtmips/pinctrl-mtmips-common.c b/drivers/pinctrl/mtmips/pinctrl-mtmips-common.c +index e361916eb2..869b781068 100644 +--- a/drivers/pinctrl/mtmips/pinctrl-mtmips-common.c ++++ b/drivers/pinctrl/mtmips/pinctrl-mtmips-common.c +@@ -13,8 +13,8 @@ + + #include "pinctrl-mtmips-common.h" + +-static void mtmips_pinctrl_reg_set(struct mtmips_pinctrl_priv *priv, +- u32 reg, u32 shift, u32 mask, u32 value) ++void mtmips_pinctrl_reg_set(struct mtmips_pinctrl_priv *priv, ++ u32 reg, u32 shift, u32 mask, u32 value) + { + u32 val; + +diff --git a/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h b/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h +index b51d8f009c..1f1023ef42 100644 +--- a/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h ++++ b/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h +@@ -22,6 +22,10 @@ struct mtmips_pmx_group { + u32 shift; + char mask; + ++ int pconf_avail; ++ u32 pconf_reg; ++ u32 pconf_shift; ++ + int nfuncs; + const struct mtmips_pmx_func *funcs; + }; +@@ -42,6 +46,14 @@ struct mtmips_pinctrl_priv { + { .name = (_name), .reg = (_reg), .shift = (_shift), .mask = (_mask), \ + .funcs = (_funcs), .nfuncs = ARRAY_SIZE(_funcs) } + ++#define GRP_PCONF(_name, _funcs, _reg, _shift, _mask, _pconf_reg, _pconf_shift) \ ++ { .name = (_name), .reg = (_reg), .shift = (_shift), .mask = (_mask), \ ++ .funcs = (_funcs), .nfuncs = ARRAY_SIZE(_funcs), .pconf_avail = 1, \ ++ .pconf_reg = (_pconf_reg), .pconf_shift = (_pconf_shift) } ++ ++void mtmips_pinctrl_reg_set(struct mtmips_pinctrl_priv *priv, ++ u32 reg, u32 shift, u32 mask, u32 value); ++ + int mtmips_get_functions_count(struct udevice *dev); + const char *mtmips_get_function_name(struct udevice *dev, + unsigned int selector); +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0011-usb-xhci-mtk-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0011-usb-xhci-mtk-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..e917166a87 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0011-usb-xhci-mtk-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,28 @@ +From ab59bb14a0efd40c12a967f73bd08ba2f27da3be Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:22:56 +0800 +Subject: [PATCH 11/25] usb: xhci-mtk: add support for MediaTek MT7621 SoC + +This patch makes xhci-mtk driver available for MediaTek MT7621 SoC + +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/usb/host/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 8f77412cc7..8f7bfe1602 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -34,7 +34,7 @@ config USB_XHCI_DWC3_OF_SIMPLE + + config USB_XHCI_MTK + bool "Support for MediaTek on-chip xHCI USB controller" +- depends on ARCH_MEDIATEK ++ depends on ARCH_MEDIATEK || SOC_MT7621 + help + Enables support for the on-chip xHCI controller on MediaTek SoCs. + +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0012-phy-mtk-tphy-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0012-phy-mtk-tphy-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..6d7adbc363 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0012-phy-mtk-tphy-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,28 @@ +From 23c19fa476929b6e94cc7f1a55f5ed4d3ab03934 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:01 +0800 +Subject: [PATCH 12/25] phy: mtk-tphy: add support for MediaTek MT7621 SoC + +This patch makes mtk-tphy driver available for MediaTek MT7621 SoC + +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/phy/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig +index c01d9e09b9..1708d4f533 100644 +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -266,7 +266,7 @@ config MT76X8_USB_PHY + config PHY_MTK_TPHY + bool "MediaTek T-PHY Driver" + depends on PHY +- depends on ARCH_MEDIATEK ++ depends on ARCH_MEDIATEK || SOC_MT7621 + help + MediaTek T-PHY driver supports usb2.0, usb3.0 ports, PCIe and + SATA, and meanwhile supports two version T-PHY which have +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0013-spi-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0013-spi-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..f20fe91c68 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0013-spi-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,28 @@ +From 34b623ccfd135e846b8464729a8b0e8df4b77a66 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:08 +0800 +Subject: [PATCH 13/25] spi: add support for MediaTek MT7621 SoC + +This patch makes mt7621_spi driver available for MediaTek MT7621 SoC + +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/spi/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index a1e515cb2b..2923ed8db3 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -240,7 +240,7 @@ config MT7620_SPI + + config MT7621_SPI + bool "MediaTek MT7621 SPI driver" +- depends on SOC_MT7628 ++ depends on SOC_MT7621 || SOC_MT7628 + help + Enable the MT7621 SPI driver. This driver can be used to access + the SPI NOR flash on platforms embedding this Ralink / MediaTek +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0014-gpio-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0014-gpio-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..c2bff6e8bf --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0014-gpio-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,29 @@ +From f265423a441a3bcb51e25238544adb69f74becc7 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:14 +0800 +Subject: [PATCH 14/25] gpio: add support for MediaTek MT7621 SoC + +This patch makes mt7621_gpio driver available for MediaTek MT7621 SoC + +Reviewed-by: Stefan Roese <sr@denx.de> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/gpio/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index d7f37f0471..8f7e630098 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -553,7 +553,7 @@ config MT7620_GPIO + + config MT7621_GPIO + bool "MediaTek MT7621 GPIO driver" +- depends on DM_GPIO && SOC_MT7628 ++ depends on DM_GPIO && (SOC_MT7621 || SOC_MT7628) + default y + help + Say yes here to support MediaTek MT7621 compatible GPIOs. +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0015-watchdog-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0015-watchdog-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..c24c835ed7 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0015-watchdog-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,29 @@ +From eb1806fbf65c60b2ce462a0ebe39d9f9e652235a Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:19 +0800 +Subject: [PATCH 15/25] watchdog: add support for MediaTek MT7621 SoC + +This patch makes mt7621_wdt driver available for MediaTek MT7621 SoC + +Reviewed-by: Stefan Roese <sr@denx.de> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/watchdog/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index c3eb8a8aec..dfb02aa468 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -191,7 +191,7 @@ config WDT_MT7620 + + config WDT_MT7621 + bool "MediaTek MT7621 watchdog timer support" +- depends on WDT && SOC_MT7628 ++ depends on WDT && (SOC_MT7621 || SOC_MT7628) + help + Select this to enable Ralink / Mediatek watchdog timer, + which can be found on some MediaTek chips. +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0016-mmc-mediatek-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0016-mmc-mediatek-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..c21b625a94 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0016-mmc-mediatek-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,47 @@ +From 4339ec44313e85dd1f6d3d708dd2e594855ce25d Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:26 +0800 +Subject: [PATCH 16/25] mmc: mediatek: add support for MediaTek MT7621 SoC + +This patch adds SDXC support for MediaTek MT7621 SoC + +Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/mmc/mtk-sd.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c +index 97182ffd7f..e61e8cf4b9 100644 +--- a/drivers/mmc/mtk-sd.c ++++ b/drivers/mmc/mtk-sd.c +@@ -1761,6 +1761,18 @@ static const struct msdc_compatible mt7620_compat = { + .default_pad_dly = true, + }; + ++static const struct msdc_compatible mt7621_compat = { ++ .clk_div_bits = 8, ++ .pad_tune0 = false, ++ .async_fifo = true, ++ .data_tune = true, ++ .busy_check = false, ++ .stop_clk_fix = false, ++ .enhance_rx = false, ++ .builtin_pad_ctrl = true, ++ .default_pad_dly = true, ++}; ++ + static const struct msdc_compatible mt7622_compat = { + .clk_div_bits = 12, + .pad_tune0 = true, +@@ -1809,6 +1821,7 @@ static const struct msdc_compatible mt8183_compat = { + + static const struct udevice_id msdc_ids[] = { + { .compatible = "mediatek,mt7620-mmc", .data = (ulong)&mt7620_compat }, ++ { .compatible = "mediatek,mt7621-mmc", .data = (ulong)&mt7621_compat }, + { .compatible = "mediatek,mt7622-mmc", .data = (ulong)&mt7622_compat }, + { .compatible = "mediatek,mt7623-mmc", .data = (ulong)&mt7623_compat }, + { .compatible = "mediatek,mt8512-mmc", .data = (ulong)&mt8512_compat }, +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0017-net-mediatek-remap-iobase-address.patch b/package/boot/uboot-mediatek/patches/001-mtk-0017-net-mediatek-remap-iobase-address.patch new file mode 100644 index 0000000000..72b38492e8 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0017-net-mediatek-remap-iobase-address.patch @@ -0,0 +1,38 @@ +From 391785398f61c85e6b55b1e9edbab94e3ba1b783 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:31 +0800 +Subject: [PATCH 17/25] net: mediatek: remap iobase address + +The iobase address from dts node is actually physical address. It's +identical to the virtual address in ARM platform. This is ok because this +driver was used only by ARM platforms (mt7622/mt7623 ...). + +But now this driver will be used by mt7621 which is a MIPS SoC. For MIPS +platform the physical address space is mapped to KSEG0 and KSEG1 and this +makes the virtual address apparently not idential to its physical address. + +To solve this issue, this patch replaces dev_read_addr with dev_remap_addr +to get the remapped iobase address. + +Reviewed-by: Ramon Fried <rfried.dev@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/net/mtk_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c +index 666ddeb10d..caa83b7cec 100644 +--- a/drivers/net/mtk_eth.c ++++ b/drivers/net/mtk_eth.c +@@ -1419,7 +1419,7 @@ static int mtk_eth_of_to_plat(struct udevice *dev) + + priv->soc = dev_get_driver_data(dev); + +- pdata->iobase = dev_read_addr(dev); ++ pdata->iobase = (phys_addr_t)dev_remap_addr(dev); + + /* get corresponding ethsys phandle */ + ret = dev_read_phandle_with_args(dev, "mediatek,ethsys", NULL, 0, 0, +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0018-net-mediatek-use-regmap-api-to-modify-ethsys-registe.patch b/package/boot/uboot-mediatek/patches/001-mtk-0018-net-mediatek-use-regmap-api-to-modify-ethsys-registe.patch new file mode 100644 index 0000000000..ab5c2a712e --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0018-net-mediatek-use-regmap-api-to-modify-ethsys-registe.patch @@ -0,0 +1,72 @@ +From 955cc76d8074df943d59d559895007f91de8eed5 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:37 +0800 +Subject: [PATCH 18/25] net: mediatek: use regmap api to modify ethsys + registers + +The address returned by regmap_get_range() is not remapped. Directly r/w +to this address is ok for ARM platforms since it's idential to the virtual +address. + +But for MIPS platform only virtual address should be used for access. +To solve this issue, the regmap api regmap_read/regmap_write should be used +since they will remap address before accessing. + +Reviewed-by: Ramon Fried <rfried.dev@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/net/mtk_eth.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c +index caa83b7cec..ac1e8abd71 100644 +--- a/drivers/net/mtk_eth.c ++++ b/drivers/net/mtk_eth.c +@@ -159,9 +159,10 @@ struct mtk_eth_priv { + + void __iomem *fe_base; + void __iomem *gmac_base; +- void __iomem *ethsys_base; + void __iomem *sgmii_base; + ++ struct regmap *ethsys_regmap; ++ + struct mii_dev *mdio_bus; + int (*mii_read)(struct mtk_eth_priv *priv, u8 phy, u8 reg); + int (*mii_write)(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 val); +@@ -233,7 +234,12 @@ static void mtk_gmac_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, u32 set) + static void mtk_ethsys_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, + u32 set) + { +- clrsetbits_le32(priv->ethsys_base + reg, clr, set); ++ uint val; ++ ++ regmap_read(priv->ethsys_regmap, reg, &val); ++ val &= ~clr; ++ val |= set; ++ regmap_write(priv->ethsys_regmap, reg, val); + } + + /* Direct MDIO clause 22/45 access via SoC */ +@@ -1427,15 +1433,9 @@ static int mtk_eth_of_to_plat(struct udevice *dev) + if (ret) + return ret; + +- regmap = syscon_node_to_regmap(args.node); +- if (IS_ERR(regmap)) +- return PTR_ERR(regmap); +- +- priv->ethsys_base = regmap_get_range(regmap, 0); +- if (!priv->ethsys_base) { +- dev_err(dev, "Unable to find ethsys\n"); +- return -ENODEV; +- } ++ priv->ethsys_regmap = syscon_node_to_regmap(args.node); ++ if (IS_ERR(priv->ethsys_regmap)) ++ return PTR_ERR(priv->ethsys_regmap); + + /* Reset controllers */ + ret = reset_get_by_name(dev, "fe", &priv->rst_fe); +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0019-net-mediatek-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0019-net-mediatek-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..ce087fe3ac --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0019-net-mediatek-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,72 @@ +From 7237a6a0c020c05bb819774391154b40b2cfaabd Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:42 +0800 +Subject: [PATCH 19/25] net: mediatek: add support for MediaTek MT7621 SoC + +This patch adds GMAC support for MediaTek MT7621 SoC. +MT7621 has the same GMAC/Switch configuration as MT7623. + +Reviewed-by: Ramon Fried <rfried.dev@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/net/mtk_eth.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c +index ac1e8abd71..4fe7ee0d36 100644 +--- a/drivers/net/mtk_eth.c ++++ b/drivers/net/mtk_eth.c +@@ -145,7 +145,8 @@ enum mtk_switch { + enum mtk_soc { + SOC_MT7623, + SOC_MT7629, +- SOC_MT7622 ++ SOC_MT7622, ++ SOC_MT7621 + }; + + struct mtk_eth_priv { +@@ -675,12 +676,18 @@ static int mt7530_pad_clk_setup(struct mtk_eth_priv *priv, int mode) + static int mt7530_setup(struct mtk_eth_priv *priv) + { + u16 phy_addr, phy_val; +- u32 val; ++ u32 val, txdrv; + int i; + +- /* Select 250MHz clk for RGMII mode */ +- mtk_ethsys_rmw(priv, ETHSYS_CLKCFG0_REG, +- ETHSYS_TRGMII_CLK_SEL362_5, 0); ++ if (priv->soc != SOC_MT7621) { ++ /* Select 250MHz clk for RGMII mode */ ++ mtk_ethsys_rmw(priv, ETHSYS_CLKCFG0_REG, ++ ETHSYS_TRGMII_CLK_SEL362_5, 0); ++ ++ txdrv = 8; ++ } else { ++ txdrv = 4; ++ } + + /* Modify HWTRAP first to allow direct access to internal PHYs */ + mt753x_reg_read(priv, HWTRAP_REG, &val); +@@ -738,7 +745,8 @@ static int mt7530_setup(struct mtk_eth_priv *priv) + /* Lower Tx Driving for TRGMII path */ + for (i = 0 ; i < NUM_TRGMII_CTRL ; i++) + mt753x_reg_write(priv, MT7530_TRGMII_TD_ODT(i), +- (8 << TD_DM_DRVP_S) | (8 << TD_DM_DRVN_S)); ++ (txdrv << TD_DM_DRVP_S) | ++ (txdrv << TD_DM_DRVN_S)); + + for (i = 0 ; i < NUM_TRGMII_CTRL; i++) + mt753x_reg_rmw(priv, MT7530_TRGMII_RD(i), RD_TAP_M, 16); +@@ -1540,6 +1548,7 @@ static const struct udevice_id mtk_eth_ids[] = { + { .compatible = "mediatek,mt7629-eth", .data = SOC_MT7629 }, + { .compatible = "mediatek,mt7623-eth", .data = SOC_MT7623 }, + { .compatible = "mediatek,mt7622-eth", .data = SOC_MT7622 }, ++ { .compatible = "mediatek,mt7621-eth", .data = SOC_MT7621 }, + {} + }; + +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0020-nand-raw-add-support-for-MediaTek-MT7621-SoC.patch b/package/boot/uboot-mediatek/patches/001-mtk-0020-nand-raw-add-support-for-MediaTek-MT7621-SoC.patch new file mode 100644 index 0000000000..16444680e4 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0020-nand-raw-add-support-for-MediaTek-MT7621-SoC.patch @@ -0,0 +1,1572 @@ +From 8d94833f13ccd7e1dfea605cfdf9a8eb53505515 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:47 +0800 +Subject: [PATCH 20/25] nand: raw: add support for MediaTek MT7621 SoC + +This patch adds NAND flash controller driver for MediaTek MT7621 SoC. +The NAND flash controller of MT7621 supports only SLC NAND flashes. +It supports 4~12 bits correction with maximum 4KB page size. + +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + drivers/mtd/nand/raw/Kconfig | 17 +- + drivers/mtd/nand/raw/Makefile | 2 + + drivers/mtd/nand/raw/mt7621_nand.c | 1205 ++++++++++++++++++++++++ + drivers/mtd/nand/raw/mt7621_nand.h | 29 + + drivers/mtd/nand/raw/mt7621_nand_spl.c | 237 +++++ + 5 files changed, 1488 insertions(+), 2 deletions(-) + create mode 100644 drivers/mtd/nand/raw/mt7621_nand.c + create mode 100644 drivers/mtd/nand/raw/mt7621_nand.h + create mode 100644 drivers/mtd/nand/raw/mt7621_nand_spl.c + +diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig +index d75f371c95..1663f1941c 100644 +--- a/drivers/mtd/nand/raw/Kconfig ++++ b/drivers/mtd/nand/raw/Kconfig +@@ -521,12 +521,25 @@ config TEGRA_NAND + help + Enables support for NAND Flash chips on Tegra SoCs platforms. + ++config NAND_MT7621 ++ bool "Support for MediaTek MT7621 NAND flash controller" ++ depends on SOC_MT7621 ++ select SYS_NAND_SELF_INIT ++ select SPL_SYS_NAND_SELF_INIT ++ imply CMD_NAND ++ help ++ This enables NAND driver for the NAND flash controller on MediaTek ++ MT7621 platform. ++ The controller supports 4~12 bits correction per 512 bytes with a ++ maximum 4KB page size. ++ + comment "Generic NAND options" + + config SYS_NAND_BLOCK_SIZE + hex "NAND chip eraseblock size" + depends on ARCH_SUNXI || SPL_NAND_SUPPORT || TPL_NAND_SUPPORT +- depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_FSL_IFC ++ depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && \ ++ !NAND_FSL_IFC && !NAND_MT7621 + help + Number of data bytes in one eraseblock for the NAND chip on the + board. This is the multiple of NAND_PAGE_SIZE and the number of +@@ -551,7 +564,7 @@ config SYS_NAND_PAGE_SIZE + depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \ + SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \ + (NAND_ATMEL && SPL_NAND_SUPPORT) || SPL_GENERATE_ATMEL_PMECC_HEADER +- depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC ++ depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_MT7621 + help + Number of data bytes in one page for the NAND chip on the + board, not including the OOB area. +diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile +index 6ec3581d20..cfc9c0fff0 100644 +--- a/drivers/mtd/nand/raw/Makefile ++++ b/drivers/mtd/nand/raw/Makefile +@@ -72,6 +72,7 @@ obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o + obj-$(CONFIG_NAND_STM32_FMC2) += stm32_fmc2_nand.o + obj-$(CONFIG_CORTINA_NAND) += cortina_nand.o + obj-$(CONFIG_ROCKCHIP_NAND) += rockchip_nfc.o ++obj-$(CONFIG_NAND_MT7621) += mt7621_nand.o + + else # minimal SPL drivers + +@@ -80,5 +81,6 @@ obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_spl.o + obj-$(CONFIG_NAND_MXC) += mxc_nand_spl.o + obj-$(CONFIG_NAND_MXS) += mxs_nand_spl.o mxs_nand.o + obj-$(CONFIG_NAND_SUNXI) += sunxi_nand_spl.o ++obj-$(CONFIG_NAND_MT7621) += mt7621_nand_spl.o mt7621_nand.o + + endif # drivers +diff --git a/drivers/mtd/nand/raw/mt7621_nand.c b/drivers/mtd/nand/raw/mt7621_nand.c +new file mode 100644 +index 0000000000..2fd8934939 +--- /dev/null ++++ b/drivers/mtd/nand/raw/mt7621_nand.c +@@ -0,0 +1,1205 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <log.h> ++#include <nand.h> ++#include <malloc.h> ++#include <asm/addrspace.h> ++#include <linux/io.h> ++#include <linux/iopoll.h> ++#include <linux/sizes.h> ++#include <linux/bitops.h> ++#include <linux/bitfield.h> ++#include "mt7621_nand.h" ++ ++/* NFI core registers */ ++#define NFI_CNFG 0x000 ++#define CNFG_OP_MODE GENMASK(14, 12) ++#define CNFG_OP_CUSTOM 6 ++#define CNFG_AUTO_FMT_EN BIT(9) ++#define CNFG_HW_ECC_EN BIT(8) ++#define CNFG_BYTE_RW BIT(6) ++#define CNFG_READ_MODE BIT(1) ++ ++#define NFI_PAGEFMT 0x004 ++#define PAGEFMT_FDM_ECC GENMASK(15, 12) ++#define PAGEFMT_FDM GENMASK(11, 8) ++#define PAGEFMT_SPARE GENMASK(5, 4) ++#define PAGEFMT_PAGE GENMASK(1, 0) ++ ++#define NFI_CON 0x008 ++#define CON_NFI_SEC GENMASK(15, 12) ++#define CON_NFI_BWR BIT(9) ++#define CON_NFI_BRD BIT(8) ++#define CON_NFI_RST BIT(1) ++#define CON_FIFO_FLUSH BIT(0) ++ ++#define NFI_ACCCON 0x00c ++#define ACCCON_POECS GENMASK(31, 28) ++#define ACCCON_POECS_DEF 3 ++#define ACCCON_PRECS GENMASK(27, 22) ++#define ACCCON_PRECS_DEF 3 ++#define ACCCON_C2R GENMASK(21, 16) ++#define ACCCON_C2R_DEF 7 ++#define ACCCON_W2R GENMASK(15, 12) ++#define ACCCON_W2R_DEF 7 ++#define ACCCON_WH GENMASK(11, 8) ++#define ACCCON_WH_DEF 15 ++#define ACCCON_WST GENMASK(7, 4) ++#define ACCCON_WST_DEF 15 ++#define ACCCON_WST_MIN 3 ++#define ACCCON_RLT GENMASK(3, 0) ++#define ACCCON_RLT_DEF 15 ++#define ACCCON_RLT_MIN 3 ++ ++#define NFI_CMD 0x020 ++ ++#define NFI_ADDRNOB 0x030 ++#define ADDR_ROW_NOB GENMASK(6, 4) ++#define ADDR_COL_NOB GENMASK(2, 0) ++ ++#define NFI_COLADDR 0x034 ++#define NFI_ROWADDR 0x038 ++ ++#define NFI_STRDATA 0x040 ++#define STR_DATA BIT(0) ++ ++#define NFI_CNRNB 0x044 ++#define CB2R_TIME GENMASK(7, 4) ++#define STR_CNRNB BIT(0) ++ ++#define NFI_DATAW 0x050 ++#define NFI_DATAR 0x054 ++ ++#define NFI_PIO_DIRDY 0x058 ++#define PIO_DIRDY BIT(0) ++ ++#define NFI_STA 0x060 ++#define STA_NFI_FSM GENMASK(19, 16) ++#define STA_FSM_CUSTOM_DATA 14 ++#define STA_BUSY BIT(8) ++#define STA_ADDR BIT(1) ++#define STA_CMD BIT(0) ++ ++#define NFI_ADDRCNTR 0x070 ++#define SEC_CNTR GENMASK(15, 12) ++#define SEC_ADDR GENMASK(9, 0) ++ ++#define NFI_CSEL 0x090 ++#define CSEL GENMASK(1, 0) ++ ++#define NFI_FDM0L 0x0a0 ++#define NFI_FDML(n) (0x0a0 + ((n) << 3)) ++ ++#define NFI_FDM0M 0x0a4 ++#define NFI_FDMM(n) (0x0a4 + ((n) << 3)) ++ ++#define NFI_MASTER_STA 0x210 ++#define MAS_ADDR GENMASK(11, 9) ++#define MAS_RD GENMASK(8, 6) ++#define MAS_WR GENMASK(5, 3) ++#define MAS_RDDLY GENMASK(2, 0) ++ ++/* ECC engine registers */ ++#define ECC_ENCCON 0x000 ++#define ENC_EN BIT(0) ++ ++#define ECC_ENCCNFG 0x004 ++#define ENC_CNFG_MSG GENMASK(28, 16) ++#define ENC_MODE GENMASK(5, 4) ++#define ENC_MODE_NFI 1 ++#define ENC_TNUM GENMASK(2, 0) ++ ++#define ECC_ENCIDLE 0x00c ++#define ENC_IDLE BIT(0) ++ ++#define ECC_DECCON 0x100 ++#define DEC_EN BIT(0) ++ ++#define ECC_DECCNFG 0x104 ++#define DEC_EMPTY_EN BIT(31) ++#define DEC_CS GENMASK(28, 16) ++#define DEC_CON GENMASK(13, 12) ++#define DEC_CON_EL 2 ++#define DEC_MODE GENMASK(5, 4) ++#define DEC_MODE_NFI 1 ++#define DEC_TNUM GENMASK(2, 0) ++ ++#define ECC_DECIDLE 0x10c ++#define DEC_IDLE BIT(1) ++ ++#define ECC_DECENUM 0x114 ++#define ERRNUM_S 2 ++#define ERRNUM_M GENMASK(3, 0) ++ ++#define ECC_DECDONE 0x118 ++#define DEC_DONE7 BIT(7) ++#define DEC_DONE6 BIT(6) ++#define DEC_DONE5 BIT(5) ++#define DEC_DONE4 BIT(4) ++#define DEC_DONE3 BIT(3) ++#define DEC_DONE2 BIT(2) ++#define DEC_DONE1 BIT(1) ++#define DEC_DONE0 BIT(0) ++ ++#define ECC_DECEL(n) (0x11c + (n) * 4) ++#define DEC_EL_ODD_S 16 ++#define DEC_EL_M 0x1fff ++#define DEC_EL_BYTE_POS_S 3 ++#define DEC_EL_BIT_POS_M GENMASK(2, 0) ++ ++#define ECC_FDMADDR 0x13c ++ ++/* ENCIDLE and DECIDLE */ ++#define ECC_IDLE BIT(0) ++ ++#define ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt) \ ++ (FIELD_PREP(ACCCON_POECS, tpoecs) | \ ++ FIELD_PREP(ACCCON_PRECS, tprecs) | \ ++ FIELD_PREP(ACCCON_C2R, tc2r) | \ ++ FIELD_PREP(ACCCON_W2R, tw2r) | \ ++ FIELD_PREP(ACCCON_WH, twh) | \ ++ FIELD_PREP(ACCCON_WST, twst) | \ ++ FIELD_PREP(ACCCON_RLT, trlt)) ++ ++#define MASTER_STA_MASK (MAS_ADDR | MAS_RD | MAS_WR | \ ++ MAS_RDDLY) ++#define NFI_RESET_TIMEOUT 1000000 ++#define NFI_CORE_TIMEOUT 500000 ++#define ECC_ENGINE_TIMEOUT 500000 ++ ++#define ECC_SECTOR_SIZE 512 ++#define ECC_PARITY_BITS 13 ++ ++#define NFI_FDM_SIZE 8 ++ ++/* Register base */ ++#define NFI_BASE 0x1e003000 ++#define NFI_ECC_BASE 0x1e003800 ++ ++static struct mt7621_nfc nfc_dev; ++ ++static const u16 mt7621_nfi_page_size[] = { SZ_512, SZ_2K, SZ_4K }; ++static const u8 mt7621_nfi_spare_size[] = { 16, 26, 27, 28 }; ++static const u8 mt7621_ecc_strength[] = { 4, 6, 8, 10, 12 }; ++ ++static inline u32 nfi_read32(struct mt7621_nfc *nfc, u32 reg) ++{ ++ return readl(nfc->nfi_regs + reg); ++} ++ ++static inline void nfi_write32(struct mt7621_nfc *nfc, u32 reg, u32 val) ++{ ++ writel(val, nfc->nfi_regs + reg); ++} ++ ++static inline u16 nfi_read16(struct mt7621_nfc *nfc, u32 reg) ++{ ++ return readw(nfc->nfi_regs + reg); ++} ++ ++static inline void nfi_write16(struct mt7621_nfc *nfc, u32 reg, u16 val) ++{ ++ writew(val, nfc->nfi_regs + reg); ++} ++ ++static inline void ecc_write16(struct mt7621_nfc *nfc, u32 reg, u16 val) ++{ ++ writew(val, nfc->ecc_regs + reg); ++} ++ ++static inline u32 ecc_read32(struct mt7621_nfc *nfc, u32 reg) ++{ ++ return readl(nfc->ecc_regs + reg); ++} ++ ++static inline void ecc_write32(struct mt7621_nfc *nfc, u32 reg, u32 val) ++{ ++ return writel(val, nfc->ecc_regs + reg); ++} ++ ++static inline u8 *oob_fdm_ptr(struct nand_chip *nand, int sect) ++{ ++ return nand->oob_poi + sect * NFI_FDM_SIZE; ++} ++ ++static inline u8 *oob_ecc_ptr(struct mt7621_nfc *nfc, int sect) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ ++ return nand->oob_poi + nand->ecc.steps * NFI_FDM_SIZE + ++ sect * (nfc->spare_per_sector - NFI_FDM_SIZE); ++} ++ ++static inline u8 *page_data_ptr(struct nand_chip *nand, const u8 *buf, ++ int sect) ++{ ++ return (u8 *)buf + sect * nand->ecc.size; ++} ++ ++static int mt7621_ecc_wait_idle(struct mt7621_nfc *nfc, u32 reg) ++{ ++ u32 val; ++ int ret; ++ ++ ret = readw_poll_timeout(nfc->ecc_regs + reg, val, val & ECC_IDLE, ++ ECC_ENGINE_TIMEOUT); ++ if (ret) { ++ pr_warn("ECC engine timed out entering idle mode\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int mt7621_ecc_decoder_wait_done(struct mt7621_nfc *nfc, u32 sect) ++{ ++ u32 val; ++ int ret; ++ ++ ret = readw_poll_timeout(nfc->ecc_regs + ECC_DECDONE, val, ++ val & (1 << sect), ECC_ENGINE_TIMEOUT); ++ if (ret) { ++ pr_warn("ECC decoder for sector %d timed out\n", sect); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static void mt7621_ecc_encoder_op(struct mt7621_nfc *nfc, bool enable) ++{ ++ mt7621_ecc_wait_idle(nfc, ECC_ENCIDLE); ++ ecc_write16(nfc, ECC_ENCCON, enable ? ENC_EN : 0); ++} ++ ++static void mt7621_ecc_decoder_op(struct mt7621_nfc *nfc, bool enable) ++{ ++ mt7621_ecc_wait_idle(nfc, ECC_DECIDLE); ++ ecc_write16(nfc, ECC_DECCON, enable ? DEC_EN : 0); ++} ++ ++static int mt7621_ecc_correct_check(struct mt7621_nfc *nfc, u8 *sector_buf, ++ u8 *fdm_buf, u32 sect) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ u32 decnum, num_error_bits, fdm_end_bits; ++ u32 error_locations, error_bit_loc; ++ u32 error_byte_pos, error_bit_pos; ++ int bitflips = 0; ++ u32 i; ++ ++ decnum = ecc_read32(nfc, ECC_DECENUM); ++ num_error_bits = (decnum >> (sect << ERRNUM_S)) & ERRNUM_M; ++ fdm_end_bits = (nand->ecc.size + NFI_FDM_SIZE) << 3; ++ ++ if (!num_error_bits) ++ return 0; ++ ++ if (num_error_bits == ERRNUM_M) ++ return -1; ++ ++ for (i = 0; i < num_error_bits; i++) { ++ error_locations = ecc_read32(nfc, ECC_DECEL(i / 2)); ++ error_bit_loc = (error_locations >> ((i % 2) * DEC_EL_ODD_S)) & ++ DEC_EL_M; ++ error_byte_pos = error_bit_loc >> DEC_EL_BYTE_POS_S; ++ error_bit_pos = error_bit_loc & DEC_EL_BIT_POS_M; ++ ++ if (error_bit_loc < (nand->ecc.size << 3)) { ++ if (sector_buf) { ++ sector_buf[error_byte_pos] ^= ++ (1 << error_bit_pos); ++ } ++ } else if (error_bit_loc < fdm_end_bits) { ++ if (fdm_buf) { ++ fdm_buf[error_byte_pos - nand->ecc.size] ^= ++ (1 << error_bit_pos); ++ } ++ } ++ ++ bitflips++; ++ } ++ ++ return bitflips; ++} ++ ++static int mt7621_nfc_wait_write_completion(struct mt7621_nfc *nfc, ++ struct nand_chip *nand) ++{ ++ u16 val; ++ int ret; ++ ++ ret = readw_poll_timeout(nfc->nfi_regs + NFI_ADDRCNTR, val, ++ FIELD_GET(SEC_CNTR, val) >= nand->ecc.steps, ++ NFI_CORE_TIMEOUT); ++ ++ if (ret) { ++ pr_warn("NFI core write operation timed out\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return ret; ++} ++ ++static void mt7621_nfc_hw_reset(struct mt7621_nfc *nfc) ++{ ++ u32 val; ++ int ret; ++ ++ /* reset all registers and force the NFI master to terminate */ ++ nfi_write16(nfc, NFI_CON, CON_FIFO_FLUSH | CON_NFI_RST); ++ ++ /* wait for the master to finish the last transaction */ ++ ret = readw_poll_timeout(nfc->nfi_regs + NFI_MASTER_STA, val, ++ !(val & MASTER_STA_MASK), NFI_RESET_TIMEOUT); ++ if (ret) { ++ pr_warn("Failed to reset NFI master in %dms\n", ++ NFI_RESET_TIMEOUT); ++ } ++ ++ /* ensure any status register affected by the NFI master is reset */ ++ nfi_write16(nfc, NFI_CON, CON_FIFO_FLUSH | CON_NFI_RST); ++ nfi_write16(nfc, NFI_STRDATA, 0); ++} ++ ++static inline void mt7621_nfc_hw_init(struct mt7621_nfc *nfc) ++{ ++ u32 acccon; ++ ++ /* ++ * CNRNB: nand ready/busy register ++ * ------------------------------- ++ * 7:4: timeout register for polling the NAND busy/ready signal ++ * 0 : poll the status of the busy/ready signal after [7:4]*16 cycles. ++ */ ++ nfi_write16(nfc, NFI_CNRNB, CB2R_TIME | STR_CNRNB); ++ ++ mt7621_nfc_hw_reset(nfc); ++ ++ /* Apply default access timing */ ++ acccon = ACCTIMING(ACCCON_POECS_DEF, ACCCON_PRECS_DEF, ACCCON_C2R_DEF, ++ ACCCON_W2R_DEF, ACCCON_WH_DEF, ACCCON_WST_DEF, ++ ACCCON_RLT_DEF); ++ ++ nfi_write32(nfc, NFI_ACCCON, acccon); ++} ++ ++static int mt7621_nfc_send_command(struct mt7621_nfc *nfc, u8 command) ++{ ++ u32 val; ++ int ret; ++ ++ nfi_write32(nfc, NFI_CMD, command); ++ ++ ret = readl_poll_timeout(nfc->nfi_regs + NFI_STA, val, !(val & STA_CMD), ++ NFI_CORE_TIMEOUT); ++ if (ret) { ++ pr_warn("NFI core timed out entering command mode\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int mt7621_nfc_send_address_byte(struct mt7621_nfc *nfc, int addr) ++{ ++ u32 val; ++ int ret; ++ ++ nfi_write32(nfc, NFI_COLADDR, addr); ++ nfi_write32(nfc, NFI_ROWADDR, 0); ++ nfi_write16(nfc, NFI_ADDRNOB, 1); ++ ++ ret = readl_poll_timeout(nfc->nfi_regs + NFI_STA, val, ++ !(val & STA_ADDR), NFI_CORE_TIMEOUT); ++ if (ret) { ++ pr_warn("NFI core timed out entering address mode\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void mt7621_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, ++ unsigned int ctrl) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); ++ ++ if (ctrl & NAND_ALE) { ++ mt7621_nfc_send_address_byte(nfc, dat & 0xff); ++ } else if (ctrl & NAND_CLE) { ++ mt7621_nfc_hw_reset(nfc); ++ nfi_write16(nfc, NFI_CNFG, ++ FIELD_PREP(CNFG_OP_MODE, CNFG_OP_CUSTOM)); ++ mt7621_nfc_send_command(nfc, dat); ++ } ++} ++ ++static int mt7621_nfc_dev_ready(struct mtd_info *mtd) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); ++ ++ if (nfi_read32(nfc, NFI_STA) & STA_BUSY) ++ return 0; ++ ++ return 1; ++} ++ ++static void mt7621_nfc_select_chip(struct mtd_info *mtd, int chipnr) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); ++ ++ nfi_write16(nfc, NFI_CSEL, 0); ++} ++ ++static void mt7621_nfc_wait_pio_ready(struct mt7621_nfc *nfc) ++{ ++ int ret; ++ u16 val; ++ ++ ret = readw_poll_timeout(nfc->nfi_regs + NFI_PIO_DIRDY, val, ++ val & PIO_DIRDY, NFI_CORE_TIMEOUT); ++ if (ret < 0) ++ pr_err("NFI core PIO mode not ready\n"); ++} ++ ++static u32 mt7621_nfc_pio_read(struct mt7621_nfc *nfc, bool br) ++{ ++ u32 reg, fsm; ++ ++ /* after each byte read, the NFI_STA reg is reset by the hardware */ ++ reg = nfi_read32(nfc, NFI_STA); ++ fsm = FIELD_GET(STA_NFI_FSM, reg); ++ ++ if (fsm != STA_FSM_CUSTOM_DATA) { ++ reg = nfi_read16(nfc, NFI_CNFG); ++ reg |= CNFG_READ_MODE | CNFG_BYTE_RW; ++ if (!br) ++ reg &= ~CNFG_BYTE_RW; ++ nfi_write16(nfc, NFI_CNFG, reg); ++ ++ /* ++ * set to max sector to allow the HW to continue reading over ++ * unaligned accesses ++ */ ++ nfi_write16(nfc, NFI_CON, CON_NFI_SEC | CON_NFI_BRD); ++ ++ /* trigger to fetch data */ ++ nfi_write16(nfc, NFI_STRDATA, STR_DATA); ++ } ++ ++ mt7621_nfc_wait_pio_ready(nfc); ++ ++ return nfi_read32(nfc, NFI_DATAR); ++} ++ ++static void mt7621_nfc_read_data(struct mt7621_nfc *nfc, u8 *buf, u32 len) ++{ ++ while (((uintptr_t)buf & 3) && len) { ++ *buf = mt7621_nfc_pio_read(nfc, true); ++ buf++; ++ len--; ++ } ++ ++ while (len >= 4) { ++ *(u32 *)buf = mt7621_nfc_pio_read(nfc, false); ++ buf += 4; ++ len -= 4; ++ } ++ ++ while (len) { ++ *buf = mt7621_nfc_pio_read(nfc, true); ++ buf++; ++ len--; ++ } ++} ++ ++static void mt7621_nfc_read_data_discard(struct mt7621_nfc *nfc, u32 len) ++{ ++ while (len >= 4) { ++ mt7621_nfc_pio_read(nfc, false); ++ len -= 4; ++ } ++ ++ while (len) { ++ mt7621_nfc_pio_read(nfc, true); ++ len--; ++ } ++} ++ ++static void mt7621_nfc_pio_write(struct mt7621_nfc *nfc, u32 val, bool bw) ++{ ++ u32 reg, fsm; ++ ++ reg = nfi_read32(nfc, NFI_STA); ++ fsm = FIELD_GET(STA_NFI_FSM, reg); ++ ++ if (fsm != STA_FSM_CUSTOM_DATA) { ++ reg = nfi_read16(nfc, NFI_CNFG); ++ reg &= ~(CNFG_READ_MODE | CNFG_BYTE_RW); ++ if (bw) ++ reg |= CNFG_BYTE_RW; ++ nfi_write16(nfc, NFI_CNFG, reg); ++ ++ nfi_write16(nfc, NFI_CON, CON_NFI_SEC | CON_NFI_BWR); ++ nfi_write16(nfc, NFI_STRDATA, STR_DATA); ++ } ++ ++ mt7621_nfc_wait_pio_ready(nfc); ++ nfi_write32(nfc, NFI_DATAW, val); ++} ++ ++static void mt7621_nfc_write_data(struct mt7621_nfc *nfc, const u8 *buf, ++ u32 len) ++{ ++ while (((uintptr_t)buf & 3) && len) { ++ mt7621_nfc_pio_write(nfc, *buf, true); ++ buf++; ++ len--; ++ } ++ ++ while (len >= 4) { ++ mt7621_nfc_pio_write(nfc, *(const u32 *)buf, false); ++ buf += 4; ++ len -= 4; ++ } ++ ++ while (len) { ++ mt7621_nfc_pio_write(nfc, *buf, true); ++ buf++; ++ len--; ++ } ++} ++ ++static void mt7621_nfc_write_data_empty(struct mt7621_nfc *nfc, u32 len) ++{ ++ while (len >= 4) { ++ mt7621_nfc_pio_write(nfc, 0xffffffff, false); ++ len -= 4; ++ } ++ ++ while (len) { ++ mt7621_nfc_pio_write(nfc, 0xff, true); ++ len--; ++ } ++} ++ ++static void mt7621_nfc_write_byte(struct mtd_info *mtd, u8 byte) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); ++ ++ mt7621_nfc_pio_write(nfc, byte, true); ++} ++ ++static void mt7621_nfc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); ++ ++ return mt7621_nfc_write_data(nfc, buf, len); ++} ++ ++static u8 mt7621_nfc_read_byte(struct mtd_info *mtd) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); ++ ++ return mt7621_nfc_pio_read(nfc, true); ++} ++ ++static void mt7621_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int len) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); ++ ++ mt7621_nfc_read_data(nfc, buf, len); ++} ++ ++static int mt7621_nfc_calc_ecc_strength(struct mt7621_nfc *nfc, ++ u32 avail_ecc_bytes) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ u32 strength; ++ int i; ++ ++ strength = avail_ecc_bytes * 8 / ECC_PARITY_BITS; ++ ++ /* Find the closest supported ecc strength */ ++ for (i = ARRAY_SIZE(mt7621_ecc_strength) - 1; i >= 0; i--) { ++ if (mt7621_ecc_strength[i] <= strength) ++ break; ++ } ++ ++ if (unlikely(i < 0)) { ++ pr_err("OOB size (%u) is not supported\n", mtd->oobsize); ++ return -EINVAL; ++ } ++ ++ nand->ecc.strength = mt7621_ecc_strength[i]; ++ nand->ecc.bytes = DIV_ROUND_UP(nand->ecc.strength * ECC_PARITY_BITS, 8); ++ ++ pr_debug("ECC strength adjusted to %u bits\n", nand->ecc.strength); ++ ++ return i; ++} ++ ++static int mt7621_nfc_set_spare_per_sector(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ u32 size; ++ int i; ++ ++ size = nand->ecc.bytes + NFI_FDM_SIZE; ++ ++ /* Find the closest supported spare size */ ++ for (i = 0; i < ARRAY_SIZE(mt7621_nfi_spare_size); i++) { ++ if (mt7621_nfi_spare_size[i] >= size) ++ break; ++ } ++ ++ if (unlikely(i >= ARRAY_SIZE(mt7621_nfi_spare_size))) { ++ pr_err("OOB size (%u) is not supported\n", mtd->oobsize); ++ return -EINVAL; ++ } ++ ++ nfc->spare_per_sector = mt7621_nfi_spare_size[i]; ++ ++ return i; ++} ++ ++static int mt7621_nfc_ecc_init(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ u32 avail_ecc_bytes, encode_block_size, decode_block_size; ++ u32 ecc_enccfg, ecc_deccfg; ++ int ecc_cap; ++ ++ nand->ecc.options |= NAND_ECC_CUSTOM_PAGE_ACCESS; ++ ++ nand->ecc.size = ECC_SECTOR_SIZE; ++ nand->ecc.steps = mtd->writesize / nand->ecc.size; ++ ++ avail_ecc_bytes = mtd->oobsize / nand->ecc.steps - NFI_FDM_SIZE; ++ ++ ecc_cap = mt7621_nfc_calc_ecc_strength(nfc, avail_ecc_bytes); ++ if (ecc_cap < 0) ++ return ecc_cap; ++ ++ /* Sector + FDM */ ++ encode_block_size = (nand->ecc.size + NFI_FDM_SIZE) * 8; ++ ecc_enccfg = ecc_cap | FIELD_PREP(ENC_MODE, ENC_MODE_NFI) | ++ FIELD_PREP(ENC_CNFG_MSG, encode_block_size); ++ ++ /* Sector + FDM + ECC parity bits */ ++ decode_block_size = ((nand->ecc.size + NFI_FDM_SIZE) * 8) + ++ nand->ecc.strength * ECC_PARITY_BITS; ++ ecc_deccfg = ecc_cap | FIELD_PREP(DEC_MODE, DEC_MODE_NFI) | ++ FIELD_PREP(DEC_CS, decode_block_size) | ++ FIELD_PREP(DEC_CON, DEC_CON_EL) | DEC_EMPTY_EN; ++ ++ mt7621_ecc_encoder_op(nfc, false); ++ ecc_write32(nfc, ECC_ENCCNFG, ecc_enccfg); ++ ++ mt7621_ecc_decoder_op(nfc, false); ++ ecc_write32(nfc, ECC_DECCNFG, ecc_deccfg); ++ ++ return 0; ++} ++ ++static int mt7621_nfc_set_page_format(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ int i, spare_size; ++ u32 pagefmt; ++ ++ spare_size = mt7621_nfc_set_spare_per_sector(nfc); ++ if (spare_size < 0) ++ return spare_size; ++ ++ for (i = 0; i < ARRAY_SIZE(mt7621_nfi_page_size); i++) { ++ if (mt7621_nfi_page_size[i] == mtd->writesize) ++ break; ++ } ++ ++ if (unlikely(i >= ARRAY_SIZE(mt7621_nfi_page_size))) { ++ pr_err("Page size (%u) is not supported\n", mtd->writesize); ++ return -EINVAL; ++ } ++ ++ pagefmt = FIELD_PREP(PAGEFMT_PAGE, i) | ++ FIELD_PREP(PAGEFMT_SPARE, spare_size) | ++ FIELD_PREP(PAGEFMT_FDM, NFI_FDM_SIZE) | ++ FIELD_PREP(PAGEFMT_FDM_ECC, NFI_FDM_SIZE); ++ ++ nfi_write16(nfc, NFI_PAGEFMT, pagefmt); ++ ++ return 0; ++} ++ ++static int mt7621_nfc_attach_chip(struct nand_chip *nand) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int ret; ++ ++ if (nand->options & NAND_BUSWIDTH_16) { ++ pr_err("16-bit buswidth is not supported"); ++ return -EINVAL; ++ } ++ ++ ret = mt7621_nfc_ecc_init(nfc); ++ if (ret) ++ return ret; ++ ++ return mt7621_nfc_set_page_format(nfc); ++} ++ ++static void mt7621_nfc_write_fdm(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ u32 vall, valm; ++ u8 *oobptr; ++ int i, j; ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ vall = 0; ++ valm = 0; ++ oobptr = oob_fdm_ptr(nand, i); ++ ++ for (j = 0; j < 4; j++) ++ vall |= (u32)oobptr[j] << (j * 8); ++ ++ for (j = 0; j < 4; j++) ++ valm |= (u32)oobptr[j + 4] << (j * 8); ++ ++ nfi_write32(nfc, NFI_FDML(i), vall); ++ nfi_write32(nfc, NFI_FDMM(i), valm); ++ } ++} ++ ++static void mt7621_nfc_read_sector_fdm(struct mt7621_nfc *nfc, u32 sect) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ u32 vall, valm; ++ u8 *oobptr; ++ int i; ++ ++ vall = nfi_read32(nfc, NFI_FDML(sect)); ++ valm = nfi_read32(nfc, NFI_FDMM(sect)); ++ oobptr = oob_fdm_ptr(nand, sect); ++ ++ for (i = 0; i < 4; i++) ++ oobptr[i] = (vall >> (i * 8)) & 0xff; ++ ++ for (i = 0; i < 4; i++) ++ oobptr[i + 4] = (valm >> (i * 8)) & 0xff; ++} ++ ++static int mt7621_nfc_read_page_hwecc(struct mtd_info *mtd, ++ struct nand_chip *nand, uint8_t *buf, ++ int oob_required, int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int bitflips = 0, ret = 0; ++ int rc, i; ++ ++ nand_read_page_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, FIELD_PREP(CNFG_OP_MODE, CNFG_OP_CUSTOM) | ++ CNFG_READ_MODE | CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN); ++ ++ mt7621_ecc_decoder_op(nfc, true); ++ ++ nfi_write16(nfc, NFI_CON, FIELD_PREP(CON_NFI_SEC, nand->ecc.steps) | ++ CON_NFI_BRD); ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ if (buf) ++ mt7621_nfc_read_data(nfc, page_data_ptr(nand, buf, i), ++ nand->ecc.size); ++ else ++ mt7621_nfc_read_data_discard(nfc, nand->ecc.size); ++ ++ rc = mt7621_ecc_decoder_wait_done(nfc, i); ++ ++ mt7621_nfc_read_sector_fdm(nfc, i); ++ ++ if (rc < 0) { ++ ret = -EIO; ++ continue; ++ } ++ ++ rc = mt7621_ecc_correct_check(nfc, ++ buf ? page_data_ptr(nand, buf, i) : NULL, ++ oob_fdm_ptr(nand, i), i); ++ ++ if (rc < 0) { ++ pr_warn("Uncorrectable ECC error at page %d step %d\n", ++ page, i); ++ bitflips = nand->ecc.strength + 1; ++ mtd->ecc_stats.failed++; ++ } else { ++ if (rc > bitflips) ++ bitflips = rc; ++ mtd->ecc_stats.corrected += rc; ++ } ++ } ++ ++ mt7621_ecc_decoder_op(nfc, false); ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ if (ret < 0) ++ return ret; ++ ++ return bitflips; ++} ++ ++static int mt7621_nfc_read_page_raw(struct mtd_info *mtd, ++ struct nand_chip *nand, uint8_t *buf, ++ int oob_required, int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int i; ++ ++ nand_read_page_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, FIELD_PREP(CNFG_OP_MODE, CNFG_OP_CUSTOM) | ++ CNFG_READ_MODE); ++ ++ nfi_write16(nfc, NFI_CON, FIELD_PREP(CON_NFI_SEC, nand->ecc.steps) | ++ CON_NFI_BRD); ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ /* Read data */ ++ if (buf) ++ mt7621_nfc_read_data(nfc, page_data_ptr(nand, buf, i), ++ nand->ecc.size); ++ else ++ mt7621_nfc_read_data_discard(nfc, nand->ecc.size); ++ ++ /* Read FDM */ ++ mt7621_nfc_read_data(nfc, oob_fdm_ptr(nand, i), NFI_FDM_SIZE); ++ ++ /* Read ECC parity data */ ++ mt7621_nfc_read_data(nfc, oob_ecc_ptr(nfc, i), ++ nfc->spare_per_sector - NFI_FDM_SIZE); ++ } ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ return 0; ++} ++ ++static int mt7621_nfc_read_oob_hwecc(struct mtd_info *mtd, ++ struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_read_page_hwecc(mtd, nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_read_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_read_page_raw(mtd, nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_check_empty_page(struct nand_chip *nand, const u8 *buf) ++{ ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ u8 *oobptr; ++ u32 i, j; ++ ++ if (buf) { ++ for (i = 0; i < mtd->writesize; i++) ++ if (buf[i] != 0xff) ++ return 0; ++ } ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ oobptr = oob_fdm_ptr(nand, i); ++ for (j = 0; j < NFI_FDM_SIZE; j++) ++ if (oobptr[j] != 0xff) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int mt7621_nfc_write_page_hwecc(struct mtd_info *mtd, ++ struct nand_chip *nand, ++ const u8 *buf, int oob_required, ++ int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ ++ if (mt7621_nfc_check_empty_page(nand, buf)) { ++ /* ++ * MT7621 ECC engine always generates parity code for input ++ * pages, even for empty pages. Doing so will write back ECC ++ * parity code to the oob region, which means such pages will ++ * no longer be empty pages. ++ * ++ * To avoid this, stop write operation if current page is an ++ * empty page. ++ */ ++ return 0; ++ } ++ ++ nand_prog_page_begin_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, FIELD_PREP(CNFG_OP_MODE, CNFG_OP_CUSTOM) | ++ CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN); ++ ++ mt7621_ecc_encoder_op(nfc, true); ++ ++ mt7621_nfc_write_fdm(nfc); ++ ++ nfi_write16(nfc, NFI_CON, FIELD_PREP(CON_NFI_SEC, nand->ecc.steps) | ++ CON_NFI_BWR); ++ ++ if (buf) ++ mt7621_nfc_write_data(nfc, buf, mtd->writesize); ++ else ++ mt7621_nfc_write_data_empty(nfc, mtd->writesize); ++ ++ mt7621_nfc_wait_write_completion(nfc, nand); ++ ++ mt7621_ecc_encoder_op(nfc, false); ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ return nand_prog_page_end_op(nand); ++} ++ ++static int mt7621_nfc_write_page_raw(struct mtd_info *mtd, ++ struct nand_chip *nand, ++ const u8 *buf, int oob_required, ++ int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int i; ++ ++ nand_prog_page_begin_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, FIELD_PREP(CNFG_OP_MODE, CNFG_OP_CUSTOM)); ++ ++ nfi_write16(nfc, NFI_CON, FIELD_PREP(CON_NFI_SEC, nand->ecc.steps) | ++ CON_NFI_BWR); ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ /* Write data */ ++ if (buf) ++ mt7621_nfc_write_data(nfc, page_data_ptr(nand, buf, i), ++ nand->ecc.size); ++ else ++ mt7621_nfc_write_data_empty(nfc, nand->ecc.size); ++ ++ /* Write FDM */ ++ mt7621_nfc_write_data(nfc, oob_fdm_ptr(nand, i), ++ NFI_FDM_SIZE); ++ ++ /* Write dummy ECC parity data */ ++ mt7621_nfc_write_data_empty(nfc, nfc->spare_per_sector - ++ NFI_FDM_SIZE); ++ } ++ ++ mt7621_nfc_wait_write_completion(nfc, nand); ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ return nand_prog_page_end_op(nand); ++} ++ ++static int mt7621_nfc_write_oob_hwecc(struct mtd_info *mtd, ++ struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_write_page_hwecc(mtd, nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_write_oob_raw(struct mtd_info *mtd, ++ struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_write_page_raw(mtd, nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oob_region) ++{ ++ struct nand_chip *nand = mtd_to_nand(mtd); ++ ++ if (section >= nand->ecc.steps) ++ return -ERANGE; ++ ++ oob_region->length = NFI_FDM_SIZE - 1; ++ oob_region->offset = section * NFI_FDM_SIZE + 1; ++ ++ return 0; ++} ++ ++static int mt7621_nfc_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oob_region) ++{ ++ struct nand_chip *nand = mtd_to_nand(mtd); ++ ++ if (section) ++ return -ERANGE; ++ ++ oob_region->offset = NFI_FDM_SIZE * nand->ecc.steps; ++ oob_region->length = mtd->oobsize - oob_region->offset; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops mt7621_nfc_ooblayout_ops = { ++ .rfree = mt7621_nfc_ooblayout_free, ++ .ecc = mt7621_nfc_ooblayout_ecc, ++}; ++ ++/* ++ * This function will override the default one which is not supposed to be ++ * used for ECC syndrome based pages. ++ */ ++static int mt7621_nfc_block_bad(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct nand_chip *nand = mtd_to_nand(mtd); ++ struct mtd_oob_ops ops; ++ int ret, i = 0; ++ u16 bad; ++ ++ memset(&ops, 0, sizeof(ops)); ++ ops.oobbuf = (uint8_t *)&bad; ++ ops.ooboffs = nand->badblockpos; ++ if (nand->options & NAND_BUSWIDTH_16) { ++ ops.ooboffs &= ~0x01; ++ ops.ooblen = 2; ++ } else { ++ ops.ooblen = 1; ++ } ++ ops.mode = MTD_OPS_RAW; ++ ++ /* Read from first/last page(s) if necessary */ ++ if (nand->bbt_options & NAND_BBT_SCANLASTPAGE) ++ ofs += mtd->erasesize - mtd->writesize; ++ ++ do { ++ ret = mtd_read_oob(mtd, ofs, &ops); ++ if (ret) ++ return ret; ++ ++ if (likely(nand->badblockbits == 8)) ++ ret = bad != 0xFF; ++ else ++ ret = hweight8(bad) < nand->badblockbits; ++ ++ i++; ++ ofs += mtd->writesize; ++ } while (!ret && (nand->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); ++ ++ return ret; ++} ++ ++static void mt7621_nfc_init_chip(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd; ++ int ret; ++ ++ nand_set_controller_data(nand, nfc); ++ ++ nand->options |= NAND_NO_SUBPAGE_WRITE; ++ ++ nand->ecc.mode = NAND_ECC_HW_SYNDROME; ++ nand->ecc.read_page = mt7621_nfc_read_page_hwecc; ++ nand->ecc.read_page_raw = mt7621_nfc_read_page_raw; ++ nand->ecc.write_page = mt7621_nfc_write_page_hwecc; ++ nand->ecc.write_page_raw = mt7621_nfc_write_page_raw; ++ nand->ecc.read_oob = mt7621_nfc_read_oob_hwecc; ++ nand->ecc.read_oob_raw = mt7621_nfc_read_oob_raw; ++ nand->ecc.write_oob = mt7621_nfc_write_oob_hwecc; ++ nand->ecc.write_oob_raw = mt7621_nfc_write_oob_raw; ++ ++ nand->dev_ready = mt7621_nfc_dev_ready; ++ nand->select_chip = mt7621_nfc_select_chip; ++ nand->write_byte = mt7621_nfc_write_byte; ++ nand->write_buf = mt7621_nfc_write_buf; ++ nand->read_byte = mt7621_nfc_read_byte; ++ nand->read_buf = mt7621_nfc_read_buf; ++ nand->cmd_ctrl = mt7621_nfc_cmd_ctrl; ++ nand->block_bad = mt7621_nfc_block_bad; ++ ++ mtd = nand_to_mtd(nand); ++ mtd_set_ooblayout(mtd, &mt7621_nfc_ooblayout_ops); ++ ++ /* Reset NFI master */ ++ mt7621_nfc_hw_init(nfc); ++ ++ ret = nand_scan_ident(mtd, 1, NULL); ++ if (ret) ++ return; ++ ++ mt7621_nfc_attach_chip(nand); ++ ++ ret = nand_scan_tail(mtd); ++ if (ret) ++ return; ++ ++ nand_register(0, mtd); ++} ++ ++static void mt7621_nfc_set_regs(struct mt7621_nfc *nfc) ++{ ++ nfc->nfi_regs = (void __iomem *)CKSEG1ADDR(NFI_BASE); ++ nfc->ecc_regs = (void __iomem *)CKSEG1ADDR(NFI_ECC_BASE); ++} ++ ++void mt7621_nfc_spl_init(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ ++ mt7621_nfc_set_regs(nfc); ++ ++ nand_set_controller_data(nand, nfc); ++ ++ nand->options |= NAND_NO_SUBPAGE_WRITE; ++ ++ nand->ecc.mode = NAND_ECC_HW_SYNDROME; ++ nand->ecc.read_page = mt7621_nfc_read_page_hwecc; ++ ++ nand->dev_ready = mt7621_nfc_dev_ready; ++ nand->select_chip = mt7621_nfc_select_chip; ++ nand->read_byte = mt7621_nfc_read_byte; ++ nand->read_buf = mt7621_nfc_read_buf; ++ nand->cmd_ctrl = mt7621_nfc_cmd_ctrl; ++ ++ /* Reset NFI master */ ++ mt7621_nfc_hw_init(nfc); ++} ++ ++int mt7621_nfc_spl_post_init(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ int nand_maf_id, nand_dev_id; ++ struct nand_flash_dev *type; ++ ++ type = nand_get_flash_type(&nand->mtd, nand, &nand_maf_id, ++ &nand_dev_id, NULL); ++ ++ if (IS_ERR(type)) ++ return PTR_ERR(type); ++ ++ nand->numchips = 1; ++ nand->mtd.size = nand->chipsize; ++ ++ return mt7621_nfc_attach_chip(nand); ++} ++ ++void board_nand_init(void) ++{ ++ mt7621_nfc_set_regs(&nfc_dev); ++ mt7621_nfc_init_chip(&nfc_dev); ++} +diff --git a/drivers/mtd/nand/raw/mt7621_nand.h b/drivers/mtd/nand/raw/mt7621_nand.h +new file mode 100644 +index 0000000000..af4bc55961 +--- /dev/null ++++ b/drivers/mtd/nand/raw/mt7621_nand.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#ifndef _MT7621_NAND_H_ ++#define _MT7621_NAND_H_ ++ ++#include <linux/types.h> ++#include <linux/mtd/mtd.h> ++#include <linux/compiler.h> ++#include <linux/mtd/rawnand.h> ++ ++struct mt7621_nfc { ++ struct nand_chip nand; ++ ++ void __iomem *nfi_regs; ++ void __iomem *ecc_regs; ++ ++ u32 spare_per_sector; ++}; ++ ++/* for SPL */ ++void mt7621_nfc_spl_init(struct mt7621_nfc *nfc); ++int mt7621_nfc_spl_post_init(struct mt7621_nfc *nfc); ++ ++#endif /* _MT7621_NAND_H_ */ +diff --git a/drivers/mtd/nand/raw/mt7621_nand_spl.c b/drivers/mtd/nand/raw/mt7621_nand_spl.c +new file mode 100644 +index 0000000000..114fc8b7ce +--- /dev/null ++++ b/drivers/mtd/nand/raw/mt7621_nand_spl.c +@@ -0,0 +1,237 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Weijie Gao <weijie.gao@mediatek.com> ++ */ ++ ++#include <image.h> ++#include <malloc.h> ++#include <linux/sizes.h> ++#include <linux/delay.h> ++#include <linux/mtd/rawnand.h> ++#include "mt7621_nand.h" ++ ++static struct mt7621_nfc nfc_dev; ++static u8 *buffer; ++static int nand_valid; ++ ++static void nand_command_lp(struct mtd_info *mtd, unsigned int command, ++ int column, int page_addr) ++{ ++ register struct nand_chip *chip = mtd_to_nand(mtd); ++ ++ /* Command latch cycle */ ++ chip->cmd_ctrl(mtd, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); ++ ++ if (column != -1 || page_addr != -1) { ++ int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; ++ ++ /* Serially input address */ ++ if (column != -1) { ++ chip->cmd_ctrl(mtd, column, ctrl); ++ ctrl &= ~NAND_CTRL_CHANGE; ++ if (command != NAND_CMD_READID) ++ chip->cmd_ctrl(mtd, column >> 8, ctrl); ++ } ++ if (page_addr != -1) { ++ chip->cmd_ctrl(mtd, page_addr, ctrl); ++ chip->cmd_ctrl(mtd, page_addr >> 8, ++ NAND_NCE | NAND_ALE); ++ if (chip->options & NAND_ROW_ADDR_3) ++ chip->cmd_ctrl(mtd, page_addr >> 16, ++ NAND_NCE | NAND_ALE); ++ } ++ } ++ chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); ++ ++ /* ++ * Program and erase have their own busy handlers status, sequential ++ * in and status need no delay. ++ */ ++ switch (command) { ++ case NAND_CMD_STATUS: ++ case NAND_CMD_READID: ++ case NAND_CMD_SET_FEATURES: ++ return; ++ ++ case NAND_CMD_READ0: ++ chip->cmd_ctrl(mtd, NAND_CMD_READSTART, ++ NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); ++ chip->cmd_ctrl(mtd, NAND_CMD_NONE, ++ NAND_NCE | NAND_CTRL_CHANGE); ++ } ++ ++ /* ++ * Apply this short delay always to ensure that we do wait tWB in ++ * any case on any machine. ++ */ ++ ndelay(100); ++ ++ nand_wait_ready(mtd); ++} ++ ++static int nfc_read_page_hwecc(struct mtd_info *mtd, void *buf, ++ unsigned int page) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ int ret; ++ ++ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, page); ++ ++ ret = chip->ecc.read_page(mtd, chip, buf, 1, page); ++ if (ret < 0 || ret > chip->ecc.strength) ++ return -1; ++ ++ return 0; ++} ++ ++static int nfc_read_oob_hwecc(struct mtd_info *mtd, void *buf, u32 len, ++ unsigned int page) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ int ret; ++ ++ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, page); ++ ++ ret = chip->ecc.read_page(mtd, chip, NULL, 1, page); ++ if (ret < 0) ++ return -1; ++ ++ if (len > mtd->oobsize) ++ len = mtd->oobsize; ++ ++ memcpy(buf, chip->oob_poi, len); ++ ++ return 0; ++} ++ ++static int nfc_check_bad_block(struct mtd_info *mtd, unsigned int page) ++{ ++ struct nand_chip *chip = mtd_to_nand(mtd); ++ u32 pages_per_block, i = 0; ++ int ret; ++ u8 bad; ++ ++ pages_per_block = 1 << (mtd->erasesize_shift - mtd->writesize_shift); ++ ++ /* Read from first/last page(s) if necessary */ ++ if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) { ++ page += pages_per_block - 1; ++ if (chip->bbt_options & NAND_BBT_SCAN2NDPAGE) ++ page--; ++ } ++ ++ do { ++ ret = nfc_read_oob_hwecc(mtd, &bad, 1, page); ++ if (ret) ++ return ret; ++ ++ ret = bad != 0xFF; ++ ++ i++; ++ page++; ++ } while (!ret && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); ++ ++ return ret; ++} ++ ++int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest) ++{ ++ struct mt7621_nfc *nfc = &nfc_dev; ++ struct nand_chip *chip = &nfc->nand; ++ struct mtd_info *mtd = &chip->mtd; ++ u32 addr, col, page, chksz; ++ bool check_bad = true; ++ ++ if (!nand_valid) ++ return -ENODEV; ++ ++ while (size) { ++ if (check_bad || !(offs & mtd->erasesize_mask)) { ++ addr = offs & (~mtd->erasesize_mask); ++ page = addr >> mtd->writesize_shift; ++ if (nfc_check_bad_block(mtd, page)) { ++ /* Skip bad block */ ++ if (addr >= mtd->size - mtd->erasesize) ++ return -1; ++ ++ offs += mtd->erasesize; ++ continue; ++ } ++ ++ check_bad = false; ++ } ++ ++ col = offs & mtd->writesize_mask; ++ page = offs >> mtd->writesize_shift; ++ chksz = min(mtd->writesize - col, (uint32_t)size); ++ ++ if (unlikely(chksz < mtd->writesize)) { ++ /* Not reading a full page */ ++ if (nfc_read_page_hwecc(mtd, buffer, page)) ++ return -1; ++ ++ memcpy(dest, buffer + col, chksz); ++ } else { ++ if (nfc_read_page_hwecc(mtd, dest, page)) ++ return -1; ++ } ++ ++ dest += chksz; ++ offs += chksz; ++ size -= chksz; ++ } ++ ++ return 0; ++} ++ ++int nand_default_bbt(struct mtd_info *mtd) ++{ ++ return 0; ++} ++ ++unsigned long nand_size(void) ++{ ++ if (!nand_valid) ++ return 0; ++ ++ /* Unlikely that NAND size > 2GBytes */ ++ if (nfc_dev.nand.chipsize <= SZ_2G) ++ return nfc_dev.nand.chipsize; ++ ++ return SZ_2G; ++} ++ ++void nand_deselect(void) ++{ ++} ++ ++void nand_init(void) ++{ ++ struct mtd_info *mtd; ++ struct nand_chip *chip; ++ ++ if (nand_valid) ++ return; ++ ++ mt7621_nfc_spl_init(&nfc_dev); ++ ++ chip = &nfc_dev.nand; ++ mtd = &chip->mtd; ++ chip->cmdfunc = nand_command_lp; ++ ++ if (mt7621_nfc_spl_post_init(&nfc_dev)) ++ return; ++ ++ mtd->erasesize_shift = ffs(mtd->erasesize) - 1; ++ mtd->writesize_shift = ffs(mtd->writesize) - 1; ++ mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; ++ mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; ++ ++ buffer = malloc(mtd->writesize); ++ if (!buffer) ++ return; ++ ++ nand_valid = 1; ++} +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0021-spl-allow-using-nand-base-without-standard-nand-driv.patch b/package/boot/uboot-mediatek/patches/001-mtk-0021-spl-allow-using-nand-base-without-standard-nand-driv.patch new file mode 100644 index 0000000000..d3f24f7284 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0021-spl-allow-using-nand-base-without-standard-nand-driv.patch @@ -0,0 +1,29 @@ +From 474082b03ae2b569f9daf43f78b91b57f7a1ae50 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:53 +0800 +Subject: [PATCH 21/25] spl: allow using nand base without standard nand driver + +This patch removes the dependency to SPL_NAND_DRIVERS for SPL_NAND_BASE to +allow minimal spl nand driver to use nand base for probing NAND chips. + +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + common/spl/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/common/spl/Kconfig b/common/spl/Kconfig +index 50ff113cab..eee9315e43 100644 +--- a/common/spl/Kconfig ++++ b/common/spl/Kconfig +@@ -764,7 +764,7 @@ config SPL_NAND_SIMPLE + expose the cmd_ctrl() interface. + + config SPL_NAND_BASE +- depends on SPL_NAND_DRIVERS ++ depends on SPL_NAND_SUPPORT + bool "Use Base NAND Driver" + help + Include nand_base.c in the SPL. +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0022-spl-spl_legacy-fix-the-use-of-SPL_COPY_PAYLOAD_ONLY.patch b/package/boot/uboot-mediatek/patches/001-mtk-0022-spl-spl_legacy-fix-the-use-of-SPL_COPY_PAYLOAD_ONLY.patch new file mode 100644 index 0000000000..91810673e9 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0022-spl-spl_legacy-fix-the-use-of-SPL_COPY_PAYLOAD_ONLY.patch @@ -0,0 +1,69 @@ +From ba9c81e720f39b5dbc14592252bfc9402afee79d Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:23:58 +0800 +Subject: [PATCH 22/25] spl: spl_legacy: fix the use of SPL_COPY_PAYLOAD_ONLY + +If the payload is compressed, SPL_COPY_PAYLOAD_ONLY should always be set +since the payload will not be directly read to its load address. The +payload will first be read to a temporary buffer, and then be decompressed +to its load address, without image header. + +If the payload is not compressed, and SPL_COPY_PAYLOAD_ONLY is set, image +header should be skipped on loading. Otherwise image header should also be +read to its load address. + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + common/spl/spl_legacy.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c +index 2ec7154423..ae8731c782 100644 +--- a/common/spl/spl_legacy.c ++++ b/common/spl/spl_legacy.c +@@ -88,15 +88,29 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, + /* Read header into local struct */ + load->read(load, header, sizeof(hdr), &hdr); + ++ /* ++ * If the payload is compressed, the decompressed data should be ++ * directly write to its load address. ++ */ ++ if (spl_image_get_comp(&hdr) != IH_COMP_NONE) ++ spl_image->flags |= SPL_COPY_PAYLOAD_ONLY; ++ + ret = spl_parse_image_header(spl_image, bootdev, &hdr); + if (ret) + return ret; + +- dataptr = header + sizeof(hdr); +- + /* Read image */ + switch (spl_image_get_comp(&hdr)) { + case IH_COMP_NONE: ++ dataptr = header; ++ ++ /* ++ * Image header will be skipped only if SPL_COPY_PAYLOAD_ONLY ++ * is set ++ */ ++ if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) ++ dataptr += sizeof(hdr); ++ + load->read(load, dataptr, spl_image->size, + (void *)(unsigned long)spl_image->load_addr); + break; +@@ -104,6 +118,9 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, + case IH_COMP_LZMA: + lzma_len = LZMA_LEN; + ++ /* dataptr points to compressed payload */ ++ dataptr = header + sizeof(hdr); ++ + debug("LZMA: Decompressing %08lx to %08lx\n", + dataptr, spl_image->load_addr); + src = malloc(spl_image->size); +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0023-spl-nand-support-loading-legacy-image-with-payload-c.patch b/package/boot/uboot-mediatek/patches/001-mtk-0023-spl-nand-support-loading-legacy-image-with-payload-c.patch new file mode 100644 index 0000000000..7bcc896565 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0023-spl-nand-support-loading-legacy-image-with-payload-c.patch @@ -0,0 +1,64 @@ +From b4e5137067d34a099efd921532ece177560789ca Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:24:04 +0800 +Subject: [PATCH 23/25] spl: nand: support loading legacy image with payload + compressed + +Add support to load legacy image with payload compressed. This redirects +the boot flow for all legacy images. If the payload is not compressed, the +actual behavior will remain unchanged. + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + common/spl/spl_nand.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c +index 82a10ffa63..7b7579a2df 100644 +--- a/common/spl/spl_nand.c ++++ b/common/spl/spl_nand.c +@@ -56,6 +56,21 @@ static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs, + return size / load->bl_len; + } + ++static ulong spl_nand_legacy_read(struct spl_load_info *load, ulong offs, ++ ulong size, void *dst) ++{ ++ int err; ++ ++ debug("%s: offs %lx, size %lx, dst %p\n", ++ __func__, offs, size, dst); ++ ++ err = nand_spl_load_image(offs, size, dst); ++ if (err) ++ return 0; ++ ++ return size; ++} ++ + struct mtd_info * __weak nand_get_mtd(void) + { + return NULL; +@@ -93,6 +108,18 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, + load.bl_len = bl_len; + load.read = spl_nand_fit_read; + return spl_load_imx_container(spl_image, &load, offset / bl_len); ++ } else if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT) && ++ image_get_magic(header) == IH_MAGIC) { ++ struct spl_load_info load; ++ ++ debug("Found legacy image\n"); ++ load.dev = NULL; ++ load.priv = NULL; ++ load.filename = NULL; ++ load.bl_len = 1; ++ load.read = spl_nand_legacy_read; ++ ++ return spl_load_legacy_img(spl_image, bootdev, &load, offset); + } else { + err = spl_parse_image_header(spl_image, bootdev, header); + if (err) +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0024-tools-mtk_image-add-support-for-MT7621-NAND-images.patch b/package/boot/uboot-mediatek/patches/001-mtk-0024-tools-mtk_image-add-support-for-MT7621-NAND-images.patch new file mode 100644 index 0000000000..e317cc4829 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0024-tools-mtk_image-add-support-for-MT7621-NAND-images.patch @@ -0,0 +1,340 @@ +From 18dd1ef9417d0880f2f492b55bd4d9ede499f137 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:24:10 +0800 +Subject: [PATCH 24/25] tools: mtk_image: add support for MT7621 NAND images + +The BootROM of MT7621 requires a image header for SPL to record its size +and load address when booting from NAND. + +To create such an image, one can use the following command line: +mkimage -T mtk_image -a 0x80200000 -e 0x80200000 -n "mt7621=1" +-d u-boot-spl-ddr.bin u-boot-spl-ddr.img + +Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + tools/mtk_image.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++ + tools/mtk_image.h | 24 ++++++ + 2 files changed, 206 insertions(+) + +diff --git a/tools/mtk_image.c b/tools/mtk_image.c +index 418c5fd54b..de5ce4d964 100644 +--- a/tools/mtk_image.c ++++ b/tools/mtk_image.c +@@ -6,7 +6,9 @@ + * Author: Weijie Gao <weijie.gao@mediatek.com> + */ + ++#include <time.h> + #include <image.h> ++#include <u-boot/crc.h> + #include <u-boot/sha256.h> + #include "imagetool.h" + #include "mtk_image.h" +@@ -251,17 +253,45 @@ static uint32_t img_size; + static enum brlyt_img_type hdr_media; + static uint32_t hdr_offset; + static int use_lk_hdr; ++static int use_mt7621_hdr; + static bool is_arm64_image; + + /* LK image name */ + static char lk_name[32] = "U-Boot"; + ++/* CRC32 normal table required by MT7621 image */ ++static uint32_t crc32tbl[256]; ++ + /* NAND header selected by user */ + static const union nand_boot_header *hdr_nand; + + /* GFH header + 2 * 4KB pages of NAND */ + static char hdr_tmp[sizeof(struct gfh_header) + 0x2000]; + ++static uint32_t crc32_normal_cal(uint32_t crc, const void *data, size_t length, ++ const uint32_t *crc32c_table) ++{ ++ const uint8_t *p = data; ++ ++ while (length--) ++ crc = crc32c_table[(uint8_t)((crc >> 24) ^ *p++)] ^ (crc << 8); ++ ++ return crc; ++} ++ ++static void crc32_normal_init(uint32_t *crc32c_table, uint32_t poly) ++{ ++ uint32_t v, i, j; ++ ++ for (i = 0; i < 256; i++) { ++ v = i << 24; ++ for (j = 0; j < 8; j++) ++ v = (v << 1) ^ ((v & (1 << 31)) ? poly : 0); ++ ++ crc32c_table[i] = v; ++ } ++} ++ + static int mtk_image_check_image_types(uint8_t type) + { + if (type == IH_TYPE_MTKIMAGE) +@@ -283,6 +313,7 @@ static int mtk_brom_parse_imagename(const char *imagename) + static const char *hdr_offs = ""; + static const char *nandinfo = ""; + static const char *lk = ""; ++ static const char *mt7621 = ""; + static const char *arm64_param = ""; + + key = buf; +@@ -332,6 +363,9 @@ static int mtk_brom_parse_imagename(const char *imagename) + if (!strcmp(key, "lk")) + lk = val; + ++ if (!strcmp(key, "mt7621")) ++ mt7621 = val; ++ + if (!strcmp(key, "lkname")) + snprintf(lk_name, sizeof(lk_name), "%s", val); + +@@ -352,6 +386,13 @@ static int mtk_brom_parse_imagename(const char *imagename) + return 0; + } + ++ /* if user specified MT7621 image header, skip following checks */ ++ if (mt7621 && mt7621[0] == '1') { ++ use_mt7621_hdr = 1; ++ free(buf); ++ return 0; ++ } ++ + /* parse media type */ + for (i = 0; i < ARRAY_SIZE(brom_images); i++) { + if (!strcmp(brom_images[i].name, media)) { +@@ -419,6 +460,13 @@ static int mtk_image_vrec_header(struct image_tool_params *params, + return 0; + } + ++ if (use_mt7621_hdr) { ++ tparams->header_size = image_get_header_size(); ++ tparams->hdr = &hdr_tmp; ++ memset(&hdr_tmp, 0, tparams->header_size); ++ return 0; ++ } ++ + if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) + tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize); + else +@@ -579,9 +627,90 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print) + return 0; + } + ++static uint32_t crc32be_cal(const void *data, size_t length) ++{ ++ uint32_t crc = 0; ++ uint8_t c; ++ ++ if (crc32tbl[1] != MT7621_IH_CRC_POLYNOMIAL) ++ crc32_normal_init(crc32tbl, MT7621_IH_CRC_POLYNOMIAL); ++ ++ crc = crc32_normal_cal(crc, data, length, crc32tbl); ++ ++ for (; length; length >>= 8) { ++ c = length & 0xff; ++ crc = crc32_normal_cal(crc, &c, 1, crc32tbl); ++ } ++ ++ return ~crc; ++} ++ ++static int mtk_image_verify_mt7621_header(const uint8_t *ptr, int print) ++{ ++ const image_header_t *hdr = (const image_header_t *)ptr; ++ struct mt7621_nand_header *nhdr; ++ uint32_t spl_size, crcval; ++ image_header_t header; ++ int ret; ++ ++ spl_size = image_get_size(hdr); ++ ++ if (spl_size > img_size) { ++ if (print) ++ printf("Incomplete SPL image\n"); ++ return -1; ++ } ++ ++ ret = image_check_hcrc(hdr); ++ if (!ret) { ++ if (print) ++ printf("Bad header CRC\n"); ++ return -1; ++ } ++ ++ ret = image_check_dcrc(hdr); ++ if (!ret) { ++ if (print) ++ printf("Bad data CRC\n"); ++ return -1; ++ } ++ ++ /* Copy header so we can blank CRC field for re-calculation */ ++ memmove(&header, hdr, image_get_header_size()); ++ image_set_hcrc(&header, 0); ++ ++ nhdr = (struct mt7621_nand_header *)header.ih_name; ++ crcval = be32_to_cpu(nhdr->crc); ++ nhdr->crc = 0; ++ ++ if (crcval != crc32be_cal(&header, image_get_header_size())) { ++ if (print) ++ printf("Bad NAND header CRC\n"); ++ return -1; ++ } ++ ++ if (print) { ++ printf("Load Address: %08x\n", image_get_load(hdr)); ++ ++ printf("Image Name: %.*s\n", MT7621_IH_NMLEN, ++ image_get_name(hdr)); ++ ++ if (IMAGE_ENABLE_TIMESTAMP) { ++ printf("Created: "); ++ genimg_print_time((time_t)image_get_time(hdr)); ++ } ++ ++ printf("Data Size: "); ++ genimg_print_size(image_get_data_size(hdr)); ++ } ++ ++ return 0; ++} ++ + static int mtk_image_verify_header(unsigned char *ptr, int image_size, + struct image_tool_params *params) + { ++ image_header_t *hdr = (image_header_t *)ptr; + union lk_hdr *lk = (union lk_hdr *)ptr; + + /* nothing to verify for LK image header */ +@@ -590,6 +719,9 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size, + + img_size = image_size; + ++ if (image_get_magic(hdr) == IH_MAGIC) ++ return mtk_image_verify_mt7621_header(ptr, 0); ++ + if (!strcmp((char *)ptr, NAND_BOOT_NAME)) + return mtk_image_verify_nand_header(ptr, 0); + else +@@ -600,6 +732,7 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size, + + static void mtk_image_print_header(const void *ptr) + { ++ image_header_t *hdr = (image_header_t *)ptr; + union lk_hdr *lk = (union lk_hdr *)ptr; + + if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) { +@@ -610,6 +743,11 @@ static void mtk_image_print_header(const void *ptr) + + printf("Image Type: MediaTek BootROM Loadable Image\n"); + ++ if (image_get_magic(hdr) == IH_MAGIC) { ++ mtk_image_verify_mt7621_header(ptr, 1); ++ return; ++ } ++ + if (!strcmp((char *)ptr, NAND_BOOT_NAME)) + mtk_image_verify_nand_header(ptr, 1); + else +@@ -773,6 +911,45 @@ static void mtk_image_set_nand_header(void *ptr, off_t filesize, + filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN); + } + ++static void mtk_image_set_mt7621_header(void *ptr, off_t filesize, ++ uint32_t loadaddr) ++{ ++ image_header_t *hdr = (image_header_t *)ptr; ++ struct mt7621_stage1_header *shdr; ++ struct mt7621_nand_header *nhdr; ++ uint32_t datasize, crcval; ++ ++ datasize = filesize - image_get_header_size(); ++ nhdr = (struct mt7621_nand_header *)hdr->ih_name; ++ shdr = (struct mt7621_stage1_header *)(ptr + image_get_header_size()); ++ ++ shdr->ep = cpu_to_be32(loadaddr); ++ shdr->stage_size = cpu_to_be32(datasize); ++ ++ image_set_magic(hdr, IH_MAGIC); ++ image_set_time(hdr, time(NULL)); ++ image_set_size(hdr, datasize); ++ image_set_load(hdr, loadaddr); ++ image_set_ep(hdr, loadaddr); ++ image_set_os(hdr, IH_OS_U_BOOT); ++ image_set_arch(hdr, IH_ARCH_MIPS); ++ image_set_type(hdr, IH_TYPE_STANDALONE); ++ image_set_comp(hdr, IH_COMP_NONE); ++ ++ crcval = crc32(0, (uint8_t *)shdr, datasize); ++ image_set_dcrc(hdr, crcval); ++ ++ strncpy(nhdr->ih_name, "MT7621 NAND", MT7621_IH_NMLEN); ++ ++ nhdr->ih_stage_offset = cpu_to_be32(image_get_header_size()); ++ ++ crcval = crc32be_cal(hdr, image_get_header_size()); ++ nhdr->crc = cpu_to_be32(crcval); ++ ++ crcval = crc32(0, (uint8_t *)hdr, image_get_header_size()); ++ image_set_hcrc(hdr, crcval); ++} ++ + static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd, + struct image_tool_params *params) + { +@@ -791,6 +968,11 @@ static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd, + img_gen = true; + img_size = sbuf->st_size; + ++ if (use_mt7621_hdr) { ++ mtk_image_set_mt7621_header(ptr, sbuf->st_size, params->addr); ++ return; ++ } ++ + if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) + mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr); + else +diff --git a/tools/mtk_image.h b/tools/mtk_image.h +index 7dda71ce88..d868545a33 100644 +--- a/tools/mtk_image.h ++++ b/tools/mtk_image.h +@@ -200,4 +200,28 @@ union lk_hdr { + + #define LK_PART_MAGIC 0x58881688 + ++/* MT7621 NAND SPL image header */ ++ ++#define MT7621_IH_NMLEN 12 ++#define MT7621_IH_CRC_POLYNOMIAL 0x04c11db7 ++ ++struct mt7621_nand_header { ++ char ih_name[MT7621_IH_NMLEN]; ++ uint32_t nand_ac_timing; ++ uint32_t ih_stage_offset; ++ uint32_t ih_bootloader_offset; ++ uint32_t nand_info_1_data; ++ uint32_t crc; ++}; ++ ++struct mt7621_stage1_header { ++ uint32_t jump_insn[2]; ++ uint32_t ep; ++ uint32_t stage_size; ++ uint32_t has_stage2; ++ uint32_t next_ep; ++ uint32_t next_size; ++ uint32_t next_offset; ++}; ++ + #endif /* _MTK_IMAGE_H */ +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0025-MAINTAINERS-update-maintainer-for-MediaTek-MIPS-plat.patch b/package/boot/uboot-mediatek/patches/001-mtk-0025-MAINTAINERS-update-maintainer-for-MediaTek-MIPS-plat.patch new file mode 100644 index 0000000000..1b6d19aa10 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/001-mtk-0025-MAINTAINERS-update-maintainer-for-MediaTek-MIPS-plat.patch @@ -0,0 +1,44 @@ +From e5fc4022af3cfd59e3459276305671a595ac5ff0 Mon Sep 17 00:00:00 2001 +From: Weijie Gao <weijie.gao@mediatek.com> +Date: Fri, 20 May 2022 11:24:16 +0800 +Subject: [PATCH 25/25] MAINTAINERS: update maintainer for MediaTek MIPS + platform + +Update maintainer for MediaTek MIPS platform + +Signed-off-by: Weijie Gao <weijie.gao@mediatek.com> +--- + MAINTAINERS | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 7f27ff4c20..d8d060bd92 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1007,15 +1007,23 @@ R: GSS_MTK_Uboot_upstream <GSS_MTK_Uboot_upstream@mediatek.com> + S: Maintained + F: arch/mips/mach-mtmips/ + F: arch/mips/dts/mt7620.dtsi ++F: arch/mips/dts/mt7621.dtsi + F: arch/mips/dts/mt7620-u-boot.dtsi ++F: arch/mips/dts/mt7621-u-boot.dtsi + F: include/configs/mt7620.h ++F: include/configs/mt7621.h + F: include/dt-bindings/clock/mt7620-clk.h ++F: include/dt-bindings/clock/mt7621-clk.h + F: include/dt-bindings/clock/mt7628-clk.h + F: include/dt-bindings/reset/mt7620-reset.h ++F: include/dt-bindings/reset/mt7621-reset.h + F: include/dt-bindings/reset/mt7628-reset.h + F: drivers/clk/mtmips/ + F: drivers/pinctrl/mtmips/ + F: drivers/gpio/mt7620_gpio.c ++F: drivers/mtd/nand/raw/mt7621_nand.c ++F: drivers/mtd/nand/raw/mt7621_nand.h ++F: drivers/mtd/nand/raw/mt7621_nand_spl.c + F: drivers/net/mt7620-eth.c + F: drivers/phy/mt7620-usb-phy.c + F: drivers/reset/reset-mtmips.c +-- +2.36.1 + diff --git a/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch b/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch index bb7045916f..a784f32f34 100644 --- a/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch +++ b/package/boot/uboot-mediatek/patches/412-add-ubnt-unifi-6-lr.patch @@ -420,7 +420,7 @@ DECLARE_GLOBAL_DATA_PTR; -@@ -392,6 +393,21 @@ static int initr_onenand(void) +@@ -392,6 +393,20 @@ static int initr_onenand(void) } #endif @@ -430,11 +430,10 @@ +{ + struct udevice *new; + -+ spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, -+ CONFIG_SF_DEFAULT_CS, -+ CONFIG_SF_DEFAULT_SPEED, -+ CONFIG_SF_DEFAULT_MODE, -+ &new); ++spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, ++ CONFIG_SF_DEFAULT_CS, ++ &new); ++ + return 0; +} +#endif diff --git a/package/boot/uboot-ramips/patches/0001-add-support-for-RAVPower-RP-WD009.patch b/package/boot/uboot-mediatek/patches/420-add-support-for-RAVPower-RP-WD009.patch index 1833a627dc..80af85a959 100644 --- a/package/boot/uboot-ramips/patches/0001-add-support-for-RAVPower-RP-WD009.patch +++ b/package/boot/uboot-mediatek/patches/420-add-support-for-RAVPower-RP-WD009.patch @@ -20,23 +20,16 @@ Subject: [PATCH] add support for RAVPower RP-WD009 create mode 100644 configs/ravpower-rp-wd009-ram_defconfig create mode 100644 include/configs/ravpower-rp-wd009.h -diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile -index c9d75596f2..23868ae1d2 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile -@@ -2,7 +2,8 @@ - - dtb-$(CONFIG_ARCH_MTMIPS) += \ - gardena-smart-gateway-mt7688.dtb \ -- linkit-smart-7688.dtb -+ linkit-smart-7688.dtb \ -+ ravpower-rp-wd009.dtb - dtb-$(CONFIG_TARGET_AP121) += ap121.dtb - dtb-$(CONFIG_TARGET_AP143) += ap143.dtb - dtb-$(CONFIG_TARGET_AP152) += ap152.dtb -diff --git a/arch/mips/dts/ravpower-rp-wd009.dts b/arch/mips/dts/ravpower-rp-wd009.dts -new file mode 100644 -index 0000000000..b271d5bfbc +@@ -25,6 +25,7 @@ dtb-$(CONFIG_TARGET_OCTEON_EBB7304) += m + dtb-$(CONFIG_TARGET_OCTEON_NIC23) += mrvl,octeon-nic23.dtb + dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb + dtb-$(CONFIG_BOARD_NETGEAR_DGND3700V2) += netgear,dgnd3700v2.dtb ++dtb-$(CONFIG_BOARD_RAVPOWER_RP_WD009) += ravpower-rp-wd009.dtb + dtb-$(CONFIG_BOARD_SAGEM_FAST1704) += sagem,f@st1704.dtb + dtb-$(CONFIG_BOARD_SFR_NB4_SER) += sfr,nb4-ser.dtb + dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb --- /dev/null +++ b/arch/mips/dts/ravpower-rp-wd009.dts @@ -0,0 +1,50 @@ @@ -90,36 +83,6 @@ index 0000000000..b271d5bfbc + pinctrl-names = "default"; + pinctrl-0 = <&ephy_router_mode>; +}; -diff --git a/arch/mips/mach-mtmips/Kconfig b/arch/mips/mach-mtmips/Kconfig -index c8dcf19c0d..85ac8878ab 100644 ---- a/arch/mips/mach-mtmips/Kconfig -+++ b/arch/mips/mach-mtmips/Kconfig -@@ -32,6 +32,14 @@ config BOARD_GARDENA_SMART_GATEWAY_MT7688 - 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_RAVPOWER_RP_WD009 -+ bool "RAVPower RP-WD009" -+ depends on SOC_MT7628 -+ select BOARD_LATE_INIT -+ select SUPPORTS_BOOT_RAM -+ help -+ RAVPower RP-WD009 -+ - config BOARD_LINKIT_SMART_7688 - bool "LinkIt Smart 7688" - depends on SOC_MT7628 -@@ -133,6 +141,7 @@ config SUPPORTS_BOOT_RAM - bool - - source "board/gardena/smart-gateway-mt7688/Kconfig" -+source "board/ravpower/rp-wd009/Kconfig" - source "board/seeed/linkit-smart-7688/Kconfig" - - endmenu -diff --git a/board/ravpower/rp-wd009/Kconfig b/board/ravpower/rp-wd009/Kconfig -new file mode 100644 -index 0000000000..111f8e4478 --- /dev/null +++ b/board/ravpower/rp-wd009/Kconfig @@ -0,0 +1,12 @@ @@ -135,18 +98,12 @@ index 0000000000..111f8e4478 + default "ravpower-rp-wd009" + +endif -diff --git a/board/ravpower/rp-wd009/Makefile b/board/ravpower/rp-wd009/Makefile -new file mode 100644 -index 0000000000..70cd7a8e56 --- /dev/null +++ b/board/ravpower/rp-wd009/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += board.o -diff --git a/board/ravpower/rp-wd009/board.c b/board/ravpower/rp-wd009/board.c -new file mode 100644 -index 0000000000..eabcf85735 --- /dev/null +++ b/board/ravpower/rp-wd009/board.c @@ -0,0 +1,16 @@ @@ -166,16 +123,14 @@ index 0000000000..eabcf85735 +{ + return 0; +} -diff --git a/configs/ravpower-rp-wd009-ram_defconfig b/configs/ravpower-rp-wd009-ram_defconfig -new file mode 100644 -index 0000000000..08cbf40638 --- /dev/null +++ b/configs/ravpower-rp-wd009-ram_defconfig -@@ -0,0 +1,59 @@ +@@ -0,0 +1,61 @@ +CONFIG_MIPS=y -+CONFIG_SYS_TEXT_BASE=0x80010000 ++CONFIG_SYS_LOAD_ADDR=0x80010000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_ARCH_MTMIPS=y ++CONFIG_SOC_MT7628=y +CONFIG_MIPS_BOOT_FDT=y +CONFIG_LEGACY_IMAGE_FORMAT=y +CONFIG_OF_STDOUT_VIA_ALIAS=y @@ -185,7 +140,6 @@ index 0000000000..08cbf40638 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_VERSION_VARIABLE=y +CONFIG_BOARD_RAVPOWER_RP_WD009=y -+CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_HUSH_PARSER=y +CONFIG_CMD_LICENSE=y +# CONFIG_CMD_ELF is not set @@ -203,6 +157,8 @@ index 0000000000..08cbf40638 +CONFIG_CMD_TIME=y +CONFIG_CMD_UUID=y +CONFIG_CMD_MTDPARTS=y ++CONFIG_FIT=y ++CONFIG_FIT_ENABLE_SHA256_SUPPORT=y +CONFIG_MTDIDS_DEFAULT="nor0=spi0.0" +CONFIG_MTDPARTS_DEFAULT="spi0.0:192k(factory-uboot),64k(config),64k(factory),1536k(loader),64k(params),64k(user_backup),64k(user),14272k(firmware),64k(mode)" +CONFIG_DEFAULT_DEVICE_TREE="ravpower-rp-wd009" @@ -231,12 +187,9 @@ index 0000000000..08cbf40638 +CONFIG_WDT_MT7621=y +CONFIG_LZMA=y +CONFIG_BAUDRATE=57600 -diff --git a/include/configs/ravpower-rp-wd009.h b/include/configs/ravpower-rp-wd009.h -new file mode 100644 -index 0000000000..bb4145197c --- /dev/null +++ b/include/configs/ravpower-rp-wd009.h -@@ -0,0 +1,48 @@ +@@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Stefan Roese <sr@denx.de> @@ -251,8 +204,6 @@ index 0000000000..bb4145197c +/* RAM */ +#define CONFIG_SYS_SDRAM_BASE 0x80000000 + -+#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_SDRAM_BASE + 0x100000 -+ +#define CONFIG_SYS_INIT_SP_OFFSET 0x400000 + +#ifdef CONFIG_BOOT_RAM @@ -269,13 +220,9 @@ index 0000000000..bb4145197c + +/* Memory usage */ +#define CONFIG_SYS_MAXARGS 64 -+#define CONFIG_SYS_MALLOC_LEN (16 * 1024 * 1024) +#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024) +#define CONFIG_SYS_CBSIZE 512 + -+/* U-Boot */ -+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE -+ +/* Environment settings */ + +/* @@ -285,6 +232,28 @@ index 0000000000..bb4145197c +#define CONFIG_BOARD_SIZE_LIMIT CONFIG_ENV_OFFSET + +#endif /* __CONFIG_RAVPOWER_RP_WD009_H */ --- -2.27.0 - +--- a/arch/mips/mach-mtmips/mt7628/Kconfig ++++ b/arch/mips/mach-mtmips/mt7628/Kconfig +@@ -27,6 +27,14 @@ config BOARD_MT7628_RFB + SPI-NOR flash, 1 built-in switch with 5 ports, 1 UART, 1 USB host, + 1 SDXC, 1 PCIe socket and JTAG pins. + ++config BOARD_RAVPOWER_RP_WD009 ++ bool "RAVPower RP-WD009" ++ depends on SOC_MT7628 ++ select BOARD_LATE_INIT ++ select SUPPORTS_BOOT_RAM ++ help ++ RAVPower RP-WD009 ++ + config BOARD_VOCORE2 + bool "VoCore2" + select SPL_SERIAL +@@ -53,6 +61,7 @@ config SYS_CONFIG_NAME + default "mt7628" if BOARD_MT7628_RFB + + source "board/gardena/smart-gateway-mt7688/Kconfig" ++source "board/ravpower/rp-wd009/Kconfig" + source "board/seeed/linkit-smart-7688/Kconfig" + source "board/vocore/vocore2/Kconfig" + diff --git a/package/boot/uboot-ramips/Makefile b/package/boot/uboot-ramips/Makefile deleted file mode 100644 index 337ea00479..0000000000 --- a/package/boot/uboot-ramips/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_VERSION:=2020.04 -PKG_RELEASE:=$(AUTORELEASE) - -PKG_HASH:=fe732aaf037d9cc3c0909bad8362af366ae964bbdac6913a34081ff4ad565372 - -include $(INCLUDE_DIR)/u-boot.mk -include $(INCLUDE_DIR)/package.mk - -define U-Boot/Default - BUILD_TARGET:=ramips - UBOOT_IMAGE:=u-boot.bin -endef - -define U-Boot/ravpower_rp-wd009 - BUILD_DEVICES:=ravpower_rp-wd009 - BUILD_SUBTARGET:=mt76x8 - NAME:=RAVPower RP-WD009 - UBOOT_CONFIG:=ravpower-rp-wd009-ram -endef - -UBOOT_TARGETS := \ - ravpower_rp-wd009 - -define Build/InstallDev - $(INSTALL_DIR) $(STAGING_DIR_IMAGE) - $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(UBOOT_IMAGE) $(STAGING_DIR_IMAGE)/$(VARIANT)-$(UBOOT_IMAGE) -endef - -$(eval $(call BuildPackage/U-Boot)) |