diff --git a/include/kernel-5.10 b/include/kernel-5.10 index 762e467468..4143799e89 100644 --- a/include/kernel-5.10 +++ b/include/kernel-5.10 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.10 = .137 -LINUX_KERNEL_HASH-5.10.137 = c16bcd4d1453d7e645007d0a25270f52401331c7df81c364f57bde914e1616c8 +LINUX_VERSION-5.10 = .138 +LINUX_KERNEL_HASH-5.10.138 = 29a003bb8e0e3a45942f703370fb0b3460e6fdcbbad37424423c9cf831ab5ba8 diff --git a/include/kernel-5.15 b/include/kernel-5.15 index 622349cf46..4ce0e0ccd8 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .62 -LINUX_KERNEL_HASH-5.15.62 = 06817cde8e57cdb6dbf20eaa5122fee110024f6e8b783799c98cb65dc753f141 +LINUX_VERSION-5.15 = .63 +LINUX_KERNEL_HASH-5.15.63 = 6dd3cd1e5a629d0002bc6c6ec7e8ea96710104f38664122dd56c83dfd4eb7341 diff --git a/include/trusted-firmware-a.mk b/include/trusted-firmware-a.mk index d95250452b..46fc52b15e 100644 --- a/include/trusted-firmware-a.mk +++ b/include/trusted-firmware-a.mk @@ -72,10 +72,13 @@ define Build/Configure/Trusted-Firmware-A $(INSTALL_DIR) $(STAGING_DIR)/usr/include endef +DTC=$(wildcard $(LINUX_DIR)/scripts/dtc/dtc) + define Build/Compile/Trusted-Firmware-A +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ CROSS_COMPILE=$(TARGET_CROSS) \ OPENSSL_DIR=$(STAGING_DIR_HOST) \ + $(if $(DTC),DTC="$(DTC)") \ PLAT=$(PLAT) \ BUILD_STRING="OpenWrt v$(PKG_VERSION)-$(PKG_RELEASE) ($(VARIANT))" \ $(TFA_MAKE_FLAGS) diff --git a/package/boot/arm-trusted-firmware-bcm63xx/Makefile b/package/boot/arm-trusted-firmware-bcm63xx/Makefile index 12571e8d96..7db1fbfff0 100644 --- a/package/boot/arm-trusted-firmware-bcm63xx/Makefile +++ b/package/boot/arm-trusted-firmware-bcm63xx/Makefile @@ -13,6 +13,7 @@ PKG_MIRROR_HASH:=9d5d04f572b1b6ddc6eb3064b9cb09f5fe982e82d350790041d35316349af12 PKG_MAINTAINER:=Rafał Miłecki +include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/trusted-firmware-a.mk include $(INCLUDE_DIR)/package.mk diff --git a/package/boot/arm-trusted-firmware-mediatek/Makefile b/package/boot/arm-trusted-firmware-mediatek/Makefile index 30488333f8..583517b866 100644 --- a/package/boot/arm-trusted-firmware-mediatek/Makefile +++ b/package/boot/arm-trusted-firmware-mediatek/Makefile @@ -13,68 +13,166 @@ PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://github.com/mtk-openwrt/arm-trusted-firmware.git -PKG_SOURCE_DATE:=2021-05-08 -PKG_SOURCE_VERSION:=d2c75b2139be003887af9cc5a94da5e9bdc59de7 -PKG_MIRROR_HASH:=4af9ce8e11511afee7f588cc982946c06339edbfa47afef6a7f3e2231ac9f34d +PKG_SOURCE_DATE:=2022-08-18 +PKG_SOURCE_VERSION:=9c9c49945c24634e4ae6cd924dbb88cf85c7926d +PKG_MIRROR_HASH:=26b474f40c02da12b7bed56597aeef209757ad1b40a4f0a652794954018b2198 PKG_MAINTAINER:=Daniel Golle +include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/trusted-firmware-a.mk include $(INCLUDE_DIR)/package.mk define Trusted-Firmware-A/Default BUILD_TARGET:=mediatek - BUILD_SUBTARGET:=mt7622 - PLAT:=mt7622 TFA_IMAGE:=bl2.img bl31.bin BOOT_DEVICE:= DDR3_FLYBY:= + DDR_TYPE:= + NAND_TYPE:= endef define Trusted-Firmware-A/mt7622-nor-1ddr NAME:=MediaTek MT7622 (SPI-NOR, 1x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=nor endef define Trusted-Firmware-A/mt7622-nor-2ddr NAME:=MediaTek MT7622 (SPI-NOR, 2x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=nor DDR3_FLYBY:=1 endef define Trusted-Firmware-A/mt7622-snand-1ddr NAME:=MediaTek MT7622 (SPI-NAND, 1x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=snand endef define Trusted-Firmware-A/mt7622-snand-2ddr NAME:=MediaTek MT7622 (SPI-NAND, 2x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=snand DDR3_FLYBY:=1 endef define Trusted-Firmware-A/mt7622-emmc-1ddr NAME:=MediaTek MT7622 (eMMC, 1x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=emmc endef define Trusted-Firmware-A/mt7622-emmc-2ddr NAME:=MediaTek MT7622 (eMMC, 2x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=emmc DDR3_FLYBY:=1 endef define Trusted-Firmware-A/mt7622-sdmmc-1ddr - NAME:=MediaTek MT7622 (SDcard, 1x DDR3) + NAME:=MediaTek MT7622 (SD card, 1x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=sdmmc endef define Trusted-Firmware-A/mt7622-sdmmc-2ddr - NAME:=MediaTek MT7622 (SDcard, 2x DDR3) + NAME:=MediaTek MT7622 (SD card, 2x DDR3) + BUILD_SUBTARGET:=mt7622 + PLAT:=mt7622 BOOT_DEVICE:=sdmmc DDR3_FLYBY:=1 endef +define Trusted-Firmware-A/mt7986-nor-ddr4 + NAME:=MediaTek MT7986 (SPI-NOR, DDR4) + BOOT_DEVICE:=nor + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr4 +endef + +define Trusted-Firmware-A/mt7986-emmc-ddr4 + NAME:=MediaTek MT7986 (eMMC, DDR4) + BOOT_DEVICE:=emmc + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr4 +endef + +define Trusted-Firmware-A/mt7986-sdmmc-ddr4 + NAME:=MediaTek MT7986 (SD card, DDR4) + BOOT_DEVICE:=sdmmc + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr4 +endef + +define Trusted-Firmware-A/mt7986-snand-ddr4 + NAME:=MediaTek MT7986 (SPI-NAND via SNFI, DDR4) + BOOT_DEVICE:=snand + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr4 +endef + +define Trusted-Firmware-A/mt7986-spim-nand-ddr4 + NAME:=MediaTek MT7986 (SPI-NAND via SPIM, DDR4) + BOOT_DEVICE:=spim-nand + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr4 + NAND_TYPE:=spim:2k+64 +endef + +define Trusted-Firmware-A/mt7986-nor-ddr3 + NAME:=MediaTek MT7986 (SPI-NOR, DDR3) + BOOT_DEVICE:=nor + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr3 +endef + +define Trusted-Firmware-A/mt7986-emmc-ddr3 + NAME:=MediaTek MT7986 (eMMC, DDR3) + BOOT_DEVICE:=emmc + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr3 +endef + +define Trusted-Firmware-A/mt7986-sdmmc-ddr3 + NAME:=MediaTek MT7986 (SD card, DDR3) + BOOT_DEVICE:=sdmmc + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr3 +endef + +define Trusted-Firmware-A/mt7986-snand-ddr3 + NAME:=MediaTek MT7986 (SPI-NAND via SNFI, DDR3) + BOOT_DEVICE:=snand + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr3 +endef + +define Trusted-Firmware-A/mt7986-spim-nand-ddr3 + NAME:=MediaTek MT7986 (SPI-NAND via SPIM, DDR3) + BOOT_DEVICE:=spim-nand + BUILD_SUBTARGET:=filogic + PLAT:=mt7986 + DDR_TYPE:=ddr3 +endef + TFA_TARGETS:= \ mt7622-nor-1ddr \ mt7622-nor-2ddr \ @@ -83,18 +181,31 @@ TFA_TARGETS:= \ mt7622-emmc-1ddr \ mt7622-emmc-2ddr \ mt7622-sdmmc-1ddr \ - mt7622-sdmmc-2ddr + mt7622-sdmmc-2ddr \ + mt7986-emmc-ddr3 \ + mt7986-nor-ddr3 \ + mt7986-sdmmc-ddr3 \ + mt7986-snand-ddr3 \ + mt7986-spim-nand-ddr3 \ + mt7986-emmc-ddr4 \ + mt7986-nor-ddr4 \ + mt7986-sdmmc-ddr4 \ + mt7986-snand-ddr4 \ + mt7986-spim-nand-ddr4 TFA_MAKE_FLAGS += \ BOOT_DEVICE=$(BOOT_DEVICE) \ USE_MKIMAGE=1 MKIMAGE=$(STAGING_DIR_HOST)/bin/mkimage \ + $(if $(findstring ddr4,$(DDR_TYPE)),DRAM_USE_DDR4=1) \ + $(if $(NAND_TYPE),NAND_TYPE=$(NAND_TYPE)) \ + HAVE_DRAM_OBJ_FILE=yes \ $(if $(DDR3_FLYBY),DDR3_FLYBY=1) \ all define Package/trusted-firmware-a/install $(INSTALL_DIR) $(STAGING_DIR_IMAGE) - $(INSTALL_DATA) $(PKG_BUILD_DIR)/build/mt7622/release/bl2.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl2.img - $(INSTALL_DATA) $(PKG_BUILD_DIR)/build/mt7622/release/bl31.bin $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl31.bin + $(INSTALL_DATA) $(PKG_BUILD_DIR)/build/$(PLAT)/release/bl2.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl2.img + $(INSTALL_DATA) $(PKG_BUILD_DIR)/build/$(PLAT)/release/bl31.bin $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl31.bin endef $(eval $(call BuildPackage/Trusted-Firmware-A)) diff --git a/package/boot/arm-trusted-firmware-mediatek/patches/0001-spi-nor-add-more-Winbond-device-IDs.patch b/package/boot/arm-trusted-firmware-mediatek/patches/0001-spi-nor-add-more-Winbond-device-IDs.patch new file mode 100644 index 0000000000..d0e2f8a2c3 --- /dev/null +++ b/package/boot/arm-trusted-firmware-mediatek/patches/0001-spi-nor-add-more-Winbond-device-IDs.patch @@ -0,0 +1,32 @@ +From daaac60b504e6d5e77156ad0dc3dceca8b786e2d Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 27 Aug 2022 03:41:57 +0100 +Subject: [PATCH] spi-nor: add more Winbond device IDs + +Add device IDs for Winbond W25Q256 and W25Q512 variants. + +Signed-off-by: Daniel Golle +--- + drivers/mtd/nor/spi_nor.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/nor/spi_nor.c ++++ b/drivers/mtd/nor/spi_nor.c +@@ -327,8 +327,15 @@ int spi_nor_read(unsigned int offset, ui + + struct nor_device_info nor_flash_info_table[] = { + {"MX25L51245G", {0xC2, 0x20, 0x1A}, 0x4000000, 0}, +- {"W25Q256JW",{0xEF,0x80, 0x19}, 0x2000000, 0}, +- {"MX25U25635",{0xC2, 0x25, 0x39}, 0x2000000, 0} ++ {"W25Q256JV-IM", {0xEF, 0x70, 0x19}, 0x2000000, 0}, ++ {"W25Q256JV-IQ", {0xEF, 0x40, 0x19}, 0x2000000, 0}, ++ {"W25Q256JW", {0xEF, 0x60, 0x19}, 0x2000000, 0}, ++ {"W25Q256JW-IM", {0xEF, 0x80, 0x19}, 0x2000000, 0}, ++ {"W25Q512JV-IM", {0xEF, 0x70, 0x20}, 0x4000000, 0}, ++ {"W25Q512JV-IQ", {0xEF, 0x40, 0x20}, 0x4000000, 0}, ++ {"W25Q512NW-IM", {0xEF, 0x80, 0x20}, 0x4000000, 0}, ++ {"W25Q512NW-IQ/IN", {0xEF, 0x60, 0x20}, 0x4000000, 0}, ++ {"MX25U25635", {0xC2, 0x25, 0x39}, 0x2000000, 0} + }; + + diff --git a/package/boot/arm-trusted-firmware-mediatek/patches/0002-mediatek-mt7622-initialize-watchdog-after-DDR-init.patch b/package/boot/arm-trusted-firmware-mediatek/patches/0002-mediatek-mt7622-initialize-watchdog-after-DDR-init.patch new file mode 100644 index 0000000000..d8905986e2 --- /dev/null +++ b/package/boot/arm-trusted-firmware-mediatek/patches/0002-mediatek-mt7622-initialize-watchdog-after-DDR-init.patch @@ -0,0 +1,40 @@ +From 2a012775b3ab6e72091c8be1c2d4bf5972407eb5 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 27 Aug 2022 21:38:33 +0100 +Subject: [PATCH] mediatek: mt7622: initialize watchdog after DDR init + +Initializing the WDT before memory calibration breaks reboot at least +on some MT7622 boards like the Bananapi BPi-R64: +NOTICE: BL2: v2.7(release):OpenWrt v2022-08-18-9c9c4994-2 (mt7622-emmc-2ddr) +NOTICE: BL2: Built : 04:00:25, Aug 27 2022 +ERROR: Cannot find any pass-window +ERROR: no DATLAT taps pass, DATLAT calibration fail! +ERROR: DATLAT calibration fail, write back to 20! +ERROR: EMI: complex R/W mem test failed: -2 + +Move watchdog initialization to happen only after memory initialization +has completed to avoid the problem. + +Signed-off-by: Daniel Golle +--- + plat/mediatek/mt7622/bl2_plat_setup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/plat/mediatek/mt7622/bl2_plat_setup.c ++++ b/plat/mediatek/mt7622/bl2_plat_setup.c +@@ -277,7 +277,6 @@ void bl2_platform_setup(void) + plat_mt_cpuxgpt_init(); + generic_delay_timer_init(); + +- mtk_wdt_init(); + mtk_pin_init(); + #ifndef USING_BL2PL + mtk_pll_init(); +@@ -285,6 +284,7 @@ void bl2_platform_setup(void) + mtk_pwrap_init(); + mtk_pmic_init(); + mtk_mem_init(); ++ mtk_wdt_init(); + + mtk_io_setup(); + } diff --git a/package/boot/arm-trusted-firmware-mediatek/patches/100-increase-nor-bl3-size.patch b/package/boot/arm-trusted-firmware-mediatek/patches/100-increase-nor-bl3-size.patch deleted file mode 100644 index 8de3cd77f6..0000000000 --- a/package/boot/arm-trusted-firmware-mediatek/patches/100-increase-nor-bl3-size.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/plat/mediatek/mt7622/bl2_boot_nor.c -+++ b/plat/mediatek/mt7622/bl2_boot_nor.c -@@ -12,7 +12,7 @@ - #define MT7622_NOR_MAP_BASE 0x30000000 - - #define FIP_BASE 0x20000 --#define FIP_SIZE 0x80000 -+#define FIP_SIZE 0xa0000 - - const io_block_spec_t mtk_boot_dev_fip_spec = { - .offset = MT7622_NOR_MAP_BASE + FIP_BASE, diff --git a/package/boot/arm-trusted-firmware-mediatek/patches/120-mt7622-bl2_boot_snand-skip-bad-blocks.patch b/package/boot/arm-trusted-firmware-mediatek/patches/120-mt7622-bl2_boot_snand-skip-bad-blocks.patch deleted file mode 100644 index 31384d010e..0000000000 --- a/package/boot/arm-trusted-firmware-mediatek/patches/120-mt7622-bl2_boot_snand-skip-bad-blocks.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/plat/mediatek/mt7622/bl2_boot_snand.c -+++ b/plat/mediatek/mt7622/bl2_boot_snand.c -@@ -21,6 +21,10 @@ - #define FIP_BASE 0x80000 - #define FIP_SIZE 0x200000 - -+#ifndef NMBM -+#define SNAND_MAX_BAD_BLOCK 3 -+#endif -+ - struct snfi_gpio_mux_info { - const uint32_t *pins; - uint32_t count; -@@ -45,12 +49,26 @@ static size_t snand_read_range(int lba, - size_t sizeremain = size, chunksize; - uint64_t off = lba * cinfo.pagesize; - uint8_t *ptr = (uint8_t *)buf; -+ struct mtk_snand_chip_info info; -+ unsigned int bad_blocks = 0; - int ret = 0; - - if (!snf) - return 0; - -+ ret = mtk_snand_get_chip_info(snf, &info); -+ if (ret) -+ return 0; -+ - while (sizeremain) { -+ while (mtk_snand_block_isbad(snf, off)) { -+ if (bad_blocks > SNAND_MAX_BAD_BLOCK) -+ return size - sizeremain; -+ -+ off += info.blocksize; -+ ++bad_blocks; -+ } -+ - chunksize = cinfo.pagesize; - if (chunksize > sizeremain) - chunksize = sizeremain; diff --git a/package/boot/arm-trusted-firmware-mvebu/Makefile b/package/boot/arm-trusted-firmware-mvebu/Makefile index 9a7e1340a9..dba4836a6b 100644 --- a/package/boot/arm-trusted-firmware-mvebu/Makefile +++ b/package/boot/arm-trusted-firmware-mvebu/Makefile @@ -13,6 +13,7 @@ PKG_HASH:=53422dc649153838e03820330ba17cb10afe3e330ecde0db11e4d5f1361a33e6 PKG_MAINTAINER:=Vladimir Vid +include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/trusted-firmware-a.mk include $(INCLUDE_DIR)/package.mk diff --git a/package/boot/arm-trusted-firmware-sunxi/Makefile b/package/boot/arm-trusted-firmware-sunxi/Makefile index 0abfbae750..178b3958b8 100644 --- a/package/boot/arm-trusted-firmware-sunxi/Makefile +++ b/package/boot/arm-trusted-firmware-sunxi/Makefile @@ -21,6 +21,7 @@ PKG_LICENSE_FILES:=license.md PKG_MAINTAINER:=Hauke Mehrtens +include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/trusted-firmware-a.mk include $(INCLUDE_DIR)/package.mk diff --git a/package/boot/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-envtools/files/mediatek_filogic new file mode 100644 index 0000000000..a82f140a6e --- /dev/null +++ b/package/boot/uboot-envtools/files/mediatek_filogic @@ -0,0 +1,45 @@ +# +# Copyright (C) 2021 OpenWrt.org +# + +[ -e /etc/config/ubootenv ] && exit 0 + +touch /etc/config/ubootenv + +. /lib/uboot-envtools.sh +. /lib/functions.sh + +board=$(board_name) + +case "$board" in +bananapi,bpi-r3) + . /lib/upgrade/common.sh + export_bootdevice + export_partdevice rootdev 0 + case "$rootdev" in + mmc*) + local envdev=$(find_mmc_part "ubootenv" $rootdev) + ubootenv_add_uci_config "$envdev" "0x0" "0x40000" "0x40000" "1" + ubootenv_add_uci_config "$envdev" "0x40000" "0x40000" "0x40000" "1" + ;; + mtd*) + local envdev=/dev/mtd$(find_mtd_index "u-boot-env") + ubootenv_add_uci_config "$envdev" "0x0" "0x20000" "0x20000" "1" + ubootenv_add_uci_config "$envdev" "0x20000" "0x20000" "0x20000" "1" + ;; + *) + . /lib/upgrade/nand.sh + local envubi=$(nand_find_ubi ubi) + local envdev=/dev/$(nand_find_volume $envubi ubootenv) + local envdev2=/dev/$(nand_find_volume $envubi ubootenv2) + ubootenv_add_uci_config "$envdev" "0x0" "0x1f000" "0x1f000" "1" + ubootenv_add_uci_config "$envdev2" "0x0" "0x1f000" "0x1f000" "1" + ;; + esac + ;; +esac + +config_load ubootenv +config_foreach ubootenv_add_app_config ubootenv + +exit 0 diff --git a/package/boot/uboot-envtools/files/mediatek_mt7622 b/package/boot/uboot-envtools/files/mediatek_mt7622 index 830414225e..654f78056a 100644 --- a/package/boot/uboot-envtools/files/mediatek_mt7622 +++ b/package/boot/uboot-envtools/files/mediatek_mt7622 @@ -39,7 +39,7 @@ ruijie,rg-ew3200gx-pro) ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x20000" "0x20000" ;; ubnt,unifi-6-lr-ubootmod) - ubootenv_add_uci_config "/dev/mtd2" "0x0" "0x4000" "0x10000" + ubootenv_add_uci_config "/dev/mtd2" "0x0" "0x4000" "0x1000" ;; xiaomi,redmi-router-ax6s) ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x10000" "0x40000" diff --git a/package/boot/uboot-mediatek/Makefile b/package/boot/uboot-mediatek/Makefile index 314cb8b84b..7bfc8fd64b 100644 --- a/package/boot/uboot-mediatek/Makefile +++ b/package/boot/uboot-mediatek/Makefile @@ -132,6 +132,7 @@ define U-Boot/mt7622_ubnt_unifi-6-lr BL2_BOOTDEV:=nor BL2_DDRBLOB:=2 DEPENDS:=+trusted-firmware-a-mt7622-nor-2ddr + FIP_COMPRESS:=1 endef define U-Boot/mt7623a_unielec_u7623 @@ -174,6 +175,67 @@ define U-Boot/mt7629_rfb UBOOT_CONFIG:=mt7629_rfb endef +define U-Boot/mt7986_rfb + NAME:=MT7986 Reference Board + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=mediatek_mt7986-rfb + UBOOT_CONFIG:=mt7986_rfb + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=sdmmc + BL2_SOC:=mt7986 + BL2_DDRTYPE:=ddr4 + DEPENDS:=+trusted-firmware-a-mt7986-sdmmc-ddr4 +endef + +define U-Boot/mt7986_bananapi_bpi-r3-emmc + NAME:=BananaPi BPi-R3 + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=bananapi_bpi-r3 + UBOOT_CONFIG:=mt7986a_bpi-r3-emmc + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=emmc + BL2_SOC:=mt7986 + BL2_DDRTYPE:=ddr4 + DEPENDS:=+trusted-firmware-a-mt7986-emmc-ddr4 +endef + +define U-Boot/mt7986_bananapi_bpi-r3-sdmmc + NAME:=BananaPi BPi-R3 + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=bananapi_bpi-r3 + UBOOT_CONFIG:=mt7986a_bpi-r3-sd + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=sdmmc + BL2_SOC:=mt7986 + BL2_DDRTYPE:=ddr4 + DEPENDS:=+trusted-firmware-a-mt7986-sdmmc-ddr4 +endef + +define U-Boot/mt7986_bananapi_bpi-r3-snand + NAME:=BananaPi BPi-R3 + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=bananapi_bpi-r3 + UBOOT_CONFIG:=mt7986a_bpi-r3-snand + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=spim-nand + BL2_SOC:=mt7986 + BL2_DDRTYPE:=ddr4 + DEPENDS:=+trusted-firmware-a-mt7986-spim-nand-ddr4 +endef + +define U-Boot/mt7986_bananapi_bpi-r3-nor + NAME:=BananaPi BPi-R3 + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=bananapi_bpi-r3 + UBOOT_CONFIG:=mt7986a_bpi-r3-nor + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=nor + BL2_SOC:=mt7986 + BL2_DDRTYPE:=ddr4 + DEPENDS:=+trusted-firmware-a-mt7986-nor-ddr4 + FIP_COMPRESS:=1 +endef + UBOOT_TARGETS := \ mt7620_mt7530_rfb \ mt7620_rfb \ @@ -189,16 +251,25 @@ UBOOT_TARGETS := \ mt7623a_unielec_u7623 \ mt7628_rfb \ ravpower_rp-wd009 \ - mt7629_rfb + mt7629_rfb \ + mt7986_bananapi_bpi-r3-emmc \ + mt7986_bananapi_bpi-r3-sdmmc \ + mt7986_bananapi_bpi-r3-snand \ + mt7986_bananapi_bpi-r3-nor \ + mt7986_rfb ifdef CONFIG_TARGET_mediatek UBOOT_MAKE_FLAGS += $(UBOOT_IMAGE:.fip=.bin) endif define Build/fip-image + $(if $(FIP_COMPRESS),\ + xz -f -e -k -9 -C crc32 $(STAGING_DIR_IMAGE)/$(if $(BL2_SOC),$(BL2_SOC),$(BUILD_SUBTARGET))-$(BL2_BOOTDEV)-$(if $(BL2_DDRTYPE),$(BL2_DDRTYPE)-)$(if $(BL2_DDRBLOB),$(BL2_DDRBLOB)ddr-)bl31.bin ;\ + xz -f -e -k -9 -C crc32 $(PKG_BUILD_DIR)/u-boot.bin \ + ) $(STAGING_DIR_HOST)/bin/fiptool create \ - --soc-fw $(STAGING_DIR_IMAGE)/$(BUILD_SUBTARGET)-$(BL2_BOOTDEV)-$(BL2_DDRBLOB)ddr-bl31.bin \ - --nt-fw $(PKG_BUILD_DIR)/u-boot.bin \ + --soc-fw $(STAGING_DIR_IMAGE)/$(if $(BL2_SOC),$(BL2_SOC),$(BUILD_SUBTARGET))-$(BL2_BOOTDEV)-$(if $(BL2_DDRTYPE),$(BL2_DDRTYPE)-)$(if $(BL2_DDRBLOB),$(BL2_DDRBLOB)ddr-)bl31.bin$(if $(FIP_COMPRESS),.xz) \ + --nt-fw $(PKG_BUILD_DIR)/u-boot.bin$(if $(FIP_COMPRESS),.xz) \ $(PKG_BUILD_DIR)/u-boot.fip endef diff --git a/package/boot/uboot-mediatek/patches/000-mtk-01-Revert-clk-Add-debugging-for-return-values.patch b/package/boot/uboot-mediatek/patches/000-mtk-01-Revert-clk-Add-debugging-for-return-values.patch deleted file mode 100644 index 3b68c52713..0000000000 --- a/package/boot/uboot-mediatek/patches/000-mtk-01-Revert-clk-Add-debugging-for-return-values.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 34ed9f6d3018d32c7c015e57c9985d3c4c07b706 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Thu, 11 Mar 2021 10:28:53 +0000 -Subject: [PATCH 01/12] Revert "clk: Add debugging for return values" - -This reverts commit 5c5992cb90cf9ca4d51e38d9a95a13c293904df5. ---- - drivers/clk/clk-uclass.c | 16 +++++----------- - 1 file changed, 5 insertions(+), 11 deletions(-) - ---- a/drivers/clk/clk-uclass.c -+++ b/drivers/clk/clk-uclass.c -@@ -88,7 +88,7 @@ static int clk_get_by_index_tail(int ret - if (ret) { - debug("%s: uclass_get_device_by_of_offset failed: err=%d\n", - __func__, ret); -- return log_msg_ret("get", ret); -+ return ret; - } - - clk->dev = dev_clk; -@@ -101,15 +101,14 @@ static int clk_get_by_index_tail(int ret - ret = clk_of_xlate_default(clk, args); - if (ret) { - debug("of_xlate() failed: %d\n", ret); -- return log_msg_ret("xlate", ret); -+ return ret; - } - - return clk_request(dev_clk, clk); - err: - debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n", - __func__, ofnode_get_name(node), list_name, index, ret); -- -- return log_msg_ret("prop", ret); -+ return ret; - } - - static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name, -@@ -128,7 +127,7 @@ static int clk_get_by_indexed_prop(struc - if (ret) { - debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n", - __func__, ret); -- return log_ret(ret); -+ return ret; - } - - -@@ -469,7 +468,6 @@ void clk_free(struct clk *clk) - ulong clk_get_rate(struct clk *clk) - { - const struct clk_ops *ops; -- int ret; - - debug("%s(clk=%p)\n", __func__, clk); - if (!clk_valid(clk)) -@@ -479,11 +477,7 @@ ulong clk_get_rate(struct clk *clk) - if (!ops->get_rate) - return -ENOSYS; - -- ret = ops->get_rate(clk); -- if (ret) -- return log_ret(ret); -- -- return 0; -+ return ops->get_rate(clk); - } - - struct clk *clk_get_parent(struct clk *clk) diff --git a/package/boot/uboot-mediatek/patches/000-mtk-20-configs-mt7622-enable-environment-for-mt7622_rfb.patch b/package/boot/uboot-mediatek/patches/000-mtk-20-configs-mt7622-enable-environment-for-mt7622_rfb.patch index cc5fb57324..cf2e48d5c4 100644 --- a/package/boot/uboot-mediatek/patches/000-mtk-20-configs-mt7622-enable-environment-for-mt7622_rfb.patch +++ b/package/boot/uboot-mediatek/patches/000-mtk-20-configs-mt7622-enable-environment-for-mt7622_rfb.patch @@ -21,7 +21,7 @@ Signed-off-by: Weijie Gao CONFIG_DEBUG_UART_BASE=0x11002000 CONFIG_DEBUG_UART_CLOCK=25000000 CONFIG_SYS_LOAD_ADDR=0x4007ff28 -@@ -22,6 +24,9 @@ CONFIG_CMD_SF_TEST=y +@@ -21,6 +23,9 @@ CONFIG_CMD_SF_TEST=y CONFIG_CMD_PING=y CONFIG_CMD_SMC=y CONFIG_ENV_OVERWRITE=y diff --git a/package/boot/uboot-mediatek/patches/001-mtk-0100-arm-dts-mt7622-remove-default-pinctrl-of-uart0.patch b/package/boot/uboot-mediatek/patches/001-mtk-0100-arm-dts-mt7622-remove-default-pinctrl-of-uart0.patch index 63e189f56c..603896f260 100644 --- a/package/boot/uboot-mediatek/patches/001-mtk-0100-arm-dts-mt7622-remove-default-pinctrl-of-uart0.patch +++ b/package/boot/uboot-mediatek/patches/001-mtk-0100-arm-dts-mt7622-remove-default-pinctrl-of-uart0.patch @@ -34,7 +34,7 @@ Signed-off-by: Weijie Gao --- a/arch/arm/dts/mt7622-rfb.dts +++ b/arch/arm/dts/mt7622-rfb.dts -@@ -196,8 +196,6 @@ +@@ -189,8 +189,6 @@ }; &uart0 { diff --git a/package/boot/uboot-mediatek/patches/002-0001-arm-mediatek-add-support-for-MediaTek-MT7986-SoC.patch b/package/boot/uboot-mediatek/patches/002-0001-arm-mediatek-add-support-for-MediaTek-MT7986-SoC.patch new file mode 100644 index 0000000000..663f06c22c --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0001-arm-mediatek-add-support-for-MediaTek-MT7986-SoC.patch @@ -0,0 +1,552 @@ +From a299de45833df13d4ec28092201ea5fec0ba24fe Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 15:17:58 +0800 +Subject: [PATCH 01/31] arm: mediatek: add support for MediaTek MT7986 SoC + +This patch adds basic support for MediaTek MT7986 SoC. +This include the file that will initialize the SoC after boot and its +device tree. + +Signed-off-by: Weijie Gao +--- + arch/arm/dts/mt7986-u-boot.dtsi | 33 ++ + arch/arm/dts/mt7986.dtsi | 341 ++++++++++++++++++ + arch/arm/mach-mediatek/Kconfig | 11 + + arch/arm/mach-mediatek/Makefile | 1 + + arch/arm/mach-mediatek/mt7986/Makefile | 4 + + arch/arm/mach-mediatek/mt7986/init.c | 51 +++ + arch/arm/mach-mediatek/mt7986/lowlevel_init.S | 32 ++ + 7 files changed, 473 insertions(+) + create mode 100644 arch/arm/dts/mt7986-u-boot.dtsi + create mode 100644 arch/arm/dts/mt7986.dtsi + create mode 100644 arch/arm/mach-mediatek/mt7986/Makefile + create mode 100644 arch/arm/mach-mediatek/mt7986/init.c + create mode 100644 arch/arm/mach-mediatek/mt7986/lowlevel_init.S + +--- /dev/null ++++ b/arch/arm/dts/mt7986-u-boot.dtsi +@@ -0,0 +1,33 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++&topckgen { ++ u-boot,dm-pre-reloc; ++}; ++ ++&pericfg { ++ u-boot,dm-pre-reloc; ++}; ++ ++&apmixedsys { ++ u-boot,dm-pre-reloc; ++}; ++ ++&timer0 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&uart0 { ++ u-boot,dm-pre-reloc; ++}; ++ ++&snand { ++ u-boot,dm-pre-reloc; ++}; ++ ++&pinctrl { ++ u-boot,dm-pre-reloc; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7986.dtsi +@@ -0,0 +1,341 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/ { ++ compatible = "mediatek,mt7986"; ++ interrupt-parent = <&gic>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ config { ++ u-boot,mmc-env-partition = "u-boot-env"; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0>; ++ }; ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x1>; ++ }; ++ cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x1>; ++ }; ++ cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x1>; ++ }; ++ }; ++ ++ dummy_clk: dummy12m { ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++ #clock-cells = <0>; ++ /* must need this line, or uart uanable to get dummy_clk */ ++ u-boot,dm-pre-reloc; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupt-parent = <&gic>; ++ clock-frequency = <13000000>; ++ interrupts = , ++ , ++ , ++ ; ++ arm,cpu-registers-not-fw-configured; ++ }; ++ ++ timer0: timer@10008000 { ++ compatible = "mediatek,mt7986-timer"; ++ reg = <0x10008000 0x1000>; ++ interrupts = ; ++ clocks = <&infracfg CK_INFRA_CK_F26M>; ++ clock-names = "gpt-clk"; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ watchdog: watchdog@1001c000 { ++ compatible = "mediatek,mt7986-wdt"; ++ reg = <0x1001c000 0x1000>; ++ interrupts = ; ++ #reset-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ gic: interrupt-controller@c000000 { ++ compatible = "arm,gic-v3"; ++ #interrupt-cells = <3>; ++ interrupt-parent = <&gic>; ++ interrupt-controller; ++ reg = <0x0c000000 0x40000>, /* GICD */ ++ <0x0c080000 0x200000>; /* GICR */ ++ ++ interrupts = ; ++ }; ++ ++ fixed_plls: apmixedsys@1001E000 { ++ compatible = "mediatek,mt7986-fixed-plls"; ++ reg = <0x1001E000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ topckgen: topckgen@1001B000 { ++ compatible = "mediatek,mt7986-topckgen"; ++ reg = <0x1001B000 0x1000>; ++ clock-parent = <&fixed_plls>; ++ #clock-cells = <1>; ++ }; ++ ++ infracfg_ao: infracfg_ao@10001000 { ++ compatible = "mediatek,mt7986-infracfg_ao"; ++ reg = <0x10001000 0x68>; ++ clock-parent = <&infracfg>; ++ #clock-cells = <1>; ++ }; ++ ++ infracfg: infracfg@10001040 { ++ compatible = "mediatek,mt7986-infracfg"; ++ reg = <0x10001000 0x1000>; ++ clock-parent = <&topckgen>; ++ #clock-cells = <1>; ++ }; ++ ++ pinctrl: pinctrl@1001f000 { ++ compatible = "mediatek,mt7986-pinctrl"; ++ reg = <0x1001f000 0x1000>, ++ <0x11c30000 0x1000>, ++ <0x11c40000 0x1000>, ++ <0x11e20000 0x1000>, ++ <0x11e30000 0x1000>, ++ <0x11f00000 0x1000>, ++ <0x11f10000 0x1000>, ++ <0x1000b000 0x1000>; ++ reg-names = "gpio_base", "iocfg_rt_base", "iocfg_rb_base", ++ "iocfg_lt_base", "iocfg_lb_base", "iocfg_tr_base", ++ "iocfg_tl_base", "eint"; ++ gpio: gpio-controller { ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++ ++ pwm: pwm@10048000 { ++ compatible = "mediatek,mt7986-pwm"; ++ reg = <0x10048000 0x1000>; ++ #clock-cells = <1>; ++ #pwm-cells = <2>; ++ interrupts = ; ++ clocks = <&infracfg CK_INFRA_PWM>, ++ <&infracfg_ao CK_INFRA_PWM_BSEL>, ++ <&infracfg_ao CK_INFRA_PWM1_CK>, ++ <&infracfg_ao CK_INFRA_PWM2_CK>; ++ assigned-clocks = <&topckgen CK_TOP_PWM_SEL>, ++ <&infracfg CK_INFRA_PWM_BSEL>, ++ <&infracfg CK_INFRA_PWM1_SEL>, ++ <&infracfg CK_INFRA_PWM2_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_M_D4>, ++ <&infracfg CK_INFRA_PWM>, ++ <&infracfg CK_INFRA_PWM>, ++ <&infracfg CK_INFRA_PWM>; ++ clock-names = "top", "main", "pwm1", "pwm2"; ++ status = "disabled"; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ uart0: serial@11002000 { ++ compatible = "mediatek,hsuart"; ++ reg = <0x11002000 0x400>; ++ interrupts = ; ++ clocks = <&infracfg_ao CK_INFRA_UART0_CK>; ++ assigned-clocks = <&topckgen CK_TOP_UART_SEL>, ++ <&infracfg_ao CK_INFRA_UART0_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>, ++ <&infracfg CK_INFRA_UART>; ++ mediatek,force-highspeed; ++ status = "disabled"; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ uart1: serial@11003000 { ++ compatible = "mediatek,hsuart"; ++ reg = <0x11003000 0x400>; ++ interrupts = ; ++ clocks = <&infracfg_ao CK_INFRA_UART1_CK>; ++ assigned-clocks = <&infracfg CK_INFRA_UART1_SEL>; ++ assigned-clock-parents = <&infracfg CK_INFRA_CK_F26M>; ++ mediatek,force-highspeed; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@11004000 { ++ compatible = "mediatek,hsuart"; ++ reg = <0x11004000 0x400>; ++ interrupts = ; ++ clocks = <&infracfg_ao CK_INFRA_UART2_CK>; ++ assigned-clocks = <&infracfg CK_INFRA_UART2_SEL>; ++ assigned-clock-parents = <&infracfg CK_INFRA_CK_F26M>; ++ mediatek,force-highspeed; ++ status = "disabled"; ++ }; ++ ++ snand: snand@11005000 { ++ compatible = "mediatek,mt7986-snand"; ++ reg = <0x11005000 0x1000>, ++ <0x11006000 0x1000>; ++ reg-names = "nfi", "ecc"; ++ clocks = <&infracfg_ao CK_INFRA_SPINFI1_CK>, ++ <&infracfg_ao CK_INFRA_NFI1_CK>, ++ <&infracfg_ao CK_INFRA_NFI_HCK_CK>; ++ clock-names = "pad_clk", "nfi_clk", "nfi_hclk"; ++ assigned-clocks = <&topckgen CK_TOP_SPINFI_SEL>, ++ <&topckgen CK_TOP_NFI1X_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_M_D8>, ++ <&topckgen CK_TOP_CB_M_D8>; ++ status = "disabled"; ++ }; ++ ++ ethsys: syscon@15000000 { ++ compatible = "mediatek,mt7986-ethsys", "syscon"; ++ reg = <0x15000000 0x1000>; ++ clock-parent = <&topckgen>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ eth: ethernet@15100000 { ++ compatible = "mediatek,mt7986-eth", "syscon"; ++ reg = <0x15100000 0x20000>; ++ resets = <ðsys ETHSYS_FE_RST>; ++ reset-names = "fe"; ++ mediatek,ethsys = <ðsys>; ++ mediatek,sgmiisys = <&sgmiisys0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ sgmiisys0: syscon@10060000 { ++ compatible = "mediatek,mt7986-sgmiisys", "syscon"; ++ reg = <0x10060000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ sgmiisys1: syscon@10070000 { ++ compatible = "mediatek,mt7986-sgmiisys", "syscon"; ++ reg = <0x10070000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ spi0: spi@1100a000 { ++ compatible = "mediatek,ipm-spi"; ++ reg = <0x1100a000 0x100>; ++ clocks = <&infracfg_ao CK_INFRA_SPI0_CK>, ++ <&topckgen CK_TOP_SPI_SEL>; ++ assigned-clocks = <&topckgen CK_TOP_SPI_SEL>, ++ <&infracfg CK_INFRA_SPI0_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>, ++ <&topckgen CK_INFRA_ISPI0>; ++ clock-names = "sel-clk", "spi-clk"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ spi1: spi@1100b000 { ++ compatible = "mediatek,ipm-spi"; ++ reg = <0x1100b000 0x100>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ mmc0: mmc@11230000 { ++ compatible = "mediatek,mt7986-mmc"; ++ reg = <0x11230000 0x1000>, ++ <0x11C20000 0x1000>; ++ interrupts = ; ++ clocks = <&topckgen CK_TOP_EMMC_416M>, ++ <&topckgen CK_TOP_EMMC_250M>, ++ <&infracfg_ao CK_INFRA_MSDC_CK>; ++ assigned-clocks = <&topckgen CK_TOP_EMMC_416M_SEL>, ++ <&topckgen CK_TOP_EMMC_250M_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_M_416M>, ++ <&topckgen CK_TOP_NET1_D5_D2>; ++ clock-names = "source", "hclk", "source_cg"; ++ status = "disabled"; ++ }; ++ ++ xhci: xhci@11200000 { ++ compatible = "mediatek,mt7986-xhci", ++ "mediatek,mtk-xhci"; ++ reg = <0x11200000 0x2e00>, ++ <0x11203e00 0x0100>; ++ reg-names = "mac", "ippc"; ++ interrupts = ; ++ phys = <&u2port0 PHY_TYPE_USB2>, ++ <&u3port0 PHY_TYPE_USB3>, ++ <&u2port1 PHY_TYPE_USB2>; ++ clocks = <&dummy_clk>, ++ <&dummy_clk>, ++ <&dummy_clk>, ++ <&dummy_clk>, ++ <&dummy_clk>; ++ clock-names = "sys_ck", ++ "xhci_ck", ++ "ref_ck", ++ "mcu_ck", ++ "dma_ck"; ++ tpl-support; ++ status = "okay"; ++ }; ++ ++ usbtphy: usb-phy@11e10000 { ++ compatible = "mediatek,mt7986", ++ "mediatek,generic-tphy-v2"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ status = "okay"; ++ ++ u2port0: usb-phy@11e10000 { ++ reg = <0x11e10000 0x700>; ++ clocks = <&dummy_clk>; ++ clock-names = "ref"; ++ #phy-cells = <1>; ++ status = "okay"; ++ }; ++ ++ u3port0: usb-phy@11e10700 { ++ reg = <0x11e10700 0x900>; ++ clocks = <&dummy_clk>; ++ clock-names = "ref"; ++ #phy-cells = <1>; ++ status = "okay"; ++ }; ++ ++ u2port1: usb-phy@11e11000 { ++ reg = <0x11e11000 0x700>; ++ clocks = <&dummy_clk>; ++ clock-names = "ref"; ++ #phy-cells = <1>; ++ status = "okay"; ++ }; ++ }; ++}; +--- a/arch/arm/mach-mediatek/Kconfig ++++ b/arch/arm/mach-mediatek/Kconfig +@@ -40,6 +40,14 @@ config TARGET_MT7629 + including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet, + switch, USB3.0, PCIe, UART, SPI, I2C and PWM. + ++config TARGET_MT7986 ++ bool "MediaTek MT7986 SoC" ++ select ARM64 ++ help ++ The MediaTek MT7986 is a ARM64-based SoC with a quad-core Cortex-A53. ++ including UART, SPI, SPI flash, USB3.0, MMC, NAND, SNFI, PWM, PCIe, ++ Gigabit Ethernet, I2C, built-in 4x4 Wi-Fi, and PCIe. ++ + config TARGET_MT8183 + bool "MediaTek MT8183 SoC" + select ARM64 +@@ -84,6 +92,7 @@ config SYS_BOARD + default "mt7622" if TARGET_MT7622 + default "mt7623" if TARGET_MT7623 + default "mt7629" if TARGET_MT7629 ++ default "mt7986" if TARGET_MT7986 + default "mt8183" if TARGET_MT8183 + default "mt8512" if TARGET_MT8512 + default "mt8516" if TARGET_MT8516 +@@ -99,6 +108,7 @@ config SYS_CONFIG_NAME + default "mt7622" if TARGET_MT7622 + default "mt7623" if TARGET_MT7623 + default "mt7629" if TARGET_MT7629 ++ default "mt7986" if TARGET_MT7986 + default "mt8183" if TARGET_MT8183 + default "mt8512" if TARGET_MT8512 + default "mt8516" if TARGET_MT8516 +@@ -113,6 +123,7 @@ config MTK_BROM_HEADER_INFO + string + default "media=nor" if TARGET_MT8518 || TARGET_MT8512 || TARGET_MT7629 || TARGET_MT7622 + default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8183 ++ default "media=snand;nandinfo=2k+64" if TARGET_MT7986 + default "lk=1" if TARGET_MT7623 + + endif +--- a/arch/arm/mach-mediatek/Makefile ++++ b/arch/arm/mach-mediatek/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += mt8512/ + obj-$(CONFIG_TARGET_MT7622) += mt7622/ + obj-$(CONFIG_TARGET_MT7623) += mt7623/ + obj-$(CONFIG_TARGET_MT7629) += mt7629/ ++obj-$(CONFIG_TARGET_MT7986) += mt7986/ + obj-$(CONFIG_TARGET_MT8183) += mt8183/ + obj-$(CONFIG_TARGET_MT8516) += mt8516/ + obj-$(CONFIG_TARGET_MT8518) += mt8518/ +--- /dev/null ++++ b/arch/arm/mach-mediatek/mt7986/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += init.o ++obj-y += lowlevel_init.o +--- /dev/null ++++ b/arch/arm/mach-mediatek/mt7986/init.c +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++int print_cpuinfo(void) ++{ ++ printf("CPU: MediaTek MT7986\n"); ++ return 0; ++} ++ ++int dram_init(void) ++{ ++ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_2G); ++ ++ return 0; ++} ++ ++void reset_cpu(ulong addr) ++{ ++ psci_system_reset(); ++} ++ ++static struct mm_region mt7986_mem_map[] = { ++ { ++ /* DDR */ ++ .virt = 0x40000000UL, ++ .phys = 0x40000000UL, ++ .size = 0x80000000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE, ++ }, { ++ .virt = 0x00000000UL, ++ .phys = 0x00000000UL, ++ .size = 0x40000000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ }, { ++ 0, ++ } ++}; ++ ++struct mm_region *mem_map = mt7986_mem_map; +--- /dev/null ++++ b/arch/arm/mach-mediatek/mt7986/lowlevel_init.S +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/* ++ * Switch from AArch64 EL2 to AArch32 EL2 ++ * @param inputs: ++ * x0: argument, zero ++ * x1: machine nr ++ * x2: fdt address ++ * x3: input argument ++ * x4: kernel entry point ++ * @param outputs for secure firmware: ++ * x0: function id ++ * x1: kernel entry point ++ * x2: machine nr ++ * x3: fdt address ++ * ++ * [1] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/mediatek/common/mtk_sip_svc.c ++*/ ++ ++.global armv8_el2_to_aarch32 ++armv8_el2_to_aarch32: ++ mov x3, x2 ++ mov x2, x1 ++ mov x1, x4 ++ mov x4, #0 ++ ldr x0, =0x82000200 /* MTK_SIP_KERNEL_BOOT_AARCH32 */ ++ SMC #0 ++ ret diff --git a/package/boot/uboot-mediatek/patches/002-0002-arm-mediatek-add-support-for-MediaTek-MT7981-SoC.patch b/package/boot/uboot-mediatek/patches/002-0002-arm-mediatek-add-support-for-MediaTek-MT7981-SoC.patch new file mode 100644 index 0000000000..93596af53d --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0002-arm-mediatek-add-support-for-MediaTek-MT7981-SoC.patch @@ -0,0 +1,462 @@ +From 38faebb811868f9e6734dea7894d0fa5a61f3a22 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 15:58:11 +0800 +Subject: [PATCH 02/31] arm: mediatek: add support for MediaTek MT7981 SoC + +This patch adds basic support for MediaTek MT7981 SoC. +This include the file that will initialize the SoC after boot and its +device tree. + +Signed-off-by: Weijie Gao +--- + arch/arm/dts/mt7981.dtsi | 288 ++++++++++++++++++ + arch/arm/mach-mediatek/Kconfig | 12 +- + arch/arm/mach-mediatek/Makefile | 1 + + arch/arm/mach-mediatek/mt7981/Makefile | 4 + + arch/arm/mach-mediatek/mt7981/init.c | 51 ++++ + arch/arm/mach-mediatek/mt7981/lowlevel_init.S | 32 ++ + 6 files changed, 387 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/dts/mt7981.dtsi + create mode 100644 arch/arm/mach-mediatek/mt7981/Makefile + create mode 100644 arch/arm/mach-mediatek/mt7981/init.c + create mode 100644 arch/arm/mach-mediatek/mt7981/lowlevel_init.S + +--- /dev/null ++++ b/arch/arm/dts/mt7981.dtsi +@@ -0,0 +1,288 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/ { ++ compatible = "mediatek,mt7981"; ++ interrupt-parent = <&gic>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0>; ++ }; ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x1>; ++ }; ++ }; ++ ++ gpt_clk: gpt_dummy20m { ++ compatible = "fixed-clock"; ++ clock-frequency = <13000000>; ++ #clock-cells = <0>; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupt-parent = <&gic>; ++ clock-frequency = <13000000>; ++ interrupts = , ++ , ++ , ++ ; ++ arm,cpu-registers-not-fw-configured; ++ }; ++ ++ timer0: timer@10008000 { ++ compatible = "mediatek,mt7986-timer"; ++ reg = <0x10008000 0x1000>; ++ interrupts = ; ++ clocks = <&gpt_clk>; ++ clock-names = "gpt-clk"; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ watchdog: watchdog@1001c000 { ++ compatible = "mediatek,mt7986-wdt"; ++ reg = <0x1001c000 0x1000>; ++ interrupts = ; ++ #reset-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ gic: interrupt-controller@c000000 { ++ compatible = "arm,gic-v3"; ++ #interrupt-cells = <3>; ++ interrupt-parent = <&gic>; ++ interrupt-controller; ++ reg = <0x0c000000 0x40000>, /* GICD */ ++ <0x0c080000 0x200000>; /* GICR */ ++ ++ interrupts = ; ++ }; ++ ++ fixed_plls: apmixedsys@1001e000 { ++ compatible = "mediatek,mt7981-fixed-plls"; ++ reg = <0x1001e000 0x1000>; ++ #clock-cells = <1>; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ topckgen: topckgen@1001b000 { ++ compatible = "mediatek,mt7981-topckgen"; ++ reg = <0x1001b000 0x1000>; ++ clock-parent = <&fixed_plls>; ++ #clock-cells = <1>; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ infracfg_ao: infracfg_ao@10001000 { ++ compatible = "mediatek,mt7981-infracfg_ao"; ++ reg = <0x10001000 0x80>; ++ clock-parent = <&infracfg>; ++ #clock-cells = <1>; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ infracfg: infracfg@10001000 { ++ compatible = "mediatek,mt7981-infracfg"; ++ reg = <0x10001000 0x30>; ++ clock-parent = <&topckgen>; ++ #clock-cells = <1>; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ pinctrl: pinctrl@11d00000 { ++ compatible = "mediatek,mt7981-pinctrl"; ++ reg = <0x11d00000 0x1000>, ++ <0x11c00000 0x1000>, ++ <0x11c10000 0x1000>, ++ <0x11d20000 0x1000>, ++ <0x11e00000 0x1000>, ++ <0x11e20000 0x1000>, ++ <0x11f00000 0x1000>, ++ <0x11f10000 0x1000>, ++ <0x1000b000 0x1000>; ++ reg-names = "gpio_base", "iocfg_rt_base", "iocfg_rm_base", ++ "iocfg_rb_base", "iocfg_lb_base", "iocfg_bl_base", ++ "iocfg_tm_base", "iocfg_tl_base", "eint"; ++ gpio: gpio-controller { ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ }; ++ ++ pwm: pwm@10048000 { ++ compatible = "mediatek,mt7981-pwm"; ++ reg = <0x10048000 0x1000>; ++ #clock-cells = <1>; ++ #pwm-cells = <2>; ++ interrupts = ; ++ clocks = <&infracfg CK_INFRA_PWM>, ++ <&infracfg_ao CK_INFRA_PWM_BSEL>, ++ <&infracfg_ao CK_INFRA_PWM1_CK>, ++ <&infracfg_ao CK_INFRA_PWM2_CK>, ++ /* FIXME */ ++ <&infracfg_ao CK_INFRA_PWM2_CK>; ++ assigned-clocks = <&topckgen CK_TOP_PWM_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>; ++ clock-names = "top", "main", "pwm1", "pwm2", "pwm3"; ++ status = "disabled"; ++ }; ++ ++ uart0: serial@11002000 { ++ compatible = "mediatek,hsuart"; ++ reg = <0x11002000 0x400>; ++ interrupts = ; ++ clocks = <&infracfg_ao CK_INFRA_UART0_CK>; ++ assigned-clocks = <&topckgen CK_TOP_UART_SEL>, ++ <&infracfg_ao CK_INFRA_UART0_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>, ++ <&infracfg CK_INFRA_UART>; ++ mediatek,force-highspeed; ++ status = "disabled"; ++ u-boot,dm-pre-reloc; ++ }; ++ ++ uart1: serial@11003000 { ++ compatible = "mediatek,hsuart"; ++ reg = <0x11003000 0x400>; ++ interrupts = ; ++ clocks = <&infracfg_ao CK_INFRA_UART1_CK>; ++ assigned-clocks = <&topckgen CK_TOP_UART_SEL>, ++ <&infracfg_ao CK_INFRA_UART1_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>, ++ <&infracfg CK_INFRA_UART>; ++ mediatek,force-highspeed; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@11004000 { ++ compatible = "mediatek,hsuart"; ++ reg = <0x11004000 0x400>; ++ interrupts = ; ++ clocks = <&infracfg_ao CK_INFRA_UART2_CK>; ++ assigned-clocks = <&topckgen CK_TOP_UART_SEL>, ++ <&infracfg_ao CK_INFRA_UART2_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_CKSQ_40M>, ++ <&infracfg CK_INFRA_UART>; ++ mediatek,force-highspeed; ++ status = "disabled"; ++ }; ++ ++ snand: snand@11005000 { ++ compatible = "mediatek,mt7986-snand"; ++ reg = <0x11005000 0x1000>, ++ <0x11006000 0x1000>; ++ reg-names = "nfi", "ecc"; ++ clocks = <&infracfg_ao CK_INFRA_SPINFI1_CK>, ++ <&infracfg_ao CK_INFRA_NFI1_CK>, ++ <&infracfg_ao CK_INFRA_NFI_HCK_CK>; ++ clock-names = "pad_clk", "nfi_clk", "nfi_hclk"; ++ assigned-clocks = <&topckgen CK_TOP_SPINFI_SEL>, ++ <&topckgen CK_TOP_NFI1X_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_M_D8>, ++ <&topckgen CK_TOP_CB_M_D8>; ++ status = "disabled"; ++ }; ++ ++ ethsys: syscon@15000000 { ++ compatible = "mediatek,mt7981-ethsys", "syscon"; ++ reg = <0x15000000 0x1000>; ++ clock-parent = <&topckgen>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ eth: ethernet@15100000 { ++ compatible = "mediatek,mt7981-eth", "syscon"; ++ reg = <0x15100000 0x20000>; ++ resets = <ðsys ETHSYS_FE_RST>; ++ reset-names = "fe"; ++ mediatek,ethsys = <ðsys>; ++ mediatek,sgmiisys = <&sgmiisys0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ sgmiisys0: syscon@10060000 { ++ compatible = "mediatek,mt7986-sgmiisys", "syscon"; ++ reg = <0x10060000 0x1000>; ++ pn_swap; ++ #clock-cells = <1>; ++ }; ++ ++ sgmiisys1: syscon@10070000 { ++ compatible = "mediatek,mt7986-sgmiisys", "syscon"; ++ reg = <0x10070000 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ spi0: spi@1100a000 { ++ compatible = "mediatek,ipm-spi"; ++ reg = <0x1100a000 0x100>; ++ clocks = <&infracfg_ao CK_INFRA_SPI0_CK>, ++ <&topckgen CK_TOP_SPI_SEL>; ++ assigned-clocks = <&topckgen CK_TOP_SPI_SEL>, ++ <&infracfg CK_INFRA_SPI0_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>, ++ <&topckgen CK_INFRA_ISPI0>; ++ clock-names = "sel-clk", "spi-clk"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ spi1: spi@1100b000 { ++ compatible = "mediatek,ipm-spi"; ++ reg = <0x1100b000 0x100>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ spi2: spi@11009000 { ++ compatible = "mediatek,ipm-spi"; ++ reg = <0x11009000 0x100>; ++ clocks = <&infracfg_ao CK_INFRA_SPI0_CK>, ++ <&topckgen CK_TOP_SPI_SEL>; ++ assigned-clocks = <&topckgen CK_TOP_SPI_SEL>, ++ <&infracfg CK_INFRA_SPI0_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_M_D2>, ++ <&topckgen CK_INFRA_ISPI0>; ++ clock-names = "sel-clk", "spi-clk"; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ mmc0: mmc@11230000 { ++ compatible = "mediatek,mt7981-mmc"; ++ reg = <0x11230000 0x1000>, ++ <0x11C20000 0x1000>; ++ interrupts = ; ++ clocks = <&topckgen CK_TOP_EMMC_400M>, ++ <&topckgen CK_TOP_EMMC_208M>, ++ <&infracfg_ao CK_INFRA_MSDC_CK>; ++ assigned-clocks = <&topckgen CK_TOP_EMMC_400M_SEL>, ++ <&topckgen CK_TOP_EMMC_208M_SEL>; ++ assigned-clock-parents = <&topckgen CK_TOP_CB_NET2_D2>, ++ <&topckgen CK_TOP_CB_M_D2>; ++ clock-names = "source", "hclk", "source_cg"; ++ status = "disabled"; ++ }; ++ ++}; +--- a/arch/arm/mach-mediatek/Kconfig ++++ b/arch/arm/mach-mediatek/Kconfig +@@ -40,6 +40,14 @@ config TARGET_MT7629 + including DDR3, crypto engine, 3x3 11n/ac Wi-Fi, Gigabit Ethernet, + switch, USB3.0, PCIe, UART, SPI, I2C and PWM. + ++config TARGET_MT7981 ++ bool "MediaTek MT7981 SoC" ++ select ARM64 ++ help ++ The MediaTek MT7981 is a ARM64-based SoC with a dual-core Cortex-A53. ++ including UART, SPI, USB, NAND, SNFI, PWM, Gigabit Ethernet, I2C, ++ built-in Wi-Fi, and PCIe. ++ + config TARGET_MT7986 + bool "MediaTek MT7986 SoC" + select ARM64 +@@ -92,6 +100,7 @@ config SYS_BOARD + default "mt7622" if TARGET_MT7622 + default "mt7623" if TARGET_MT7623 + default "mt7629" if TARGET_MT7629 ++ default "mt7981" if TARGET_MT7981 + default "mt7986" if TARGET_MT7986 + default "mt8183" if TARGET_MT8183 + default "mt8512" if TARGET_MT8512 +@@ -108,6 +117,7 @@ config SYS_CONFIG_NAME + default "mt7622" if TARGET_MT7622 + default "mt7623" if TARGET_MT7623 + default "mt7629" if TARGET_MT7629 ++ default "mt7981" if TARGET_MT7981 + default "mt7986" if TARGET_MT7986 + default "mt8183" if TARGET_MT8183 + default "mt8512" if TARGET_MT8512 +@@ -123,7 +133,7 @@ config MTK_BROM_HEADER_INFO + string + default "media=nor" if TARGET_MT8518 || TARGET_MT8512 || TARGET_MT7629 || TARGET_MT7622 + default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8183 +- default "media=snand;nandinfo=2k+64" if TARGET_MT7986 ++ default "media=snand;nandinfo=2k+64" if TARGET_MT7981 || TARGET_MT7986 + default "lk=1" if TARGET_MT7623 + + endif +--- a/arch/arm/mach-mediatek/Makefile ++++ b/arch/arm/mach-mediatek/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += mt8512/ + obj-$(CONFIG_TARGET_MT7622) += mt7622/ + obj-$(CONFIG_TARGET_MT7623) += mt7623/ + obj-$(CONFIG_TARGET_MT7629) += mt7629/ ++obj-$(CONFIG_TARGET_MT7981) += mt7981/ + obj-$(CONFIG_TARGET_MT7986) += mt7986/ + obj-$(CONFIG_TARGET_MT8183) += mt8183/ + obj-$(CONFIG_TARGET_MT8516) += mt8516/ +--- /dev/null ++++ b/arch/arm/mach-mediatek/mt7981/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += init.o ++obj-y += lowlevel_init.o +--- /dev/null ++++ b/arch/arm/mach-mediatek/mt7981/init.c +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++int print_cpuinfo(void) ++{ ++ printf("CPU: MediaTek MT7981\n"); ++ return 0; ++} ++ ++int dram_init(void) ++{ ++ gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_2G); ++ ++ return 0; ++} ++ ++void reset_cpu(ulong addr) ++{ ++ psci_system_reset(); ++} ++ ++static struct mm_region mt7981_mem_map[] = { ++ { ++ /* DDR */ ++ .virt = 0x40000000UL, ++ .phys = 0x40000000UL, ++ .size = 0x80000000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE, ++ }, { ++ .virt = 0x00000000UL, ++ .phys = 0x00000000UL, ++ .size = 0x40000000UL, ++ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | ++ PTE_BLOCK_NON_SHARE | ++ PTE_BLOCK_PXN | PTE_BLOCK_UXN ++ }, { ++ 0, ++ } ++}; ++ ++struct mm_region *mem_map = mt7981_mem_map; +--- /dev/null ++++ b/arch/arm/mach-mediatek/mt7981/lowlevel_init.S +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/* ++ * Switch from AArch64 EL2 to AArch32 EL2 ++ * @param inputs: ++ * x0: argument, zero ++ * x1: machine nr ++ * x2: fdt address ++ * x3: input argument ++ * x4: kernel entry point ++ * @param outputs for secure firmware: ++ * x0: function id ++ * x1: kernel entry point ++ * x2: machine nr ++ * x3: fdt address ++ * ++ * [1] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/mediatek/common/mtk_sip_svc.c ++*/ ++ ++.global armv8_el2_to_aarch32 ++armv8_el2_to_aarch32: ++ mov x3, x2 ++ mov x2, x1 ++ mov x1, x4 ++ mov x4, #0 ++ ldr x0, =0x82000200 /* MTK_SIP_KERNEL_BOOT_AARCH32 */ ++ SMC #0 ++ ret diff --git a/package/boot/uboot-mediatek/patches/002-0003-board-mediatek-add-MT7986-reference-boards.patch b/package/boot/uboot-mediatek/patches/002-0003-board-mediatek-add-MT7986-reference-boards.patch new file mode 100644 index 0000000000..8cbd57459d --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0003-board-mediatek-add-MT7986-reference-boards.patch @@ -0,0 +1,1148 @@ +From ab3f81920b4e47bd2894388540363700d5b1e59c Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 15:26:31 +0800 +Subject: [PATCH 03/31] board: mediatek: add MT7986 reference boards + +Add general board files based on MT7986 SoCs. + +MT7986 uses one mmc controller for booting from both SD and eMMC. +Both MT7986A and MT7986B use the same pins for spi controller. + +Configs for various boot types: +1. mt7986_rfb_defconfig - SPI-NOR and SPI-NAND for MT7986A/B +2. mt7986a_bpir3_emmc_defconfig - eMMC for MT7986A only +3. mt7986a_bpir3_sd_defconfig - SD for MT7986A only + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + arch/arm/dts/Makefile | 6 + + arch/arm/dts/mt7986a-emmc-rfb.dts | 16 ++ + arch/arm/dts/mt7986a-rfb.dts | 218 +++++++++++++++++++++++++++ + arch/arm/dts/mt7986a-sd-rfb.dts | 177 ++++++++++++++++++++++ + arch/arm/dts/mt7986b-emmc-rfb.dts | 16 ++ + arch/arm/dts/mt7986b-rfb.dts | 204 +++++++++++++++++++++++++ + arch/arm/dts/mt7986b-sd-rfb.dts | 173 +++++++++++++++++++++ + board/mediatek/mt7986/MAINTAINERS | 10 ++ + board/mediatek/mt7986/Makefile | 3 + + board/mediatek/mt7986/mt7986_rfb.c | 10 ++ + configs/mt7986_rfb_defconfig | 66 ++++++++ + configs/mt7986a_bpir3_emmc_defconfig | 64 ++++++++ + configs/mt7986a_bpir3_sd_defconfig | 64 ++++++++ + include/configs/mt7986.h | 26 ++++ + 14 files changed, 1053 insertions(+) + create mode 100644 arch/arm/dts/mt7986a-emmc-rfb.dts + create mode 100644 arch/arm/dts/mt7986a-rfb.dts + create mode 100644 arch/arm/dts/mt7986a-sd-rfb.dts + create mode 100644 arch/arm/dts/mt7986b-emmc-rfb.dts + create mode 100644 arch/arm/dts/mt7986b-rfb.dts + create mode 100644 arch/arm/dts/mt7986b-sd-rfb.dts + create mode 100644 board/mediatek/mt7986/MAINTAINERS + create mode 100644 board/mediatek/mt7986/Makefile + create mode 100644 board/mediatek/mt7986/mt7986_rfb.c + create mode 100644 configs/mt7986_rfb_defconfig + create mode 100644 configs/mt7986a_bpir3_emmc_defconfig + create mode 100644 configs/mt7986a_bpir3_sd_defconfig + create mode 100644 include/configs/mt7986.h + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -1205,6 +1205,12 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt7622-bananapi-bpi-r64.dtb \ + mt7623n-bananapi-bpi-r2.dtb \ + mt7629-rfb.dtb \ ++ mt7986a-rfb.dtb \ ++ mt7986b-rfb.dtb \ ++ mt7986a-sd-rfb.dtb \ ++ mt7986b-sd-rfb.dtb \ ++ mt7986a-emmc-rfb.dtb \ ++ mt7986b-emmc-rfb.dtb \ + mt8183-pumpkin.dtb \ + mt8512-bm1-emmc.dtb \ + mt8516-pumpkin.dtb \ +--- /dev/null ++++ b/arch/arm/dts/mt7986a-emmc-rfb.dts +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986a-rfb.dts" ++ ++/ { ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb", ++ "mediatek,mt7986-emmc-rfb"; ++ bl2_verify { ++ bl2_compatible = "emmc"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7986a-rfb.dts +@@ -0,0 +1,218 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7986-rfb"; ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ snfi_pins: snfi-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "snfi"; ++ }; ++ ++ clk { ++ pins = "SPI0_CLK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-pu { ++ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI0_MOSI", "SPI0_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_2"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ pwm_pins: pwm0-pins-func-1 { ++ mux { ++ function = "pwm"; ++ groups = "pwm0"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_51"; ++ }; ++ ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-dsl { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; ++ }; ++ ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&snand { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&snfi_pins>; ++ status = "okay"; ++ quad-spi; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nor@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ }; ++ ++ spi_nand@1 { ++ compatible = "spi-nand"; ++ reg = <1>; ++ spi-max-frequency = <52000000>; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <8>; ++ max-frequency = <52000000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++ non-removable; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7986a-sd-rfb.dts +@@ -0,0 +1,177 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7986-rfb"; ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb", ++ "mediatek,mt7986-sd-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_2"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ pwm_pins: pwm0-pins-func-1 { ++ mux { ++ function = "pwm"; ++ groups = "pwm0"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_51"; ++ }; ++ ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-dsl { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; ++ }; ++ ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nor@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ }; ++ ++ spi_nand@1 { ++ compatible = "spi-nand"; ++ reg = <1>; ++ spi-max-frequency = <52000000>; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <4>; ++ max-frequency = <52000000>; ++ cap-sd-highspeed; ++ r_smpl = <1>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_3p3v>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7986b-emmc-rfb.dts +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986a-rfb.dts" ++ ++/ { ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb", ++ "mediatek,mt7986-emmc-rfb"; ++ bl2_verify { ++ bl2_compatible = "emmc"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7986b-rfb.dts +@@ -0,0 +1,204 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7986-rfb"; ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ snfi_pins: snfi-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "snfi"; ++ }; ++ ++ clk { ++ pins = "SPI0_CLK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-pu { ++ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI0_MOSI", "SPI0_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_2"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ pwm_pins: pwm0-pins-func-1 { ++ mux { ++ function = "pwm"; ++ groups = "pwm0"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_45"; ++ input-schmitt-enable; ++ }; ++ ++ conf-cmd-dat { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO", ++ "SPI0_CS", "SPI0_HOLD", "SPI0_WP", ++ "SPI1_CLK", "SPI1_MOSI", "SPI1_MISO"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-clk { ++ pins = "SPI1_CS"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-rst { ++ pins = "PWM1"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&snand { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&snfi_pins>; ++ status = "okay"; ++ quad-spi; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nor@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ }; ++ ++ spi_nand@1 { ++ compatible = "spi-nand"; ++ reg = <1>; ++ spi-max-frequency = <52000000>; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <8>; ++ max-frequency = <52000000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ vmmc-supply = <®_3p3v>; ++ non-removable; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7986b-sd-rfb.dts +@@ -0,0 +1,173 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7986-rfb"; ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb", ++ "mediatek,mt7986-sd-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_2"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ pwm_pins: pwm0-pins-func-1 { ++ mux { ++ function = "pwm"; ++ groups = "pwm0"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_45"; ++ input-schmitt-enable; ++ }; ++ ++ conf-cmd-dat { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO", ++ "SPI0_CS", "SPI0_HOLD", "SPI0_WP", ++ "SPI1_CLK", "SPI1_MOSI", "SPI1_MISO"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-clk { ++ pins = "SPI1_CS"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-rst { ++ pins = "PWM1"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nor@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ }; ++ ++ spi_nand@1 { ++ compatible = "spi-nand"; ++ reg = <1>; ++ spi-max-frequency = <52000000>; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <4>; ++ max-frequency = <52000000>; ++ cap-sd-highspeed; ++ r_smpl = <1>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_3p3v>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/board/mediatek/mt7986/MAINTAINERS +@@ -0,0 +1,10 @@ ++MT7986 ++M: Sam Shih ++S: Maintained ++F: board/mediatek/mt7986 ++F: include/configs/mt7986.h ++F: configs/mt7986_rfb_defconfig ++F: configs/mt7986a_emmc_rfb_defconfig ++F: configs/mt7986a_sd_rfb_defconfig ++F: configs/mt7986b_emmc_rfb_defconfig ++F: configs/mt7986b_sd_rfb_defconfig +--- /dev/null ++++ b/board/mediatek/mt7986/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += mt7986_rfb.o +--- /dev/null ++++ b/board/mediatek/mt7986/mt7986_rfb.c +@@ -0,0 +1,10 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++int board_init(void) ++{ ++ return 0; ++} +--- /dev/null ++++ b/configs/mt7986_rfb_defconfig +@@ -0,0 +1,66 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-rfb" ++CONFIG_TARGET_MT7986=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_AUTOBOOT is not set ++CONFIG_DEFAULT_FDT_FILE="mt7986a-rfb" ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_SYS_CBSIZE=512 ++CONFIG_SYS_PBSIZE=1049 ++# 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_UNLZ4 is not set ++# CONFIG_CMD_UNZIP is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_SMC=y ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++# CONFIG_MMC is not set ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_DM_SPI_FLASH=y ++CONFIG_SPI_FLASH_SFDP_SUPPORT=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_SPI_FLASH_MTD=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPIM=y ++CONFIG_HEXDUMP=y +--- /dev/null ++++ b/configs/mt7986a_bpir3_emmc_defconfig +@@ -0,0 +1,64 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x80000 ++CONFIG_ENV_OFFSET=0x300000 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-emmc-rfb" ++CONFIG_TARGET_MT7986=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_AUTOBOOT is not set ++CONFIG_DEFAULT_FDT_FILE="mt7986a-emmc-rfb" ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_SYS_CBSIZE=512 ++CONFIG_SYS_PBSIZE=1049 ++# 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_UNLZ4 is not set ++# CONFIG_CMD_UNZIP is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_GPT_RENAME=y ++CONFIG_CMD_LSBLK=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_READ=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_PARTITION_TYPE_GUID=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_FAT_WRITE=y ++CONFIG_HEXDUMP=y ++# CONFIG_EFI_LOADER is not set +--- /dev/null ++++ b/configs/mt7986a_bpir3_sd_defconfig +@@ -0,0 +1,64 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x80000 ++CONFIG_ENV_OFFSET=0x300000 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-sd-rfb" ++CONFIG_TARGET_MT7986=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_AUTOBOOT is not set ++CONFIG_DEFAULT_FDT_FILE="mt7986a-sd-rfb" ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_SYS_CBSIZE=512 ++CONFIG_SYS_PBSIZE=1049 ++# 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_UNLZ4 is not set ++# CONFIG_CMD_UNZIP is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_GPT_RENAME=y ++CONFIG_CMD_LSBLK=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_READ=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_PARTITION_TYPE_GUID=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_FAT_WRITE=y ++CONFIG_HEXDUMP=y ++# CONFIG_EFI_LOADER is not set +--- /dev/null ++++ b/include/configs/mt7986.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Configuration for MediaTek MT7986 SoC ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#ifndef __MT7986_H ++#define __MT7986_H ++ ++#include ++ ++#define CONFIG_SYS_NONCACHED_MEMORY SZ_1M ++#define CONFIG_SYS_MMC_ENV_DEV 0 ++ ++/* Uboot definition */ ++#define CONFIG_SYS_UBOOT_BASE CONFIG_SYS_TEXT_BASE ++ ++/* SPL -> Uboot */ ++#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE ++ ++/* DRAM */ ++#define CONFIG_SYS_SDRAM_BASE 0x40000000 ++ ++#endif diff --git a/package/boot/uboot-mediatek/patches/002-0004-board-mediatek-add-MT7981-reference-boards.patch b/package/boot/uboot-mediatek/patches/002-0004-board-mediatek-add-MT7981-reference-boards.patch new file mode 100644 index 0000000000..6e08843bdc --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0004-board-mediatek-add-MT7981-reference-boards.patch @@ -0,0 +1,779 @@ +From 89a31bfa05c384a2b4e56ddb9814633325b7feab Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 16:02:37 +0800 +Subject: [PATCH 04/31] board: mediatek: add MT7981 reference boards + +This patch adds general board files based on MT7981 SoCs. + +MT7981 uses one mmc controller for booting from both SD and eMMC, and the +pins of mmc controller are also shared with spi controller. +So three configs are need for these boot types: + +1. mt7981_rfb_defconfig - SPI-NOR and SPI-NAND +2. mt7981_emmc_rfb_defconfig - eMMC only +3. mt7981_sd_rfb_defconfig - SD only + +Signed-off-by: Weijie Gao +--- + arch/arm/dts/Makefile | 3 + + arch/arm/dts/mt7981-emmc-rfb.dts | 139 +++++++++++++++++++++++ + arch/arm/dts/mt7981-rfb.dts | 173 +++++++++++++++++++++++++++++ + arch/arm/dts/mt7981-sd-rfb.dts | 139 +++++++++++++++++++++++ + board/mediatek/mt7981/MAINTAINERS | 10 ++ + board/mediatek/mt7981/Makefile | 3 + + board/mediatek/mt7981/mt7981_rfb.c | 10 ++ + configs/mt7981_emmc_rfb_defconfig | 64 +++++++++++ + configs/mt7981_rfb_defconfig | 69 ++++++++++++ + configs/mt7981_sd_rfb_defconfig | 64 +++++++++++ + include/configs/mt7981.h | 26 +++++ + 11 files changed, 700 insertions(+) + create mode 100644 arch/arm/dts/mt7981-emmc-rfb.dts + create mode 100644 arch/arm/dts/mt7981-rfb.dts + create mode 100644 arch/arm/dts/mt7981-sd-rfb.dts + create mode 100644 board/mediatek/mt7981/MAINTAINERS + create mode 100644 board/mediatek/mt7981/Makefile + create mode 100644 board/mediatek/mt7981/mt7981_rfb.c + create mode 100644 configs/mt7981_emmc_rfb_defconfig + create mode 100644 configs/mt7981_rfb_defconfig + create mode 100644 configs/mt7981_sd_rfb_defconfig + create mode 100644 include/configs/mt7981.h + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -1205,6 +1205,9 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt7622-bananapi-bpi-r64.dtb \ + mt7623n-bananapi-bpi-r2.dtb \ + mt7629-rfb.dtb \ ++ mt7981-rfb.dtb \ ++ mt7981-emmc-rfb.dtb \ ++ mt7981-sd-rfb.dtb \ + mt7986a-rfb.dtb \ + mt7986b-rfb.dtb \ + mt7986a-sd-rfb.dtb \ +--- /dev/null ++++ b/arch/arm/dts/mt7981-emmc-rfb.dts +@@ -0,0 +1,139 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7981-rfb"; ++ compatible = "mediatek,mt7981", "mediatek,mt7981-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_1"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 */ ++ one_pwm_pins: one-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 and pin14 as pwm1 */ ++ two_pwm_pins: two-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0"; ++ }; ++ }; ++ ++ /* pin15 as pwm0, pin14 as pwm1, pin7 as pwm2 */ ++ three_pwm_pins: three-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0", "pwm2"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_45"; ++ }; ++ conf-cmd-dat { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO", ++ "SPI0_CS", "SPI0_HOLD", "SPI0_WP", ++ "SPI1_CLK", "SPI1_MOSI", "SPI1_MISO"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ conf-clk { ++ pins = "SPI1_CS"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ conf-rst { ++ pins = "PWM0"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&two_pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <8>; ++ max-frequency = <52000000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ vmmc-supply = <®_3p3v>; ++ non-removable; ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7981-rfb.dts +@@ -0,0 +1,173 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7981-rfb"; ++ compatible = "mediatek,mt7981", "mediatek,mt7981-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ spi2_flash_pins: spi2-spi2-pins { ++ mux { ++ function = "spi"; ++ groups = "spi2", "spi2_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_1"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 */ ++ one_pwm_pins: one-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 and pin14 as pwm1 */ ++ two_pwm_pins: two-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0"; ++ }; ++ }; ++ ++ /* pin15 as pwm0, pin14 as pwm1, pin7 as pwm2 */ ++ three_pwm_pins: three-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0", "pwm2"; ++ }; ++ }; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nand@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ }; ++}; ++ ++&spi2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nor@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&two_pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; +--- /dev/null ++++ b/arch/arm/dts/mt7981-sd-rfb.dts +@@ -0,0 +1,139 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7981-rfb"; ++ compatible = "mediatek,mt7981", "mediatek,mt7981-sd-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_1"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 */ ++ one_pwm_pins: one-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 and pin14 as pwm1 */ ++ two_pwm_pins: two-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0"; ++ }; ++ }; ++ ++ /* pin15 as pwm0, pin14 as pwm1, pin7 as pwm2 */ ++ three_pwm_pins: three-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0", "pwm2"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_45"; ++ }; ++ conf-cmd-dat { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO", ++ "SPI0_CS", "SPI0_HOLD", "SPI0_WP", ++ "SPI1_CLK", "SPI1_MOSI", "SPI1_MISO"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ conf-clk { ++ pins = "SPI1_CS"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ conf-rst { ++ pins = "PWM0"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&two_pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <4>; ++ max-frequency = <52000000>; ++ cap-sd-highspeed; ++ r_smpl = <0>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_3p3v>; ++ status = "okay"; ++}; +--- /dev/null ++++ b/board/mediatek/mt7981/MAINTAINERS +@@ -0,0 +1,10 @@ ++MT7981 ++M: Sam Shih ++S: Maintained ++F: board/mediatek/mt7981 ++F: include/configs/mt7981.h ++F: configs/mt7981_emmc_rfb_defconfig ++F: configs/mt7981_rfb_defconfig ++F: configs/mt7981_sd_rfb_defconfig ++F: configs/mt7981_spim_nand_rfb_defconfig ++F: configs/mt7981_spim_nor_rfb_defconfig +--- /dev/null ++++ b/board/mediatek/mt7981/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += mt7981_rfb.o +--- /dev/null ++++ b/board/mediatek/mt7981/mt7981_rfb.c +@@ -0,0 +1,10 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++int board_init(void) ++{ ++ return 0; ++} +--- /dev/null ++++ b/configs/mt7981_emmc_rfb_defconfig +@@ -0,0 +1,64 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x80000 ++CONFIG_ENV_OFFSET=0x300000 ++CONFIG_DEFAULT_DEVICE_TREE="mt7981-emmc-rfb" ++CONFIG_TARGET_MT7981=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_AUTOBOOT is not set ++CONFIG_DEFAULT_FDT_FILE="mt7981-emmc-rfb" ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7981> " ++CONFIG_SYS_CBSIZE=512 ++CONFIG_SYS_PBSIZE=1049 ++# 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_UNLZ4 is not set ++# CONFIG_CMD_UNZIP is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_GPT_RENAME=y ++CONFIG_CMD_LSBLK=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_READ=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_PARTITION_TYPE_GUID=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_FAT_WRITE=y ++CONFIG_HEXDUMP=y ++# CONFIG_EFI_LOADER is not set +--- /dev/null ++++ b/configs/mt7981_rfb_defconfig +@@ -0,0 +1,69 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7981-rfb" ++CONFIG_TARGET_MT7981=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_AUTOBOOT is not set ++CONFIG_DEFAULT_FDT_FILE="mt7981-rfb" ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7981> " ++CONFIG_SYS_CBSIZE=512 ++CONFIG_SYS_PBSIZE=1049 ++# 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_UNLZ4 is not set ++# CONFIG_CMD_UNZIP is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_SMC=y ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_BLK=y ++CONFIG_HAVE_BLOCK_DEVICE=y ++CONFIG_CLK=y ++# CONFIG_MMC is not set ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_DM_SPI_FLASH=y ++CONFIG_SPI_FLASH_SFDP_SUPPORT=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_SPI_FLASH_MTD=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPIM=y ++CONFIG_HEXDUMP=y ++# CONFIG_EFI_LOADER is not set +--- /dev/null ++++ b/configs/mt7981_sd_rfb_defconfig +@@ -0,0 +1,64 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x80000 ++CONFIG_ENV_OFFSET=0x300000 ++CONFIG_DEFAULT_DEVICE_TREE="mt7981-sd-rfb" ++CONFIG_TARGET_MT7981=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_AUTOBOOT is not set ++CONFIG_DEFAULT_FDT_FILE="mt7981-sd-rfb" ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7981> " ++CONFIG_SYS_CBSIZE=512 ++CONFIG_SYS_PBSIZE=1049 ++# 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_UNLZ4 is not set ++# CONFIG_CMD_UNZIP is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_GPT_RENAME=y ++CONFIG_CMD_LSBLK=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_READ=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_PARTITION_TYPE_GUID=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_FAT_WRITE=y ++CONFIG_HEXDUMP=y ++# CONFIG_EFI_LOADER is not set +--- /dev/null ++++ b/include/configs/mt7981.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Configuration for MediaTek MT7981 SoC ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#ifndef __MT7981_H ++#define __MT7981_H ++ ++#include ++ ++#define CONFIG_SYS_NONCACHED_MEMORY SZ_1M ++#define CONFIG_SYS_MMC_ENV_DEV 0 ++ ++/* Uboot definition */ ++#define CONFIG_SYS_UBOOT_BASE CONFIG_SYS_TEXT_BASE ++ ++/* SPL -> Uboot */ ++#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE ++ ++/* DRAM */ ++#define CONFIG_SYS_SDRAM_BASE 0x40000000 ++ ++#endif diff --git a/package/boot/uboot-mediatek/patches/002-0005-mmc-mediatek-add-support-for-MediaTek-MT7891-MT7986-.patch b/package/boot/uboot-mediatek/patches/002-0005-mmc-mediatek-add-support-for-MediaTek-MT7891-MT7986-.patch new file mode 100644 index 0000000000..281c289c6a --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0005-mmc-mediatek-add-support-for-MediaTek-MT7891-MT7986-.patch @@ -0,0 +1,132 @@ +From 3831266fedf14ef415791a93dd03a9e637eb8b5e Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Tue, 26 Jul 2022 09:24:13 +0800 +Subject: [PATCH 05/31] mmc: mediatek: add support for MediaTek MT7891/MT7986 + SoCs + +Add eMMC and SDXC support for MediaTek MT7981/MT7986 SoCs +Both chips support SDXC and eMMC 4.5. MT7986A supports eMMC 5.1. + +Reviewed-by: Jaehoon Chung +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/mmc/mtk-sd.c | 68 ++++++++++++++++++++++++++++++++++---------- + 1 file changed, 53 insertions(+), 15 deletions(-) + +--- a/drivers/mmc/mtk-sd.c ++++ b/drivers/mmc/mtk-sd.c +@@ -1496,7 +1496,12 @@ static void msdc_init_hw(struct msdc_hos + /* Enable data & cmd interrupts */ + writel(DATA_INTS_MASK | CMD_INTS_MASK, &host->base->msdc_inten); + +- writel(0, tune_reg); ++ if (host->top_base) { ++ writel(0, &host->top_base->emmc_top_control); ++ writel(0, &host->top_base->emmc_top_cmd); ++ } else { ++ writel(0, tune_reg); ++ } + writel(0, &host->base->msdc_iocon); + + if (host->r_smpl) +@@ -1507,9 +1512,14 @@ static void msdc_init_hw(struct msdc_hos + writel(0x403c0046, &host->base->patch_bit0); + writel(0xffff4089, &host->base->patch_bit1); + +- if (host->dev_comp->stop_clk_fix) ++ if (host->dev_comp->stop_clk_fix) { + clrsetbits_le32(&host->base->patch_bit1, MSDC_PB1_STOP_DLY_M, + 3 << MSDC_PB1_STOP_DLY_S); ++ clrbits_le32(&host->base->sdc_fifo_cfg, ++ SDC_FIFO_CFG_WRVALIDSEL); ++ clrbits_le32(&host->base->sdc_fifo_cfg, ++ SDC_FIFO_CFG_RDVALIDSEL); ++ } + + if (host->dev_comp->busy_check) + clrbits_le32(&host->base->patch_bit1, (1 << 7)); +@@ -1544,15 +1554,28 @@ static void msdc_init_hw(struct msdc_hos + } + + if (host->dev_comp->data_tune) { +- setbits_le32(tune_reg, +- MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL); +- clrsetbits_le32(&host->base->patch_bit0, +- MSDC_INT_DAT_LATCH_CK_SEL_M, +- host->latch_ck << +- MSDC_INT_DAT_LATCH_CK_SEL_S); ++ if (host->top_base) { ++ setbits_le32(&host->top_base->emmc_top_control, ++ PAD_DAT_RD_RXDLY_SEL); ++ clrbits_le32(&host->top_base->emmc_top_control, ++ DATA_K_VALUE_SEL); ++ setbits_le32(&host->top_base->emmc_top_cmd, ++ PAD_CMD_RD_RXDLY_SEL); ++ } else { ++ setbits_le32(tune_reg, ++ MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL); ++ clrsetbits_le32(&host->base->patch_bit0, ++ MSDC_INT_DAT_LATCH_CK_SEL_M, ++ host->latch_ck << ++ MSDC_INT_DAT_LATCH_CK_SEL_S); ++ } + } else { + /* choose clock tune */ +- setbits_le32(tune_reg, MSDC_PAD_TUNE_RXDLYSEL); ++ if (host->top_base) ++ setbits_le32(&host->top_base->emmc_top_control, ++ PAD_RXDLY_SEL); ++ else ++ setbits_le32(tune_reg, MSDC_PAD_TUNE_RXDLYSEL); + } + + if (host->dev_comp->builtin_pad_ctrl) { +@@ -1604,12 +1627,6 @@ static void msdc_init_hw(struct msdc_hos + clrsetbits_le32(&host->base->sdc_cfg, SDC_CFG_DTOC_M, + 3 << SDC_CFG_DTOC_S); + +- if (host->dev_comp->stop_clk_fix) { +- clrbits_le32(&host->base->sdc_fifo_cfg, +- SDC_FIFO_CFG_WRVALIDSEL); +- clrbits_le32(&host->base->sdc_fifo_cfg, +- SDC_FIFO_CFG_RDVALIDSEL); +- } + + host->def_tune_para.iocon = readl(&host->base->msdc_iocon); + host->def_tune_para.pad_tune = readl(&host->base->pad_tune); +@@ -1792,6 +1809,25 @@ static const struct msdc_compatible mt76 + .enhance_rx = false + }; + ++static const struct msdc_compatible mt7986_compat = { ++ .clk_div_bits = 12, ++ .pad_tune0 = true, ++ .async_fifo = true, ++ .data_tune = true, ++ .busy_check = true, ++ .stop_clk_fix = true, ++ .enhance_rx = true, ++}; ++ ++static const struct msdc_compatible mt7981_compat = { ++ .clk_div_bits = 12, ++ .pad_tune0 = true, ++ .async_fifo = true, ++ .data_tune = true, ++ .busy_check = true, ++ .stop_clk_fix = true, ++}; ++ + static const struct msdc_compatible mt8512_compat = { + .clk_div_bits = 12, + .pad_tune0 = true, +@@ -1824,6 +1860,8 @@ static const struct udevice_id msdc_ids[ + { .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,mt7986-mmc", .data = (ulong)&mt7986_compat }, ++ { .compatible = "mediatek,mt7981-mmc", .data = (ulong)&mt7981_compat }, + { .compatible = "mediatek,mt8512-mmc", .data = (ulong)&mt8512_compat }, + { .compatible = "mediatek,mt8516-mmc", .data = (ulong)&mt8516_compat }, + { .compatible = "mediatek,mt8183-mmc", .data = (ulong)&mt8183_compat }, diff --git a/package/boot/uboot-mediatek/patches/002-0006-net-mediatek-use-a-struct-to-cover-variations-of-all.patch b/package/boot/uboot-mediatek/patches/002-0006-net-mediatek-use-a-struct-to-cover-variations-of-all.patch new file mode 100644 index 0000000000..2a1f5892d8 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0006-net-mediatek-use-a-struct-to-cover-variations-of-all.patch @@ -0,0 +1,163 @@ +From 5c5af768c4cceaa9d7497c3e5bfbc9d1ea8b279c Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Tue, 26 Jul 2022 10:44:57 +0800 +Subject: [PATCH 06/31] net: mediatek: use a struct to cover variations of all + SoCs + +Using a single soc id to control different initialization and TX/RX flow +for all SoCs is not extensible if more hardware variations are added in +the future. + +This patch introduces a struct to replace the original mtk_soc to allow +the driver be able handle newer hardwares. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/net/mtk_eth.c | 56 ++++++++++++++++++++++++++++++------------- + drivers/net/mtk_eth.h | 25 ++++++++++++++++++- + 2 files changed, 64 insertions(+), 17 deletions(-) + +--- a/drivers/net/mtk_eth.c ++++ b/drivers/net/mtk_eth.c +@@ -142,11 +142,15 @@ enum mtk_switch { + SW_MT7531 + }; + +-enum mtk_soc { +- SOC_MT7623, +- SOC_MT7629, +- SOC_MT7622, +- SOC_MT7621 ++/* struct mtk_soc_data - This is the structure holding all differences ++ * among various plaforms ++ * @caps Flags shown the extra capability for the SoC ++ * @ana_rgc3: The offset for register ANA_RGC3 related to ++ * sgmiisys syscon ++ */ ++struct mtk_soc_data { ++ u32 caps; ++ u32 ana_rgc3; + }; + + struct mtk_eth_priv { +@@ -171,7 +175,7 @@ struct mtk_eth_priv { + int (*mmd_write)(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg, + u16 val); + +- enum mtk_soc soc; ++ const struct mtk_soc_data *soc; + int gmac_id; + int force_mode; + int speed; +@@ -679,7 +683,7 @@ static int mt7530_setup(struct mtk_eth_p + u32 val, txdrv; + int i; + +- if (priv->soc != SOC_MT7621) { ++ if (!MTK_HAS_CAPS(priv->soc->caps, MTK_TRGMII_MT7621_CLK)) { + /* Select 250MHz clk for RGMII mode */ + mtk_ethsys_rmw(priv, ETHSYS_CLKCFG0_REG, + ETHSYS_TRGMII_CLK_SEL362_5, 0); +@@ -1108,9 +1112,8 @@ static int mtk_phy_probe(struct udevice + static void mtk_sgmii_init(struct mtk_eth_priv *priv) + { + /* Set SGMII GEN2 speed(2.5G) */ +- clrsetbits_le32(priv->sgmii_base + ((priv->soc == SOC_MT7622) ? +- SGMSYS_GEN2_SPEED : SGMSYS_GEN2_SPEED_V2), +- SGMSYS_SPEED_2500, SGMSYS_SPEED_2500); ++ setbits_le32(priv->sgmii_base + priv->soc->ana_rgc3, ++ SGMSYS_SPEED_2500); + + /* Disable SGMII AN */ + clrsetbits_le32(priv->sgmii_base + SGMSYS_PCS_CONTROL_1, +@@ -1182,7 +1185,8 @@ static void mtk_mac_init(struct mtk_eth_ + mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr); + } + +- if (priv->soc == SOC_MT7623) { ++ if (MTK_HAS_CAPS(priv->soc->caps, MTK_GMAC1_TRGMII) && ++ !MTK_HAS_CAPS(priv->soc->caps, MTK_TRGMII_MT7621_CLK)) { + /* Lower Tx Driving for TRGMII path */ + for (i = 0 ; i < NUM_TRGMII_CTRL; i++) + mtk_gmac_write(priv, GMAC_TRGMII_TD_ODT(i), +@@ -1431,7 +1435,11 @@ static int mtk_eth_of_to_plat(struct ude + ofnode subnode; + int ret; + +- priv->soc = dev_get_driver_data(dev); ++ priv->soc = (const struct mtk_soc_data *)dev_get_driver_data(dev); ++ if (!priv->soc) { ++ dev_err(dev, "missing soc compatible data\n"); ++ return -EINVAL; ++ } + + pdata->iobase = (phys_addr_t)dev_remap_addr(dev); + +@@ -1544,11 +1552,27 @@ static int mtk_eth_of_to_plat(struct ude + return 0; + } + ++static const struct mtk_soc_data mt7629_data = { ++ .ana_rgc3 = 0x128, ++}; ++ ++static const struct mtk_soc_data mt7623_data = { ++ .caps = MT7623_CAPS, ++}; ++ ++static const struct mtk_soc_data mt7622_data = { ++ .ana_rgc3 = 0x2028, ++}; ++ ++static const struct mtk_soc_data mt7621_data = { ++ .caps = MT7621_CAPS, ++}; ++ + 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 }, ++ { .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data }, ++ { .compatible = "mediatek,mt7623-eth", .data = (ulong)&mt7623_data }, ++ { .compatible = "mediatek,mt7622-eth", .data = (ulong)&mt7622_data }, ++ { .compatible = "mediatek,mt7621-eth", .data = (ulong)&mt7621_data }, + {} + }; + +--- a/drivers/net/mtk_eth.h ++++ b/drivers/net/mtk_eth.h +@@ -9,8 +9,31 @@ + #ifndef _MTK_ETH_H_ + #define _MTK_ETH_H_ + +-/* Frame Engine Register Bases */ + #include ++ ++enum mkt_eth_capabilities { ++ MTK_TRGMII_BIT, ++ MTK_TRGMII_MT7621_CLK_BIT, ++ ++ /* PATH BITS */ ++ MTK_ETH_PATH_GMAC1_TRGMII_BIT, ++}; ++ ++#define MTK_TRGMII BIT(MTK_TRGMII_BIT) ++#define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) ++ ++/* Supported path present on SoCs */ ++#define MTK_ETH_PATH_GMAC1_TRGMII BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT) ++ ++#define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) ++ ++#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) ++ ++#define MT7621_CAPS (MTK_GMAC1_TRGMII | MTK_TRGMII_MT7621_CLK) ++ ++#define MT7623_CAPS (MTK_GMAC1_TRGMII) ++ ++/* Frame Engine Register Bases */ + #define PDMA_BASE 0x0800 + #define GDMA1_BASE 0x0500 + #define GDMA2_BASE 0x1500 diff --git a/package/boot/uboot-mediatek/patches/002-0007-net-mediatek-stop-using-bitfileds-for-DMA-descriptor.patch b/package/boot/uboot-mediatek/patches/002-0007-net-mediatek-stop-using-bitfileds-for-DMA-descriptor.patch new file mode 100644 index 0000000000..3cf45b7f3e --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0007-net-mediatek-stop-using-bitfileds-for-DMA-descriptor.patch @@ -0,0 +1,317 @@ +From b978c067075fddbac341bf551ebef29e78767b75 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 09:32:29 +0800 +Subject: [PATCH 07/31] net: mediatek: stop using bitfileds for DMA descriptors + +This patch is a preparation for adding a new version of PDMA of which the +DMA descriptor fields has changed. Using bitfields will result in a complex +modification. Convert bitfields to u32 units can solve this problem easily. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/net/mtk_eth.c | 144 ++++++++++++++---------------------------- + drivers/net/mtk_eth.h | 32 ++++++++++ + 2 files changed, 80 insertions(+), 96 deletions(-) + +--- a/drivers/net/mtk_eth.c ++++ b/drivers/net/mtk_eth.c +@@ -65,77 +65,6 @@ + (DP_DISCARD << MC_DP_S) | \ + (DP_DISCARD << UN_DP_S)) + +-struct pdma_rxd_info1 { +- u32 PDP0; +-}; +- +-struct pdma_rxd_info2 { +- u32 PLEN1 : 14; +- u32 LS1 : 1; +- u32 UN_USED : 1; +- u32 PLEN0 : 14; +- u32 LS0 : 1; +- u32 DDONE : 1; +-}; +- +-struct pdma_rxd_info3 { +- u32 PDP1; +-}; +- +-struct pdma_rxd_info4 { +- u32 FOE_ENTRY : 14; +- u32 CRSN : 5; +- u32 SP : 3; +- u32 L4F : 1; +- u32 L4VLD : 1; +- u32 TACK : 1; +- u32 IP4F : 1; +- u32 IP4 : 1; +- u32 IP6 : 1; +- u32 UN_USED : 4; +-}; +- +-struct pdma_rxdesc { +- struct pdma_rxd_info1 rxd_info1; +- struct pdma_rxd_info2 rxd_info2; +- struct pdma_rxd_info3 rxd_info3; +- struct pdma_rxd_info4 rxd_info4; +-}; +- +-struct pdma_txd_info1 { +- u32 SDP0; +-}; +- +-struct pdma_txd_info2 { +- u32 SDL1 : 14; +- u32 LS1 : 1; +- u32 BURST : 1; +- u32 SDL0 : 14; +- u32 LS0 : 1; +- u32 DDONE : 1; +-}; +- +-struct pdma_txd_info3 { +- u32 SDP1; +-}; +- +-struct pdma_txd_info4 { +- u32 VLAN_TAG : 16; +- u32 INS : 1; +- u32 RESV : 2; +- u32 UDF : 6; +- u32 FPORT : 3; +- u32 TSO : 1; +- u32 TUI_CO : 3; +-}; +- +-struct pdma_txdesc { +- struct pdma_txd_info1 txd_info1; +- struct pdma_txd_info2 txd_info2; +- struct pdma_txd_info3 txd_info3; +- struct pdma_txd_info4 txd_info4; +-}; +- + enum mtk_switch { + SW_NONE, + SW_MT7530, +@@ -151,13 +80,15 @@ enum mtk_switch { + struct mtk_soc_data { + u32 caps; + u32 ana_rgc3; ++ u32 txd_size; ++ u32 rxd_size; + }; + + struct mtk_eth_priv { + char pkt_pool[TOTAL_PKT_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); + +- struct pdma_txdesc *tx_ring_noc; +- struct pdma_rxdesc *rx_ring_noc; ++ void *tx_ring_noc; ++ void *rx_ring_noc; + + int rx_dma_owner_idx0; + int tx_cpu_owner_idx0; +@@ -1202,14 +1133,16 @@ static void mtk_mac_init(struct mtk_eth_ + static void mtk_eth_fifo_init(struct mtk_eth_priv *priv) + { + char *pkt_base = priv->pkt_pool; ++ struct mtk_tx_dma *txd; ++ struct mtk_rx_dma *rxd; + int i; + + mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0); + udelay(500); + +- memset(priv->tx_ring_noc, 0, NUM_TX_DESC * sizeof(struct pdma_txdesc)); +- memset(priv->rx_ring_noc, 0, NUM_RX_DESC * sizeof(struct pdma_rxdesc)); +- memset(priv->pkt_pool, 0, TOTAL_PKT_BUF_SIZE); ++ memset(priv->tx_ring_noc, 0, NUM_TX_DESC * priv->soc->txd_size); ++ memset(priv->rx_ring_noc, 0, NUM_RX_DESC * priv->soc->rxd_size); ++ memset(priv->pkt_pool, 0xff, TOTAL_PKT_BUF_SIZE); + + flush_dcache_range((ulong)pkt_base, + (ulong)(pkt_base + TOTAL_PKT_BUF_SIZE)); +@@ -1218,17 +1151,21 @@ static void mtk_eth_fifo_init(struct mtk + priv->tx_cpu_owner_idx0 = 0; + + for (i = 0; i < NUM_TX_DESC; i++) { +- priv->tx_ring_noc[i].txd_info2.LS0 = 1; +- priv->tx_ring_noc[i].txd_info2.DDONE = 1; +- priv->tx_ring_noc[i].txd_info4.FPORT = priv->gmac_id + 1; ++ txd = priv->tx_ring_noc + i * priv->soc->txd_size; ++ ++ txd->txd1 = virt_to_phys(pkt_base); ++ txd->txd2 = PDMA_TXD2_DDONE | PDMA_TXD2_LS0; ++ txd->txd4 = PDMA_TXD4_FPORT_SET(priv->gmac_id + 1); + +- priv->tx_ring_noc[i].txd_info1.SDP0 = virt_to_phys(pkt_base); + pkt_base += PKTSIZE_ALIGN; + } + + for (i = 0; i < NUM_RX_DESC; i++) { +- priv->rx_ring_noc[i].rxd_info2.PLEN0 = PKTSIZE_ALIGN; +- priv->rx_ring_noc[i].rxd_info1.PDP0 = virt_to_phys(pkt_base); ++ rxd = priv->rx_ring_noc + i * priv->soc->rxd_size; ++ ++ rxd->rxd1 = virt_to_phys(pkt_base); ++ rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN); ++ + pkt_base += PKTSIZE_ALIGN; + } + +@@ -1315,20 +1252,22 @@ static int mtk_eth_send(struct udevice * + { + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->tx_cpu_owner_idx0; ++ struct mtk_tx_dma *txd; + void *pkt_base; + +- if (!priv->tx_ring_noc[idx].txd_info2.DDONE) { ++ txd = priv->tx_ring_noc + idx * priv->soc->txd_size; ++ ++ if (!(txd->txd2 & PDMA_TXD2_DDONE)) { + debug("mtk-eth: TX DMA descriptor ring is full\n"); + return -EPERM; + } + +- pkt_base = (void *)phys_to_virt(priv->tx_ring_noc[idx].txd_info1.SDP0); ++ pkt_base = (void *)phys_to_virt(txd->txd1); + memcpy(pkt_base, packet, length); + flush_dcache_range((ulong)pkt_base, (ulong)pkt_base + + roundup(length, ARCH_DMA_MINALIGN)); + +- priv->tx_ring_noc[idx].txd_info2.SDL0 = length; +- priv->tx_ring_noc[idx].txd_info2.DDONE = 0; ++ txd->txd2 = PDMA_TXD2_LS0 | PDMA_TXD2_SDL0_SET(length); + + priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC; + mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0); +@@ -1340,16 +1279,20 @@ static int mtk_eth_recv(struct udevice * + { + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->rx_dma_owner_idx0; ++ struct mtk_rx_dma *rxd; + uchar *pkt_base; + u32 length; + +- if (!priv->rx_ring_noc[idx].rxd_info2.DDONE) { ++ rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size; ++ ++ if (!(rxd->rxd2 & PDMA_RXD2_DDONE)) { + debug("mtk-eth: RX DMA descriptor ring is empty\n"); + return -EAGAIN; + } + +- length = priv->rx_ring_noc[idx].rxd_info2.PLEN0; +- pkt_base = (void *)phys_to_virt(priv->rx_ring_noc[idx].rxd_info1.PDP0); ++ length = PDMA_RXD2_PLEN0_GET(rxd->rxd2); ++ ++ pkt_base = (void *)phys_to_virt(rxd->rxd1); + invalidate_dcache_range((ulong)pkt_base, (ulong)pkt_base + + roundup(length, ARCH_DMA_MINALIGN)); + +@@ -1363,10 +1306,11 @@ static int mtk_eth_free_pkt(struct udevi + { + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->rx_dma_owner_idx0; ++ struct mtk_rx_dma *rxd; ++ ++ rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size; + +- priv->rx_ring_noc[idx].rxd_info2.DDONE = 0; +- priv->rx_ring_noc[idx].rxd_info2.LS0 = 0; +- priv->rx_ring_noc[idx].rxd_info2.PLEN0 = PKTSIZE_ALIGN; ++ rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN); + + mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx); + priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC; +@@ -1393,11 +1337,11 @@ static int mtk_eth_probe(struct udevice + return ret; + + /* Prepare for tx/rx rings */ +- priv->tx_ring_noc = (struct pdma_txdesc *) +- noncached_alloc(sizeof(struct pdma_txdesc) * NUM_TX_DESC, ++ priv->tx_ring_noc = (void *) ++ noncached_alloc(priv->soc->txd_size * NUM_TX_DESC, + ARCH_DMA_MINALIGN); +- priv->rx_ring_noc = (struct pdma_rxdesc *) +- noncached_alloc(sizeof(struct pdma_rxdesc) * NUM_RX_DESC, ++ priv->rx_ring_noc = (void *) ++ noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC, + ARCH_DMA_MINALIGN); + + /* Set MAC mode */ +@@ -1554,18 +1498,26 @@ static int mtk_eth_of_to_plat(struct ude + + static const struct mtk_soc_data mt7629_data = { + .ana_rgc3 = 0x128, ++ .txd_size = sizeof(struct mtk_tx_dma), ++ .rxd_size = sizeof(struct mtk_rx_dma), + }; + + static const struct mtk_soc_data mt7623_data = { + .caps = MT7623_CAPS, ++ .txd_size = sizeof(struct mtk_tx_dma), ++ .rxd_size = sizeof(struct mtk_rx_dma), + }; + + static const struct mtk_soc_data mt7622_data = { + .ana_rgc3 = 0x2028, ++ .txd_size = sizeof(struct mtk_tx_dma), ++ .rxd_size = sizeof(struct mtk_rx_dma), + }; + + static const struct mtk_soc_data mt7621_data = { + .caps = MT7621_CAPS, ++ .txd_size = sizeof(struct mtk_tx_dma), ++ .rxd_size = sizeof(struct mtk_rx_dma), + }; + + static const struct udevice_id mtk_eth_ids[] = { +--- a/drivers/net/mtk_eth.h ++++ b/drivers/net/mtk_eth.h +@@ -10,6 +10,7 @@ + #define _MTK_ETH_H_ + + #include ++#include + + enum mkt_eth_capabilities { + MTK_TRGMII_BIT, +@@ -435,4 +436,35 @@ enum mkt_eth_capabilities { + #define PHY_POWER_SAVING_M 0x300 + #define PHY_POWER_SAVING_TX 0x0 + ++/* PDMA descriptors */ ++struct mtk_rx_dma { ++ unsigned int rxd1; ++ unsigned int rxd2; ++ unsigned int rxd3; ++ unsigned int rxd4; ++} __packed __aligned(4); ++ ++struct mtk_tx_dma { ++ unsigned int txd1; ++ unsigned int txd2; ++ unsigned int txd3; ++ unsigned int txd4; ++} __packed __aligned(4); ++ ++/* PDMA TXD fields */ ++#define PDMA_TXD2_DDONE BIT(31) ++#define PDMA_TXD2_LS0 BIT(30) ++#define PDMA_TXD2_SDL0_M GENMASK(29, 16) ++#define PDMA_TXD2_SDL0_SET(_v) FIELD_PREP(PDMA_TXD2_SDL0_M, (_v)) ++ ++#define PDMA_TXD4_FPORT_M GENMASK(27, 25) ++#define PDMA_TXD4_FPORT_SET(_v) FIELD_PREP(PDMA_TXD4_FPORT_M, (_v)) ++ ++/* PDMA RXD fields */ ++#define PDMA_RXD2_DDONE BIT(31) ++#define PDMA_RXD2_LS0 BIT(30) ++#define PDMA_RXD2_PLEN0_M GENMASK(29, 16) ++#define PDMA_RXD2_PLEN0_GET(_v) FIELD_GET(PDMA_RXD2_PLEN0_M, (_v)) ++#define PDMA_RXD2_PLEN0_SET(_v) FIELD_PREP(PDMA_RXD2_PLEN0_M, (_v)) ++ + #endif /* _MTK_ETH_H_ */ diff --git a/package/boot/uboot-mediatek/patches/002-0008-net-mediatek-add-support-for-PDMA-v2.patch b/package/boot/uboot-mediatek/patches/002-0008-net-mediatek-add-support-for-PDMA-v2.patch new file mode 100644 index 0000000000..0fc0f4cafb --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0008-net-mediatek-add-support-for-PDMA-v2.patch @@ -0,0 +1,298 @@ +From 2f53795aac940d960bc5f3b08a730c4d480fc5f6 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 09:56:30 +0800 +Subject: [PATCH 08/31] net: mediatek: add support for PDMA v2 + +This patch adds support for PDMA v2 hardware. The PDMA v2 has extended the +DMA descriptor to 8-words, and some of its fields have changed comparing +to the v1 hardware. + +Reviewed-by: Ramon Fried +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/net/mtk_eth.c | 54 ++++++++++++++++++++++++++++++++----------- + drivers/net/mtk_eth.h | 53 +++++++++++++++++++++++++++++++++++------- + 2 files changed, 86 insertions(+), 21 deletions(-) + +--- a/drivers/net/mtk_eth.c ++++ b/drivers/net/mtk_eth.c +@@ -76,10 +76,14 @@ enum mtk_switch { + * @caps Flags shown the extra capability for the SoC + * @ana_rgc3: The offset for register ANA_RGC3 related to + * sgmiisys syscon ++ * @pdma_base: Register base of PDMA block ++ * @txd_size: Tx DMA descriptor size. ++ * @rxd_size: Rx DMA descriptor size. + */ + struct mtk_soc_data { + u32 caps; + u32 ana_rgc3; ++ u32 pdma_base; + u32 txd_size; + u32 rxd_size; + }; +@@ -130,13 +134,13 @@ struct mtk_eth_priv { + + static void mtk_pdma_write(struct mtk_eth_priv *priv, u32 reg, u32 val) + { +- writel(val, priv->fe_base + PDMA_BASE + reg); ++ writel(val, priv->fe_base + priv->soc->pdma_base + reg); + } + + static void mtk_pdma_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, + u32 set) + { +- clrsetbits_le32(priv->fe_base + PDMA_BASE + reg, clr, set); ++ clrsetbits_le32(priv->fe_base + priv->soc->pdma_base + reg, clr, set); + } + + static void mtk_gdma_write(struct mtk_eth_priv *priv, int no, u32 reg, +@@ -1133,8 +1137,8 @@ static void mtk_mac_init(struct mtk_eth_ + static void mtk_eth_fifo_init(struct mtk_eth_priv *priv) + { + char *pkt_base = priv->pkt_pool; +- struct mtk_tx_dma *txd; +- struct mtk_rx_dma *rxd; ++ struct mtk_tx_dma_v2 *txd; ++ struct mtk_rx_dma_v2 *rxd; + int i; + + mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0); +@@ -1155,7 +1159,11 @@ static void mtk_eth_fifo_init(struct mtk + + txd->txd1 = virt_to_phys(pkt_base); + txd->txd2 = PDMA_TXD2_DDONE | PDMA_TXD2_LS0; +- txd->txd4 = PDMA_TXD4_FPORT_SET(priv->gmac_id + 1); ++ ++ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2)) ++ txd->txd5 = PDMA_V2_TXD5_FPORT_SET(priv->gmac_id + 1); ++ else ++ txd->txd4 = PDMA_V1_TXD4_FPORT_SET(priv->gmac_id + 1); + + pkt_base += PKTSIZE_ALIGN; + } +@@ -1164,7 +1172,11 @@ static void mtk_eth_fifo_init(struct mtk + rxd = priv->rx_ring_noc + i * priv->soc->rxd_size; + + rxd->rxd1 = virt_to_phys(pkt_base); +- rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN); ++ ++ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2)) ++ rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN); ++ else ++ rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN); + + pkt_base += PKTSIZE_ALIGN; + } +@@ -1193,6 +1205,9 @@ static int mtk_eth_start(struct udevice + reset_deassert(&priv->rst_fe); + mdelay(10); + ++ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2)) ++ setbits_le32(priv->fe_base + FE_GLO_MISC_REG, PDMA_VER_V2); ++ + /* Packets forward to PDMA */ + mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG, GDMA_FWD_TO_CPU); + +@@ -1227,7 +1242,7 @@ static void mtk_eth_stop(struct udevice + TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN, 0); + udelay(500); + +- wait_for_bit_le32(priv->fe_base + PDMA_BASE + PDMA_GLO_CFG_REG, ++ wait_for_bit_le32(priv->fe_base + priv->soc->pdma_base + PDMA_GLO_CFG_REG, + RX_DMA_BUSY | TX_DMA_BUSY, 0, 5000, 0); + } + +@@ -1252,7 +1267,7 @@ static int mtk_eth_send(struct udevice * + { + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->tx_cpu_owner_idx0; +- struct mtk_tx_dma *txd; ++ struct mtk_tx_dma_v2 *txd; + void *pkt_base; + + txd = priv->tx_ring_noc + idx * priv->soc->txd_size; +@@ -1267,7 +1282,10 @@ static int mtk_eth_send(struct udevice * + flush_dcache_range((ulong)pkt_base, (ulong)pkt_base + + roundup(length, ARCH_DMA_MINALIGN)); + +- txd->txd2 = PDMA_TXD2_LS0 | PDMA_TXD2_SDL0_SET(length); ++ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2)) ++ txd->txd2 = PDMA_TXD2_LS0 | PDMA_V2_TXD2_SDL0_SET(length); ++ else ++ txd->txd2 = PDMA_TXD2_LS0 | PDMA_V1_TXD2_SDL0_SET(length); + + priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC; + mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0); +@@ -1279,7 +1297,7 @@ static int mtk_eth_recv(struct udevice * + { + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->rx_dma_owner_idx0; +- struct mtk_rx_dma *rxd; ++ struct mtk_rx_dma_v2 *rxd; + uchar *pkt_base; + u32 length; + +@@ -1290,7 +1308,10 @@ static int mtk_eth_recv(struct udevice * + return -EAGAIN; + } + +- length = PDMA_RXD2_PLEN0_GET(rxd->rxd2); ++ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2)) ++ length = PDMA_V2_RXD2_PLEN0_GET(rxd->rxd2); ++ else ++ length = PDMA_V1_RXD2_PLEN0_GET(rxd->rxd2); + + pkt_base = (void *)phys_to_virt(rxd->rxd1); + invalidate_dcache_range((ulong)pkt_base, (ulong)pkt_base + +@@ -1306,11 +1327,14 @@ static int mtk_eth_free_pkt(struct udevi + { + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->rx_dma_owner_idx0; +- struct mtk_rx_dma *rxd; ++ struct mtk_rx_dma_v2 *rxd; + + rxd = priv->rx_ring_noc + idx * priv->soc->rxd_size; + +- rxd->rxd2 = PDMA_RXD2_PLEN0_SET(PKTSIZE_ALIGN); ++ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V2)) ++ rxd->rxd2 = PDMA_V2_RXD2_PLEN0_SET(PKTSIZE_ALIGN); ++ else ++ rxd->rxd2 = PDMA_V1_RXD2_PLEN0_SET(PKTSIZE_ALIGN); + + mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx); + priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC; +@@ -1498,24 +1522,28 @@ static int mtk_eth_of_to_plat(struct ude + + static const struct mtk_soc_data mt7629_data = { + .ana_rgc3 = 0x128, ++ .pdma_base = PDMA_V1_BASE, + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), + }; + + static const struct mtk_soc_data mt7623_data = { + .caps = MT7623_CAPS, ++ .pdma_base = PDMA_V1_BASE, + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), + }; + + static const struct mtk_soc_data mt7622_data = { + .ana_rgc3 = 0x2028, ++ .pdma_base = PDMA_V1_BASE, + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), + }; + + static const struct mtk_soc_data mt7621_data = { + .caps = MT7621_CAPS, ++ .pdma_base = PDMA_V1_BASE, + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), + }; +--- a/drivers/net/mtk_eth.h ++++ b/drivers/net/mtk_eth.h +@@ -15,6 +15,7 @@ + enum mkt_eth_capabilities { + MTK_TRGMII_BIT, + MTK_TRGMII_MT7621_CLK_BIT, ++ MTK_NETSYS_V2_BIT, + + /* PATH BITS */ + MTK_ETH_PATH_GMAC1_TRGMII_BIT, +@@ -22,6 +23,7 @@ enum mkt_eth_capabilities { + + #define MTK_TRGMII BIT(MTK_TRGMII_BIT) + #define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) ++#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT) + + /* Supported path present on SoCs */ + #define MTK_ETH_PATH_GMAC1_TRGMII BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT) +@@ -35,7 +37,8 @@ enum mkt_eth_capabilities { + #define MT7623_CAPS (MTK_GMAC1_TRGMII) + + /* Frame Engine Register Bases */ +-#define PDMA_BASE 0x0800 ++#define PDMA_V1_BASE 0x0800 ++#define PDMA_V2_BASE 0x6000 + #define GDMA1_BASE 0x0500 + #define GDMA2_BASE 0x1500 + #define GMAC_BASE 0x10000 +@@ -74,6 +77,8 @@ enum mkt_eth_capabilities { + #define SGMSYS_SPEED_2500 BIT(2) + + /* Frame Engine Registers */ ++#define FE_GLO_MISC_REG 0x124 ++#define PDMA_VER_V2 BIT(4) + + /* PDMA */ + #define TX_BASE_PTR_REG(n) (0x000 + (n) * 0x10) +@@ -444,6 +449,17 @@ struct mtk_rx_dma { + unsigned int rxd4; + } __packed __aligned(4); + ++struct mtk_rx_dma_v2 { ++ unsigned int rxd1; ++ unsigned int rxd2; ++ unsigned int rxd3; ++ unsigned int rxd4; ++ unsigned int rxd5; ++ unsigned int rxd6; ++ unsigned int rxd7; ++ unsigned int rxd8; ++} __packed __aligned(4); ++ + struct mtk_tx_dma { + unsigned int txd1; + unsigned int txd2; +@@ -451,20 +467,41 @@ struct mtk_tx_dma { + unsigned int txd4; + } __packed __aligned(4); + ++struct mtk_tx_dma_v2 { ++ unsigned int txd1; ++ unsigned int txd2; ++ unsigned int txd3; ++ unsigned int txd4; ++ unsigned int txd5; ++ unsigned int txd6; ++ unsigned int txd7; ++ unsigned int txd8; ++} __packed __aligned(4); ++ + /* PDMA TXD fields */ + #define PDMA_TXD2_DDONE BIT(31) + #define PDMA_TXD2_LS0 BIT(30) +-#define PDMA_TXD2_SDL0_M GENMASK(29, 16) +-#define PDMA_TXD2_SDL0_SET(_v) FIELD_PREP(PDMA_TXD2_SDL0_M, (_v)) ++#define PDMA_V1_TXD2_SDL0_M GENMASK(29, 16) ++#define PDMA_V1_TXD2_SDL0_SET(_v) FIELD_PREP(PDMA_V1_TXD2_SDL0_M, (_v)) ++#define PDMA_V2_TXD2_SDL0_M GENMASK(23, 8) ++#define PDMA_V2_TXD2_SDL0_SET(_v) FIELD_PREP(PDMA_V2_TXD2_SDL0_M, (_v)) ++ ++#define PDMA_V1_TXD4_FPORT_M GENMASK(27, 25) ++#define PDMA_V1_TXD4_FPORT_SET(_v) FIELD_PREP(PDMA_V1_TXD4_FPORT_M, (_v)) ++#define PDMA_V2_TXD4_FPORT_M GENMASK(27, 24) ++#define PDMA_V2_TXD4_FPORT_SET(_v) FIELD_PREP(PDMA_V2_TXD4_FPORT_M, (_v)) + +-#define PDMA_TXD4_FPORT_M GENMASK(27, 25) +-#define PDMA_TXD4_FPORT_SET(_v) FIELD_PREP(PDMA_TXD4_FPORT_M, (_v)) ++#define PDMA_V2_TXD5_FPORT_M GENMASK(19, 16) ++#define PDMA_V2_TXD5_FPORT_SET(_v) FIELD_PREP(PDMA_V2_TXD5_FPORT_M, (_v)) + + /* PDMA RXD fields */ + #define PDMA_RXD2_DDONE BIT(31) + #define PDMA_RXD2_LS0 BIT(30) +-#define PDMA_RXD2_PLEN0_M GENMASK(29, 16) +-#define PDMA_RXD2_PLEN0_GET(_v) FIELD_GET(PDMA_RXD2_PLEN0_M, (_v)) +-#define PDMA_RXD2_PLEN0_SET(_v) FIELD_PREP(PDMA_RXD2_PLEN0_M, (_v)) ++#define PDMA_V1_RXD2_PLEN0_M GENMASK(29, 16) ++#define PDMA_V1_RXD2_PLEN0_GET(_v) FIELD_GET(PDMA_V1_RXD2_PLEN0_M, (_v)) ++#define PDMA_V1_RXD2_PLEN0_SET(_v) FIELD_PREP(PDMA_V1_RXD2_PLEN0_M, (_v)) ++#define PDMA_V2_RXD2_PLEN0_M GENMASK(23, 8) ++#define PDMA_V2_RXD2_PLEN0_GET(_v) FIELD_GET(PDMA_V2_RXD2_PLEN0_M, (_v)) ++#define PDMA_V2_RXD2_PLEN0_SET(_v) FIELD_PREP(PDMA_V2_RXD2_PLEN0_M, (_v)) + + #endif /* _MTK_ETH_H_ */ diff --git a/package/boot/uboot-mediatek/patches/002-0009-net-mediatek-add-support-for-MediaTek-MT7981-MT7986.patch b/package/boot/uboot-mediatek/patches/002-0009-net-mediatek-add-support-for-MediaTek-MT7981-MT7986.patch new file mode 100644 index 0000000000..7afd49d457 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0009-net-mediatek-add-support-for-MediaTek-MT7981-MT7986.patch @@ -0,0 +1,100 @@ +From 5e06e9a78bbc81f64fdb4c8502a8e7175d8b6216 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 10:03:17 +0800 +Subject: [PATCH 09/31] net: mediatek: add support for MediaTek MT7981/MT7986 + +This patch adds support for MediaTek MT7981 and MT7986. Both chips uses +PDMA v2. + +Reviewed-by: Ramon Fried +Signed-off-by: Weijie Gao +--- + drivers/net/mtk_eth.c | 27 +++++++++++++++++++++++++++ + drivers/net/mtk_eth.h | 5 +++++ + 2 files changed, 32 insertions(+) + +--- a/drivers/net/mtk_eth.c ++++ b/drivers/net/mtk_eth.c +@@ -115,6 +115,7 @@ struct mtk_eth_priv { + int force_mode; + int speed; + int duplex; ++ bool pn_swap; + + struct phy_device *phydev; + int phy_interface; +@@ -1057,6 +1058,12 @@ static void mtk_sgmii_init(struct mtk_et + /* SGMII force mode setting */ + writel(SGMII_FORCE_MODE, priv->sgmii_base + SGMSYS_SGMII_MODE); + ++ /* SGMII PN SWAP setting */ ++ if (priv->pn_swap) { ++ setbits_le32(priv->sgmii_base + SGMSYS_QPHY_WRAP_CTRL, ++ SGMII_PN_SWAP_TX_RX); ++ } ++ + /* Release PHYA power down state */ + clrsetbits_le32(priv->sgmii_base + SGMSYS_QPHY_PWR_STATE_CTRL, + SGMII_PHYA_PWD, 0); +@@ -1470,6 +1477,8 @@ static int mtk_eth_of_to_plat(struct ude + dev_err(dev, "Unable to find sgmii\n"); + return -ENODEV; + } ++ ++ priv->pn_swap = ofnode_read_bool(args.node, "pn_swap"); + } + + /* check for switch first, otherwise phy will be used */ +@@ -1520,6 +1529,22 @@ static int mtk_eth_of_to_plat(struct ude + return 0; + } + ++static const struct mtk_soc_data mt7986_data = { ++ .caps = MT7986_CAPS, ++ .ana_rgc3 = 0x128, ++ .pdma_base = PDMA_V2_BASE, ++ .txd_size = sizeof(struct mtk_tx_dma_v2), ++ .rxd_size = sizeof(struct mtk_rx_dma_v2), ++}; ++ ++static const struct mtk_soc_data mt7981_data = { ++ .caps = MT7986_CAPS, ++ .ana_rgc3 = 0x128, ++ .pdma_base = PDMA_V2_BASE, ++ .txd_size = sizeof(struct mtk_tx_dma_v2), ++ .rxd_size = sizeof(struct mtk_rx_dma_v2), ++}; ++ + static const struct mtk_soc_data mt7629_data = { + .ana_rgc3 = 0x128, + .pdma_base = PDMA_V1_BASE, +@@ -1549,6 +1574,8 @@ static const struct mtk_soc_data mt7621_ + }; + + static const struct udevice_id mtk_eth_ids[] = { ++ { .compatible = "mediatek,mt7986-eth", .data = (ulong)&mt7986_data }, ++ { .compatible = "mediatek,mt7981-eth", .data = (ulong)&mt7981_data }, + { .compatible = "mediatek,mt7629-eth", .data = (ulong)&mt7629_data }, + { .compatible = "mediatek,mt7623-eth", .data = (ulong)&mt7623_data }, + { .compatible = "mediatek,mt7622-eth", .data = (ulong)&mt7622_data }, +--- a/drivers/net/mtk_eth.h ++++ b/drivers/net/mtk_eth.h +@@ -36,6 +36,8 @@ enum mkt_eth_capabilities { + + #define MT7623_CAPS (MTK_GMAC1_TRGMII) + ++#define MT7986_CAPS (MTK_NETSYS_V2) ++ + /* Frame Engine Register Bases */ + #define PDMA_V1_BASE 0x0800 + #define PDMA_V2_BASE 0x6000 +@@ -72,6 +74,9 @@ enum mkt_eth_capabilities { + #define SGMSYS_QPHY_PWR_STATE_CTRL 0xe8 + #define SGMII_PHYA_PWD BIT(4) + ++#define SGMSYS_QPHY_WRAP_CTRL 0xec ++#define SGMII_PN_SWAP_TX_RX 0x03 ++ + #define SGMSYS_GEN2_SPEED 0x2028 + #define SGMSYS_GEN2_SPEED_V2 0x128 + #define SGMSYS_SPEED_2500 BIT(2) diff --git a/package/boot/uboot-mediatek/patches/002-0010-serial-mtk-add-support-for-using-dynamic-baud-clock-.patch b/package/boot/uboot-mediatek/patches/002-0010-serial-mtk-add-support-for-using-dynamic-baud-clock-.patch new file mode 100644 index 0000000000..ff7f66f067 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0010-serial-mtk-add-support-for-using-dynamic-baud-clock-.patch @@ -0,0 +1,202 @@ +From 55ed87efb110d13fce6d1a7ee6cb04fac1a2c08a Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 10:28:05 +0800 +Subject: [PATCH 10/31] serial: mtk: add support for using dynamic baud clock + souce + +The baud clock on some platform may change due to assigned-clock-parent +set in DT. In current flow the baud clock is only retrieved during probe +stage. If the parent of the source clock changes after probe stage, the +setbrg will set wrong baudrate. + +To get the right clock rate, this patch records the baud clk struct to the +driver's priv, and changes the driver's flow to get the clock rate before +calling _mtk_serial_setbrg(). + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/serial/serial_mtk.c | 80 ++++++++++++++++++++++--------------- + 1 file changed, 47 insertions(+), 33 deletions(-) + +--- a/drivers/serial/serial_mtk.c ++++ b/drivers/serial/serial_mtk.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -70,27 +71,37 @@ struct mtk_serial_regs { + #define BAUD_ALLOW_MAX(baud) ((baud) + (baud) * 3 / 100) + #define BAUD_ALLOW_MIX(baud) ((baud) - (baud) * 3 / 100) + ++/* struct mtk_serial_priv - Structure holding all information used by the ++ * driver ++ * @regs: Register base of the serial port ++ * @clk: The baud clock device ++ * @fixed_clk_rate: Fallback fixed baud clock rate if baud clock ++ * device is not specified ++ * @force_highspeed: Force using high-speed mode ++ */ + struct mtk_serial_priv { + struct mtk_serial_regs __iomem *regs; +- u32 clock; ++ struct clk clk; ++ u32 fixed_clk_rate; + bool force_highspeed; + }; + +-static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud) ++static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud, ++ uint clk_rate) + { + u32 quot, realbaud, samplecount = 1; + + /* Special case for low baud clock */ +- if (baud <= 115200 && priv->clock <= 12000000) { ++ if (baud <= 115200 && clk_rate == 12000000) { + writel(3, &priv->regs->highspeed); + +- quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud); ++ quot = DIV_ROUND_CLOSEST(clk_rate, 256 * baud); + if (quot == 0) + quot = 1; + +- samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud); ++ samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud); + +- realbaud = priv->clock / samplecount / quot; ++ realbaud = clk_rate / samplecount / quot; + if (realbaud > BAUD_ALLOW_MAX(baud) || + realbaud < BAUD_ALLOW_MIX(baud)) { + pr_info("baud %d can't be handled\n", baud); +@@ -104,7 +115,7 @@ static void _mtk_serial_setbrg(struct mt + + if (baud <= 115200) { + writel(0, &priv->regs->highspeed); +- quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud); ++ quot = DIV_ROUND_CLOSEST(clk_rate, 16 * baud); + } else if (baud <= 576000) { + writel(2, &priv->regs->highspeed); + +@@ -112,13 +123,13 @@ static void _mtk_serial_setbrg(struct mt + if ((baud == 500000) || (baud == 576000)) + baud = 460800; + +- quot = DIV_ROUND_UP(priv->clock, 4 * baud); ++ quot = DIV_ROUND_UP(clk_rate, 4 * baud); + } else { + use_hs3: + writel(3, &priv->regs->highspeed); + +- quot = DIV_ROUND_UP(priv->clock, 256 * baud); +- samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud); ++ quot = DIV_ROUND_UP(clk_rate, 256 * baud); ++ samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud); + } + + set_baud: +@@ -167,8 +178,13 @@ static int _mtk_serial_pending(struct mt + static int mtk_serial_setbrg(struct udevice *dev, int baudrate) + { + struct mtk_serial_priv *priv = dev_get_priv(dev); ++ u32 clk_rate; ++ ++ clk_rate = clk_get_rate(&priv->clk); ++ if (IS_ERR_VALUE(clk_rate) || clk_rate == 0) ++ clk_rate = priv->fixed_clk_rate; + +- _mtk_serial_setbrg(priv, baudrate); ++ _mtk_serial_setbrg(priv, baudrate, clk_rate); + + return 0; + } +@@ -211,7 +227,6 @@ static int mtk_serial_of_to_plat(struct + { + struct mtk_serial_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; +- struct clk clk; + int err; + + addr = dev_read_addr(dev); +@@ -220,22 +235,19 @@ static int mtk_serial_of_to_plat(struct + + priv->regs = map_physmem(addr, 0, MAP_NOCACHE); + +- err = clk_get_by_index(dev, 0, &clk); +- if (!err) { +- err = clk_get_rate(&clk); +- if (!IS_ERR_VALUE(err)) +- priv->clock = err; +- } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) { +- debug("mtk_serial: failed to get clock\n"); +- return err; +- } +- +- if (!priv->clock) +- priv->clock = dev_read_u32_default(dev, "clock-frequency", 0); +- +- if (!priv->clock) { +- debug("mtk_serial: clock not defined\n"); +- return -EINVAL; ++ err = clk_get_by_index(dev, 0, &priv->clk); ++ if (err) { ++ err = dev_read_u32(dev, "clock-frequency", &priv->fixed_clk_rate); ++ if (err) { ++ dev_err(dev, "baud clock not defined\n"); ++ return -EINVAL; ++ } ++ } else { ++ err = clk_get_rate(&priv->clk); ++ if (IS_ERR_VALUE(err)) { ++ dev_err(dev, "invalid baud clock\n"); ++ return -EINVAL; ++ } + } + + priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed"); +@@ -273,7 +285,7 @@ DECLARE_GLOBAL_DATA_PTR; + #define DECLARE_HSUART_PRIV(port) \ + static struct mtk_serial_priv mtk_hsuart##port = { \ + .regs = (struct mtk_serial_regs *)CONFIG_SYS_NS16550_COM##port, \ +- .clock = CONFIG_SYS_NS16550_CLK \ ++ .fixed_clk_rate = CONFIG_SYS_NS16550_CLK \ + }; + + #define DECLARE_HSUART_FUNCTIONS(port) \ +@@ -282,12 +294,14 @@ DECLARE_GLOBAL_DATA_PTR; + writel(0, &mtk_hsuart##port.regs->ier); \ + writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \ + writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \ +- _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \ ++ _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \ ++ mtk_hsuart##port.fixed_clk_rate); \ + return 0 ; \ + } \ + static void mtk_serial##port##_setbrg(void) \ + { \ +- _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \ ++ _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate, \ ++ mtk_hsuart##port.fixed_clk_rate); \ + } \ + static int mtk_serial##port##_getc(void) \ + { \ +@@ -427,13 +441,13 @@ static inline void _debug_uart_init(void + struct mtk_serial_priv priv; + + priv.regs = (void *) CONFIG_DEBUG_UART_BASE; +- priv.clock = CONFIG_DEBUG_UART_CLOCK; ++ priv.fixed_clk_rate = CONFIG_DEBUG_UART_CLOCK; + + writel(0, &priv.regs->ier); + writel(UART_MCRVAL, &priv.regs->mcr); + writel(UART_FCRVAL, &priv.regs->fcr); + +- _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE); ++ _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE, priv.fixed_clk_rate); + } + + static inline void _debug_uart_putc(int ch) diff --git a/package/boot/uboot-mediatek/patches/002-0011-arm-dts-mt7622-force-high-speed-mode-for-uart.patch b/package/boot/uboot-mediatek/patches/002-0011-arm-dts-mt7622-force-high-speed-mode-for-uart.patch new file mode 100644 index 0000000000..7ed6083c89 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0011-arm-dts-mt7622-force-high-speed-mode-for-uart.patch @@ -0,0 +1,26 @@ +From 893368e64049fd770e55fffcc8758d2619dc337d Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 16:33:13 +0800 +Subject: [PATCH 11/31] arm: dts: mt7622: force high-speed mode for uart + +The input clock for uart is too slow (25MHz) which introduces frequent data +error on both receiving and transmitting even if the baudrate is 115200. + +Using high-speed can significantly solve this issue. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + arch/arm/dts/mt7622.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/dts/mt7622.dtsi ++++ b/arch/arm/dts/mt7622.dtsi +@@ -175,6 +175,7 @@ + status = "disabled"; + assigned-clocks = <&topckgen CLK_TOP_AXI_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_SYSPLL1_D2>; ++ mediatek,force-highspeed; + }; + + mmc0: mmc@11230000 { diff --git a/package/boot/uboot-mediatek/patches/002-0012-pwm-mtk-add-support-for-MediaTek-MT7986-SoC.patch b/package/boot/uboot-mediatek/patches/002-0012-pwm-mtk-add-support-for-MediaTek-MT7986-SoC.patch new file mode 100644 index 0000000000..a19b69a53c --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0012-pwm-mtk-add-support-for-MediaTek-MT7986-SoC.patch @@ -0,0 +1,32 @@ +From 63acbf4ffe328809ca479e5c7d344882810d412c Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 11:00:15 +0800 +Subject: [PATCH 12/31] pwm: mtk: add support for MediaTek MT7986 SoC + +This patch adds PWM support for MediaTek MT7986 SoC. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/pwm/pwm-mtk.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/pwm/pwm-mtk.c ++++ b/drivers/pwm/pwm-mtk.c +@@ -171,10 +171,16 @@ static const struct mtk_pwm_soc mt7629_d + .pwm45_fixup = false, + }; + ++static const struct mtk_pwm_soc mt7986_data = { ++ .num_pwms = 2, ++ .pwm45_fixup = false, ++}; ++ + static const struct udevice_id mtk_pwm_ids[] = { + { .compatible = "mediatek,mt7622-pwm", .data = (ulong)&mt7622_data }, + { .compatible = "mediatek,mt7623-pwm", .data = (ulong)&mt7623_data }, + { .compatible = "mediatek,mt7629-pwm", .data = (ulong)&mt7629_data }, ++ { .compatible = "mediatek,mt7986-pwm", .data = (ulong)&mt7986_data }, + { } + }; + diff --git a/package/boot/uboot-mediatek/patches/002-0013-pwm-mtk-add-support-for-MediaTek-MT7981-SoC.patch b/package/boot/uboot-mediatek/patches/002-0013-pwm-mtk-add-support-for-MediaTek-MT7981-SoC.patch new file mode 100644 index 0000000000..2da5b960a3 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0013-pwm-mtk-add-support-for-MediaTek-MT7981-SoC.patch @@ -0,0 +1,99 @@ +From 4569ef02981f20b236a8cdc3a57b4d27fbdbc22e Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 11:01:34 +0800 +Subject: [PATCH 13/31] pwm: mtk: add support for MediaTek MT7981 SoC + +This patch adds PWM support for MediaTek MT7981 SoC. +MT7981 uses a different register offset so we have to add a version field +to indicate the IP core version. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/pwm/pwm-mtk.c | 34 ++++++++++++++++++++++++++++++++-- + 1 file changed, 32 insertions(+), 2 deletions(-) + +--- a/drivers/pwm/pwm-mtk.c ++++ b/drivers/pwm/pwm-mtk.c +@@ -29,13 +29,23 @@ + + #define NSEC_PER_SEC 1000000000L + +-static const unsigned int mtk_pwm_reg_offset[] = { ++enum mtk_pwm_reg_ver { ++ PWM_REG_V1, ++ PWM_REG_V2, ++}; ++ ++static const unsigned int mtk_pwm_reg_offset_v1[] = { + 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220 + }; + ++static const unsigned int mtk_pwm_reg_offset_v2[] = { ++ 0x0080, 0x00c0, 0x0100, 0x0140, 0x0180, 0x01c0, 0x0200, 0x0240 ++}; ++ + struct mtk_pwm_soc { + unsigned int num_pwms; + bool pwm45_fixup; ++ enum mtk_pwm_reg_ver reg_ver; + }; + + struct mtk_pwm_priv { +@@ -49,7 +59,16 @@ struct mtk_pwm_priv { + static void mtk_pwm_w32(struct udevice *dev, uint channel, uint reg, uint val) + { + struct mtk_pwm_priv *priv = dev_get_priv(dev); +- u32 offset = mtk_pwm_reg_offset[channel]; ++ u32 offset; ++ ++ switch (priv->soc->reg_ver) { ++ case PWM_REG_V2: ++ offset = mtk_pwm_reg_offset_v2[channel]; ++ break; ++ ++ default: ++ offset = mtk_pwm_reg_offset_v1[channel]; ++ } + + writel(val, priv->base + offset + reg); + } +@@ -159,27 +178,38 @@ static const struct pwm_ops mtk_pwm_ops + static const struct mtk_pwm_soc mt7622_data = { + .num_pwms = 6, + .pwm45_fixup = false, ++ .reg_ver = PWM_REG_V1, + }; + + static const struct mtk_pwm_soc mt7623_data = { + .num_pwms = 5, + .pwm45_fixup = true, ++ .reg_ver = PWM_REG_V1, + }; + + static const struct mtk_pwm_soc mt7629_data = { + .num_pwms = 1, + .pwm45_fixup = false, ++ .reg_ver = PWM_REG_V1, ++}; ++ ++static const struct mtk_pwm_soc mt7981_data = { ++ .num_pwms = 2, ++ .pwm45_fixup = false, ++ .reg_ver = PWM_REG_V2, + }; + + static const struct mtk_pwm_soc mt7986_data = { + .num_pwms = 2, + .pwm45_fixup = false, ++ .reg_ver = PWM_REG_V1, + }; + + static const struct udevice_id mtk_pwm_ids[] = { + { .compatible = "mediatek,mt7622-pwm", .data = (ulong)&mt7622_data }, + { .compatible = "mediatek,mt7623-pwm", .data = (ulong)&mt7623_data }, + { .compatible = "mediatek,mt7629-pwm", .data = (ulong)&mt7629_data }, ++ { .compatible = "mediatek,mt7981-pwm", .data = (ulong)&mt7981_data }, + { .compatible = "mediatek,mt7986-pwm", .data = (ulong)&mt7986_data }, + { } + }; diff --git a/package/boot/uboot-mediatek/patches/002-0014-timer-mtk-add-support-for-MediaTek-MT7981-MT7986-SoC.patch b/package/boot/uboot-mediatek/patches/002-0014-timer-mtk-add-support-for-MediaTek-MT7981-MT7986-SoC.patch new file mode 100644 index 0000000000..7889401931 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0014-timer-mtk-add-support-for-MediaTek-MT7981-MT7986-SoC.patch @@ -0,0 +1,119 @@ +From 7860bc58c43dfa939d2664be518c28aea591aeef Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 11:38:33 +0800 +Subject: [PATCH 14/31] timer: mtk: add support for MediaTek MT7981/MT7986 SoCs + +This patch add general-purpose timer support for MediaTek MT7981/MT7986. +These two SoCs uses a newer version of timer with its register definition +slightly changed. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/timer/mtk_timer.c | 59 ++++++++++++++++++++++++--------------- + 1 file changed, 37 insertions(+), 22 deletions(-) + +--- a/drivers/timer/mtk_timer.c ++++ b/drivers/timer/mtk_timer.c +@@ -13,24 +13,32 @@ + #include + #include + +-#define MTK_GPT4_CTRL 0x40 +-#define MTK_GPT4_CLK 0x44 +-#define MTK_GPT4_CNT 0x48 +- +-#define GPT4_ENABLE BIT(0) +-#define GPT4_CLEAR BIT(1) +-#define GPT4_FREERUN GENMASK(5, 4) +-#define GPT4_CLK_SYS 0x0 +-#define GPT4_CLK_DIV1 0x0 ++#define MTK_GPT4_OFFSET_V1 0x40 ++#define MTK_GPT4_OFFSET_V2 0x80 ++ ++#define MTK_GPT_CON 0x0 ++#define MTK_GPT_V1_CLK 0x4 ++#define MTK_GPT_CNT 0x8 ++ ++#define GPT_ENABLE BIT(0) ++#define GPT_CLEAR BIT(1) ++#define GPT_V1_FREERUN GENMASK(5, 4) ++#define GPT_V2_FREERUN GENMASK(6, 5) ++ ++enum mtk_gpt_ver { ++ MTK_GPT_V1, ++ MTK_GPT_V2 ++}; + + struct mtk_timer_priv { + void __iomem *base; ++ unsigned int gpt4_offset; + }; + + static u64 mtk_timer_get_count(struct udevice *dev) + { + struct mtk_timer_priv *priv = dev_get_priv(dev); +- u32 val = readl(priv->base + MTK_GPT4_CNT); ++ u32 val = readl(priv->base + priv->gpt4_offset + MTK_GPT_CNT); + + return timer_conv_64(val); + } +@@ -40,12 +48,27 @@ static int mtk_timer_probe(struct udevic + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct mtk_timer_priv *priv = dev_get_priv(dev); + struct clk clk, parent; +- int ret; ++ int ret, gpt_ver; + + priv->base = dev_read_addr_ptr(dev); ++ gpt_ver = dev_get_driver_data(dev); ++ + if (!priv->base) + return -ENOENT; + ++ if (gpt_ver == MTK_GPT_V2) { ++ priv->gpt4_offset = MTK_GPT4_OFFSET_V2; ++ ++ writel(GPT_V2_FREERUN | GPT_CLEAR | GPT_ENABLE, ++ priv->base + priv->gpt4_offset + MTK_GPT_CON); ++ } else { ++ priv->gpt4_offset = MTK_GPT4_OFFSET_V1; ++ ++ writel(GPT_V1_FREERUN | GPT_CLEAR | GPT_ENABLE, ++ priv->base + priv->gpt4_offset + MTK_GPT_CON); ++ writel(0, priv->base + priv->gpt4_offset + MTK_GPT_V1_CLK); ++ } ++ + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; +@@ -61,16 +84,6 @@ static int mtk_timer_probe(struct udevic + if (!uc_priv->clock_rate) + return -EINVAL; + +- /* +- * Initialize the timer: +- * 1. set clock source to system clock with clock divider setting to 1 +- * 2. set timer mode to free running +- * 3. reset timer counter to 0 then enable the timer +- */ +- writel(GPT4_CLK_SYS | GPT4_CLK_DIV1, priv->base + MTK_GPT4_CLK); +- writel(GPT4_FREERUN | GPT4_CLEAR | GPT4_ENABLE, +- priv->base + MTK_GPT4_CTRL); +- + return 0; + } + +@@ -79,8 +92,10 @@ static const struct timer_ops mtk_timer_ + }; + + static const struct udevice_id mtk_timer_ids[] = { +- { .compatible = "mediatek,timer" }, +- { .compatible = "mediatek,mt6577-timer" }, ++ { .compatible = "mediatek,timer", .data = MTK_GPT_V1 }, ++ { .compatible = "mediatek,mt6577-timer", .data = MTK_GPT_V1 }, ++ { .compatible = "mediatek,mt7981-timer", .data = MTK_GPT_V2 }, ++ { .compatible = "mediatek,mt7986-timer", .data = MTK_GPT_V2 }, + { } + }; + diff --git a/package/boot/uboot-mediatek/patches/002-0015-watchdog-mediatek-add-support-for-MediaTek-MT7986-So.patch b/package/boot/uboot-mediatek/patches/002-0015-watchdog-mediatek-add-support-for-MediaTek-MT7986-So.patch new file mode 100644 index 0000000000..09ffc5c7d9 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0015-watchdog-mediatek-add-support-for-MediaTek-MT7986-So.patch @@ -0,0 +1,23 @@ +From ec7e5d3e4d6e9239f3d7ac861f07ca4a52bec9fa Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 11:47:50 +0800 +Subject: [PATCH 15/31] watchdog: mediatek: add support for MediaTek MT7986 SoC + +Add watchdog support for MediaTek MT7986 SoC + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/watchdog/mtk_wdt.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/watchdog/mtk_wdt.c ++++ b/drivers/watchdog/mtk_wdt.c +@@ -145,6 +145,7 @@ static const struct wdt_ops mtk_wdt_ops + static const struct udevice_id mtk_wdt_ids[] = { + { .compatible = "mediatek,wdt"}, + { .compatible = "mediatek,mt6589-wdt"}, ++ { .compatible = "mediatek,mt7986-wdt" }, + {} + }; + diff --git a/package/boot/uboot-mediatek/patches/002-0016-spi-add-support-for-MediaTek-spi-mem-controller.patch b/package/boot/uboot-mediatek/patches/002-0016-spi-add-support-for-MediaTek-spi-mem-controller.patch new file mode 100644 index 0000000000..04c2df3b48 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0016-spi-add-support-for-MediaTek-spi-mem-controller.patch @@ -0,0 +1,748 @@ +From f85493e3c2d1e4fd411061540b4f4943c09114df Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 16:58:38 +0800 +Subject: [PATCH 16/31] spi: add support for MediaTek spi-mem controller + +This patch adds support for spi-mem controller found on newer MediaTek SoCs +This controller supports Single/Dual/Quad SPI mode. + +Reviewed-by: Simon Glass +Signed-off-by: SkyLake.Huang +--- + drivers/spi/Kconfig | 8 + + drivers/spi/Makefile | 1 + + drivers/spi/mtk_spim.c | 701 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 710 insertions(+) + create mode 100644 drivers/spi/mtk_spim.c + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -262,6 +262,14 @@ config MTK_SNFI_SPI + used to access SPI memory devices like SPI-NOR or SPI-NAND on + platforms embedding this IP core, like MT7622/M7629. + ++config MTK_SPIM ++ bool "Mediatek SPI-MEM master controller driver" ++ depends on SPI_MEM ++ help ++ Enable MediaTek SPI-MEM master controller driver. This driver mainly ++ supports SPI flashes. You can use single, dual or quad mode ++ transmission on this controller. ++ + config MVEBU_A3700_SPI + bool "Marvell Armada 3700 SPI driver" + select CLK_ARMADA_3720 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -41,6 +41,7 @@ obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o + obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o + obj-$(CONFIG_MTK_SNFI_SPI) += mtk_snfi_spi.o + obj-$(CONFIG_MTK_SNOR) += mtk_snor.o ++obj-$(CONFIG_MTK_SPIM) += mtk_spim.o + obj-$(CONFIG_MT7620_SPI) += mt7620_spi.o + obj-$(CONFIG_MT7621_SPI) += mt7621_spi.o + obj-$(CONFIG_MSCC_BB_SPI) += mscc_bb_spi.o +--- /dev/null ++++ b/drivers/spi/mtk_spim.c +@@ -0,0 +1,701 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: SkyLake.Huang ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SPI_CFG0_REG 0x0000 ++#define SPI_CFG1_REG 0x0004 ++#define SPI_TX_SRC_REG 0x0008 ++#define SPI_RX_DST_REG 0x000c ++#define SPI_TX_DATA_REG 0x0010 ++#define SPI_RX_DATA_REG 0x0014 ++#define SPI_CMD_REG 0x0018 ++#define SPI_IRQ_REG 0x001c ++#define SPI_STATUS_REG 0x0020 ++#define SPI_PAD_SEL_REG 0x0024 ++#define SPI_CFG2_REG 0x0028 ++#define SPI_TX_SRC_REG_64 0x002c ++#define SPI_RX_DST_REG_64 0x0030 ++#define SPI_CFG3_IPM_REG 0x0040 ++ ++#define SPI_CFG0_SCK_HIGH_OFFSET 0 ++#define SPI_CFG0_SCK_LOW_OFFSET 8 ++#define SPI_CFG0_CS_HOLD_OFFSET 16 ++#define SPI_CFG0_CS_SETUP_OFFSET 24 ++#define SPI_ADJUST_CFG0_CS_HOLD_OFFSET 0 ++#define SPI_ADJUST_CFG0_CS_SETUP_OFFSET 16 ++ ++#define SPI_CFG1_CS_IDLE_OFFSET 0 ++#define SPI_CFG1_PACKET_LOOP_OFFSET 8 ++#define SPI_CFG1_PACKET_LENGTH_OFFSET 16 ++#define SPI_CFG1_GET_TICKDLY_OFFSET 29 ++ ++#define SPI_CFG1_GET_TICKDLY_MASK GENMASK(31, 29) ++#define SPI_CFG1_CS_IDLE_MASK 0xff ++#define SPI_CFG1_PACKET_LOOP_MASK 0xff00 ++#define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000 ++#define SPI_CFG1_IPM_PACKET_LENGTH_MASK GENMASK(31, 16) ++#define SPI_CFG2_SCK_HIGH_OFFSET 0 ++#define SPI_CFG2_SCK_LOW_OFFSET 16 ++#define SPI_CFG2_SCK_HIGH_MASK GENMASK(15, 0) ++#define SPI_CFG2_SCK_LOW_MASK GENMASK(31, 16) ++ ++#define SPI_CMD_ACT BIT(0) ++#define SPI_CMD_RESUME BIT(1) ++#define SPI_CMD_RST BIT(2) ++#define SPI_CMD_PAUSE_EN BIT(4) ++#define SPI_CMD_DEASSERT BIT(5) ++#define SPI_CMD_SAMPLE_SEL BIT(6) ++#define SPI_CMD_CS_POL BIT(7) ++#define SPI_CMD_CPHA BIT(8) ++#define SPI_CMD_CPOL BIT(9) ++#define SPI_CMD_RX_DMA BIT(10) ++#define SPI_CMD_TX_DMA BIT(11) ++#define SPI_CMD_TXMSBF BIT(12) ++#define SPI_CMD_RXMSBF BIT(13) ++#define SPI_CMD_RX_ENDIAN BIT(14) ++#define SPI_CMD_TX_ENDIAN BIT(15) ++#define SPI_CMD_FINISH_IE BIT(16) ++#define SPI_CMD_PAUSE_IE BIT(17) ++#define SPI_CMD_IPM_NONIDLE_MODE BIT(19) ++#define SPI_CMD_IPM_SPIM_LOOP BIT(21) ++#define SPI_CMD_IPM_GET_TICKDLY_OFFSET 22 ++ ++#define SPI_CMD_IPM_GET_TICKDLY_MASK GENMASK(24, 22) ++ ++#define PIN_MODE_CFG(x) ((x) / 2) ++ ++#define SPI_CFG3_IPM_PIN_MODE_OFFSET 0 ++#define SPI_CFG3_IPM_HALF_DUPLEX_DIR BIT(2) ++#define SPI_CFG3_IPM_HALF_DUPLEX_EN BIT(3) ++#define SPI_CFG3_IPM_XMODE_EN BIT(4) ++#define SPI_CFG3_IPM_NODATA_FLAG BIT(5) ++#define SPI_CFG3_IPM_CMD_BYTELEN_OFFSET 8 ++#define SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET 12 ++#define SPI_CFG3_IPM_DUMMY_BYTELEN_OFFSET 16 ++ ++#define SPI_CFG3_IPM_CMD_PIN_MODE_MASK GENMASK(1, 0) ++#define SPI_CFG3_IPM_CMD_BYTELEN_MASK GENMASK(11, 8) ++#define SPI_CFG3_IPM_ADDR_BYTELEN_MASK GENMASK(15, 12) ++#define SPI_CFG3_IPM_DUMMY_BYTELEN_MASK GENMASK(19, 16) ++ ++#define MT8173_SPI_MAX_PAD_SEL 3 ++ ++#define MTK_SPI_PAUSE_INT_STATUS 0x2 ++ ++#define MTK_SPI_IDLE 0 ++#define MTK_SPI_PAUSED 1 ++ ++#define MTK_SPI_MAX_FIFO_SIZE 32U ++#define MTK_SPI_PACKET_SIZE 1024 ++#define MTK_SPI_IPM_PACKET_SIZE SZ_64K ++#define MTK_SPI_IPM_PACKET_LOOP SZ_256 ++ ++#define MTK_SPI_32BITS_MASK 0xffffffff ++ ++#define DMA_ADDR_EXT_BITS 36 ++#define DMA_ADDR_DEF_BITS 32 ++ ++#define CLK_TO_US(freq, clkcnt) DIV_ROUND_UP((clkcnt), (freq) / 1000000) ++ ++/* struct mtk_spim_capability ++ * @enhance_timing: Some IC design adjust cfg register to enhance time accuracy ++ * @dma_ext: Some IC support DMA addr extension ++ * @ipm_design: The IPM IP design improves some features, and supports dual/quad mode ++ * @support_quad: Whether quad mode is supported ++ */ ++struct mtk_spim_capability { ++ bool enhance_timing; ++ bool dma_ext; ++ bool ipm_design; ++ bool support_quad; ++}; ++ ++/* struct mtk_spim_priv ++ * @base: Base address of the spi controller ++ * @state: Controller state ++ * @sel_clk: Pad clock ++ * @spi_clk: Core clock ++ * @xfer_len: Current length of data for transfer ++ * @hw_cap: Controller capabilities ++ * @tick_dly: Used to postpone SPI sampling time ++ * @sample_sel: Sample edge of MISO ++ * @dev: udevice of this spi controller ++ * @tx_dma: Tx DMA address ++ * @rx_dma: Rx DMA address ++ */ ++struct mtk_spim_priv { ++ void __iomem *base; ++ u32 state; ++ struct clk sel_clk, spi_clk; ++ u32 xfer_len; ++ struct mtk_spim_capability hw_cap; ++ u32 tick_dly; ++ u32 sample_sel; ++ ++ struct device *dev; ++ dma_addr_t tx_dma; ++ dma_addr_t rx_dma; ++}; ++ ++static void mtk_spim_reset(struct mtk_spim_priv *priv) ++{ ++ /* set the software reset bit in SPI_CMD_REG. */ ++ setbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST); ++ clrbits_le32(priv->base + SPI_CMD_REG, SPI_CMD_RST); ++} ++ ++static int mtk_spim_hw_init(struct spi_slave *slave) ++{ ++ struct udevice *bus = dev_get_parent(slave->dev); ++ struct mtk_spim_priv *priv = dev_get_priv(bus); ++ u16 cpha, cpol; ++ u32 reg_val; ++ ++ cpha = slave->mode & SPI_CPHA ? 1 : 0; ++ cpol = slave->mode & SPI_CPOL ? 1 : 0; ++ ++ if (priv->hw_cap.enhance_timing) { ++ if (priv->hw_cap.ipm_design) { ++ /* CFG3 reg only used for spi-mem, ++ * here write to default value ++ */ ++ writel(0x0, priv->base + SPI_CFG3_IPM_REG); ++ clrsetbits_le32(priv->base + SPI_CMD_REG, ++ SPI_CMD_IPM_GET_TICKDLY_MASK, ++ priv->tick_dly << ++ SPI_CMD_IPM_GET_TICKDLY_OFFSET); ++ } else { ++ clrsetbits_le32(priv->base + SPI_CFG1_REG, ++ SPI_CFG1_GET_TICKDLY_MASK, ++ priv->tick_dly << ++ SPI_CFG1_GET_TICKDLY_OFFSET); ++ } ++ } ++ ++ reg_val = readl(priv->base + SPI_CMD_REG); ++ if (priv->hw_cap.ipm_design) { ++ /* SPI transfer without idle time until packet length done */ ++ reg_val |= SPI_CMD_IPM_NONIDLE_MODE; ++ if (slave->mode & SPI_LOOP) ++ reg_val |= SPI_CMD_IPM_SPIM_LOOP; ++ else ++ reg_val &= ~SPI_CMD_IPM_SPIM_LOOP; ++ } ++ ++ if (cpha) ++ reg_val |= SPI_CMD_CPHA; ++ else ++ reg_val &= ~SPI_CMD_CPHA; ++ if (cpol) ++ reg_val |= SPI_CMD_CPOL; ++ else ++ reg_val &= ~SPI_CMD_CPOL; ++ ++ /* set the mlsbx and mlsbtx */ ++ if (slave->mode & SPI_LSB_FIRST) { ++ reg_val &= ~SPI_CMD_TXMSBF; ++ reg_val &= ~SPI_CMD_RXMSBF; ++ } else { ++ reg_val |= SPI_CMD_TXMSBF; ++ reg_val |= SPI_CMD_RXMSBF; ++ } ++ ++ /* do not reverse tx/rx endian */ ++ reg_val &= ~SPI_CMD_TX_ENDIAN; ++ reg_val &= ~SPI_CMD_RX_ENDIAN; ++ ++ if (priv->hw_cap.enhance_timing) { ++ /* set CS polarity */ ++ if (slave->mode & SPI_CS_HIGH) ++ reg_val |= SPI_CMD_CS_POL; ++ else ++ reg_val &= ~SPI_CMD_CS_POL; ++ ++ if (priv->sample_sel) ++ reg_val |= SPI_CMD_SAMPLE_SEL; ++ else ++ reg_val &= ~SPI_CMD_SAMPLE_SEL; ++ } ++ ++ /* disable dma mode */ ++ reg_val &= ~(SPI_CMD_TX_DMA | SPI_CMD_RX_DMA); ++ ++ /* disable deassert mode */ ++ reg_val &= ~SPI_CMD_DEASSERT; ++ ++ writel(reg_val, priv->base + SPI_CMD_REG); ++ ++ return 0; ++} ++ ++static void mtk_spim_prepare_transfer(struct mtk_spim_priv *priv, ++ u32 speed_hz) ++{ ++ u32 spi_clk_hz, div, sck_time, cs_time, reg_val; ++ ++ spi_clk_hz = clk_get_rate(&priv->spi_clk); ++ if (speed_hz <= spi_clk_hz / 4) ++ div = DIV_ROUND_UP(spi_clk_hz, speed_hz); ++ else ++ div = 4; ++ ++ sck_time = (div + 1) / 2; ++ cs_time = sck_time * 2; ++ ++ if (priv->hw_cap.enhance_timing) { ++ reg_val = ((sck_time - 1) & 0xffff) ++ << SPI_CFG2_SCK_HIGH_OFFSET; ++ reg_val |= ((sck_time - 1) & 0xffff) ++ << SPI_CFG2_SCK_LOW_OFFSET; ++ writel(reg_val, priv->base + SPI_CFG2_REG); ++ ++ reg_val = ((cs_time - 1) & 0xffff) ++ << SPI_ADJUST_CFG0_CS_HOLD_OFFSET; ++ reg_val |= ((cs_time - 1) & 0xffff) ++ << SPI_ADJUST_CFG0_CS_SETUP_OFFSET; ++ writel(reg_val, priv->base + SPI_CFG0_REG); ++ } else { ++ reg_val = ((sck_time - 1) & 0xff) ++ << SPI_CFG0_SCK_HIGH_OFFSET; ++ reg_val |= ((sck_time - 1) & 0xff) << SPI_CFG0_SCK_LOW_OFFSET; ++ reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_HOLD_OFFSET; ++ reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG0_CS_SETUP_OFFSET; ++ writel(reg_val, priv->base + SPI_CFG0_REG); ++ } ++ ++ reg_val = readl(priv->base + SPI_CFG1_REG); ++ reg_val &= ~SPI_CFG1_CS_IDLE_MASK; ++ reg_val |= ((cs_time - 1) & 0xff) << SPI_CFG1_CS_IDLE_OFFSET; ++ writel(reg_val, priv->base + SPI_CFG1_REG); ++} ++ ++/** ++ * mtk_spim_setup_packet() - setup packet format. ++ * @priv: controller priv ++ * ++ * This controller sents/receives data in packets. The packet size is ++ * configurable. ++ * ++ * This function calculates the maximum packet size available for current ++ * data, and calculates the number of packets required to sent/receive data ++ * as much as possible. ++ */ ++static void mtk_spim_setup_packet(struct mtk_spim_priv *priv) ++{ ++ u32 packet_size, packet_loop, reg_val; ++ ++ /* Calculate maximum packet size */ ++ if (priv->hw_cap.ipm_design) ++ packet_size = min_t(u32, ++ priv->xfer_len, ++ MTK_SPI_IPM_PACKET_SIZE); ++ else ++ packet_size = min_t(u32, ++ priv->xfer_len, ++ MTK_SPI_PACKET_SIZE); ++ ++ /* Calculates number of packets to sent/receive */ ++ packet_loop = priv->xfer_len / packet_size; ++ ++ reg_val = readl(priv->base + SPI_CFG1_REG); ++ if (priv->hw_cap.ipm_design) ++ reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK; ++ else ++ reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK; ++ ++ reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; ++ ++ reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK; ++ ++ reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET; ++ ++ writel(reg_val, priv->base + SPI_CFG1_REG); ++} ++ ++static void mtk_spim_enable_transfer(struct mtk_spim_priv *priv) ++{ ++ u32 cmd; ++ ++ cmd = readl(priv->base + SPI_CMD_REG); ++ if (priv->state == MTK_SPI_IDLE) ++ cmd |= SPI_CMD_ACT; ++ else ++ cmd |= SPI_CMD_RESUME; ++ writel(cmd, priv->base + SPI_CMD_REG); ++} ++ ++static bool mtk_spim_supports_op(struct spi_slave *slave, ++ const struct spi_mem_op *op) ++{ ++ struct udevice *bus = dev_get_parent(slave->dev); ++ struct mtk_spim_priv *priv = dev_get_priv(bus); ++ ++ if (op->cmd.buswidth == 0 || op->cmd.buswidth > 4 || ++ op->addr.buswidth > 4 || op->dummy.buswidth > 4 || ++ op->data.buswidth > 4) ++ return false; ++ ++ if (!priv->hw_cap.support_quad && (op->cmd.buswidth > 2 || ++ op->addr.buswidth > 2 || op->dummy.buswidth > 2 || ++ op->data.buswidth > 2)) ++ return false; ++ ++ if (op->addr.nbytes && op->dummy.nbytes && ++ op->addr.buswidth != op->dummy.buswidth) ++ return false; ++ ++ if (op->addr.nbytes + op->dummy.nbytes > 16) ++ return false; ++ ++ if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { ++ if (op->data.nbytes / MTK_SPI_IPM_PACKET_SIZE > ++ MTK_SPI_IPM_PACKET_LOOP || ++ op->data.nbytes % MTK_SPI_IPM_PACKET_SIZE != 0) ++ return false; ++ } ++ ++ return true; ++} ++ ++static void mtk_spim_setup_dma_xfer(struct mtk_spim_priv *priv, ++ const struct spi_mem_op *op) ++{ ++ writel((u32)(priv->tx_dma & MTK_SPI_32BITS_MASK), ++ priv->base + SPI_TX_SRC_REG); ++ ++ if (priv->hw_cap.dma_ext) ++ writel((u32)(priv->tx_dma >> 32), ++ priv->base + SPI_TX_SRC_REG_64); ++ ++ if (op->data.dir == SPI_MEM_DATA_IN) { ++ writel((u32)(priv->rx_dma & MTK_SPI_32BITS_MASK), ++ priv->base + SPI_RX_DST_REG); ++ ++ if (priv->hw_cap.dma_ext) ++ writel((u32)(priv->rx_dma >> 32), ++ priv->base + SPI_RX_DST_REG_64); ++ } ++} ++ ++static int mtk_spim_transfer_wait(struct spi_slave *slave, ++ const struct spi_mem_op *op) ++{ ++ struct udevice *bus = dev_get_parent(slave->dev); ++ struct mtk_spim_priv *priv = dev_get_priv(bus); ++ u32 sck_l, sck_h, spi_bus_clk, clk_count, reg; ++ ulong us = 1; ++ int ret = 0; ++ ++ if (op->data.dir == SPI_MEM_NO_DATA) ++ clk_count = 32; ++ else ++ clk_count = op->data.nbytes; ++ ++ spi_bus_clk = clk_get_rate(&priv->spi_clk); ++ sck_l = readl(priv->base + SPI_CFG2_REG) >> SPI_CFG2_SCK_LOW_OFFSET; ++ sck_h = readl(priv->base + SPI_CFG2_REG) & SPI_CFG2_SCK_HIGH_MASK; ++ do_div(spi_bus_clk, sck_l + sck_h + 2); ++ ++ us = CLK_TO_US(spi_bus_clk, clk_count * 8); ++ us += 1000 * 1000; /* 1s tolerance */ ++ ++ if (us > UINT_MAX) ++ us = UINT_MAX; ++ ++ ret = readl_poll_timeout(priv->base + SPI_STATUS_REG, reg, ++ reg & 0x1, us); ++ if (ret < 0) { ++ dev_err(priv->dev, "transfer timeout, val: 0x%lx\n", us); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int mtk_spim_exec_op(struct spi_slave *slave, ++ const struct spi_mem_op *op) ++{ ++ struct udevice *bus = dev_get_parent(slave->dev); ++ struct mtk_spim_priv *priv = dev_get_priv(bus); ++ u32 reg_val, nio = 1, tx_size; ++ char *tx_tmp_buf; ++ char *rx_tmp_buf; ++ int i, ret = 0; ++ ++ mtk_spim_reset(priv); ++ mtk_spim_hw_init(slave); ++ mtk_spim_prepare_transfer(priv, slave->max_hz); ++ ++ reg_val = readl(priv->base + SPI_CFG3_IPM_REG); ++ /* opcode byte len */ ++ reg_val &= ~SPI_CFG3_IPM_CMD_BYTELEN_MASK; ++ reg_val |= 1 << SPI_CFG3_IPM_CMD_BYTELEN_OFFSET; ++ ++ /* addr & dummy byte len */ ++ if (op->addr.nbytes || op->dummy.nbytes) ++ reg_val |= (op->addr.nbytes + op->dummy.nbytes) << ++ SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET; ++ ++ /* data byte len */ ++ if (!op->data.nbytes) { ++ reg_val |= SPI_CFG3_IPM_NODATA_FLAG; ++ writel(0, priv->base + SPI_CFG1_REG); ++ } else { ++ reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG; ++ priv->xfer_len = op->data.nbytes; ++ mtk_spim_setup_packet(priv); ++ } ++ ++ if (op->addr.nbytes || op->dummy.nbytes) { ++ if (op->addr.buswidth == 1 || op->dummy.buswidth == 1) ++ reg_val |= SPI_CFG3_IPM_XMODE_EN; ++ else ++ reg_val &= ~SPI_CFG3_IPM_XMODE_EN; ++ } ++ ++ if (op->addr.buswidth == 2 || ++ op->dummy.buswidth == 2 || ++ op->data.buswidth == 2) ++ nio = 2; ++ else if (op->addr.buswidth == 4 || ++ op->dummy.buswidth == 4 || ++ op->data.buswidth == 4) ++ nio = 4; ++ ++ reg_val &= ~SPI_CFG3_IPM_CMD_PIN_MODE_MASK; ++ reg_val |= PIN_MODE_CFG(nio) << SPI_CFG3_IPM_PIN_MODE_OFFSET; ++ ++ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN; ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR; ++ else ++ reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR; ++ writel(reg_val, priv->base + SPI_CFG3_IPM_REG); ++ ++ tx_size = 1 + op->addr.nbytes + op->dummy.nbytes; ++ if (op->data.dir == SPI_MEM_DATA_OUT) ++ tx_size += op->data.nbytes; ++ ++ tx_size = max(tx_size, (u32)32); ++ ++ /* Fill up tx data */ ++ tx_tmp_buf = kzalloc(tx_size, GFP_KERNEL); ++ if (!tx_tmp_buf) { ++ ret = -ENOMEM; ++ goto exit; ++ } ++ ++ tx_tmp_buf[0] = op->cmd.opcode; ++ ++ if (op->addr.nbytes) { ++ for (i = 0; i < op->addr.nbytes; i++) ++ tx_tmp_buf[i + 1] = op->addr.val >> ++ (8 * (op->addr.nbytes - i - 1)); ++ } ++ ++ if (op->dummy.nbytes) ++ memset(tx_tmp_buf + op->addr.nbytes + 1, 0xff, ++ op->dummy.nbytes); ++ ++ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) ++ memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1, ++ op->data.buf.out, op->data.nbytes); ++ /* Finish filling up tx data */ ++ ++ priv->tx_dma = dma_map_single(tx_tmp_buf, tx_size, DMA_TO_DEVICE); ++ if (dma_mapping_error(priv->dev, priv->tx_dma)) { ++ ret = -ENOMEM; ++ goto tx_free; ++ } ++ ++ if (op->data.dir == SPI_MEM_DATA_IN) { ++ if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) { ++ rx_tmp_buf = kzalloc(op->data.nbytes, GFP_KERNEL); ++ if (!rx_tmp_buf) { ++ ret = -ENOMEM; ++ goto tx_unmap; ++ } ++ } else { ++ rx_tmp_buf = op->data.buf.in; ++ } ++ ++ priv->rx_dma = dma_map_single(rx_tmp_buf, op->data.nbytes, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(priv->dev, priv->rx_dma)) { ++ ret = -ENOMEM; ++ goto rx_free; ++ } ++ } ++ ++ reg_val = readl(priv->base + SPI_CMD_REG); ++ reg_val |= SPI_CMD_TX_DMA; ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ reg_val |= SPI_CMD_RX_DMA; ++ ++ writel(reg_val, priv->base + SPI_CMD_REG); ++ ++ mtk_spim_setup_dma_xfer(priv, op); ++ ++ mtk_spim_enable_transfer(priv); ++ ++ /* Wait for the interrupt. */ ++ ret = mtk_spim_transfer_wait(slave, op); ++ if (ret) ++ goto rx_unmap; ++ ++ if (op->data.dir == SPI_MEM_DATA_IN && ++ !IS_ALIGNED((size_t)op->data.buf.in, 4)) ++ memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes); ++ ++rx_unmap: ++ /* spi disable dma */ ++ reg_val = readl(priv->base + SPI_CMD_REG); ++ reg_val &= ~SPI_CMD_TX_DMA; ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ reg_val &= ~SPI_CMD_RX_DMA; ++ writel(reg_val, priv->base + SPI_CMD_REG); ++ ++ writel(0, priv->base + SPI_TX_SRC_REG); ++ writel(0, priv->base + SPI_RX_DST_REG); ++ ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ dma_unmap_single(priv->rx_dma, ++ op->data.nbytes, DMA_FROM_DEVICE); ++rx_free: ++ if (op->data.dir == SPI_MEM_DATA_IN && ++ !IS_ALIGNED((size_t)op->data.buf.in, 4)) ++ kfree(rx_tmp_buf); ++tx_unmap: ++ dma_unmap_single(priv->tx_dma, ++ tx_size, DMA_TO_DEVICE); ++tx_free: ++ kfree(tx_tmp_buf); ++exit: ++ return ret; ++} ++ ++static int mtk_spim_adjust_op_size(struct spi_slave *slave, ++ struct spi_mem_op *op) ++{ ++ int opcode_len; ++ ++ if (!op->data.nbytes) ++ return 0; ++ ++ if (op->data.dir != SPI_MEM_NO_DATA) { ++ opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes; ++ if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { ++ op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len; ++ /* force data buffer dma-aligned. */ ++ op->data.nbytes -= op->data.nbytes % 4; ++ } ++ } ++ ++ return 0; ++} ++ ++static int mtk_spim_get_attr(struct mtk_spim_priv *priv, struct udevice *dev) ++{ ++ int ret; ++ ++ priv->hw_cap.enhance_timing = dev_read_bool(dev, "enhance_timing"); ++ priv->hw_cap.dma_ext = dev_read_bool(dev, "dma_ext"); ++ priv->hw_cap.ipm_design = dev_read_bool(dev, "ipm_design"); ++ priv->hw_cap.support_quad = dev_read_bool(dev, "support_quad"); ++ ++ ret = dev_read_u32(dev, "tick_dly", &priv->tick_dly); ++ if (ret < 0) ++ dev_err(priv->dev, "tick dly not set.\n"); ++ ++ ret = dev_read_u32(dev, "sample_sel", &priv->sample_sel); ++ if (ret < 0) ++ dev_err(priv->dev, "sample sel not set.\n"); ++ ++ return ret; ++} ++ ++static int mtk_spim_probe(struct udevice *dev) ++{ ++ struct mtk_spim_priv *priv = dev_get_priv(dev); ++ int ret; ++ ++ priv->base = (void __iomem *)devfdt_get_addr(dev); ++ if (!priv->base) ++ return -EINVAL; ++ ++ mtk_spim_get_attr(priv, dev); ++ ++ ret = clk_get_by_name(dev, "sel-clk", &priv->sel_clk); ++ if (ret < 0) { ++ dev_err(dev, "failed to get sel-clk\n"); ++ return ret; ++ } ++ ++ ret = clk_get_by_name(dev, "spi-clk", &priv->spi_clk); ++ if (ret < 0) { ++ dev_err(dev, "failed to get spi-clk\n"); ++ return ret; ++ } ++ ++ clk_enable(&priv->sel_clk); ++ clk_enable(&priv->spi_clk); ++ ++ return 0; ++} ++ ++static int mtk_spim_set_speed(struct udevice *dev, uint speed) ++{ ++ return 0; ++} ++ ++static int mtk_spim_set_mode(struct udevice *dev, uint mode) ++{ ++ return 0; ++} ++ ++static const struct spi_controller_mem_ops mtk_spim_mem_ops = { ++ .adjust_op_size = mtk_spim_adjust_op_size, ++ .supports_op = mtk_spim_supports_op, ++ .exec_op = mtk_spim_exec_op ++}; ++ ++static const struct dm_spi_ops mtk_spim_ops = { ++ .mem_ops = &mtk_spim_mem_ops, ++ .set_speed = mtk_spim_set_speed, ++ .set_mode = mtk_spim_set_mode, ++}; ++ ++static const struct udevice_id mtk_spim_ids[] = { ++ { .compatible = "mediatek,ipm-spi" }, ++ {} ++}; ++ ++U_BOOT_DRIVER(mtk_spim) = { ++ .name = "mtk_spim", ++ .id = UCLASS_SPI, ++ .of_match = mtk_spim_ids, ++ .ops = &mtk_spim_ops, ++ .priv_auto = sizeof(struct mtk_spim_priv), ++ .probe = mtk_spim_probe, ++}; diff --git a/package/boot/uboot-mediatek/patches/002-0017-i2c-add-support-for-MediaTek-I2C-interface.patch b/package/boot/uboot-mediatek/patches/002-0017-i2c-add-support-for-MediaTek-I2C-interface.patch new file mode 100644 index 0000000000..c2bc33cdaa --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0017-i2c-add-support-for-MediaTek-I2C-interface.patch @@ -0,0 +1,870 @@ +From de6f2293ab087f405dbcf7b8df45d1f9b03fc091 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 17:16:38 +0800 +Subject: [PATCH 17/31] i2c: add support for MediaTek I2C interface + +This patch adds support for MediaTek I2C interface + +Reviewed-by: Heiko Schocher +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/i2c/Kconfig | 9 + + drivers/i2c/Makefile | 1 + + drivers/i2c/mtk_i2c.c | 822 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 832 insertions(+) + create mode 100644 drivers/i2c/mtk_i2c.c + +--- a/drivers/i2c/Kconfig ++++ b/drivers/i2c/Kconfig +@@ -261,6 +261,15 @@ config SYS_I2C_MESON + internal buffer holding up to 8 bytes for transfers and supports + both 7-bit and 10-bit addresses. + ++config SYS_I2C_MTK ++ bool "MediaTek I2C driver" ++ help ++ This selects the MediaTek Integrated Inter Circuit bus driver. ++ The I2C bus adapter is the base for some other I2C client, ++ eg: touch, sensors. ++ If you want to use MediaTek I2C interface, say Y here. ++ If unsure, say N. ++ + config SYS_I2C_MICROCHIP + bool "Microchip I2C driver" + help +--- a/drivers/i2c/Makefile ++++ b/drivers/i2c/Makefile +@@ -32,6 +32,7 @@ obj-$(CONFIG_SYS_I2C_MICROCHIP) += i2c-m + obj-$(CONFIG_SYS_I2C_MV) += mv_i2c.o + obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o + obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o ++obj-$(CONFIG_SYS_I2C_MTK) += mtk_i2c.o + obj-$(CONFIG_SYS_I2C_NEXELL) += nx_i2c.o + obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o + obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o +--- /dev/null ++++ b/drivers/i2c/mtk_i2c.c +@@ -0,0 +1,822 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Mingming Lee ++ * ++ * MediaTek I2C Interface driver ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define I2C_RS_TRANSFER BIT(4) ++#define I2C_HS_NACKERR BIT(2) ++#define I2C_ACKERR BIT(1) ++#define I2C_TRANSAC_COMP BIT(0) ++#define I2C_TRANSAC_START BIT(0) ++#define I2C_RS_MUL_CNFG BIT(15) ++#define I2C_RS_MUL_TRIG BIT(14) ++#define I2C_DCM_DISABLE 0x0000 ++#define I2C_IO_CONFIG_OPEN_DRAIN 0x0003 ++#define I2C_IO_CONFIG_PUSH_PULL 0x0000 ++#define I2C_SOFT_RST 0x0001 ++#define I2C_FIFO_ADDR_CLR 0x0001 ++#define I2C_DELAY_LEN 0x0002 ++#define I2C_ST_START_CON 0x8001 ++#define I2C_FS_START_CON 0x1800 ++#define I2C_TIME_CLR_VALUE 0x0000 ++#define I2C_TIME_DEFAULT_VALUE 0x0003 ++#define I2C_WRRD_TRANAC_VALUE 0x0002 ++#define I2C_RD_TRANAC_VALUE 0x0001 ++ ++#define I2C_DMA_CON_TX 0x0000 ++#define I2C_DMA_CON_RX 0x0001 ++#define I2C_DMA_START_EN 0x0001 ++#define I2C_DMA_INT_FLAG_NONE 0x0000 ++#define I2C_DMA_CLR_FLAG 0x0000 ++#define I2C_DMA_TX_RX 0x0000 ++#define I2C_DMA_HARD_RST 0x0002 ++ ++#define MAX_ST_MODE_SPEED 100000 ++#define MAX_FS_MODE_SPEED 400000 ++#define MAX_HS_MODE_SPEED 3400000 ++#define MAX_SAMPLE_CNT_DIV 8 ++#define MAX_STEP_CNT_DIV 64 ++#define MAX_HS_STEP_CNT_DIV 8 ++#define I2C_DEFAULT_CLK_DIV 4 ++ ++#define MAX_I2C_ADDR 0x7f ++#define MAX_I2C_LEN 0xff ++#define TRANS_ADDR_ONLY BIT(8) ++#define TRANSFER_TIMEOUT 50000 /* us */ ++#define I2C_FIFO_STAT1_MASK 0x001f ++#define TIMING_SAMPLE_OFFSET 8 ++#define HS_SAMPLE_OFFSET 12 ++#define HS_STEP_OFFSET 8 ++ ++#define I2C_CONTROL_WRAPPER BIT(0) ++#define I2C_CONTROL_RS BIT(1) ++#define I2C_CONTROL_DMA_EN BIT(2) ++#define I2C_CONTROL_CLK_EXT_EN BIT(3) ++#define I2C_CONTROL_DIR_CHANGE BIT(4) ++#define I2C_CONTROL_ACKERR_DET_EN BIT(5) ++#define I2C_CONTROL_TRANSFER_LEN_CHANGE BIT(6) ++#define I2C_CONTROL_DMAACK BIT(8) ++#define I2C_CONTROL_ASYNC BIT(9) ++ ++#define I2C_MASTER_WR BIT(0) ++#define I2C_MASTER_RD BIT(1) ++#define I2C_MASTER_WRRD (I2C_MASTER_WR | I2C_MASTER_RD) ++ ++enum I2C_REGS_OFFSET { ++ REG_PORT, ++ REG_SLAVE_ADDR, ++ REG_INTR_MASK, ++ REG_INTR_STAT, ++ REG_CONTROL, ++ REG_TRANSFER_LEN, ++ REG_TRANSAC_LEN, ++ REG_DELAY_LEN, ++ REG_TIMING, ++ REG_START, ++ REG_EXT_CONF, ++ REG_FIFO_STAT1, ++ REG_LTIMING, ++ REG_FIFO_STAT, ++ REG_FIFO_THRESH, ++ REG_FIFO_ADDR_CLR, ++ REG_IO_CONFIG, ++ REG_RSV_DEBUG, ++ REG_HS, ++ REG_SOFTRESET, ++ REG_DCM_EN, ++ REG_PATH_DIR, ++ REG_DEBUGSTAT, ++ REG_DEBUGCTRL, ++ REG_TRANSFER_LEN_AUX, ++ REG_CLOCK_DIV, ++ REG_SCL_HL_RATIO, ++ REG_SCL_HS_HL_RATIO, ++ REG_SCL_MIS_COMP_POINT, ++ REG_STA_STOP_AC_TIME, ++ REG_HS_STA_STOP_AC_TIME, ++ REG_DATA_TIME, ++}; ++ ++enum DMA_REGS_OFFSET { ++ REG_INT_FLAG = 0x0, ++ REG_INT_EN = 0x04, ++ REG_EN = 0x08, ++ REG_RST = 0x0c, ++ REG_CON = 0x18, ++ REG_TX_MEM_ADDR = 0x1c, ++ REG_RX_MEM_ADDR = 0x20, ++ REG_TX_LEN = 0x24, ++ REG_RX_LEN = 0x28, ++}; ++ ++static const uint mt_i2c_regs_v1[] = { ++ [REG_PORT] = 0x0, ++ [REG_SLAVE_ADDR] = 0x4, ++ [REG_INTR_MASK] = 0x8, ++ [REG_INTR_STAT] = 0xc, ++ [REG_CONTROL] = 0x10, ++ [REG_TRANSFER_LEN] = 0x14, ++ [REG_TRANSAC_LEN] = 0x18, ++ [REG_DELAY_LEN] = 0x1c, ++ [REG_TIMING] = 0x20, ++ [REG_START] = 0x24, ++ [REG_EXT_CONF] = 0x28, ++ [REG_FIFO_STAT1] = 0x2c, ++ [REG_FIFO_STAT] = 0x30, ++ [REG_FIFO_THRESH] = 0x34, ++ [REG_FIFO_ADDR_CLR] = 0x38, ++ [REG_IO_CONFIG] = 0x40, ++ [REG_RSV_DEBUG] = 0x44, ++ [REG_HS] = 0x48, ++ [REG_SOFTRESET] = 0x50, ++ [REG_SOFTRESET] = 0x50, ++ [REG_DCM_EN] = 0x54, ++ [REG_DEBUGSTAT] = 0x64, ++ [REG_DEBUGCTRL] = 0x68, ++ [REG_TRANSFER_LEN_AUX] = 0x6c, ++ [REG_CLOCK_DIV] = 0x70, ++ [REG_SCL_HL_RATIO] = 0x74, ++ [REG_SCL_HS_HL_RATIO] = 0x78, ++ [REG_SCL_MIS_COMP_POINT] = 0x7c, ++ [REG_STA_STOP_AC_TIME] = 0x80, ++ [REG_HS_STA_STOP_AC_TIME] = 0x84, ++ [REG_DATA_TIME] = 0x88, ++}; ++ ++static const uint mt_i2c_regs_v2[] = { ++ [REG_PORT] = 0x0, ++ [REG_SLAVE_ADDR] = 0x4, ++ [REG_INTR_MASK] = 0x8, ++ [REG_INTR_STAT] = 0xc, ++ [REG_CONTROL] = 0x10, ++ [REG_TRANSFER_LEN] = 0x14, ++ [REG_TRANSAC_LEN] = 0x18, ++ [REG_DELAY_LEN] = 0x1c, ++ [REG_TIMING] = 0x20, ++ [REG_START] = 0x24, ++ [REG_EXT_CONF] = 0x28, ++ [REG_LTIMING] = 0x2c, ++ [REG_HS] = 0x30, ++ [REG_IO_CONFIG] = 0x34, ++ [REG_FIFO_ADDR_CLR] = 0x38, ++ [REG_TRANSFER_LEN_AUX] = 0x44, ++ [REG_CLOCK_DIV] = 0x48, ++ [REG_SOFTRESET] = 0x50, ++ [REG_DEBUGSTAT] = 0xe0, ++ [REG_DEBUGCTRL] = 0xe8, ++ [REG_FIFO_STAT] = 0xf4, ++ [REG_FIFO_THRESH] = 0xf8, ++ [REG_DCM_EN] = 0xf88, ++}; ++ ++struct mtk_i2c_soc_data { ++ const uint *regs; ++ uint dma_sync: 1; ++}; ++ ++struct mtk_i2c_priv { ++ /* set in i2c probe */ ++ void __iomem *base; /* i2c base addr */ ++ void __iomem *pdmabase; /* dma base address*/ ++ struct clk clk_main; /* main clock for i2c bus */ ++ struct clk clk_dma; /* DMA clock for i2c via DMA */ ++ const struct mtk_i2c_soc_data *soc_data; /* Compatible data for different IC */ ++ int op; /* operation mode */ ++ bool zero_len; /* Only transfer slave address, no data */ ++ bool pushpull; /* push pull mode or open drain mode */ ++ bool filter_msg; /* filter msg error log */ ++ bool auto_restart; /* restart mode */ ++ bool ignore_restart_irq; /* ignore restart IRQ */ ++ uint speed; /* i2c speed, unit: hz */ ++}; ++ ++static inline void i2c_writel(struct mtk_i2c_priv *priv, uint reg, uint value) ++{ ++ u32 offset = priv->soc_data->regs[reg]; ++ ++ writel(value, priv->base + offset); ++} ++ ++static inline uint i2c_readl(struct mtk_i2c_priv *priv, uint offset) ++{ ++ return readl(priv->base + priv->soc_data->regs[offset]); ++} ++ ++static int mtk_i2c_clk_enable(struct mtk_i2c_priv *priv) ++{ ++ int ret; ++ ++ ret = clk_enable(&priv->clk_main); ++ if (ret) ++ return log_msg_ret("enable clk_main", ret); ++ ++ ret = clk_enable(&priv->clk_dma); ++ if (ret) ++ return log_msg_ret("enable clk_dma", ret); ++ ++ return 0; ++} ++ ++static int mtk_i2c_clk_disable(struct mtk_i2c_priv *priv) ++{ ++ int ret; ++ ++ ret = clk_disable(&priv->clk_dma); ++ if (ret) ++ return log_msg_ret("disable clk_dma", ret); ++ ++ ret = clk_disable(&priv->clk_main); ++ if (ret) ++ return log_msg_ret("disable clk_main", ret); ++ ++ return 0; ++} ++ ++static void mtk_i2c_init_hw(struct mtk_i2c_priv *priv) ++{ ++ uint control_reg; ++ ++ writel(I2C_DMA_HARD_RST, priv->pdmabase + REG_RST); ++ writel(I2C_DMA_CLR_FLAG, priv->pdmabase + REG_RST); ++ i2c_writel(priv, REG_SOFTRESET, I2C_SOFT_RST); ++ /* set ioconfig */ ++ if (priv->pushpull) ++ i2c_writel(priv, REG_IO_CONFIG, I2C_IO_CONFIG_PUSH_PULL); ++ else ++ i2c_writel(priv, REG_IO_CONFIG, I2C_IO_CONFIG_OPEN_DRAIN); ++ ++ i2c_writel(priv, REG_DCM_EN, I2C_DCM_DISABLE); ++ control_reg = I2C_CONTROL_ACKERR_DET_EN | I2C_CONTROL_CLK_EXT_EN; ++ if (priv->soc_data->dma_sync) ++ control_reg |= I2C_CONTROL_DMAACK | I2C_CONTROL_ASYNC; ++ i2c_writel(priv, REG_CONTROL, control_reg); ++ i2c_writel(priv, REG_DELAY_LEN, I2C_DELAY_LEN); ++} ++ ++/* ++ * Calculate i2c port speed ++ * ++ * Hardware design: ++ * i2c_bus_freq = parent_clk / (clock_div * 2 * sample_cnt * step_cnt) ++ * clock_div: fixed in hardware, but may be various in different SoCs ++ * ++ * The calculation want to pick the highest bus frequency that is still ++ * less than or equal to target_speed. The calculation try to get ++ * sample_cnt and step_cn ++ * @param[in] ++ * clk_src: i2c clock source ++ * @param[out] ++ * timing_step_cnt: step cnt calculate result ++ * @param[out] ++ * timing_sample_cnt: sample cnt calculate result ++ * @return ++ * 0, set speed successfully. ++ * -EINVAL, Unsupported speed. ++ */ ++static int mtk_i2c_calculate_speed(uint clk_src, ++ uint target_speed, ++ uint *timing_step_cnt, ++ uint *timing_sample_cnt) ++{ ++ uint base_sample_cnt = MAX_SAMPLE_CNT_DIV; ++ uint base_step_cnt; ++ uint max_step_cnt; ++ uint sample_cnt; ++ uint step_cnt; ++ uint opt_div; ++ uint best_mul; ++ uint cnt_mul; ++ ++ if (target_speed > MAX_HS_MODE_SPEED) ++ target_speed = MAX_HS_MODE_SPEED; ++ ++ if (target_speed > MAX_FS_MODE_SPEED) ++ max_step_cnt = MAX_HS_STEP_CNT_DIV; ++ else ++ max_step_cnt = MAX_STEP_CNT_DIV; ++ ++ base_step_cnt = max_step_cnt; ++ /* Find the best combination */ ++ opt_div = DIV_ROUND_UP(clk_src >> 1, target_speed); ++ best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt; ++ ++ /* ++ * Search for the best pair (sample_cnt, step_cnt) with ++ * 0 < sample_cnt < MAX_SAMPLE_CNT_DIV ++ * 0 < step_cnt < max_step_cnt ++ * sample_cnt * step_cnt >= opt_div ++ * optimizing for sample_cnt * step_cnt being minimal ++ */ ++ for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) { ++ step_cnt = DIV_ROUND_UP(opt_div, sample_cnt); ++ cnt_mul = step_cnt * sample_cnt; ++ if (step_cnt > max_step_cnt) ++ continue; ++ ++ if (cnt_mul < best_mul) { ++ best_mul = cnt_mul; ++ base_sample_cnt = sample_cnt; ++ base_step_cnt = step_cnt; ++ if (best_mul == opt_div) ++ break; ++ } ++ } ++ ++ sample_cnt = base_sample_cnt; ++ step_cnt = base_step_cnt; ++ ++ if ((clk_src / (2 * sample_cnt * step_cnt)) > target_speed) { ++ /* ++ * In this case, hardware can't support such ++ * low i2c_bus_freq ++ */ ++ debug("Unsupported speed(%uhz)\n", target_speed); ++ return log_msg_ret("calculate speed", -EINVAL); ++ } ++ ++ *timing_step_cnt = step_cnt - 1; ++ *timing_sample_cnt = sample_cnt - 1; ++ ++ return 0; ++} ++ ++/* ++ * mtk_i2c_set_speed ++ * ++ * @par Description ++ * Calculate i2c speed and write sample_cnt, step_cnt to TIMING register. ++ * @param[in] ++ * dev: udevice pointer, struct udevice contains i2c source clock, ++ * clock divide and speed. ++ * @return ++ * 0, set speed successfully.\n ++ * error code from mtk_i2c_calculate_speed(). ++ */ ++static int mtk_i2c_set_speed(struct udevice *dev, uint speed) ++{ ++ struct mtk_i2c_priv *priv = dev_get_priv(dev); ++ uint high_speed_reg; ++ uint sample_cnt; ++ uint timing_reg; ++ uint step_cnt; ++ uint clk_src; ++ int ret = 0; ++ ++ priv->speed = speed; ++ if (mtk_i2c_clk_enable(priv)) ++ return log_msg_ret("set_speed enable clk", -1); ++ ++ clk_src = clk_get_rate(&priv->clk_main) / I2C_DEFAULT_CLK_DIV; ++ i2c_writel(priv, REG_CLOCK_DIV, (I2C_DEFAULT_CLK_DIV - 1)); ++ if (priv->speed > MAX_FS_MODE_SPEED) { ++ /* Set master code speed register */ ++ ret = mtk_i2c_calculate_speed(clk_src, MAX_FS_MODE_SPEED, ++ &step_cnt, &sample_cnt); ++ if (ret < 0) ++ goto exit; ++ ++ timing_reg = (sample_cnt << TIMING_SAMPLE_OFFSET) | step_cnt; ++ i2c_writel(priv, REG_TIMING, timing_reg); ++ /* Set the high speed mode register */ ++ ret = mtk_i2c_calculate_speed(clk_src, priv->speed, ++ &step_cnt, &sample_cnt); ++ if (ret < 0) ++ goto exit; ++ ++ high_speed_reg = I2C_TIME_DEFAULT_VALUE | ++ (sample_cnt << HS_SAMPLE_OFFSET) | ++ (step_cnt << HS_STEP_OFFSET); ++ i2c_writel(priv, REG_HS, high_speed_reg); ++ } else { ++ ret = mtk_i2c_calculate_speed(clk_src, priv->speed, ++ &step_cnt, &sample_cnt); ++ if (ret < 0) ++ goto exit; ++ ++ timing_reg = (sample_cnt << TIMING_SAMPLE_OFFSET) | step_cnt; ++ /* Disable the high speed transaction */ ++ high_speed_reg = I2C_TIME_CLR_VALUE; ++ i2c_writel(priv, REG_TIMING, timing_reg); ++ i2c_writel(priv, REG_HS, high_speed_reg); ++ } ++exit: ++ if (mtk_i2c_clk_disable(priv)) ++ return log_msg_ret("set_speed disable clk", -1); ++ ++ return ret; ++} ++ ++/* ++ * mtk_i2c_do_transfer ++ * ++ * @par Description ++ * Configure i2c register and trigger transfer. ++ * @param[in] ++ * priv: mtk_i2cmtk_i2c_priv pointer, struct mtk_i2c_priv contains register base\n ++ * address, operation mode, interrupt status and i2c driver data. ++ * @param[in] ++ * msgs: i2c_msg pointer, struct i2c_msg contains slave\n ++ * address, operation mode, msg length and data buffer. ++ * @param[in] ++ * num: i2c_msg number. ++ * @param[in] ++ * left_num: left i2c_msg number. ++ * @return ++ * 0, i2c transfer successfully.\n ++ * -ETIMEDOUT, i2c transfer timeout.\n ++ * -EREMOTEIO, i2c transfer ack error. ++ */ ++static int mtk_i2c_do_transfer(struct mtk_i2c_priv *priv, ++ struct i2c_msg *msgs, ++ int num, int left_num) ++{ ++ struct i2c_msg *msg_rx = NULL; ++ uint restart_flag = 0; ++ uint trans_error = 0; ++ uint irq_stat = 0; ++ uint tmo_poll = 0; ++ uint control_reg; ++ bool tmo = false; ++ uint start_reg; ++ uint addr_reg; ++ int ret = 0; ++ ++ if (priv->auto_restart) ++ restart_flag = I2C_RS_TRANSFER; ++ ++ control_reg = i2c_readl(priv, REG_CONTROL) & ++ ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS); ++ ++ if (priv->speed > MAX_FS_MODE_SPEED || num > 1) ++ control_reg |= I2C_CONTROL_RS; ++ ++ if (priv->op == I2C_MASTER_WRRD) ++ control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS; ++ ++ control_reg |= I2C_CONTROL_DMA_EN; ++ i2c_writel(priv, REG_CONTROL, control_reg); ++ ++ /* set start condition */ ++ if (priv->speed <= MAX_ST_MODE_SPEED) ++ i2c_writel(priv, REG_EXT_CONF, I2C_ST_START_CON); ++ else ++ i2c_writel(priv, REG_EXT_CONF, I2C_FS_START_CON); ++ ++ addr_reg = msgs->addr << 1; ++ if (priv->op == I2C_MASTER_RD) ++ addr_reg |= I2C_M_RD; ++ if (priv->zero_len) ++ i2c_writel(priv, REG_SLAVE_ADDR, addr_reg | TRANS_ADDR_ONLY); ++ else ++ i2c_writel(priv, REG_SLAVE_ADDR, addr_reg); ++ ++ /* clear interrupt status */ ++ i2c_writel(priv, REG_INTR_STAT, restart_flag | I2C_HS_NACKERR | ++ I2C_ACKERR | I2C_TRANSAC_COMP); ++ i2c_writel(priv, REG_FIFO_ADDR_CLR, I2C_FIFO_ADDR_CLR); ++ ++ /* enable interrupt */ ++ i2c_writel(priv, REG_INTR_MASK, restart_flag | I2C_HS_NACKERR | ++ I2C_ACKERR | I2C_TRANSAC_COMP); ++ ++ /* set transfer and transaction len */ ++ if (priv->op == I2C_MASTER_WRRD) { ++ i2c_writel(priv, REG_TRANSFER_LEN, msgs->len); ++ i2c_writel(priv, REG_TRANSFER_LEN_AUX, (msgs + 1)->len); ++ i2c_writel(priv, REG_TRANSAC_LEN, I2C_WRRD_TRANAC_VALUE); ++ } else { ++ i2c_writel(priv, REG_TRANSFER_LEN, msgs->len); ++ i2c_writel(priv, REG_TRANSAC_LEN, num); ++ } ++ ++ /* Clear DMA interrupt flag */ ++ writel(I2C_DMA_INT_FLAG_NONE, priv->pdmabase + REG_INT_FLAG); ++ ++ /* Flush cache for first msg */ ++ flush_cache((ulong)msgs->buf, msgs->len); ++ ++ /* ++ * prepare buffer data to start transfer ++ * three cases here: read, write, write then read ++ */ ++ if (priv->op & I2C_MASTER_WR) { ++ /* Set DMA direction TX (w/ or w/o RX) */ ++ writel(I2C_DMA_CON_TX, priv->pdmabase + REG_CON); ++ ++ /* Write the tx buffer address to dma register */ ++ writel((ulong)msgs->buf, priv->pdmabase + REG_TX_MEM_ADDR); ++ /* Write the tx length to dma register */ ++ writel(msgs->len, priv->pdmabase + REG_TX_LEN); ++ ++ if (priv->op & I2C_MASTER_RD) { ++ /* write then read */ ++ msg_rx = msgs + 1; ++ ++ /* Flush cache for second msg */ ++ flush_cache((ulong)msg_rx->buf, msg_rx->len); ++ } ++ } ++ ++ if (priv->op & I2C_MASTER_RD) { ++ if (!msg_rx) { ++ /* Set DMA direction RX */ ++ writel(I2C_DMA_CON_RX, priv->pdmabase + REG_CON); ++ ++ msg_rx = msgs; ++ } ++ ++ /* Write the rx buffer address to dma register */ ++ writel((ulong)msg_rx->buf, priv->pdmabase + REG_RX_MEM_ADDR); ++ /* Write the rx length to dma register */ ++ writel(msg_rx->len, priv->pdmabase + REG_RX_LEN); ++ } ++ ++ writel(I2C_DMA_START_EN, priv->pdmabase + REG_EN); ++ ++ if (!priv->auto_restart) { ++ start_reg = I2C_TRANSAC_START; ++ } else { ++ start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG; ++ if (left_num >= 1) ++ start_reg |= I2C_RS_MUL_CNFG; ++ } ++ i2c_writel(priv, REG_START, start_reg); ++ ++ for (;;) { ++ irq_stat = i2c_readl(priv, REG_INTR_STAT); ++ ++ /* ignore the first restart irq after the master code */ ++ if (priv->ignore_restart_irq && (irq_stat & restart_flag)) { ++ priv->ignore_restart_irq = false; ++ irq_stat = 0; ++ i2c_writel(priv, REG_START, I2C_RS_MUL_CNFG | ++ I2C_RS_MUL_TRIG | I2C_TRANSAC_START); ++ } ++ ++ if (irq_stat & (I2C_TRANSAC_COMP | restart_flag)) { ++ tmo = false; ++ if (irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) ++ trans_error = 1; ++ ++ break; ++ } ++ udelay(1); ++ if (tmo_poll++ >= TRANSFER_TIMEOUT) { ++ tmo = true; ++ break; ++ } ++ } ++ ++ /* clear interrupt mask */ ++ i2c_writel(priv, REG_INTR_MASK, ~(restart_flag | I2C_HS_NACKERR | ++ I2C_ACKERR | I2C_TRANSAC_COMP)); ++ ++ if (!tmo && trans_error != 0) { ++ if (tmo) { ++ ret = -ETIMEDOUT; ++ if (!priv->filter_msg) ++ debug("I2C timeout! addr: 0x%x,\n", msgs->addr); ++ } else { ++ ret = -EREMOTEIO; ++ if (!priv->filter_msg) ++ debug("I2C ACKERR! addr: 0x%x,IRQ:0x%x\n", ++ msgs->addr, irq_stat); ++ } ++ mtk_i2c_init_hw(priv); ++ } ++ ++ return ret; ++} ++ ++/* ++ * mtk_i2c_transfer ++ * ++ * @par Description ++ * Common i2c transfer API. Set i2c transfer mode according to i2c_msg\n ++ * information, then call mtk_i2c_do_transfer() to configure i2c register\n ++ * and trigger transfer. ++ * @param[in] ++ * dev: udevice pointer, struct udevice contains struct mtk_i2c_priv, \n ++ * struct mtk_i2c_priv contains register base\n ++ * address, operation mode, interrupt status and i2c driver data. ++ * @param[in] ++ * msgs: i2c_msg pointer, struct i2c_msg contains slave\n ++ * address, operation mode, msg length and data buffer. ++ * @param[in] ++ * num: i2c_msg number. ++ * @return ++ * i2c_msg number, i2c transfer successfully.\n ++ * -EINVAL, msg length is more than 16\n ++ * use DMA MODE or slave address more than 0x7f.\n ++ * error code from mtk_i2c_init_base().\n ++ * error code from mtk_i2c_set_speed().\n ++ * error code from mtk_i2c_do_transfer(). ++ */ ++static int mtk_i2c_transfer(struct udevice *dev, struct i2c_msg *msg, ++ int nmsgs) ++{ ++ struct mtk_i2c_priv *priv = dev_get_priv(dev); ++ int left_num; ++ uint num_cnt; ++ int ret; ++ ++ priv->auto_restart = true; ++ left_num = nmsgs; ++ if (mtk_i2c_clk_enable(priv)) ++ return log_msg_ret("transfer enable clk", -1); ++ ++ for (num_cnt = 0; num_cnt < nmsgs; num_cnt++) { ++ if (((msg + num_cnt)->addr) > MAX_I2C_ADDR) { ++ ret = -EINVAL; ++ goto err_exit; ++ } ++ if ((msg + num_cnt)->len > MAX_I2C_LEN) { ++ ret = -EINVAL; ++ goto err_exit; ++ } ++ } ++ ++ /* check if we can skip restart and optimize using WRRD mode */ ++ if (priv->auto_restart && nmsgs == 2) { ++ if (!(msg[0].flags & I2C_M_RD) && (msg[1].flags & I2C_M_RD) && ++ msg[0].addr == msg[1].addr) { ++ priv->auto_restart = false; ++ } ++ } ++ ++ if (priv->auto_restart && nmsgs >= 2 && priv->speed > MAX_FS_MODE_SPEED) ++ /* ignore the first restart irq after the master code, ++ * otherwise the first transfer will be discarded. ++ */ ++ priv->ignore_restart_irq = true; ++ else ++ priv->ignore_restart_irq = false; ++ ++ while (left_num--) { ++ /* transfer slave address only to support devices detect */ ++ if (!msg->buf) ++ priv->zero_len = true; ++ else ++ priv->zero_len = false; ++ ++ if (msg->flags & I2C_M_RD) ++ priv->op = I2C_MASTER_RD; ++ else ++ priv->op = I2C_MASTER_WR; ++ ++ if (!priv->auto_restart) { ++ if (nmsgs > 1) { ++ /* combined two messages into one transaction */ ++ priv->op = I2C_MASTER_WRRD; ++ left_num--; ++ } ++ } ++ ret = mtk_i2c_do_transfer(priv, msg, nmsgs, left_num); ++ if (ret < 0) ++ goto err_exit; ++ msg++; ++ } ++ ret = 0; ++ ++err_exit: ++ if (mtk_i2c_clk_disable(priv)) ++ return log_msg_ret("transfer disable clk", -1); ++ ++ return ret; ++} ++ ++static int mtk_i2c_of_to_plat(struct udevice *dev) ++{ ++ struct mtk_i2c_priv *priv = dev_get_priv(dev); ++ int ret; ++ ++ priv->base = dev_remap_addr_index(dev, 0); ++ priv->pdmabase = dev_remap_addr_index(dev, 1); ++ ret = clk_get_by_index(dev, 0, &priv->clk_main); ++ if (ret) ++ return log_msg_ret("clk_get_by_index 0", ret); ++ ++ ret = clk_get_by_index(dev, 1, &priv->clk_dma); ++ ++ return ret; ++} ++ ++static int mtk_i2c_probe(struct udevice *dev) ++{ ++ struct mtk_i2c_priv *priv = dev_get_priv(dev); ++ ++ priv->soc_data = (struct mtk_i2c_soc_data *)dev_get_driver_data(dev); ++ ++ if (mtk_i2c_clk_enable(priv)) ++ return log_msg_ret("probe enable clk", -1); ++ ++ mtk_i2c_init_hw(priv); ++ ++ if (mtk_i2c_clk_disable(priv)) ++ return log_msg_ret("probe disable clk", -1); ++ ++ return 0; ++} ++ ++static int mtk_i2c_deblock(struct udevice *dev) ++{ ++ struct mtk_i2c_priv *priv = dev_get_priv(dev); ++ ++ if (mtk_i2c_clk_enable(priv)) ++ return log_msg_ret("deblock enable clk", -1); ++ ++ mtk_i2c_init_hw(priv); ++ ++ if (mtk_i2c_clk_disable(priv)) ++ return log_msg_ret("deblock disable clk", -1); ++ ++ return 0; ++} ++ ++static const struct mtk_i2c_soc_data mt76xx_soc_data = { ++ .regs = mt_i2c_regs_v1, ++ .dma_sync = 0, ++}; ++ ++static const struct mtk_i2c_soc_data mt7981_soc_data = { ++ .regs = mt_i2c_regs_v1, ++ .dma_sync = 1, ++}; ++ ++static const struct mtk_i2c_soc_data mt7986_soc_data = { ++ .regs = mt_i2c_regs_v1, ++ .dma_sync = 1, ++}; ++ ++static const struct mtk_i2c_soc_data mt8183_soc_data = { ++ .regs = mt_i2c_regs_v2, ++ .dma_sync = 1, ++}; ++ ++static const struct mtk_i2c_soc_data mt8518_soc_data = { ++ .regs = mt_i2c_regs_v1, ++ .dma_sync = 0, ++}; ++ ++static const struct mtk_i2c_soc_data mt8512_soc_data = { ++ .regs = mt_i2c_regs_v1, ++ .dma_sync = 1, ++}; ++ ++static const struct dm_i2c_ops mtk_i2c_ops = { ++ .xfer = mtk_i2c_transfer, ++ .set_bus_speed = mtk_i2c_set_speed, ++ .deblock = mtk_i2c_deblock, ++}; ++ ++static const struct udevice_id mtk_i2c_ids[] = { ++ { ++ .compatible = "mediatek,mt7622-i2c", ++ .data = (ulong)&mt76xx_soc_data, ++ }, { ++ .compatible = "mediatek,mt7623-i2c", ++ .data = (ulong)&mt76xx_soc_data, ++ }, { ++ .compatible = "mediatek,mt7629-i2c", ++ .data = (ulong)&mt76xx_soc_data, ++ }, { ++ .compatible = "mediatek,mt7981-i2c", ++ .data = (ulong)&mt7981_soc_data, ++ }, { ++ .compatible = "mediatek,mt7986-i2c", ++ .data = (ulong)&mt7986_soc_data, ++ }, { ++ .compatible = "mediatek,mt8183-i2c", ++ .data = (ulong)&mt8183_soc_data, ++ }, { ++ .compatible = "mediatek,mt8512-i2c", ++ .data = (ulong)&mt8512_soc_data, ++ }, { ++ .compatible = "mediatek,mt8518-i2c", ++ .data = (ulong)&mt8518_soc_data, ++ } ++}; ++ ++U_BOOT_DRIVER(mtk_i2c) = { ++ .name = "mtk_i2c", ++ .id = UCLASS_I2C, ++ .of_match = mtk_i2c_ids, ++ .of_to_plat = mtk_i2c_of_to_plat, ++ .probe = mtk_i2c_probe, ++ .priv_auto = sizeof(struct mtk_i2c_priv), ++ .ops = &mtk_i2c_ops, ++}; diff --git a/package/boot/uboot-mediatek/patches/002-0018-arm-dts-mt7622-add-i2c-support.patch b/package/boot/uboot-mediatek/patches/002-0018-arm-dts-mt7622-add-i2c-support.patch new file mode 100644 index 0000000000..378078882e --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0018-arm-dts-mt7622-add-i2c-support.patch @@ -0,0 +1,76 @@ +From 9ae337317d5634569bda83dfc5e0658fce34b1e2 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 16:30:30 +0800 +Subject: [PATCH 18/31] arm: dts: mt7622: add i2c support + +Add both hardware and software i2c support for mt7622. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + arch/arm/dts/mt7622-rfb.dts | 18 ++++++++++++++++++ + arch/arm/dts/mt7622.dtsi | 24 ++++++++++++++++++++++++ + 2 files changed, 42 insertions(+) + +--- a/arch/arm/dts/mt7622-rfb.dts ++++ b/arch/arm/dts/mt7622-rfb.dts +@@ -159,6 +159,14 @@ + }; + + }; ++ ++ i2c1_pins_default: i2c1-default { ++ mux { ++ function = "i2c"; ++ groups = "i2c1_0"; ++ }; ++ }; ++ + }; + + &snfi { +@@ -242,3 +250,13 @@ + &u3phy { + status = "okay"; + }; ++ ++&soft_i2c { ++ status = "disabled"; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins_default>; ++ status = "okay"; ++}; +--- a/arch/arm/dts/mt7622.dtsi ++++ b/arch/arm/dts/mt7622.dtsi +@@ -424,4 +424,28 @@ + status = "disabled"; + }; + ++ soft_i2c: soft_i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "i2c-gpio"; ++ gpios = <&gpio 56 GPIO_ACTIVE_HIGH>, /* SDA */ ++ <&gpio 55 GPIO_ACTIVE_HIGH>; /* CLK */ ++ i2c-gpio,delay-us = <5>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@11008000 { ++ compatible = "mediatek,mt7622-i2c"; ++ reg = <0x11008000 0x90>, ++ <0x11000180 0x80>; ++ interrupts = ; ++ clock-div = <16>; ++ clocks = <&pericfg CLK_PERI_I2C1_PD>, ++ <&pericfg CLK_PERI_AP_DMA_PD>; ++ clock-names = "main", "dma"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + }; diff --git a/package/boot/uboot-mediatek/patches/002-0019-dt-bindings-pinctrl-mediatek-add-a-header-for-common.patch b/package/boot/uboot-mediatek/patches/002-0019-dt-bindings-pinctrl-mediatek-add-a-header-for-common.patch new file mode 100644 index 0000000000..385ec1395b --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0019-dt-bindings-pinctrl-mediatek-add-a-header-for-common.patch @@ -0,0 +1,60 @@ +From 920ba7b9ba1787fd03dad7a5bdc894073936c197 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Thu, 28 Jul 2022 09:37:26 +0800 +Subject: [PATCH 19/31] dt-bindings: pinctrl: mediatek: add a header for common + pinconf parameters + +This patch adds a pinctrl header for common pinconf parameters such as +pull-up/pull-down resistors and drive strengths. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + include/dt-bindings/pinctrl/mt65xx.h | 41 ++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + create mode 100644 include/dt-bindings/pinctrl/mt65xx.h + +--- /dev/null ++++ b/include/dt-bindings/pinctrl/mt65xx.h +@@ -0,0 +1,41 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Hongzhou.Yang ++ */ ++ ++#ifndef _DT_BINDINGS_PINCTRL_MT65XX_H ++#define _DT_BINDINGS_PINCTRL_MT65XX_H ++ ++#define MTK_PIN_NO(x) ((x) << 8) ++#define MTK_GET_PIN_NO(x) ((x) >> 8) ++#define MTK_GET_PIN_FUNC(x) ((x) & 0xf) ++ ++#define MTK_PUPD_SET_R1R0_00 100 ++#define MTK_PUPD_SET_R1R0_01 101 ++#define MTK_PUPD_SET_R1R0_10 102 ++#define MTK_PUPD_SET_R1R0_11 103 ++ ++#define MTK_PULL_SET_RSEL_000 200 ++#define MTK_PULL_SET_RSEL_001 201 ++#define MTK_PULL_SET_RSEL_010 202 ++#define MTK_PULL_SET_RSEL_011 203 ++#define MTK_PULL_SET_RSEL_100 204 ++#define MTK_PULL_SET_RSEL_101 205 ++#define MTK_PULL_SET_RSEL_110 206 ++#define MTK_PULL_SET_RSEL_111 207 ++ ++#define MTK_DRIVE_2mA 2 ++#define MTK_DRIVE_4mA 4 ++#define MTK_DRIVE_6mA 6 ++#define MTK_DRIVE_8mA 8 ++#define MTK_DRIVE_10mA 10 ++#define MTK_DRIVE_12mA 12 ++#define MTK_DRIVE_14mA 14 ++#define MTK_DRIVE_16mA 16 ++#define MTK_DRIVE_20mA 20 ++#define MTK_DRIVE_24mA 24 ++#define MTK_DRIVE_28mA 28 ++#define MTK_DRIVE_32mA 32 ++ ++#endif /* _DT_BINDINGS_PINCTRL_MT65XX_H */ diff --git a/package/boot/uboot-mediatek/patches/002-0020-pinctrl-mediatek-add-pinctrl-driver-for-MT7981-SoC.patch b/package/boot/uboot-mediatek/patches/002-0020-pinctrl-mediatek-add-pinctrl-driver-for-MT7981-SoC.patch new file mode 100644 index 0000000000..809b3cbc9b --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0020-pinctrl-mediatek-add-pinctrl-driver-for-MT7981-SoC.patch @@ -0,0 +1,1091 @@ +From 49e7b1e01cf80437c7e22f8b6579d4a81e7f8a3a Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Thu, 28 Jul 2022 09:57:58 +0800 +Subject: [PATCH 20/31] pinctrl: mediatek: add pinctrl driver for MT7981 SoC + +This patch adds pinctrl and gpio support for MT7981 SoC + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/pinctrl/mediatek/Kconfig | 4 + + drivers/pinctrl/mediatek/Makefile | 1 + + drivers/pinctrl/mediatek/pinctrl-mt7981.c | 1049 +++++++++++++++++++++ + 3 files changed, 1054 insertions(+) + create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7981.c + +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -16,6 +16,10 @@ config PINCTRL_MT7629 + bool "MT7629 SoC pinctrl driver" + select PINCTRL_MTK + ++config PINCTRL_MT7981 ++ bool "MT7981 SoC pinctrl driver" ++ select PINCTRL_MTK ++ + config PINCTRL_MT8512 + bool "MT8512 SoC pinctrl driver" + select PINCTRL_MTK +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk + obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o + obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o + obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o ++obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o + obj-$(CONFIG_PINCTRL_MT8512) += pinctrl-mt8512.o + obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o + obj-$(CONFIG_PINCTRL_MT8518) += pinctrl-mt8518.o +--- /dev/null ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c +@@ -0,0 +1,1049 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * The MT7981 driver based on Linux generic pinctrl binding. ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include "pinctrl-mtk-common.h" ++ ++#define MT7981_TYPE0_PIN(_number, _name) \ ++ MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP0) ++ ++#define MT7981_TYPE1_PIN(_number, _name) \ ++ MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP1) ++ ++#define PIN_FIELD_GPIO(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \ ++ PIN_FIELD_BASE_CALC(_s_pin, _e_pin, GPIO_BASE, _s_addr, _x_addrs, \ ++ _s_bit, _x_bits, 32, 0) ++ ++#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ ++ _x_bits) \ ++ PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ ++ _x_bits, 32, 0) ++ ++/** ++ * enum - Locking variants of the iocfg bases ++ * ++ * MT7981 have multiple bases to program pin configuration listed as the below: ++ * iocfg_rt:0x11c00000, iocfg_rm:0x11c10000, iocfg_rb:0x11d20000, ++ * iocfg_lb:0x11e00000, iocfg_bl:0x11e20000, iocfg_tm:0x11f00000, ++ * iocfg_tl:0x11f10000, ++ * _i_based could be used to indicate what base the pin should be mapped into. ++ * ++ * Each iocfg register base control different group of pads on the SoC ++ * ++ * ++ * chip carrier ++ * ++ * A B C D E F G H ++ * +------------------------+ ++ * 8 | o o o o o o o o | ++ * 7 | o o o o o o o o | ++ * 6 | o o o o o o o o | ++ * 5 | o o o o o o o o | ++ * 4 | o o o o o o o o | ++ * 3 | o o o o o o o o | ++ * 2 | o o o o o o o o | ++ * 1 | o o o o o o o o | ++ * +------------------------+ ++ * ++ * inside Chip carrier ++ * ++ * A B C D E F G H ++ * +------------------------+ ++ * 8 | | ++ * 7 | TL TM | ++ * 6 | +---------+ | ++ * 5 | | | RT | ++ * 4 | | | RM | ++ * 3 | LB | | RB | ++ * 2 | +---------+ | ++ * 1 | BL | ++ * +------------------------+ ++ * ++ */ ++ ++enum { ++ GPIO_BASE, ++ IOCFG_RT_BASE, ++ IOCFG_RM_BASE, ++ IOCFG_RB_BASE, ++ IOCFG_LB_BASE, ++ IOCFG_BL_BASE, ++ IOCFG_TM_BASE, ++ IOCFG_TL_BASE, ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_mode_range[] = { ++ PIN_FIELD_GPIO(0, 56, 0x300, 0x10, 0, 4), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_dir_range[] = { ++ PIN_FIELD_GPIO(0, 56, 0x0, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_di_range[] = { ++ PIN_FIELD_GPIO(0, 56, 0x200, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_do_range[] = { ++ PIN_FIELD_GPIO(0, 56, 0x100, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_ies_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x10, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x10, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(9, 9, 4, 0x20, 0x10, 9, 1), ++ ++ PIN_FIELD_BASE(10, 10, 5, 0x20, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x20, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x20, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x20, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x20, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x20, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x20, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x20, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x20, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x20, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x10, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x10, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x20, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x20, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x10, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x10, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 1, 1), ++ ++ PIN_FIELD_BASE(40, 40, 7, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x30, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x30, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x30, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x10, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x10, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x10, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x10, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x10, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x10, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x10, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_smt_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x60, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x60, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x90, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x80, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x80, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x80, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x80, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x80, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x80, 0x10, 4, 1), ++ PIN_FIELD_BASE(9, 9, 4, 0x80, 0x10, 9, 1), ++ ++ PIN_FIELD_BASE(10, 10, 5, 0x90, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x90, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x90, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x90, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x80, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x90, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x90, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x90, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x90, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x90, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x90, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x90, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x90, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x90, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x90, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x90, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x90, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x90, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x90, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x90, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x90, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x60, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x60, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x80, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x80, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x60, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x60, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x60, 0x10, 1, 1), ++ ++ PIN_FIELD_BASE(40, 40, 7, 0x70, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x70, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x70, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x70, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x70, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x70, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x70, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x70, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x70, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x50, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_pu_range[] = { ++ PIN_FIELD_BASE(40, 40, 7, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x50, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x50, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x50, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x50, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x30, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_pd_range[] = { ++ PIN_FIELD_BASE(40, 40, 7, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(41, 41, 7, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(42, 42, 7, 0x40, 0x10, 9, 1), ++ PIN_FIELD_BASE(43, 43, 7, 0x40, 0x10, 7, 1), ++ PIN_FIELD_BASE(44, 44, 7, 0x40, 0x10, 8, 1), ++ PIN_FIELD_BASE(45, 45, 7, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(46, 46, 7, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(47, 47, 7, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(48, 48, 7, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(49, 49, 7, 0x40, 0x10, 2, 1), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(51, 51, 6, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(52, 52, 6, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(53, 53, 6, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(54, 54, 6, 0x20, 0x10, 5, 1), ++ PIN_FIELD_BASE(55, 55, 6, 0x20, 0x10, 6, 1), ++ PIN_FIELD_BASE(56, 56, 6, 0x20, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_drv_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(1, 1, 1, 0x00, 0x10, 0, 3), ++ ++ PIN_FIELD_BASE(2, 2, 5, 0x00, 0x10, 18, 3), ++ ++ PIN_FIELD_BASE(3, 3, 4, 0x00, 0x10, 18, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x00, 0x10, 6, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(6, 6, 4, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(9, 9, 4, 0x00, 0x10, 27, 3), ++ ++ PIN_FIELD_BASE(10, 10, 5, 0x00, 0x10, 24, 3), ++ PIN_FIELD_BASE(11, 11, 5, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(12, 12, 5, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(13, 13, 5, 0x00, 0x10, 3, 3), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x00, 0x10, 27, 3), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(16, 16, 2, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(17, 17, 2, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(18, 18, 2, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(19, 19, 2, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(20, 20, 2, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(21, 21, 2, 0x00, 0x10, 18, 3), ++ PIN_FIELD_BASE(22, 22, 2, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(23, 23, 2, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(24, 24, 2, 0x00, 0x10, 27, 3), ++ PIN_FIELD_BASE(25, 25, 2, 0x00, 0x10, 24, 3), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(27, 27, 5, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(28, 28, 5, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(29, 29, 5, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(30, 30, 5, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(31, 31, 5, 0x00, 0x10, 15, 3), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(33, 33, 1, 0x00, 0x10, 12, 3), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(35, 35, 4, 0x00, 0x10, 21, 3), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(37, 37, 3, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(38, 38, 3, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(39, 39, 3, 0x00, 0x10, 3, 3), ++ ++ PIN_FIELD_BASE(40, 40, 7, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(41, 41, 7, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(42, 42, 7, 0x00, 0x10, 27, 3), ++ PIN_FIELD_BASE(43, 43, 7, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(44, 44, 7, 0x00, 0x10, 24, 3), ++ PIN_FIELD_BASE(45, 45, 7, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(46, 46, 7, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(47, 47, 7, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(48, 48, 7, 0x00, 0x10, 18, 3), ++ PIN_FIELD_BASE(49, 49, 7, 0x00, 0x10, 6, 3), ++ ++ PIN_FIELD_BASE(50, 50, 6, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(51, 51, 6, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(52, 52, 6, 0x00, 0x10, 9, 3), ++ PIN_FIELD_BASE(53, 53, 6, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(54, 54, 6, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(55, 55, 6, 0x00, 0x10, 18, 3), ++ PIN_FIELD_BASE(56, 56, 6, 0x00, 0x10, 3, 3), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_pupd_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x20, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(9, 9, 4, 0x30, 0x10, 9, 1), ++ ++ PIN_FIELD_BASE(10, 10, 5, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x30, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x30, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x30, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x30, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x90, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x30, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x30, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x30, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x30, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x30, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x20, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x30, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x20, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x20, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_r0_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(9, 9, 4, 0x40, 0x10, 9, 1), ++ ++ PIN_FIELD_BASE(10, 10, 5, 0x40, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x40, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x40, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x40, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x40, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x40, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x40, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x40, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x30, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x40, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x30, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7981_pin_r1_range[] = { ++ PIN_FIELD_BASE(0, 0, 1, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(1, 1, 1, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(2, 2, 5, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(3, 3, 4, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(4, 4, 4, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(5, 5, 4, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(6, 6, 4, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(7, 7, 4, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(8, 8, 4, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(9, 9, 4, 0x50, 0x10, 9, 1), ++ ++ PIN_FIELD_BASE(10, 10, 5, 0x50, 0x10, 8, 1), ++ PIN_FIELD_BASE(11, 11, 5, 0x50, 0x10, 10, 1), ++ PIN_FIELD_BASE(12, 12, 5, 0x50, 0x10, 7, 1), ++ PIN_FIELD_BASE(13, 13, 5, 0x50, 0x10, 11, 1), ++ ++ PIN_FIELD_BASE(14, 14, 4, 0x50, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(15, 15, 2, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(16, 16, 2, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(17, 17, 2, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(18, 18, 2, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(19, 19, 2, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(20, 20, 2, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(21, 21, 2, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(22, 22, 2, 0x50, 0x10, 7, 1), ++ PIN_FIELD_BASE(23, 23, 2, 0x50, 0x10, 10, 1), ++ PIN_FIELD_BASE(24, 24, 2, 0x50, 0x10, 9, 1), ++ PIN_FIELD_BASE(25, 25, 2, 0x50, 0x10, 8, 1), ++ ++ PIN_FIELD_BASE(26, 26, 5, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(27, 27, 5, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(28, 28, 5, 0x50, 0x10, 3, 1), ++ PIN_FIELD_BASE(29, 29, 5, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(30, 30, 5, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(31, 31, 5, 0x50, 0x10, 5, 1), ++ ++ PIN_FIELD_BASE(32, 32, 1, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(33, 33, 1, 0x40, 0x10, 3, 1), ++ ++ PIN_FIELD_BASE(34, 34, 4, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(35, 35, 4, 0x50, 0x10, 7, 1), ++ ++ PIN_FIELD_BASE(36, 36, 3, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(37, 37, 3, 0x40, 0x10, 3, 1), ++ PIN_FIELD_BASE(38, 38, 3, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(39, 39, 3, 0x40, 0x10, 1, 1), ++}; ++ ++static const struct mtk_pin_reg_calc mt7981_reg_cals[] = { ++ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7981_pin_mode_range), ++ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7981_pin_dir_range), ++ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7981_pin_di_range), ++ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7981_pin_do_range), ++ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7981_pin_smt_range), ++ [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7981_pin_ies_range), ++ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7981_pin_pu_range), ++ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7981_pin_pd_range), ++ [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7981_pin_drv_range), ++ [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7981_pin_pupd_range), ++ [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7981_pin_r0_range), ++ [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7981_pin_r1_range), ++}; ++ ++static const struct mtk_pin_desc mt7981_pins[] = { ++ MT7981_TYPE0_PIN(0, "GPIO_WPS"), ++ MT7981_TYPE0_PIN(1, "GPIO_RESET"), ++ MT7981_TYPE0_PIN(2, "SYS_WATCHDOG"), ++ MT7981_TYPE0_PIN(3, "PCIE_PERESET_N"), ++ MT7981_TYPE0_PIN(4, "JTAG_JTDO"), ++ MT7981_TYPE0_PIN(5, "JTAG_JTDI"), ++ MT7981_TYPE0_PIN(6, "JTAG_JTMS"), ++ MT7981_TYPE0_PIN(7, "JTAG_JTCLK"), ++ MT7981_TYPE0_PIN(8, "JTAG_JTRST_N"), ++ MT7981_TYPE0_PIN(9, "WO_JTAG_JTDO"), ++ MT7981_TYPE0_PIN(10, "WO_JTAG_JTDI"), ++ MT7981_TYPE0_PIN(11, "WO_JTAG_JTMS"), ++ MT7981_TYPE0_PIN(12, "WO_JTAG_JTCLK"), ++ MT7981_TYPE0_PIN(13, "WO_JTAG_JTRST_N"), ++ MT7981_TYPE0_PIN(14, "USB_VBUS"), ++ MT7981_TYPE0_PIN(15, "PWM0"), ++ MT7981_TYPE0_PIN(16, "SPI0_CLK"), ++ MT7981_TYPE0_PIN(17, "SPI0_MOSI"), ++ MT7981_TYPE0_PIN(18, "SPI0_MISO"), ++ MT7981_TYPE0_PIN(19, "SPI0_CS"), ++ MT7981_TYPE0_PIN(20, "SPI0_HOLD"), ++ MT7981_TYPE0_PIN(21, "SPI0_WP"), ++ MT7981_TYPE0_PIN(22, "SPI1_CLK"), ++ MT7981_TYPE0_PIN(23, "SPI1_MOSI"), ++ MT7981_TYPE0_PIN(24, "SPI1_MISO"), ++ MT7981_TYPE0_PIN(25, "SPI1_CS"), ++ MT7981_TYPE0_PIN(26, "SPI2_CLK"), ++ MT7981_TYPE0_PIN(27, "SPI2_MOSI"), ++ MT7981_TYPE0_PIN(28, "SPI2_MISO"), ++ MT7981_TYPE0_PIN(29, "SPI2_CS"), ++ MT7981_TYPE0_PIN(30, "SPI2_HOLD"), ++ MT7981_TYPE0_PIN(31, "SPI2_WP"), ++ MT7981_TYPE0_PIN(32, "UART0_RXD"), ++ MT7981_TYPE0_PIN(33, "UART0_TXD"), ++ MT7981_TYPE0_PIN(34, "PCIE_CLK_REQ"), ++ MT7981_TYPE0_PIN(35, "PCIE_WAKE_N"), ++ MT7981_TYPE0_PIN(36, "SMI_MDC"), ++ MT7981_TYPE0_PIN(37, "SMI_MDIO"), ++ MT7981_TYPE0_PIN(38, "GBE_INT"), ++ MT7981_TYPE0_PIN(39, "GBE_RESET"), ++ MT7981_TYPE1_PIN(40, "WF_DIG_RESETB"), ++ MT7981_TYPE1_PIN(41, "WF_CBA_RESETB"), ++ MT7981_TYPE1_PIN(42, "WF_XO_REQ"), ++ MT7981_TYPE1_PIN(43, "WF_TOP_CLK"), ++ MT7981_TYPE1_PIN(44, "WF_TOP_DATA"), ++ MT7981_TYPE1_PIN(45, "WF_HB1"), ++ MT7981_TYPE1_PIN(46, "WF_HB2"), ++ MT7981_TYPE1_PIN(47, "WF_HB3"), ++ MT7981_TYPE1_PIN(48, "WF_HB4"), ++ MT7981_TYPE1_PIN(49, "WF_HB0"), ++ MT7981_TYPE1_PIN(50, "WF_HB0_B"), ++ MT7981_TYPE1_PIN(51, "WF_HB5"), ++ MT7981_TYPE1_PIN(52, "WF_HB6"), ++ MT7981_TYPE1_PIN(53, "WF_HB7"), ++ MT7981_TYPE1_PIN(54, "WF_HB8"), ++ MT7981_TYPE1_PIN(55, "WF_HB9"), ++ MT7981_TYPE1_PIN(56, "WF_HB10"), ++}; ++ ++/* WA_AICE */ ++static int mt7981_wa_aice1_pins[] = { 0, 1, }; ++static int mt7981_wa_aice1_funcs[] = { 2, 2, }; ++ ++static int mt7981_wa_aice2_pins[] = { 0, 1, }; ++static int mt7981_wa_aice2_funcs[] = { 3, 3, }; ++ ++static int mt7981_wa_aice3_pins[] = { 28, 29, }; ++static int mt7981_wa_aice3_funcs[] = { 3, 3, }; ++ ++static int mt7981_wm_aice1_pins[] = { 9, 10, }; ++static int mt7981_wm_aice1_funcs[] = { 2, 2, }; ++ ++static int mt7981_wm_aice2_pins[] = { 30, 31, }; ++static int mt7981_wm_aice2_funcs[] = { 5, 5, }; ++ ++/* WM_UART */ ++static int mt7981_wm_uart_0_pins[] = { 0, 1, }; ++static int mt7981_wm_uart_0_funcs[] = { 5, 5, }; ++ ++static int mt7981_wm_uart_1_pins[] = { 20, 21, }; ++static int mt7981_wm_uart_1_funcs[] = { 4, 4, }; ++ ++static int mt7981_wm_uart_2_pins[] = { 30, 31, }; ++static int mt7981_wm_uart_2_funcs[] = { 3, 3, }; ++ ++/* DFD */ ++static int mt7981_dfd_pins[] = { 0, 1, 4, 5, }; ++static int mt7981_dfd_funcs[] = { 5, 5, 6, 6, }; ++ ++/* SYS_WATCHDOG */ ++static int mt7981_watchdog_pins[] = { 2, }; ++static int mt7981_watchdog_funcs[] = { 1, }; ++ ++static int mt7981_watchdog1_pins[] = { 13, }; ++static int mt7981_watchdog1_funcs[] = { 5, }; ++ ++/* PCIE_PERESET_N */ ++static int mt7981_pcie_pereset_pins[] = { 3, }; ++static int mt7981_pcie_pereset_funcs[] = { 1, }; ++ ++/* JTAG */ ++static int mt7981_jtag_pins[] = { 4, 5, 6, 7, 8, }; ++static int mt7981_jtag_funcs[] = { 1, 1, 1, 1, 1, }; ++ ++/* WM_JTAG */ ++static int mt7981_wm_jtag_0_pins[] = { 4, 5, 6, 7, 8, }; ++static int mt7981_wm_jtag_0_funcs[] = { 2, 2, 2, 2, 2, }; ++ ++static int mt7981_wm_jtag_1_pins[] = { 20, 21, 22, 23, 24, }; ++static int mt7981_wm_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; ++ ++/* WO0_JTAG */ ++static int mt7981_wo0_jtag_0_pins[] = { 9, 10, 11, 12, 13, }; ++static int mt7981_wo0_jtag_0_funcs[] = { 1, 1, 1, 1, 1, }; ++ ++static int mt7981_wo0_jtag_1_pins[] = { 25, 26, 27, 28, 29, }; ++static int mt7981_wo0_jtag_1_funcs[] = { 5, 5, 5, 5, 5, }; ++ ++/* UART2 */ ++static int mt7981_uart2_0_pins[] = { 4, 5, 6, 7, }; ++static int mt7981_uart2_0_funcs[] = { 3, 3, 3, 3, }; ++ ++/* GBE_LED0 */ ++static int mt7981_gbe_led0_pins[] = { 8, }; ++static int mt7981_gbe_led0_funcs[] = { 3, }; ++ ++/* PTA_EXT */ ++static int mt7981_pta_ext_0_pins[] = { 4, 5, 6, }; ++static int mt7981_pta_ext_0_funcs[] = { 4, 4, 4, }; ++ ++static int mt7981_pta_ext_1_pins[] = { 22, 23, 24, }; ++static int mt7981_pta_ext_1_funcs[] = { 4, 4, 4, }; ++ ++/* PWM2 */ ++static int mt7981_pwm2_pins[] = { 7, }; ++static int mt7981_pwm2_funcs[] = { 4, }; ++ ++/* NET_WO0_UART_TXD */ ++static int mt7981_net_wo0_uart_txd_0_pins[] = { 8, }; ++static int mt7981_net_wo0_uart_txd_0_funcs[] = { 4, }; ++ ++static int mt7981_net_wo0_uart_txd_1_pins[] = { 14, }; ++static int mt7981_net_wo0_uart_txd_1_funcs[] = { 3, }; ++ ++static int mt7981_net_wo0_uart_txd_2_pins[] = { 15, }; ++static int mt7981_net_wo0_uart_txd_2_funcs[] = { 4, }; ++ ++/* SPI1 */ ++static int mt7981_spi1_0_pins[] = { 4, 5, 6, 7, }; ++static int mt7981_spi1_0_funcs[] = { 5, 5, 5, 5, }; ++ ++/* I2C */ ++static int mt7981_i2c0_0_pins[] = { 6, 7, }; ++static int mt7981_i2c0_0_funcs[] = { 6, 6, }; ++ ++static int mt7981_i2c0_1_pins[] = { 30, 31, }; ++static int mt7981_i2c0_1_funcs[] = { 4, 4, }; ++ ++static int mt7981_i2c0_2_pins[] = { 36, 37, }; ++static int mt7981_i2c0_2_funcs[] = { 2, 2, }; ++ ++static int mt7981_u2_phy_i2c_pins[] = { 30, 31, }; ++static int mt7981_u2_phy_i2c_funcs[] = { 6, 6, }; ++ ++static int mt7981_u3_phy_i2c_pins[] = { 32, 33, }; ++static int mt7981_u3_phy_i2c_funcs[] = { 3, 3, }; ++ ++static int mt7981_sgmii1_phy_i2c_pins[] = { 32, 33, }; ++static int mt7981_sgmii1_phy_i2c_funcs[] = { 2, 2, }; ++ ++static int mt7981_sgmii0_phy_i2c_pins[] = { 32, 33, }; ++static int mt7981_sgmii0_phy_i2c_funcs[] = { 5, 5, }; ++ ++/* DFD_NTRST */ ++static int mt7981_dfd_ntrst_pins[] = { 8, }; ++static int mt7981_dfd_ntrst_funcs[] = { 6, }; ++ ++/* PWM0 */ ++static int mt7981_pwm0_0_pins[] = { 13, }; ++static int mt7981_pwm0_0_funcs[] = { 2, }; ++ ++static int mt7981_pwm0_1_pins[] = { 15, }; ++static int mt7981_pwm0_1_funcs[] = { 1, }; ++ ++/* PWM1 */ ++static int mt7981_pwm1_0_pins[] = { 14, }; ++static int mt7981_pwm1_0_funcs[] = { 2, }; ++ ++static int mt7981_pwm1_1_pins[] = { 15, }; ++static int mt7981_pwm1_1_funcs[] = { 3, }; ++ ++/* GBE_LED1 */ ++static int mt7981_gbe_led1_pins[] = { 13, }; ++static int mt7981_gbe_led1_funcs[] = { 3, }; ++ ++/* PCM */ ++static int mt7981_pcm_pins[] = { 9, 10, 11, 12, 13, 25 }; ++static int mt7981_pcm_funcs[] = { 4, 4, 4, 4, 4, 4, }; ++ ++/* UDI */ ++static int mt7981_udi_pins[] = { 9, 10, 11, 12, 13, }; ++static int mt7981_udi_funcs[] = { 6, 6, 6, 6, 6, }; ++ ++/* DRV_VBUS */ ++static int mt7981_drv_vbus_pins[] = { 14, }; ++static int mt7981_drv_vbus_funcs[] = { 1, }; ++ ++/* EMMC */ ++static int mt7981_emmc_45_pins[] = { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, }; ++static int mt7981_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; ++ ++/* SNFI */ ++static int mt7981_snfi_pins[] = { 16, 17, 18, 19, 20, 21, }; ++static int mt7981_snfi_funcs[] = { 3, 3, 3, 3, 3, 3, }; ++ ++/* SPI0 */ ++static int mt7981_spi0_pins[] = { 16, 17, 18, 19, }; ++static int mt7981_spi0_funcs[] = { 1, 1, 1, 1, }; ++ ++/* SPI0 */ ++static int mt7981_spi0_wp_hold_pins[] = { 20, 21, }; ++static int mt7981_spi0_wp_hold_funcs[] = { 1, 1, }; ++ ++/* SPI1 */ ++static int mt7981_spi1_1_pins[] = { 22, 23, 24, 25, }; ++static int mt7981_spi1_1_funcs[] = { 1, 1, 1, 1, }; ++ ++/* SPI2 */ ++static int mt7981_spi2_pins[] = { 26, 27, 28, 29, }; ++static int mt7981_spi2_funcs[] = { 1, 1, 1, 1, }; ++ ++/* SPI2 */ ++static int mt7981_spi2_wp_hold_pins[] = { 30, 31, }; ++static int mt7981_spi2_wp_hold_funcs[] = { 1, 1, }; ++ ++/* UART1 */ ++static int mt7981_uart1_0_pins[] = { 16, 17, 18, 19, }; ++static int mt7981_uart1_0_funcs[] = { 4, 4, 4, 4, }; ++ ++static int mt7981_uart1_1_pins[] = { 26, 27, 28, 29, }; ++static int mt7981_uart1_1_funcs[] = { 2, 2, 2, 2, }; ++ ++/* UART2 */ ++static int mt7981_uart2_1_pins[] = { 22, 23, 24, 25, }; ++static int mt7981_uart2_1_funcs[] = { 3, 3, 3, 3, }; ++ ++/* UART0 */ ++static int mt7981_uart0_pins[] = { 32, 33, }; ++static int mt7981_uart0_funcs[] = { 1, 1, }; ++ ++/* PCIE_CLK_REQ */ ++static int mt7981_pcie_clk_pins[] = { 34, }; ++static int mt7981_pcie_clk_funcs[] = { 2, }; ++ ++/* PCIE_WAKE_N */ ++static int mt7981_pcie_wake_pins[] = { 35, }; ++static int mt7981_pcie_wake_funcs[] = { 2, }; ++ ++/* MDC_MDIO */ ++static int mt7981_smi_mdc_mdio_pins[] = { 36, 37, }; ++static int mt7981_smi_mdc_mdio_funcs[] = { 1, 1, }; ++ ++static int mt7981_gbe_ext_mdc_mdio_pins[] = { 36, 37, }; ++static int mt7981_gbe_ext_mdc_mdio_funcs[] = { 3, 3, }; ++ ++/* WF0_MODE1 */ ++static int mt7981_wf0_mode1_pins[] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, ++ 50, 51, 52, 53, 54, 55, 56 }; ++static int mt7981_wf0_mode1_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ++ 1, 1, 1, 1 }; ++ ++/* WF0_MODE3 */ ++static int mt7981_wf0_mode3_pins[] = { 45, 46, 47, 48, 49, 51 }; ++static int mt7981_wf0_mode3_funcs[] = { 2, 2, 2, 2, 2, 2 }; ++ ++/* WF2G_LED */ ++static int mt7981_wf2g_led0_pins[] = { 30, }; ++static int mt7981_wf2g_led0_funcs[] = { 2, }; ++ ++static int mt7981_wf2g_led1_pins[] = { 34, }; ++static int mt7981_wf2g_led1_funcs[] = { 1, }; ++ ++/* WF5G_LED */ ++static int mt7981_wf5g_led0_pins[] = { 31, }; ++static int mt7981_wf5g_led0_funcs[] = { 2, }; ++ ++static int mt7981_wf5g_led1_pins[] = { 35, }; ++static int mt7981_wf5g_led1_funcs[] = { 1, }; ++ ++/* MT7531_INT */ ++static int mt7981_mt7531_int_pins[] = { 38, }; ++static int mt7981_mt7531_int_funcs[] = { 1, }; ++ ++/* ANT_SEL */ ++static int mt7981_ant_sel_pins[] = { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 34, 35 }; ++static int mt7981_ant_sel_funcs[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }; ++ ++static const struct mtk_group_desc mt7981_groups[] = { ++ /* @GPIO(0,1): WA_AICE(2) */ ++ PINCTRL_PIN_GROUP("wa_aice1", mt7981_wa_aice1), ++ /* @GPIO(0,1): WA_AICE(3) */ ++ PINCTRL_PIN_GROUP("wa_aice2", mt7981_wa_aice2), ++ /* @GPIO(0,1): WM_UART(5) */ ++ PINCTRL_PIN_GROUP("wm_uart_0", mt7981_wm_uart_0), ++ /* @GPIO(0,1,4,5): DFD(6) */ ++ PINCTRL_PIN_GROUP("dfd", mt7981_dfd), ++ /* @GPIO(2): SYS_WATCHDOG(1) */ ++ PINCTRL_PIN_GROUP("watchdog", mt7981_watchdog), ++ /* @GPIO(3): PCIE_PERESET_N(1) */ ++ PINCTRL_PIN_GROUP("pcie_pereset", mt7981_pcie_pereset), ++ /* @GPIO(4,8) JTAG(1) */ ++ PINCTRL_PIN_GROUP("jtag", mt7981_jtag), ++ /* @GPIO(4,8) WM_JTAG(2) */ ++ PINCTRL_PIN_GROUP("wm_jtag_0", mt7981_wm_jtag_0), ++ /* @GPIO(9,13) WO0_JTAG(1) */ ++ PINCTRL_PIN_GROUP("wo0_jtag_0", mt7981_wo0_jtag_0), ++ /* @GPIO(4,7) WM_JTAG(3) */ ++ PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_0), ++ /* @GPIO(8) GBE_LED0(3) */ ++ PINCTRL_PIN_GROUP("gbe_led0", mt7981_gbe_led0), ++ /* @GPIO(4,6) PTA_EXT(4) */ ++ PINCTRL_PIN_GROUP("pta_ext_0", mt7981_pta_ext_0), ++ /* @GPIO(7) PWM2(4) */ ++ PINCTRL_PIN_GROUP("pwm2", mt7981_pwm2), ++ /* @GPIO(8) NET_WO0_UART_TXD(4) */ ++ PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7981_net_wo0_uart_txd_0), ++ /* @GPIO(4,7) SPI1(5) */ ++ PINCTRL_PIN_GROUP("spi1_0", mt7981_spi1_0), ++ /* @GPIO(6,7) I2C(5) */ ++ PINCTRL_PIN_GROUP("i2c0_0", mt7981_i2c0_0), ++ /* @GPIO(8): DFD_NTRST(6) */ ++ PINCTRL_PIN_GROUP("dfd_ntrst", mt7981_dfd_ntrst), ++ /* @GPIO(9,10): WM_AICE(2) */ ++ PINCTRL_PIN_GROUP("wm_aice1", mt7981_wm_aice1), ++ /* @GPIO(13): PWM0(2) */ ++ PINCTRL_PIN_GROUP("pwm0_0", mt7981_pwm0_0), ++ /* @GPIO(15): PWM0(1) */ ++ PINCTRL_PIN_GROUP("pwm0_1", mt7981_pwm0_1), ++ /* @GPIO(14): PWM1(2) */ ++ PINCTRL_PIN_GROUP("pwm1_0", mt7981_pwm1_0), ++ /* @GPIO(15): PWM1(3) */ ++ PINCTRL_PIN_GROUP("pwm1_1", mt7981_pwm1_1), ++ /* @GPIO(14) NET_WO0_UART_TXD(3) */ ++ PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7981_net_wo0_uart_txd_1), ++ /* @GPIO(15) NET_WO0_UART_TXD(4) */ ++ PINCTRL_PIN_GROUP("net_wo0_uart_txd_2", mt7981_net_wo0_uart_txd_2), ++ /* @GPIO(13) GBE_LED0(3) */ ++ PINCTRL_PIN_GROUP("gbe_led1", mt7981_gbe_led1), ++ /* @GPIO(9,13) PCM(4) */ ++ PINCTRL_PIN_GROUP("pcm", mt7981_pcm), ++ /* @GPIO(13): SYS_WATCHDOG1(5) */ ++ PINCTRL_PIN_GROUP("watchdog1", mt7981_watchdog1), ++ /* @GPIO(9,13) UDI(4) */ ++ PINCTRL_PIN_GROUP("udi", mt7981_udi), ++ /* @GPIO(14) DRV_VBUS(1) */ ++ PINCTRL_PIN_GROUP("drv_vbus", mt7981_drv_vbus), ++ /* @GPIO(15,25): EMMC(2) */ ++ PINCTRL_PIN_GROUP("emmc_45", mt7981_emmc_45), ++ /* @GPIO(16,21): SNFI(3) */ ++ PINCTRL_PIN_GROUP("snfi", mt7981_snfi), ++ /* @GPIO(16,19): SPI0(1) */ ++ PINCTRL_PIN_GROUP("spi0", mt7981_spi0), ++ /* @GPIO(20,21): SPI0(1) */ ++ PINCTRL_PIN_GROUP("spi0_wp_hold", mt7981_spi0_wp_hold), ++ /* @GPIO(22,25) SPI1(1) */ ++ PINCTRL_PIN_GROUP("spi1_1", mt7981_spi1_1), ++ /* @GPIO(26,29): SPI2(1) */ ++ PINCTRL_PIN_GROUP("spi2", mt7981_spi2), ++ /* @GPIO(30,31): SPI2(1) */ ++ PINCTRL_PIN_GROUP("spi2_wp_hold", mt7981_spi2_wp_hold), ++ /* @GPIO(16,19): UART1(4) */ ++ PINCTRL_PIN_GROUP("uart1_0", mt7981_uart1_0), ++ /* @GPIO(26,29): UART1(2) */ ++ PINCTRL_PIN_GROUP("uart1_1", mt7981_uart1_1), ++ /* @GPIO(22,25): UART2(3) */ ++ PINCTRL_PIN_GROUP("uart2_0", mt7981_uart2_1), ++ /* @GPIO(22,24) PTA_EXT(4) */ ++ PINCTRL_PIN_GROUP("pta_ext_1", mt7981_pta_ext_1), ++ /* @GPIO(20,21): WM_UART(4) */ ++ PINCTRL_PIN_GROUP("wm_aurt_1", mt7981_wm_uart_1), ++ /* @GPIO(30,31): WM_UART(3) */ ++ PINCTRL_PIN_GROUP("wm_aurt_2", mt7981_wm_uart_2), ++ /* @GPIO(20,24) WM_JTAG(5) */ ++ PINCTRL_PIN_GROUP("wm_jtag_1", mt7981_wm_jtag_1), ++ /* @GPIO(25,29) WO0_JTAG(5) */ ++ PINCTRL_PIN_GROUP("wo0_jtag_1", mt7981_wo0_jtag_1), ++ /* @GPIO(28,29): WA_AICE(3) */ ++ PINCTRL_PIN_GROUP("wa_aice3", mt7981_wa_aice3), ++ /* @GPIO(30,31): WM_AICE(5) */ ++ PINCTRL_PIN_GROUP("wm_aice2", mt7981_wm_aice2), ++ /* @GPIO(30,31): I2C(4) */ ++ PINCTRL_PIN_GROUP("i2c0_1", mt7981_i2c0_1), ++ /* @GPIO(30,31): I2C(6) */ ++ PINCTRL_PIN_GROUP("u2_phy_i2c", mt7981_u2_phy_i2c), ++ /* @GPIO(32,33): I2C(1) */ ++ PINCTRL_PIN_GROUP("uart0", mt7981_uart0), ++ /* @GPIO(32,33): I2C(2) */ ++ PINCTRL_PIN_GROUP("sgmii1_phy_i2c", mt7981_sgmii1_phy_i2c), ++ /* @GPIO(32,33): I2C(3) */ ++ PINCTRL_PIN_GROUP("u3_phy_i2c", mt7981_u3_phy_i2c), ++ /* @GPIO(32,33): I2C(5) */ ++ PINCTRL_PIN_GROUP("sgmii0_phy_i2c", mt7981_sgmii0_phy_i2c), ++ /* @GPIO(34): PCIE_CLK_REQ(2) */ ++ PINCTRL_PIN_GROUP("pcie_clk", mt7981_pcie_clk), ++ /* @GPIO(35): PCIE_WAKE_N(2) */ ++ PINCTRL_PIN_GROUP("pcie_wake", mt7981_pcie_wake), ++ /* @GPIO(36,37): I2C(2) */ ++ PINCTRL_PIN_GROUP("i2c0_2", mt7981_i2c0_2), ++ /* @GPIO(36,37): MDC_MDIO(1) */ ++ PINCTRL_PIN_GROUP("smi_mdc_mdio", mt7981_smi_mdc_mdio), ++ /* @GPIO(36,37): MDC_MDIO(3) */ ++ PINCTRL_PIN_GROUP("gbe_ext_mdc_mdio", mt7981_gbe_ext_mdc_mdio), ++ /* @GPIO(40,56): WF0_MODE1(1) */ ++ PINCTRL_PIN_GROUP("wf0_mode1", mt7981_wf0_mode1), ++ /* @GPIO(45,46,47,48,49,51): WF0_MODE3(3) */ ++ PINCTRL_PIN_GROUP("wf0_mode3", mt7981_wf0_mode3), ++ /* @GPIO(30): WF2G_LED(2) */ ++ PINCTRL_PIN_GROUP("wf2g_led0", mt7981_wf2g_led0), ++ /* @GPIO(34): WF2G_LED(1) */ ++ PINCTRL_PIN_GROUP("wf2g_led1", mt7981_wf2g_led1), ++ /* @GPIO(31): WF5G_LED(2) */ ++ PINCTRL_PIN_GROUP("wf5g_led0", mt7981_wf5g_led0), ++ /* @GPIO(35): WF5G_LED(1) */ ++ PINCTRL_PIN_GROUP("wf5g_led1", mt7981_wf5g_led1), ++ /* @GPIO(38): MT7531_INT(1) */ ++ PINCTRL_PIN_GROUP("mt7531_int", mt7981_mt7531_int), ++ /* @GPIO(14,15,26,17,18,19,20,21,22,23,24,25,34,35): ANT_SEL(1) */ ++ PINCTRL_PIN_GROUP("ant_sel", mt7981_ant_sel), ++}; ++ ++static const struct mtk_io_type_desc mt7981_io_type_desc[] = { ++ [IO_TYPE_GRP0] = { ++ .name = "18OD33", ++ .bias_set = mtk_pinconf_bias_set_pupd_r1_r0, ++ .drive_set = mtk_pinconf_drive_set_v1, ++ .input_enable = mtk_pinconf_input_enable_v1, ++ }, ++ [IO_TYPE_GRP1] = { ++ .name = "18A01", ++ .bias_set = mtk_pinconf_bias_set_pu_pd, ++ .drive_set = mtk_pinconf_drive_set_v1, ++ .input_enable = mtk_pinconf_input_enable_v1, ++ }, ++}; ++ ++/* Joint those groups owning the same capability in user point of view which ++ * allows that people tend to use through the device tree. ++ */ ++static const char *const mt7981_wa_aice_groups[] = { "wa_aice1", "wa_aice2", ++ "wm_aice1_1", "wa_aice3", "wm_aice1_2", }; ++static const char *const mt7981_uart_groups[] = { "wm_uart_0", "uart2_0", ++ "net_wo0_uart_txd_0", "net_wo0_uart_txd_1", "net_wo0_uart_txd_2", ++ "uart1_0", "uart1_1", "uart2_0", "wm_aurt_1", "wm_aurt_2", "uart0", }; ++static const char *const mt7981_dfd_groups[] = { "dfd", "dfd_ntrst", }; ++static const char *const mt7981_wdt_groups[] = { "watchdog", "watchdog1", }; ++static const char *const mt7981_pcie_groups[] = { "pcie_pereset", "pcie_clk", ++ "pcie_wake", }; ++static const char *const mt7981_jtag_groups[] = { "jtag", "wm_jtag_0", ++ "wo0_jtag_0", "wo0_jtag_1", "wm_jtag_1", }; ++static const char *const mt7981_led_groups[] = { "gbe_led0", "gbe_led1", ++ "wf2g_led0", "wf2g_led1", "wf5g_led0", "wf5g_led1", }; ++static const char *const mt7981_pta_groups[] = { "pta_ext_0", "pta_ext_1", }; ++static const char *const mt7981_pwm_groups[] = { "pwm2", "pwm0_0", "pwm0_1", ++ "pwm1_0", "pwm1_1", }; ++static const char *const mt7981_spi_groups[] = { "spi1_0", "spi0", ++ "spi0_wp_hold", "spi1_1", "spi2", "spi2_wp_hold", }; ++static const char *const mt7981_i2c_groups[] = { "i2c0_0", "i2c0_1", ++ "u2_phy_i2c", "sgmii1_phy_i2c", "u3_phy_i2c", "sgmii0_phy_i2c", ++ "i2c0_2", }; ++static const char *const mt7981_pcm_groups[] = { "pcm", }; ++static const char *const mt7981_udi_groups[] = { "udi", }; ++static const char *const mt7981_usb_groups[] = { "drv_vbus", }; ++static const char *const mt7981_flash_groups[] = { "emmc_45", "snfi", }; ++static const char *const mt7981_ethernet_groups[] = { "smi_mdc_mdio", ++ "gbe_ext_mdc_mdio", "wf0_mode1", "wf0_mode3", "mt7531_int", }; ++static const char *const mt7981_ant_groups[] = { "ant_sel", }; ++ ++static const struct mtk_function_desc mt7981_functions[] = { ++ {"wa_aice", mt7981_wa_aice_groups, ARRAY_SIZE(mt7981_wa_aice_groups)}, ++ {"dfd", mt7981_dfd_groups, ARRAY_SIZE(mt7981_dfd_groups)}, ++ {"jtag", mt7981_jtag_groups, ARRAY_SIZE(mt7981_jtag_groups)}, ++ {"pta", mt7981_pta_groups, ARRAY_SIZE(mt7981_pta_groups)}, ++ {"pcm", mt7981_pcm_groups, ARRAY_SIZE(mt7981_pcm_groups)}, ++ {"udi", mt7981_udi_groups, ARRAY_SIZE(mt7981_udi_groups)}, ++ {"usb", mt7981_usb_groups, ARRAY_SIZE(mt7981_usb_groups)}, ++ {"ant", mt7981_ant_groups, ARRAY_SIZE(mt7981_ant_groups)}, ++ {"eth", mt7981_ethernet_groups, ARRAY_SIZE(mt7981_ethernet_groups)}, ++ {"i2c", mt7981_i2c_groups, ARRAY_SIZE(mt7981_i2c_groups)}, ++ {"led", mt7981_led_groups, ARRAY_SIZE(mt7981_led_groups)}, ++ {"pwm", mt7981_pwm_groups, ARRAY_SIZE(mt7981_pwm_groups)}, ++ {"spi", mt7981_spi_groups, ARRAY_SIZE(mt7981_spi_groups)}, ++ {"uart", mt7981_uart_groups, ARRAY_SIZE(mt7981_uart_groups)}, ++ {"watchdog", mt7981_wdt_groups, ARRAY_SIZE(mt7981_wdt_groups)}, ++ {"flash", mt7981_flash_groups, ARRAY_SIZE(mt7981_flash_groups)}, ++ {"pcie", mt7981_pcie_groups, ARRAY_SIZE(mt7981_pcie_groups)}, ++}; ++ ++static const char *const mt7981_pinctrl_register_base_names[] = { ++ "gpio_base", "iocfg_rt_base", "iocfg_rm_base", "iocfg_rb_base", ++ "iocfg_lb_base", "iocfg_bl_base", "iocfg_tm_base", "iocfg_tl_base", ++}; ++ ++static struct mtk_pinctrl_soc mt7981_data = { ++ .name = "mt7981_pinctrl", ++ .reg_cal = mt7981_reg_cals, ++ .pins = mt7981_pins, ++ .npins = ARRAY_SIZE(mt7981_pins), ++ .grps = mt7981_groups, ++ .ngrps = ARRAY_SIZE(mt7981_groups), ++ .funcs = mt7981_functions, ++ .nfuncs = ARRAY_SIZE(mt7981_functions), ++ .io_type = mt7981_io_type_desc, ++ .ntype = ARRAY_SIZE(mt7981_io_type_desc), ++ .gpio_mode = 0, ++ .base_names = mt7981_pinctrl_register_base_names, ++ .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), ++ .base_calc = 1, ++}; ++ ++static int mtk_pinctrl_mt7981_probe(struct udevice *dev) ++{ ++ return mtk_pinctrl_common_probe(dev, &mt7981_data); ++} ++ ++static const struct udevice_id mt7981_pctrl_match[] = { ++ {.compatible = "mediatek,mt7981-pinctrl"}, ++ { /* sentinel */ } ++}; ++ ++U_BOOT_DRIVER(mt7981_pinctrl) = { ++ .name = "mt7981_pinctrl", ++ .id = UCLASS_PINCTRL, ++ .of_match = mt7981_pctrl_match, ++ .ops = &mtk_pinctrl_ops, ++ .probe = mtk_pinctrl_mt7981_probe, ++ .priv_auto = sizeof(struct mtk_pinctrl_priv), ++}; diff --git a/package/boot/uboot-mediatek/patches/002-0021-pinctrl-mediatek-add-pinctrl-driver-for-MT7986-SoC.patch b/package/boot/uboot-mediatek/patches/002-0021-pinctrl-mediatek-add-pinctrl-driver-for-MT7986-SoC.patch new file mode 100644 index 0000000000..d0675ed4f8 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0021-pinctrl-mediatek-add-pinctrl-driver-for-MT7986-SoC.patch @@ -0,0 +1,817 @@ +From a018800db986d63cf95b0779ebb33b5e246072a7 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Thu, 28 Jul 2022 10:01:00 +0800 +Subject: [PATCH 21/31] pinctrl: mediatek: add pinctrl driver for MT7986 SoC + +This patch adds pinctrl and gpio support for MT7986 SoC + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/pinctrl/mediatek/Kconfig | 4 + + drivers/pinctrl/mediatek/Makefile | 1 + + drivers/pinctrl/mediatek/pinctrl-mt7986.c | 775 ++++++++++++++++++++++ + 3 files changed, 780 insertions(+) + create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7986.c + +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -20,6 +20,10 @@ config PINCTRL_MT7981 + bool "MT7981 SoC pinctrl driver" + select PINCTRL_MTK + ++config PINCTRL_MT7986 ++ bool "MT7986 SoC pinctrl driver" ++ select PINCTRL_MTK ++ + config PINCTRL_MT8512 + bool "MT8512 SoC pinctrl driver" + select PINCTRL_MTK +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_PINCTRL_MT7622) += pinctrl- + obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o + obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o + obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o ++obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o + obj-$(CONFIG_PINCTRL_MT8512) += pinctrl-mt8512.o + obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o + obj-$(CONFIG_PINCTRL_MT8518) += pinctrl-mt8518.o +--- /dev/null ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c +@@ -0,0 +1,775 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * The MT7986 driver based on Linux generic pinctrl binding. ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include "pinctrl-mtk-common.h" ++ ++#define MT7986_TYPE0_PIN(_number, _name) \ ++ MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP0) ++ ++#define MT7986_TYPE1_PIN(_number, _name) \ ++ MTK_TYPED_PIN(_number, _name, DRV_GRP4, IO_TYPE_GRP1) ++ ++#define PIN_FIELD_GPIO(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \ ++ PIN_FIELD_BASE_CALC(_s_pin, _e_pin, GPIO_BASE, _s_addr, _x_addrs, \ ++ _s_bit, _x_bits, 32, 0) ++ ++#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ ++ _x_bits) \ ++ PIN_FIELD_BASE_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ ++ _x_bits, 32, 0) ++ ++/** ++ * enum - Locking variants of the iocfg bases ++ * ++ * MT7986 have multiple bases to program pin configuration listed as the below: ++ * iocfg_rt:0x11c30000, iocfg_rb:0x11c40000, iocfg_lt:0x11e20000, ++ * iocfg_lb:0x11e30000, iocfg_tr:0x11f00000, iocfg_tl:0x11f10000, ++ * _i_based could be used to indicate what base the pin should be mapped into. ++ * ++ * Each iocfg register base control different group of pads on the SoC ++ * ++ * ++ * chip carrier ++ * ++ * A B C D E F G H ++ * +------------------------+ ++ * 8 | o o o o o o o o | ++ * 7 | o o o o o o o o | ++ * 6 | o o o o o o o o | ++ * 5 | o o o o o o o o | ++ * 4 | o o o o o o o o | ++ * 3 | o o o o o o o o | ++ * 2 | o o o o o o o o | ++ * 1 | o o o o o o o o | ++ * +------------------------+ ++ * ++ * inside Chip carrier ++ * ++ * A B C D E F G H ++ * +------------------------+ ++ * 8 | | ++ * 7 | TL TR | ++ * 6 | +---------+ | ++ * 5 | LT | | RT | ++ * 4 | | | | ++ * 3 | LB | | RB | ++ * 2 | +---------+ | ++ * 1 | | ++ * +------------------------+ ++ * ++ */ ++ ++enum { ++ GPIO_BASE, ++ IOCFG_RT_BASE, ++ IOCFG_RB_BASE, ++ IOCFG_LT_BASE, ++ IOCFG_LB_BASE, ++ IOCFG_TR_BASE, ++ IOCFG_TL_BASE, ++}; ++ ++static const char *const mt7986_pinctrl_register_base_names[] = { ++ "gpio", "iocfg_rt", "iocfg_rb", "iocfg_lt", "iocfg_lb", "iocfg_tr", ++ "iocfg_tl", ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_mode_range[] = { ++ PIN_FIELD_GPIO(0, 100, 0x300, 0x10, 0, 4), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_dir_range[] = { ++ PIN_FIELD_GPIO(0, 100, 0x0, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_di_range[] = { ++ PIN_FIELD_GPIO(0, 100, 0x200, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_do_range[] = { ++ PIN_FIELD_GPIO(0, 100, 0x100, 0x10, 0, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_ies_range[] = { ++ PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x40, 0x10, 17, 1), ++ PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x20, 0x10, 10, 1), ++ PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x20, 0x10, 0, 1), ++ PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x40, 0x10, 8, 1), ++ PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x30, 0x10, 12, 1), ++ PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x30, 0x10, 18, 1), ++ PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x30, 0x10, 17, 1), ++ PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x30, 0x10, 15, 1), ++ PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x30, 0x10, 19, 1), ++ PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x30, 0x10, 23, 1), ++ PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x30, 0x10, 22, 1), ++ PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x30, 0x10, 21, 1), ++ PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x20, 0x10, 4, 1), ++ PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x20, 0x10, 8, 1), ++ PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x20, 0x10, 7, 1), ++ PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x20, 0x10, 5, 1), ++ PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x20, 0x10, 9, 1), ++ PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x40, 0x10, 18, 1), ++ PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x40, 0x10, 12, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x40, 0x10, 22, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x40, 0x10, 20, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x40, 0x10, 26, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x40, 0x10, 24, 1), ++ PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x30, 0x10, 10, 1), ++ PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x40, 0x10, 15, 1), ++ PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x40, 0x10, 14, 1), ++ PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x40, 0x10, 13, 1), ++ PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x40, 0x10, 16, 1), ++ PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x20, 0x10, 2, 1), ++ PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x30, 0x10, 16, 1), ++ PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x30, 0x10, 14, 1), ++ PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x30, 0x10, 6, 1), ++ PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x30, 0x10, 9, 1), ++ PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x30, 0x10, 1, 1), ++ PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x30, 0x10, 14, 1), ++ PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x30, 0x10, 12, 1), ++ PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x30, 0x10, 2, 1), ++ PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x30, 0x10, 8, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_smt_range[] = { ++ PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0xf0, 0x10, 17, 1), ++ PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x90, 0x10, 10, 1), ++ PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x90, 0x10, 0, 1), ++ PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0xf0, 0x10, 0, 1), ++ PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x90, 0x10, 0, 1), ++ PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0xf0, 0x10, 8, 1), ++ PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0xf0, 0x10, 2, 1), ++ PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0xc0, 0x10, 12, 1), ++ PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0xc0, 0x10, 18, 1), ++ PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0xc0, 0x10, 17, 1), ++ PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0xc0, 0x10, 15, 1), ++ PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0xc0, 0x10, 19, 1), ++ PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0xc0, 0x10, 23, 1), ++ PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0xc0, 0x10, 22, 1), ++ PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0xc0, 0x10, 21, 1), ++ PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x90, 0x10, 4, 1), ++ PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x90, 0x10, 8, 1), ++ PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x90, 0x10, 7, 1), ++ PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x90, 0x10, 5, 1), ++ PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x90, 0x10, 9, 1), ++ PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0xf0, 0x10, 18, 1), ++ PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0xf0, 0x10, 12, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0xf0, 0x10, 22, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0xf0, 0x10, 20, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0xf0, 0x10, 26, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0xf0, 0x10, 24, 1), ++ PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0xc0, 0x10, 2, 1), ++ PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0xc0, 0x10, 1, 1), ++ PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0xc0, 0x10, 0, 1), ++ PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0xc0, 0x10, 10, 1), ++ PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0xf0, 0x10, 15, 1), ++ PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0xf0, 0x10, 14, 1), ++ PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0xf0, 0x10, 13, 1), ++ PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0xf0, 0x10, 16, 1), ++ PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x90, 0x10, 2, 1), ++ PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x80, 0x10, 1, 1), ++ PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x80, 0x10, 0, 1), ++ PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x80, 0x10, 16, 1), ++ PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x80, 0x10, 14, 1), ++ PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x80, 0x10, 4, 1), ++ PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x80, 0x10, 6, 1), ++ PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x80, 0x10, 2, 1), ++ PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x80, 0x10, 9, 1), ++ PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x80, 0x10, 5, 1), ++ PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x70, 0x10, 1, 1), ++ PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x70, 0x10, 0, 1), ++ PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x70, 0x10, 14, 1), ++ PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x70, 0x10, 12, 1), ++ PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x70, 0x10, 4, 1), ++ PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x70, 0x10, 2, 1), ++ PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x70, 0x10, 8, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_pu_range[] = { ++ PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x50, 0x10, 16, 1), ++ PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x50, 0x10, 14, 1), ++ PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x50, 0x10, 6, 1), ++ PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x50, 0x10, 9, 1), ++ PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x50, 0x10, 14, 1), ++ PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x50, 0x10, 12, 1), ++ PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x50, 0x10, 8, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_pd_range[] = { ++ PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x40, 0x10, 16, 1), ++ PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x40, 0x10, 14, 1), ++ PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x40, 0x10, 6, 1), ++ PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x40, 0x10, 9, 1), ++ PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x40, 0x10, 14, 1), ++ PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x40, 0x10, 12, 1), ++ PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x40, 0x10, 8, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_drv_range[] = { ++ PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x10, 0x10, 21, 3), ++ PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x10, 0x10, 0, 3), ++ PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x00, 0x10, 0, 1), ++ PIN_FIELD_BASE(5, 5, IOCFG_RB_BASE, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(6, 6, IOCFG_RB_BASE, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(11, 12, IOCFG_RB_BASE, 0x00, 0x10, 24, 3), ++ PIN_FIELD_BASE(13, 14, IOCFG_RB_BASE, 0x10, 0x10, 0, 3), ++ PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x10, 0x10, 6, 3), ++ PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x10, 0x10, 24, 3), ++ PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x10, 0x10, 21, 3), ++ PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x10, 0x10, 15, 3), ++ PIN_FIELD_BASE(28, 28, IOCFG_RT_BASE, 0x10, 0x10, 27, 3), ++ PIN_FIELD_BASE(29, 29, IOCFG_RT_BASE, 0x20, 0x10, 0, 3), ++ PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x20, 0x10, 9, 3), ++ PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x20, 0x10, 6, 3), ++ PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x20, 0x10, 3, 3), ++ PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x00, 0x10, 24, 3), ++ PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x00, 0x10, 21, 3), ++ PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x00, 0x10, 27, 3), ++ PIN_FIELD_BASE(39, 39, IOCFG_RB_BASE, 0x10, 0x10, 27, 3), ++ PIN_FIELD_BASE(40, 40, IOCFG_RB_BASE, 0x20, 0x10, 0, 3), ++ PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x10, 0x10, 6, 3), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x20, 0x10, 9, 3), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x20, 0x10, 3, 3), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x20, 0x10, 21, 3), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x20, 0x10, 15, 3), ++ PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x10, 0x10, 0, 3), ++ PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x10, 0x10, 15, 3), ++ PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x10, 0x10, 12, 3), ++ PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x10, 0x10, 9, 3), ++ PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x10, 0x10, 18, 3), ++ PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x00, 0x10, 2, 3), ++ PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x10, 0x10, 18, 3), ++ PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x10, 0x10, 12, 3), ++ PIN_FIELD_BASE(74, 77, IOCFG_TR_BASE, 0x00, 0x10, 15, 3), ++ PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(80, 80, IOCFG_TR_BASE, 0x00, 0x10, 27, 3), ++ PIN_FIELD_BASE(81, 84, IOCFG_TR_BASE, 0x10, 0x10, 0, 3), ++ PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x00, 0x10, 3, 3), ++ PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x00, 0x10, 0, 3), ++ PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x10, 0x10, 12, 3), ++ PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x10, 0x10, 6, 3), ++ PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x00, 0x10, 12, 3), ++ PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x00, 0x10, 6, 3), ++ PIN_FIELD_BASE(97, 98, IOCFG_TL_BASE, 0x00, 0x10, 24, 3), ++ PIN_FIELD_BASE(99, 100, IOCFG_TL_BASE, 0x10, 0x10, 2, 3), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_pupd_range[] = { ++ PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x60, 0x10, 17, 1), ++ PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x30, 0x10, 10, 1), ++ PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x60, 0x10, 0, 1), ++ PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x30, 0x10, 0, 1), ++ PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x60, 0x10, 8, 1), ++ PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x60, 0x10, 2, 1), ++ PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x40, 0x10, 12, 1), ++ PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x40, 0x10, 18, 1), ++ PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x40, 0x10, 17, 1), ++ PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x40, 0x10, 15, 1), ++ PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x40, 0x10, 19, 1), ++ PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x40, 0x10, 23, 1), ++ PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x40, 0x10, 22, 1), ++ PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x40, 0x10, 21, 1), ++ PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x30, 0x10, 4, 1), ++ PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x30, 0x10, 8, 1), ++ PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x30, 0x10, 7, 1), ++ PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x30, 0x10, 5, 1), ++ PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x30, 0x10, 9, 1), ++ PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x60, 0x10, 18, 1), ++ PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x60, 0x10, 12, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x60, 0x10, 23, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x60, 0x10, 21, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x60, 0x10, 27, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x60, 0x10, 25, 1), ++ PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x40, 0x10, 2, 1), ++ PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x40, 0x10, 1, 1), ++ PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x60, 0x10, 15, 1), ++ PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x60, 0x10, 14, 1), ++ PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x60, 0x10, 13, 1), ++ PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x60, 0x10, 16, 1), ++ PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x40, 0x10, 2, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_r0_range[] = { ++ PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x70, 0x10, 17, 1), ++ PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x40, 0x10, 10, 1), ++ PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x70, 0x10, 0, 1), ++ PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x40, 0x10, 0, 1), ++ PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x70, 0x10, 8, 1), ++ PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x70, 0x10, 2, 1), ++ PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x50, 0x10, 12, 1), ++ PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x50, 0x10, 18, 1), ++ PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x50, 0x10, 17, 1), ++ PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x50, 0x10, 15, 1), ++ PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x50, 0x10, 19, 1), ++ PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x50, 0x10, 23, 1), ++ PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x50, 0x10, 22, 1), ++ PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x50, 0x10, 21, 1), ++ PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x40, 0x10, 4, 1), ++ PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x40, 0x10, 8, 1), ++ PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x40, 0x10, 7, 1), ++ PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x40, 0x10, 5, 1), ++ PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x40, 0x10, 9, 1), ++ PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x70, 0x10, 18, 1), ++ PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x70, 0x10, 12, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x70, 0x10, 23, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x70, 0x10, 21, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x70, 0x10, 27, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x70, 0x10, 25, 1), ++ PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x50, 0x10, 2, 1), ++ PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x50, 0x10, 1, 1), ++ PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x50, 0x10, 10, 1), ++ PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x70, 0x10, 15, 1), ++ PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x70, 0x10, 14, 1), ++ PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x70, 0x10, 13, 1), ++ PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x70, 0x10, 16, 1), ++ PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x50, 0x10, 2, 1), ++}; ++ ++static const struct mtk_pin_field_calc mt7986_pin_r1_range[] = { ++ PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x80, 0x10, 17, 1), ++ PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x50, 0x10, 10, 1), ++ PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x60, 0x10, 0, 1), ++ PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x80, 0x10, 0, 1), ++ PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x50, 0x10, 0, 1), ++ PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x80, 0x10, 8, 1), ++ PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x80, 0x10, 2, 1), ++ PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x60, 0x10, 12, 1), ++ PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x60, 0x10, 18, 1), ++ PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x60, 0x10, 17, 1), ++ PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x60, 0x10, 15, 1), ++ PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x60, 0x10, 19, 1), ++ PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x60, 0x10, 23, 1), ++ PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x60, 0x10, 22, 1), ++ PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x60, 0x10, 21, 1), ++ PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x50, 0x10, 4, 1), ++ PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x50, 0x10, 8, 1), ++ PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x50, 0x10, 7, 1), ++ PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x50, 0x10, 5, 1), ++ PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x50, 0x10, 9, 1), ++ PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x80, 0x10, 18, 1), ++ PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x80, 0x10, 12, 1), ++ PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x80, 0x10, 23, 1), ++ PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x80, 0x10, 21, 1), ++ PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x80, 0x10, 27, 1), ++ PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x80, 0x10, 25, 1), ++ PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x60, 0x10, 2, 1), ++ PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x60, 0x10, 1, 1), ++ PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x60, 0x10, 0, 1), ++ PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x60, 0x10, 10, 1), ++ PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x80, 0x10, 15, 1), ++ PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x80, 0x10, 14, 1), ++ PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x80, 0x10, 13, 1), ++ PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x80, 0x10, 16, 1), ++ PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1), ++}; ++ ++static const struct mtk_pin_reg_calc mt7986_reg_cals[] = { ++ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range), ++ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range), ++ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7986_pin_di_range), ++ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7986_pin_do_range), ++ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7986_pin_smt_range), ++ [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7986_pin_ies_range), ++ [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7986_pin_drv_range), ++ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7986_pin_pu_range), ++ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7986_pin_pd_range), ++ [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7986_pin_pupd_range), ++ [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7986_pin_r0_range), ++ [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7986_pin_r1_range), ++}; ++ ++static const struct mtk_pin_desc mt7986_pins[] = { ++ MT7986_TYPE0_PIN(0, "SYS_WATCHDOG"), ++ MT7986_TYPE0_PIN(1, "WF2G_LED"), ++ MT7986_TYPE0_PIN(2, "WF5G_LED"), ++ MT7986_TYPE0_PIN(3, "I2C_SCL"), ++ MT7986_TYPE0_PIN(4, "I2C_SDA"), ++ MT7986_TYPE0_PIN(5, "GPIO_0"), ++ MT7986_TYPE0_PIN(6, "GPIO_1"), ++ MT7986_TYPE0_PIN(7, "GPIO_2"), ++ MT7986_TYPE0_PIN(8, "GPIO_3"), ++ MT7986_TYPE0_PIN(9, "GPIO_4"), ++ MT7986_TYPE0_PIN(10, "GPIO_5"), ++ MT7986_TYPE0_PIN(11, "GPIO_6"), ++ MT7986_TYPE0_PIN(12, "GPIO_7"), ++ MT7986_TYPE0_PIN(13, "GPIO_8"), ++ MT7986_TYPE0_PIN(14, "GPIO_9"), ++ MT7986_TYPE0_PIN(15, "GPIO_10"), ++ MT7986_TYPE0_PIN(16, "GPIO_11"), ++ MT7986_TYPE0_PIN(17, "GPIO_12"), ++ MT7986_TYPE0_PIN(18, "GPIO_13"), ++ MT7986_TYPE0_PIN(19, "GPIO_14"), ++ MT7986_TYPE0_PIN(20, "GPIO_15"), ++ MT7986_TYPE0_PIN(21, "PWM0"), ++ MT7986_TYPE0_PIN(22, "PWM1"), ++ MT7986_TYPE0_PIN(23, "SPI0_CLK"), ++ MT7986_TYPE0_PIN(24, "SPI0_MOSI"), ++ MT7986_TYPE0_PIN(25, "SPI0_MISO"), ++ MT7986_TYPE0_PIN(26, "SPI0_CS"), ++ MT7986_TYPE0_PIN(27, "SPI0_HOLD"), ++ MT7986_TYPE0_PIN(28, "SPI0_WP"), ++ MT7986_TYPE0_PIN(29, "SPI1_CLK"), ++ MT7986_TYPE0_PIN(30, "SPI1_MOSI"), ++ MT7986_TYPE0_PIN(31, "SPI1_MISO"), ++ MT7986_TYPE0_PIN(32, "SPI1_CS"), ++ MT7986_TYPE0_PIN(33, "SPI2_CLK"), ++ MT7986_TYPE0_PIN(34, "SPI2_MOSI"), ++ MT7986_TYPE0_PIN(35, "SPI2_MISO"), ++ MT7986_TYPE0_PIN(36, "SPI2_CS"), ++ MT7986_TYPE0_PIN(37, "SPI2_HOLD"), ++ MT7986_TYPE0_PIN(38, "SPI2_WP"), ++ MT7986_TYPE0_PIN(39, "UART0_RXD"), ++ MT7986_TYPE0_PIN(40, "UART0_TXD"), ++ MT7986_TYPE0_PIN(41, "PCIE_PERESET_N"), ++ MT7986_TYPE0_PIN(42, "UART1_RXD"), ++ MT7986_TYPE0_PIN(43, "UART1_TXD"), ++ MT7986_TYPE0_PIN(44, "UART1_CTS"), ++ MT7986_TYPE0_PIN(45, "UART1_RTS"), ++ MT7986_TYPE0_PIN(46, "UART2_RXD"), ++ MT7986_TYPE0_PIN(47, "UART2_TXD"), ++ MT7986_TYPE0_PIN(48, "UART2_CTS"), ++ MT7986_TYPE0_PIN(49, "UART2_RTS"), ++ MT7986_TYPE0_PIN(50, "EMMC_DATA_0"), ++ MT7986_TYPE0_PIN(51, "EMMC_DATA_1"), ++ MT7986_TYPE0_PIN(52, "EMMC_DATA_2"), ++ MT7986_TYPE0_PIN(53, "EMMC_DATA_3"), ++ MT7986_TYPE0_PIN(54, "EMMC_DATA_4"), ++ MT7986_TYPE0_PIN(55, "EMMC_DATA_5"), ++ MT7986_TYPE0_PIN(56, "EMMC_DATA_6"), ++ MT7986_TYPE0_PIN(57, "EMMC_DATA_7"), ++ MT7986_TYPE0_PIN(58, "EMMC_CMD"), ++ MT7986_TYPE0_PIN(59, "EMMC_CK"), ++ MT7986_TYPE0_PIN(60, "EMMC_DSL"), ++ MT7986_TYPE0_PIN(61, "EMMC_RSTB"), ++ MT7986_TYPE0_PIN(62, "PCM_DTX"), ++ MT7986_TYPE0_PIN(63, "PCM_DRX"), ++ MT7986_TYPE0_PIN(64, "PCM_CLK"), ++ MT7986_TYPE0_PIN(65, "PCM_FS"), ++ MT7986_TYPE0_PIN(66, "MT7531_INT"), ++ MT7986_TYPE0_PIN(67, "SMI_MDC"), ++ MT7986_TYPE0_PIN(68, "SMI_MDIO"), ++ MT7986_TYPE1_PIN(69, "WF0_DIG_RESETB"), ++ MT7986_TYPE1_PIN(70, "WF0_CBA_RESETB"), ++ MT7986_TYPE1_PIN(71, "WF0_XO_REQ"), ++ MT7986_TYPE1_PIN(72, "WF0_TOP_CLK"), ++ MT7986_TYPE1_PIN(73, "WF0_TOP_DATA"), ++ MT7986_TYPE1_PIN(74, "WF0_HB1"), ++ MT7986_TYPE1_PIN(75, "WF0_HB2"), ++ MT7986_TYPE1_PIN(76, "WF0_HB3"), ++ MT7986_TYPE1_PIN(77, "WF0_HB4"), ++ MT7986_TYPE1_PIN(78, "WF0_HB0"), ++ MT7986_TYPE1_PIN(79, "WF0_HB0_B"), ++ MT7986_TYPE1_PIN(80, "WF0_HB5"), ++ MT7986_TYPE1_PIN(81, "WF0_HB6"), ++ MT7986_TYPE1_PIN(82, "WF0_HB7"), ++ MT7986_TYPE1_PIN(83, "WF0_HB8"), ++ MT7986_TYPE1_PIN(84, "WF0_HB9"), ++ MT7986_TYPE1_PIN(85, "WF0_HB10"), ++ MT7986_TYPE1_PIN(86, "WF1_DIG_RESETB"), ++ MT7986_TYPE1_PIN(87, "WF1_CBA_RESETB"), ++ MT7986_TYPE1_PIN(88, "WF1_XO_REQ"), ++ MT7986_TYPE1_PIN(89, "WF1_TOP_CLK"), ++ MT7986_TYPE1_PIN(90, "WF1_TOP_DATA"), ++ MT7986_TYPE1_PIN(91, "WF1_HB1"), ++ MT7986_TYPE1_PIN(92, "WF1_HB2"), ++ MT7986_TYPE1_PIN(93, "WF1_HB3"), ++ MT7986_TYPE1_PIN(94, "WF1_HB4"), ++ MT7986_TYPE1_PIN(95, "WF1_HB0"), ++ MT7986_TYPE1_PIN(96, "WF1_HB0_B"), ++ MT7986_TYPE1_PIN(97, "WF1_HB5"), ++ MT7986_TYPE1_PIN(98, "WF1_HB6"), ++ MT7986_TYPE1_PIN(99, "WF1_HB7"), ++ MT7986_TYPE1_PIN(100, "WF1_HB8"), ++}; ++ ++static const struct mtk_io_type_desc mt7986_io_type_desc[] = { ++ [IO_TYPE_GRP0] = { ++ .name = "18OD33", ++ .bias_set = mtk_pinconf_bias_set_pupd_r1_r0, ++ .drive_set = mtk_pinconf_drive_set_v1, ++ .input_enable = mtk_pinconf_input_enable_v1, ++ }, ++ [IO_TYPE_GRP1] = { ++ .name = "18A01", ++ .bias_set = mtk_pinconf_bias_set_pu_pd, ++ .drive_set = mtk_pinconf_drive_set_v1, ++ .input_enable = mtk_pinconf_input_enable_v1, ++ }, ++}; ++ ++/* List all groups consisting of these pins dedicated to the enablement of ++ * certain hardware block and the corresponding mode for all of the pins. ++ * The hardware probably has multiple combinations of these pinouts. ++ */ ++ ++static int mt7986_watchdog_pins[] = { 0, }; ++static int mt7986_watchdog_funcs[] = { 1, }; ++ ++static int mt7986_wifi_led_pins[] = { 1, 2, }; ++static int mt7986_wifi_led_funcs[] = { 1, 1, }; ++ ++static int mt7986_i2c_pins[] = { 3, 4, }; ++static int mt7986_i2c_funcs[] = { 1, 1, }; ++ ++static int mt7986_uart1_0_pins[] = { 7, 8, 9, 10, }; ++static int mt7986_uart1_0_funcs[] = { 3, 3, 3, 3, }; ++ ++static int mt7986_spi1_0_pins[] = { 11, 12, 13, 14, }; ++static int mt7986_spi1_0_funcs[] = { 3, 3, 3, 3, }; ++ ++static int mt7986_pwm1_1_pins[] = { 20, }; ++static int mt7986_pwm1_1_funcs[] = { 2, }; ++ ++static int mt7986_pwm0_pins[] = { 21, }; ++static int mt7986_pwm0_funcs[] = { 1, }; ++ ++static int mt7986_pwm1_0_pins[] = { 22, }; ++static int mt7986_pwm1_0_funcs[] = { 1, }; ++ ++static int mt7986_emmc_45_pins[] = { ++ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, }; ++static int mt7986_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; ++ ++static int mt7986_snfi_pins[] = { 23, 24, 25, 26, 27, 28, }; ++static int mt7986_snfi_funcs[] = { 1, 1, 1, 1, 1, 1, }; ++ ++static int mt7986_spi1_1_pins[] = { 23, 24, 25, 26, }; ++static int mt7986_spi1_1_funcs[] = { 3, 3, 3, 3, }; ++ ++static int mt7986_uart1_1_pins[] = { 23, 24, 25, 26, }; ++static int mt7986_uart1_1_funcs[] = { 4, 4, 4, 4, }; ++ ++static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, }; ++static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, }; ++ ++static int mt7986_uart1_2_pins[] = { 29, 30, 31, 32, }; ++static int mt7986_uart1_2_funcs[] = { 3, 3, 3, 3, }; ++ ++static int mt7986_uart2_0_pins[] = { 29, 30, 31, 32, }; ++static int mt7986_uart2_0_funcs[] = { 4, 4, 4, 4, }; ++ ++static int mt7986_spi0_pins[] = { 33, 34, 35, 36, }; ++static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, }; ++ ++static int mt7986_spi0_wp_hold_pins[] = { 37, 38, }; ++static int mt7986_spi0_wp_hold_funcs[] = { 1, 1, }; ++ ++static int mt7986_uart2_1_pins[] = { 33, 34, 35, 36, }; ++static int mt7986_uart2_1_funcs[] = { 3, 3, 3, 3, }; ++ ++static int mt7986_uart1_3_rx_tx_pins[] = { 35, 36, }; ++static int mt7986_uart1_3_rx_tx_funcs[] = { 2, 2, }; ++ ++static int mt7986_uart1_3_cts_rts_pins[] = { 37, 38, }; ++static int mt7986_uart1_3_cts_rts_funcs[] = { 2, 2, }; ++ ++static int mt7986_spi1_3_pins[] = { 33, 34, 35, 36, }; ++static int mt7986_spi1_3_funcs[] = { 4, 4, 4, 4, }; ++ ++static int mt7986_uart0_pins[] = { 39, 40, }; ++static int mt7986_uart0_funcs[] = { 1, 1, }; ++ ++static int mt7986_pcie_reset_pins[] = { 41, }; ++static int mt7986_pcie_reset_funcs[] = { 1, }; ++ ++static int mt7986_uart1_pins[] = { 42, 43, 44, 45, }; ++static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, }; ++ ++static int mt7986_uart2_pins[] = { 46, 47, 48, 49, }; ++static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, }; ++ ++static int mt7986_emmc_51_pins[] = { ++ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, }; ++static int mt7986_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; ++ ++static int mt7986_pcm_pins[] = { 62, 63, 64, 65, }; ++static int mt7986_pcm_funcs[] = { 1, 1, 1, 1, }; ++ ++static int mt7986_i2s_pins[] = { 62, 63, 64, 65, }; ++static int mt7986_i2s_funcs[] = { 1, 1, 1, 1, }; ++ ++static int mt7986_switch_int_pins[] = { 66, }; ++static int mt7986_switch_int_funcs[] = { 1, }; ++ ++static int mt7986_mdc_mdio_pins[] = { 67, 68, }; ++static int mt7986_mdc_mdio_funcs[] = { 1, 1, }; ++ ++static int mt7986_wf_2g_pins[] = {74, 75, 76, 77, 78, 79, 80, 81, 82, 83, }; ++static int mt7986_wf_2g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; ++ ++static int mt7986_wf_5g_pins[] = {91, 92, 93, 94, 95, 96, 97, 98, 99, 100, }; ++static int mt7986_wf_5g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; ++ ++static int mt7986_wf_dbdc_pins[] = { ++ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, }; ++static int mt7986_wf_dbdc_funcs[] = { ++ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; ++ ++static int mt7986_pcie_clk_pins[] = { 9, }; ++static int mt7986_pcie_clk_funcs[] = { 1, }; ++ ++static int mt7986_pcie_wake_pins[] = { 10, }; ++static int mt7986_pcie_wake_funcs[] = { 1, }; ++ ++static const struct mtk_group_desc mt7986_groups[] = { ++ PINCTRL_PIN_GROUP("watchdog", mt7986_watchdog), ++ PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led), ++ PINCTRL_PIN_GROUP("i2c", mt7986_i2c), ++ PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0), ++ PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk), ++ PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake), ++ PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0), ++ PINCTRL_PIN_GROUP("pwm1_1", mt7986_pwm1_1), ++ PINCTRL_PIN_GROUP("pwm0", mt7986_pwm0), ++ PINCTRL_PIN_GROUP("pwm1_0", mt7986_pwm1_0), ++ PINCTRL_PIN_GROUP("emmc_45", mt7986_emmc_45), ++ PINCTRL_PIN_GROUP("snfi", mt7986_snfi), ++ PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1), ++ PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1), ++ PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2), ++ PINCTRL_PIN_GROUP("uart1_2", mt7986_uart1_2), ++ PINCTRL_PIN_GROUP("uart2_0", mt7986_uart2_0), ++ PINCTRL_PIN_GROUP("spi0", mt7986_spi0), ++ PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold), ++ PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1), ++ PINCTRL_PIN_GROUP("uart1_3_rx_tx", mt7986_uart1_3_rx_tx), ++ PINCTRL_PIN_GROUP("uart1_3_cts_rts", mt7986_uart1_3_cts_rts), ++ PINCTRL_PIN_GROUP("spi1_3", mt7986_spi1_3), ++ PINCTRL_PIN_GROUP("uart0", mt7986_uart0), ++ PINCTRL_PIN_GROUP("switch_int", mt7986_switch_int), ++ PINCTRL_PIN_GROUP("mdc_mdio", mt7986_mdc_mdio), ++ PINCTRL_PIN_GROUP("pcie_pereset", mt7986_pcie_reset), ++ PINCTRL_PIN_GROUP("uart1", mt7986_uart1), ++ PINCTRL_PIN_GROUP("uart2", mt7986_uart2), ++ PINCTRL_PIN_GROUP("emmc_51", mt7986_emmc_51), ++ PINCTRL_PIN_GROUP("pcm", mt7986_pcm), ++ PINCTRL_PIN_GROUP("i2s", mt7986_i2s), ++ PINCTRL_PIN_GROUP("wf_2g", mt7986_wf_2g), ++ PINCTRL_PIN_GROUP("wf_5g", mt7986_wf_5g), ++ PINCTRL_PIN_GROUP("wf_dbdc", mt7986_wf_dbdc), ++}; ++ ++/* Joint those groups owning the same capability in user point of view which ++ * allows that people tend to use through the device tree. ++ */ ++ ++static const char *const mt7986_audio_groups[] = { "pcm", "i2s" }; ++static const char *const mt7986_emmc_groups[] = { "emmc_45", "emmc_51", }; ++static const char *const mt7986_ethernet_groups[] = { "switch_int", ++ "mdc_mdio", }; ++static const char *const mt7986_i2c_groups[] = { "i2c", }; ++static const char *const mt7986_led_groups[] = { "wifi_led", }; ++static const char *const mt7986_flash_groups[] = { "snfi", }; ++static const char *const mt7986_pcie_groups[] = { "pcie_clk", "pcie_wake", ++ "pcie_pereset" }; ++static const char *const mt7986_pwm_groups[] = { "pwm0", "pwm1_0", "pwm1_1", }; ++static const char *const mt7986_spi_groups[] = { "spi0", "spi0_wp_hold", ++ "spi1_0", "spi1_1", "spi1_2", "spi1_3", }; ++static const char *const mt7986_uart_groups[] = { "uart1_0", "uart1_1", ++ "uart1_2", "uart1_3_rx_tx", "uart1_3_cts_rts", "uart2_0", "uart2_1", ++ "uart0", "uart1", "uart2", }; ++static const char *const mt7986_wdt_groups[] = { "watchdog", }; ++static const char *const mt7986_wf_groups[] = { "wf_2g", "wf_5g", "wf_dbdc", }; ++ ++static const struct mtk_function_desc mt7986_functions[] = { ++ {"audio", mt7986_audio_groups, ARRAY_SIZE(mt7986_audio_groups)}, ++ {"emmc", mt7986_emmc_groups, ARRAY_SIZE(mt7986_emmc_groups)}, ++ {"eth", mt7986_ethernet_groups, ARRAY_SIZE(mt7986_ethernet_groups)}, ++ {"i2c", mt7986_i2c_groups, ARRAY_SIZE(mt7986_i2c_groups)}, ++ {"led", mt7986_led_groups, ARRAY_SIZE(mt7986_led_groups)}, ++ {"flash", mt7986_flash_groups, ARRAY_SIZE(mt7986_flash_groups)}, ++ {"pcie", mt7986_pcie_groups, ARRAY_SIZE(mt7986_pcie_groups)}, ++ {"pwm", mt7986_pwm_groups, ARRAY_SIZE(mt7986_pwm_groups)}, ++ {"spi", mt7986_spi_groups, ARRAY_SIZE(mt7986_spi_groups)}, ++ {"uart", mt7986_uart_groups, ARRAY_SIZE(mt7986_uart_groups)}, ++ {"watchdog", mt7986_wdt_groups, ARRAY_SIZE(mt7986_wdt_groups)}, ++ {"wifi", mt7986_wf_groups, ARRAY_SIZE(mt7986_wf_groups)}, ++}; ++ ++static struct mtk_pinctrl_soc mt7986_data = { ++ .name = "mt7986_pinctrl", ++ .reg_cal = mt7986_reg_cals, ++ .pins = mt7986_pins, ++ .npins = ARRAY_SIZE(mt7986_pins), ++ .grps = mt7986_groups, ++ .ngrps = ARRAY_SIZE(mt7986_groups), ++ .funcs = mt7986_functions, ++ .nfuncs = ARRAY_SIZE(mt7986_functions), ++ .io_type = mt7986_io_type_desc, ++ .ntype = ARRAY_SIZE(mt7986_io_type_desc), ++ .gpio_mode = 0, ++ .base_names = mt7986_pinctrl_register_base_names, ++ .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), ++ .base_calc = 1, ++}; ++ ++static int mtk_pinctrl_mt7986_probe(struct udevice *dev) ++{ ++ return mtk_pinctrl_common_probe(dev, &mt7986_data); ++} ++ ++static const struct udevice_id mt7986_pctrl_match[] = { ++ {.compatible = "mediatek,mt7986-pinctrl"}, ++ { /* sentinel */ } ++}; ++ ++U_BOOT_DRIVER(mt7986_pinctrl) = { ++ .name = "mt7986_pinctrl", ++ .id = UCLASS_PINCTRL, ++ .of_match = mt7986_pctrl_match, ++ .ops = &mtk_pinctrl_ops, ++ .probe = mtk_pinctrl_mt7986_probe, ++ .priv_auto = sizeof(struct mtk_pinctrl_priv), ++}; diff --git a/package/boot/uboot-mediatek/patches/002-0022-clk-mediatek-add-CLK_BYPASS_XTAL-flag-to-allow-bypas.patch b/package/boot/uboot-mediatek/patches/002-0022-clk-mediatek-add-CLK_BYPASS_XTAL-flag-to-allow-bypas.patch new file mode 100644 index 0000000000..c26fc8090e --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0022-clk-mediatek-add-CLK_BYPASS_XTAL-flag-to-allow-bypas.patch @@ -0,0 +1,69 @@ +From 7f6c8bdfe020c45c398c01b417460e3319476606 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 10:43:39 +0800 +Subject: [PATCH 22/31] clk: mediatek: add CLK_BYPASS_XTAL flag to allow + bypassing searching clock parent of xtal clock + +The mtk clock framework in u-boot uses array index for searching clock +parent (kernel uses strings for search), so we need to specify a special +clock with ID=0 for CLK_XTAL in u-boot. + +In the mt7622/mt7629 clock tree, the clocks with ID=0 never call +mtk_topckgen_get_mux_rate, adn return xtal clock directly. This what we +expected. + +However for newer chips, they may have some clocks with ID=0 not +representing the xtal clock and still needs mtk_topckgen_get_mux_rate be +called. Current logic will make entire clock driver not working. + +This patch adds a flag to indicate that whether a clock driver needs clocks +with ID=0 to call mtk_topckgen_get_mux_rate. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/clk/mediatek/clk-mtk.c | 5 ++++- + drivers/clk/mediatek/clk-mtk.h | 6 ++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -314,12 +314,15 @@ static ulong mtk_topckgen_get_mux_rate(s + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_composite *mux = &priv->tree->muxes[off]; + u32 index; ++ u32 flag = 0; + + index = readl(priv->base + mux->mux_reg); + index &= mux->mux_mask << mux->mux_shift; + index = index >> mux->mux_shift; + +- if (mux->parent[index]) ++ if (mux->parent[index] == CLK_XTAL && priv->tree->flags & CLK_BYPASS_XTAL) ++ flag = 1; ++ if (mux->parent[index] > 0 || flag == 1) + return mtk_clk_find_parent_rate(clk, mux->parent[index], + NULL); + +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -11,6 +11,11 @@ + #define CLK_XTAL 0 + #define MHZ (1000 * 1000) + ++/* flags in struct mtk_clk_tree */ ++ ++/* clk id == 0 doesn't mean it's xtal clk */ ++#define CLK_BYPASS_XTAL BIT(0) ++ + #define HAVE_RST_BAR BIT(0) + #define CLK_DOMAIN_SCPSYS BIT(0) + #define CLK_MUX_SETCLR_UPD BIT(1) +@@ -197,6 +202,7 @@ struct mtk_clk_tree { + const struct mtk_fixed_clk *fclks; + const struct mtk_fixed_factor *fdivs; + const struct mtk_composite *muxes; ++ u32 flags; + }; + + struct mtk_clk_priv { diff --git a/package/boot/uboot-mediatek/patches/002-0023-clk-mediatek-add-support-to-configure-clock-driver-p.patch b/package/boot/uboot-mediatek/patches/002-0023-clk-mediatek-add-support-to-configure-clock-driver-p.patch new file mode 100644 index 0000000000..41600a96b5 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0023-clk-mediatek-add-support-to-configure-clock-driver-p.patch @@ -0,0 +1,198 @@ +From cd4d6be5ed0488de2e0df9c388d89ad93d781caa Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 10:57:05 +0800 +Subject: [PATCH 23/31] clk: mediatek: add support to configure clock driver + parent + +This patch adds support for a clock node to configure its parent clock +where possible. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/clk/mediatek/clk-mtk.c | 79 ++++++++++++++++++++-------------- + drivers/clk/mediatek/clk-mtk.h | 2 + + 2 files changed, 48 insertions(+), 33 deletions(-) + +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -42,20 +42,14 @@ + * the accurate frequency. + */ + static ulong mtk_clk_find_parent_rate(struct clk *clk, int id, +- const struct driver *drv) ++ struct udevice *pdev) + { + struct clk parent = { .id = id, }; + +- if (drv) { +- struct udevice *dev; +- +- if (uclass_get_device_by_driver(UCLASS_CLK, drv, &dev)) +- return -ENODEV; +- +- parent.dev = dev; +- } else { ++ if (pdev) ++ parent.dev = pdev; ++ else + parent.dev = clk->dev; +- } + + return clk_get_rate(&parent); + } +@@ -296,7 +290,7 @@ static ulong mtk_topckgen_get_factor_rat + switch (fdiv->flags & CLK_PARENT_MASK) { + case CLK_PARENT_APMIXED: + rate = mtk_clk_find_parent_rate(clk, fdiv->parent, +- DM_DRIVER_GET(mtk_clk_apmixedsys)); ++ priv->parent); + break; + case CLK_PARENT_TOPCKGEN: + rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); +@@ -322,9 +316,18 @@ static ulong mtk_topckgen_get_mux_rate(s + + if (mux->parent[index] == CLK_XTAL && priv->tree->flags & CLK_BYPASS_XTAL) + flag = 1; +- if (mux->parent[index] > 0 || flag == 1) +- return mtk_clk_find_parent_rate(clk, mux->parent[index], +- NULL); ++ if (mux->parent[index] > 0 || flag == 1) { ++ switch (mux->flags & CLK_PARENT_MASK) { ++ case CLK_PARENT_APMIXED: ++ return mtk_clk_find_parent_rate(clk, mux->parent[index], ++ priv->parent); ++ break; ++ default: ++ return mtk_clk_find_parent_rate(clk, mux->parent[index], ++ NULL); ++ break; ++ } ++ } + + return priv->tree->xtal_rate; + } +@@ -343,7 +346,7 @@ static ulong mtk_topckgen_get_rate(struc + priv->tree->muxes_offs); + } + +-static int mtk_topckgen_enable(struct clk *clk) ++static int mtk_clk_mux_enable(struct clk *clk) + { + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_composite *mux; +@@ -376,7 +379,7 @@ static int mtk_topckgen_enable(struct cl + return 0; + } + +-static int mtk_topckgen_disable(struct clk *clk) ++static int mtk_clk_mux_disable(struct clk *clk) + { + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + const struct mtk_composite *mux; +@@ -402,7 +405,7 @@ static int mtk_topckgen_disable(struct c + return 0; + } + +-static int mtk_topckgen_set_parent(struct clk *clk, struct clk *parent) ++static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent) + { + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); + +@@ -474,19 +477,7 @@ static ulong mtk_clk_gate_get_rate(struc + struct mtk_cg_priv *priv = dev_get_priv(clk->dev); + const struct mtk_gate *gate = &priv->gates[clk->id]; + +- switch (gate->flags & CLK_PARENT_MASK) { +- case CLK_PARENT_APMIXED: +- return mtk_clk_find_parent_rate(clk, gate->parent, +- DM_DRIVER_GET(mtk_clk_apmixedsys)); +- break; +- case CLK_PARENT_TOPCKGEN: +- return mtk_clk_find_parent_rate(clk, gate->parent, +- DM_DRIVER_GET(mtk_clk_topckgen)); +- break; +- +- default: +- return priv->tree->xtal_rate; +- } ++ return mtk_clk_find_parent_rate(clk, gate->parent, priv->parent); + } + + const struct clk_ops mtk_clk_apmixedsys_ops = { +@@ -497,10 +488,10 @@ const struct clk_ops mtk_clk_apmixedsys_ + }; + + const struct clk_ops mtk_clk_topckgen_ops = { +- .enable = mtk_topckgen_enable, +- .disable = mtk_topckgen_disable, ++ .enable = mtk_clk_mux_enable, ++ .disable = mtk_clk_mux_disable, + .get_rate = mtk_topckgen_get_rate, +- .set_parent = mtk_topckgen_set_parent, ++ .set_parent = mtk_common_clk_set_parent, + }; + + const struct clk_ops mtk_clk_gate_ops = { +@@ -513,11 +504,22 @@ int mtk_common_clk_init(struct udevice * + const struct mtk_clk_tree *tree) + { + struct mtk_clk_priv *priv = dev_get_priv(dev); ++ struct udevice *parent; ++ int ret; + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -ENOENT; + ++ ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent); ++ if (ret || !parent) { ++ ret = uclass_get_device_by_driver(UCLASS_CLK, ++ DM_DRIVER_GET(mtk_clk_apmixedsys), &parent); ++ if (ret || !parent) ++ return -ENOENT; ++ } ++ ++ priv->parent = parent; + priv->tree = tree; + + return 0; +@@ -528,11 +530,22 @@ int mtk_common_clk_gate_init(struct udev + const struct mtk_gate *gates) + { + struct mtk_cg_priv *priv = dev_get_priv(dev); ++ struct udevice *parent; ++ int ret; + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -ENOENT; + ++ ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent); ++ if (ret || !parent) { ++ ret = uclass_get_device_by_driver(UCLASS_CLK, ++ DM_DRIVER_GET(mtk_clk_topckgen), &parent); ++ if (ret || !parent) ++ return -ENOENT; ++ } ++ ++ priv->parent = parent; + priv->tree = tree; + priv->gates = gates; + +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -206,11 +206,13 @@ struct mtk_clk_tree { + }; + + struct mtk_clk_priv { ++ struct udevice *parent; + void __iomem *base; + const struct mtk_clk_tree *tree; + }; + + struct mtk_cg_priv { ++ struct udevice *parent; + void __iomem *base; + const struct mtk_clk_tree *tree; + const struct mtk_gate *gates; diff --git a/package/boot/uboot-mediatek/patches/002-0024-clk-mediatek-add-infrasys-clock-mux-support.patch b/package/boot/uboot-mediatek/patches/002-0024-clk-mediatek-add-infrasys-clock-mux-support.patch new file mode 100644 index 0000000000..f84fdec2b4 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0024-clk-mediatek-add-infrasys-clock-mux-support.patch @@ -0,0 +1,136 @@ +From e9c0c2ebd346aa578007c2aa88fc0974af6afb40 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 11:14:33 +0800 +Subject: [PATCH 24/31] clk: mediatek: add infrasys clock mux support + +This patch adds infrasys clock mux support for mediatek clock drivers. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/clk/mediatek/clk-mtk.c | 72 ++++++++++++++++++++++++++++++++++ + drivers/clk/mediatek/clk-mtk.h | 4 +- + 2 files changed, 75 insertions(+), 1 deletion(-) + +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -303,6 +303,24 @@ static ulong mtk_topckgen_get_factor_rat + return mtk_factor_recalc_rate(fdiv, rate); + } + ++static ulong mtk_infrasys_get_factor_rate(struct clk *clk, u32 off) ++{ ++ struct mtk_clk_priv *priv = dev_get_priv(clk->dev); ++ const struct mtk_fixed_factor *fdiv = &priv->tree->fdivs[off]; ++ ulong rate; ++ ++ switch (fdiv->flags & CLK_PARENT_MASK) { ++ case CLK_PARENT_TOPCKGEN: ++ rate = mtk_clk_find_parent_rate(clk, fdiv->parent, ++ priv->parent); ++ break; ++ default: ++ rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); ++ } ++ ++ return mtk_factor_recalc_rate(fdiv, rate); ++} ++ + static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off) + { + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); +@@ -332,6 +350,34 @@ static ulong mtk_topckgen_get_mux_rate(s + return priv->tree->xtal_rate; + } + ++static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off) ++{ ++ struct mtk_clk_priv *priv = dev_get_priv(clk->dev); ++ const struct mtk_composite *mux = &priv->tree->muxes[off]; ++ u32 index; ++ u32 flag; ++ ++ index = readl(priv->base + mux->mux_reg); ++ index &= mux->mux_mask << mux->mux_shift; ++ index = index >> mux->mux_shift; ++ ++ if (mux->parent[index] == CLK_XTAL && priv->tree->flags & CLK_BYPASS_XTAL) ++ flag = 1; ++ if (mux->parent[index] > 0 || flag == 1) { ++ switch (mux->flags & CLK_PARENT_MASK) { ++ case CLK_PARENT_TOPCKGEN: ++ return mtk_clk_find_parent_rate(clk, mux->parent[index], ++ priv->parent); ++ break; ++ default: ++ return mtk_clk_find_parent_rate(clk, mux->parent[index], ++ NULL); ++ break; ++ } ++ } ++ return 0; ++} ++ + static ulong mtk_topckgen_get_rate(struct clk *clk) + { + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); +@@ -346,6 +392,25 @@ static ulong mtk_topckgen_get_rate(struc + priv->tree->muxes_offs); + } + ++static ulong mtk_infrasys_get_rate(struct clk *clk) ++{ ++ struct mtk_clk_priv *priv = dev_get_priv(clk->dev); ++ ++ ulong rate; ++ ++ if (clk->id < priv->tree->fdivs_offs) { ++ rate = priv->tree->fclks[clk->id].rate; ++ } else if (clk->id < priv->tree->muxes_offs) { ++ rate = mtk_infrasys_get_factor_rate(clk, clk->id - ++ priv->tree->fdivs_offs); ++ } else { ++ rate = mtk_infrasys_get_mux_rate(clk, clk->id - ++ priv->tree->muxes_offs); ++ } ++ ++ return rate; ++} ++ + static int mtk_clk_mux_enable(struct clk *clk) + { + struct mtk_clk_priv *priv = dev_get_priv(clk->dev); +@@ -494,6 +559,13 @@ const struct clk_ops mtk_clk_topckgen_op + .set_parent = mtk_common_clk_set_parent, + }; + ++const struct clk_ops mtk_clk_infrasys_ops = { ++ .enable = mtk_clk_mux_enable, ++ .disable = mtk_clk_mux_disable, ++ .get_rate = mtk_infrasys_get_rate, ++ .set_parent = mtk_common_clk_set_parent, ++}; ++ + const struct clk_ops mtk_clk_gate_ops = { + .enable = mtk_clk_gate_enable, + .disable = mtk_clk_gate_disable, +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -28,7 +28,8 @@ + + #define CLK_PARENT_APMIXED BIT(4) + #define CLK_PARENT_TOPCKGEN BIT(5) +-#define CLK_PARENT_MASK GENMASK(5, 4) ++#define CLK_PARENT_INFRASYS BIT(6) ++#define CLK_PARENT_MASK GENMASK(6, 4) + + #define ETHSYS_HIFSYS_RST_CTRL_OFS 0x34 + +@@ -220,6 +221,7 @@ struct mtk_cg_priv { + + extern const struct clk_ops mtk_clk_apmixedsys_ops; + extern const struct clk_ops mtk_clk_topckgen_ops; ++extern const struct clk_ops mtk_clk_infrasys_ops; + extern const struct clk_ops mtk_clk_gate_ops; + + int mtk_common_clk_init(struct udevice *dev, diff --git a/package/boot/uboot-mediatek/patches/002-0025-clk-mediatek-add-CLK_XTAL-support-for-clock-driver.patch b/package/boot/uboot-mediatek/patches/002-0025-clk-mediatek-add-CLK_XTAL-support-for-clock-driver.patch new file mode 100644 index 0000000000..37619d22f0 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0025-clk-mediatek-add-CLK_XTAL-support-for-clock-driver.patch @@ -0,0 +1,46 @@ +From cf70b726c9844bb5d1ba4bc3c202c5ab3ba4d421 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 11:15:35 +0800 +Subject: [PATCH 25/31] clk: mediatek: add CLK_XTAL support for clock driver + +This add CLK_XTAL macro and flag to mediatek clock driver common part, +to make thi SoC that has clock directlly connect to XTAL working. + +Signed-off-by: Weijie Gao +--- + drivers/clk/mediatek/clk-mtk.c | 4 ++++ + drivers/clk/mediatek/clk-mtk.h | 3 ++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -296,6 +296,7 @@ static ulong mtk_topckgen_get_factor_rat + rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); + break; + ++ case CLK_PARENT_XTAL: + default: + rate = priv->tree->xtal_rate; + } +@@ -314,6 +315,9 @@ static ulong mtk_infrasys_get_factor_rat + rate = mtk_clk_find_parent_rate(clk, fdiv->parent, + priv->parent); + break; ++ case CLK_PARENT_XTAL: ++ rate = priv->tree->xtal_rate; ++ break; + default: + rate = mtk_clk_find_parent_rate(clk, fdiv->parent, NULL); + } +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -29,7 +29,8 @@ + #define CLK_PARENT_APMIXED BIT(4) + #define CLK_PARENT_TOPCKGEN BIT(5) + #define CLK_PARENT_INFRASYS BIT(6) +-#define CLK_PARENT_MASK GENMASK(6, 4) ++#define CLK_PARENT_XTAL BIT(7) ++#define CLK_PARENT_MASK GENMASK(7, 4) + + #define ETHSYS_HIFSYS_RST_CTRL_OFS 0x34 + diff --git a/package/boot/uboot-mediatek/patches/002-0026-clk-mediatek-add-clock-driver-support-for-MediaTek-M.patch b/package/boot/uboot-mediatek/patches/002-0026-clk-mediatek-add-clock-driver-support-for-MediaTek-M.patch new file mode 100644 index 0000000000..f42e497141 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0026-clk-mediatek-add-clock-driver-support-for-MediaTek-M.patch @@ -0,0 +1,955 @@ +From ba4acf55044a8a11fc7e11a558a8a93e3c126391 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 11:21:59 +0800 +Subject: [PATCH 26/31] clk: mediatek: add clock driver support for MediaTek + MT7986 SoC + +This patch adds clock driver support for MediaTek MT7986 SoC + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/clk/mediatek/Makefile | 1 + + drivers/clk/mediatek/clk-mt7986.c | 672 +++++++++++++++++++++++++ + include/dt-bindings/clock/mt7986-clk.h | 249 +++++++++ + 3 files changed, 922 insertions(+) + create mode 100644 drivers/clk/mediatek/clk-mt7986.c + create mode 100644 include/dt-bindings/clock/mt7986-clk.h + +--- a/drivers/clk/mediatek/Makefile ++++ b/drivers/clk/mediatek/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_MT8512) += clk-mt8512.o + obj-$(CONFIG_TARGET_MT7623) += clk-mt7623.o + obj-$(CONFIG_TARGET_MT7622) += clk-mt7622.o + obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o ++obj-$(CONFIG_TARGET_MT7986) += clk-mt7986.o + obj-$(CONFIG_TARGET_MT8183) += clk-mt8183.o + obj-$(CONFIG_TARGET_MT8516) += clk-mt8516.o + obj-$(CONFIG_TARGET_MT8518) += clk-mt8518.o +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7986.c +@@ -0,0 +1,672 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * MediaTek clock driver for MT7986 SoC ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk-mtk.h" ++ ++#define MT7986_CLK_PDN 0x250 ++#define MT7986_CLK_PDN_EN_WRITE BIT(31) ++ ++#define PLL_FACTOR(_id, _name, _parent, _mult, _div) \ ++ FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED) ++ ++#define TOP_FACTOR(_id, _name, _parent, _mult, _div) \ ++ FACTOR(_id, _parent, _mult, _div, CLK_PARENT_TOPCKGEN) ++ ++#define INFRA_FACTOR(_id, _name, _parent, _mult, _div) \ ++ FACTOR(_id, _parent, _mult, _div, CLK_PARENT_INFRASYS) ++ ++/* FIXED PLLS */ ++static const struct mtk_fixed_clk fixed_pll_clks[] = { ++ FIXED_CLK(CK_APMIXED_ARMPLL, CLK_XTAL, 2000000000), ++ FIXED_CLK(CK_APMIXED_NET2PLL, CLK_XTAL, 800000000), ++ FIXED_CLK(CK_APMIXED_MMPLL, CLK_XTAL, 1440000000), ++ FIXED_CLK(CK_APMIXED_SGMPLL, CLK_XTAL, 325000000), ++ FIXED_CLK(CK_APMIXED_WEDMCUPLL, CLK_XTAL, 760000000), ++ FIXED_CLK(CK_APMIXED_NET1PLL, CLK_XTAL, 2500000000), ++ FIXED_CLK(CK_APMIXED_MPLL, CLK_XTAL, 416000000), ++ FIXED_CLK(CK_APMIXED_APLL2, CLK_XTAL, 196608000), ++}; ++ ++/* TOPCKGEN FIXED CLK */ ++static const struct mtk_fixed_clk top_fixed_clks[] = { ++ FIXED_CLK(CK_TOP_CB_CKSQ_40M, CLK_XTAL, 40000000), ++}; ++ ++/* TOPCKGEN FIXED DIV */ ++static const struct mtk_fixed_factor top_fixed_divs[] = { ++ PLL_FACTOR(CK_TOP_CB_M_416M, "cb_m_416m", CK_APMIXED_MPLL, 1, 1), ++ PLL_FACTOR(CK_TOP_CB_M_D2, "cb_m_d2", CK_APMIXED_MPLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_M_D4, "cb_m_d4", CK_APMIXED_MPLL, 1, 4), ++ PLL_FACTOR(CK_TOP_CB_M_D8, "cb_m_d8", CK_APMIXED_MPLL, 1, 8), ++ PLL_FACTOR(CK_TOP_M_D8_D2, "m_d8_d2", CK_APMIXED_MPLL, 1, 16), ++ PLL_FACTOR(CK_TOP_M_D3_D2, "m_d3_d2", CK_APMIXED_MPLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_MM_D2, "cb_mm_d2", CK_APMIXED_MMPLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_MM_D4, "cb_mm_d4", CK_APMIXED_MMPLL, 1, 4), ++ PLL_FACTOR(CK_TOP_CB_MM_D8, "cb_mm_d8", CK_APMIXED_MMPLL, 1, 8), ++ PLL_FACTOR(CK_TOP_MM_D8_D2, "mm_d8_d2", CK_APMIXED_MMPLL, 1, 16), ++ PLL_FACTOR(CK_TOP_MM_D3_D8, "mm_d3_d8", CK_APMIXED_MMPLL, 1, 8), ++ PLL_FACTOR(CK_TOP_CB_U2_PHYD_CK, "cb_u2_phyd", CK_APMIXED_MMPLL, 1, 30), ++ PLL_FACTOR(CK_TOP_CB_APLL2_196M, "cb_apll2_196m", CK_APMIXED_APLL2, 1, ++ 1), ++ PLL_FACTOR(CK_TOP_APLL2_D4, "apll2_d4", CK_APMIXED_APLL2, 1, 4), ++ PLL_FACTOR(CK_TOP_CB_NET1_D4, "cb_net1_d4", CK_APMIXED_NET1PLL, 1, 4), ++ PLL_FACTOR(CK_TOP_CB_NET1_D5, "cb_net1_d5", CK_APMIXED_NET1PLL, 1, 5), ++ PLL_FACTOR(CK_TOP_NET1_D5_D2, "net1_d5_d2", CK_APMIXED_NET1PLL, 1, 10), ++ PLL_FACTOR(CK_TOP_NET1_D5_D4, "net1_d5_d4", CK_APMIXED_NET1PLL, 1, 20), ++ PLL_FACTOR(CK_TOP_NET1_D8_D2, "net1_d8_d2", CK_APMIXED_NET1PLL, 1, 16), ++ PLL_FACTOR(CK_TOP_NET1_D8_D4, "net1_d8_d4", CK_APMIXED_NET1PLL, 1, 32), ++ PLL_FACTOR(CK_TOP_CB_NET2_800M, "cb_net2_800m", CK_APMIXED_NET2PLL, 1, ++ 1), ++ PLL_FACTOR(CK_TOP_CB_NET2_D4, "cb_net2_d4", CK_APMIXED_NET2PLL, 1, 4), ++ PLL_FACTOR(CK_TOP_NET2_D4_D2, "net2_d4_d2", CK_APMIXED_NET2PLL, 1, 8), ++ PLL_FACTOR(CK_TOP_NET2_D3_D2, "net2_d3_d2", CK_APMIXED_NET2PLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_WEDMCU_760M, "cb_wedmcu_760m", ++ CK_APMIXED_WEDMCUPLL, 1, 1), ++ PLL_FACTOR(CK_TOP_WEDMCU_D5_D2, "wedmcu_d5_d2", CK_APMIXED_WEDMCUPLL, 1, ++ 10), ++ PLL_FACTOR(CK_TOP_CB_SGM_325M, "cb_sgm_325m", CK_APMIXED_SGMPLL, 1, 1), ++ TOP_FACTOR(CK_TOP_CB_CKSQ_40M_D2, "cb_cksq_40m_d2", CK_TOP_CB_CKSQ_40M, ++ 1, 2), ++ TOP_FACTOR(CK_TOP_CB_RTC_32K, "cb_rtc_32k", CK_TOP_CB_CKSQ_40M, 1, ++ 1250), ++ TOP_FACTOR(CK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", CK_TOP_CB_CKSQ_40M, 1, ++ 1220), ++ TOP_FACTOR(CK_TOP_NFI1X, "nfi1x", CK_TOP_NFI1X_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", CK_TOP_CB_CKSQ_40M, 1, ++ 1), ++ TOP_FACTOR(CK_TOP_USB_TX250M, "usb_tx250m", CK_TOP_CB_CKSQ_40M, 1, 1), ++ TOP_FACTOR(CK_TOP_USB_LN0_CK, "usb_ln0", CK_TOP_CB_CKSQ_40M, 1, 1), ++ TOP_FACTOR(CK_TOP_USB_CDR_CK, "usb_cdr", CK_TOP_CB_CKSQ_40M, 1, 1), ++ TOP_FACTOR(CK_TOP_SPINFI_BCK, "spinfi_bck", CK_TOP_SPINFI_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_I2C_BCK, "i2c_bck", CK_TOP_I2C_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_PEXTP_TL, "pextp_tl", CK_TOP_PEXTP_TL_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_EMMC_250M, "emmc_250m", CK_TOP_EMMC_250M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_EMMC_416M, "emmc_416m", CK_TOP_EMMC_416M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_F_26M_ADC_CK, "f_26m_adc", CK_TOP_F_26M_ADC_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_TOP_SYSAXI, "sysaxi", CK_TOP_SYSAXI_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", ++ CK_TOP_NETSYS_MCU_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_NETSYS_2X, "netsys_2x", CK_TOP_NETSYS_2X_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_SGM_325M, "sgm_325m", CK_TOP_SGM_325M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_A1SYS, "a1sys", CK_TOP_A1SYS_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_EIP_B, "eip_b", CK_TOP_EIP_B_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_F26M, "csw_f26m", CK_TOP_F26M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_AUD_L, "aud_l", CK_TOP_AUD_L_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_A_TUNER, "a_tuner", CK_TOP_A_TUNER_SEL, 2, 1), ++ TOP_FACTOR(CK_TOP_U2U3_REF, "u2u3_ref", CK_TOP_U2U3_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_U2U3_SYS, "u2u3_sys", CK_TOP_U2U3_SYS_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_U2U3_XHCI, "u2u3_xhci", CK_TOP_U2U3_XHCI_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_AP2CNN_HOST, "ap2cnn_host", CK_TOP_AP2CNN_HOST_SEL, 1, ++ 1), ++}; ++ ++/* TOPCKGEN MUX PARENTS */ ++static const int nfi1x_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D8, ++ CK_TOP_NET1_D8_D2, CK_TOP_NET2_D3_D2, ++ CK_TOP_CB_M_D4, CK_TOP_MM_D8_D2, ++ CK_TOP_WEDMCU_D5_D2, CK_TOP_CB_M_D8 }; ++ ++static const int spinfi_parents[] = { ++ CK_TOP_CB_CKSQ_40M_D2, CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4, ++ CK_TOP_CB_M_D4, CK_TOP_MM_D8_D2, CK_TOP_WEDMCU_D5_D2, ++ CK_TOP_MM_D3_D8, CK_TOP_CB_M_D8 ++}; ++ ++static const int spi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2, ++ CK_TOP_CB_MM_D8, CK_TOP_NET1_D8_D2, ++ CK_TOP_NET2_D3_D2, CK_TOP_NET1_D5_D4, ++ CK_TOP_CB_M_D4, CK_TOP_WEDMCU_D5_D2 }; ++ ++static const int uart_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D8, ++ CK_TOP_M_D8_D2 }; ++ ++static const int pwm_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2, ++ CK_TOP_NET1_D5_D4, CK_TOP_CB_M_D4 }; ++ ++static const int i2c_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4, ++ CK_TOP_CB_M_D4, CK_TOP_NET1_D8_D4 }; ++ ++static const int pextp_tl_ck_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_NET1_D5_D4, CK_TOP_NET2_D4_D2, ++ CK_TOP_CB_RTC_32K }; ++ ++static const int emmc_250m_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_NET1_D5_D2 }; ++ ++static const int emmc_416m_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_416M }; ++ ++static const int f_26m_adc_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D8_D2 }; ++ ++static const int dramc_md32_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2 }; ++ ++static const int sysaxi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2, ++ CK_TOP_CB_NET2_D4 }; ++ ++static const int sysapb_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D3_D2, ++ CK_TOP_NET2_D4_D2 }; ++ ++static const int arm_db_main_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_NET2_D3_D2 }; ++ ++static const int arm_db_jtsel_parents[] = { -1, CK_TOP_CB_CKSQ_40M }; ++ ++static const int netsys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D4 }; ++ ++static const int netsys_500m_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_NET1_D5 }; ++ ++static const int netsys_mcu_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_WEDMCU_760M, ++ CK_TOP_CB_MM_D2, CK_TOP_CB_NET1_D4, ++ CK_TOP_CB_NET1_D5 }; ++ ++static const int netsys_2x_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_NET2_800M, ++ CK_TOP_CB_WEDMCU_760M, ++ CK_TOP_CB_MM_D2 }; ++ ++static const int sgm_325m_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_SGM_325M }; ++ ++static const int sgm_reg_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D4 }; ++ ++static const int a1sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4 }; ++ ++static const int conn_mcusys_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_MM_D2 }; ++ ++static const int eip_b_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET2_800M }; ++ ++static const int aud_l_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_APLL2_196M, ++ CK_TOP_M_D8_D2 }; ++ ++static const int a_tuner_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4, ++ CK_TOP_M_D8_D2 }; ++ ++static const int u2u3_sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4 }; ++ ++static const int da_u2_refsel_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_U2_PHYD_CK }; ++ ++#define TOP_MUX(_id, _name, _parents, _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \ ++ _shift, _width, _gate, _upd_ofs, _upd) \ ++ { \ ++ .id = _id, .mux_reg = _mux_ofs, .mux_set_reg = _mux_set_ofs, \ ++ .mux_clr_reg = _mux_clr_ofs, .upd_reg = _upd_ofs, \ ++ .upd_shift = _upd, .mux_shift = _shift, \ ++ .mux_mask = BIT(_width) - 1, .gate_reg = _mux_ofs, \ ++ .gate_shift = _gate, .parent = _parents, \ ++ .num_parents = ARRAY_SIZE(_parents), \ ++ .flags = CLK_MUX_SETCLR_UPD, \ ++ } ++ ++/* TOPCKGEN MUX_GATE */ ++static const struct mtk_composite top_muxes[] = { ++ /* CLK_CFG_0 */ ++ TOP_MUX(CK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, 0x000, 0x004, ++ 0x008, 0, 3, 7, 0x1C0, 0), ++ TOP_MUX(CK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, 0x000, 0x004, ++ 0x008, 8, 3, 15, 0x1C0, 1), ++ TOP_MUX(CK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000, 0x004, 0x008, 16, ++ 3, 23, 0x1C0, 2), ++ TOP_MUX(CK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, 0x000, 0x004, ++ 0x008, 24, 3, 31, 0x1C0, 3), ++ /* CLK_CFG_1 */ ++ TOP_MUX(CK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010, 0x014, 0x018, ++ 0, 2, 7, 0x1C0, 4), ++ TOP_MUX(CK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010, 0x014, 0x018, 8, ++ 2, 15, 0x1C0, 5), ++ TOP_MUX(CK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010, 0x014, 0x018, 16, ++ 2, 23, 0x1C0, 6), ++ TOP_MUX(CK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", pextp_tl_ck_parents, ++ 0x010, 0x014, 0x018, 24, 2, 31, 0x1C0, 7), ++ /* CLK_CFG_2 */ ++ TOP_MUX(CK_TOP_EMMC_250M_SEL, "emmc_250m_sel", emmc_250m_parents, 0x020, ++ 0x024, 0x028, 0, 1, 7, 0x1C0, 8), ++ TOP_MUX(CK_TOP_EMMC_416M_SEL, "emmc_416m_sel", emmc_416m_parents, 0x020, ++ 0x024, 0x028, 8, 1, 15, 0x1C0, 9), ++ TOP_MUX(CK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", f_26m_adc_parents, 0x020, ++ 0x024, 0x028, 16, 1, 23, 0x1C0, 10), ++ TOP_MUX(CK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, 0x020, 0x024, ++ 0x028, 24, 1, 31, 0x1C0, 11), ++ /* CLK_CFG_3 */ ++ TOP_MUX(CK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", dramc_md32_parents, ++ 0x030, 0x034, 0x038, 0, 1, 7, 0x1C0, 12), ++ TOP_MUX(CK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, 0x030, 0x034, ++ 0x038, 8, 2, 15, 0x1C0, 13), ++ TOP_MUX(CK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, 0x030, 0x034, ++ 0x038, 16, 2, 23, 0x1C0, 14), ++ TOP_MUX(CK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", arm_db_main_parents, ++ 0x030, 0x034, 0x038, 24, 1, 31, 0x1C0, 15), ++ /* CLK_CFG_4 */ ++ TOP_MUX(CK_TOP_ARM_DB_JTSEL, "arm_db_jtsel", arm_db_jtsel_parents, ++ 0x040, 0x044, 0x048, 0, 1, 7, 0x1C0, 16), ++ TOP_MUX(CK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, 0x040, 0x044, ++ 0x048, 8, 1, 15, 0x1C0, 17), ++ TOP_MUX(CK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", netsys_500m_parents, ++ 0x040, 0x044, 0x048, 16, 1, 23, 0x1C0, 18), ++ TOP_MUX(CK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", netsys_mcu_parents, ++ 0x040, 0x044, 0x048, 24, 3, 31, 0x1C0, 19), ++ /* CLK_CFG_5 */ ++ TOP_MUX(CK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", netsys_2x_parents, 0x050, ++ 0x054, 0x058, 0, 2, 7, 0x1C0, 20), ++ TOP_MUX(CK_TOP_SGM_325M_SEL, "sgm_325m_sel", sgm_325m_parents, 0x050, ++ 0x054, 0x058, 8, 1, 15, 0x1C0, 21), ++ TOP_MUX(CK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, 0x050, ++ 0x054, 0x058, 16, 1, 23, 0x1C0, 22), ++ TOP_MUX(CK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, 0x050, 0x054, ++ 0x058, 24, 1, 31, 0x1C0, 23), ++ /* CLK_CFG_6 */ ++ TOP_MUX(CK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel", conn_mcusys_parents, ++ 0x060, 0x064, 0x068, 0, 1, 7, 0x1C0, 24), ++ TOP_MUX(CK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents, 0x060, 0x064, ++ 0x068, 8, 1, 15, 0x1C0, 25), ++ TOP_MUX(CK_TOP_PCIE_PHY_SEL, "pcie_phy_sel", f_26m_adc_parents, 0x060, ++ 0x064, 0x068, 16, 1, 23, 0x1C0, 26), ++ TOP_MUX(CK_TOP_USB3_PHY_SEL, "usb3_phy_sel", f_26m_adc_parents, 0x060, ++ 0x064, 0x068, 24, 1, 31, 0x1C0, 27), ++ /* CLK_CFG_7 */ ++ TOP_MUX(CK_TOP_F26M_SEL, "csw_f26m_sel", f_26m_adc_parents, 0x070, ++ 0x074, 0x078, 0, 1, 7, 0x1C0, 28), ++ TOP_MUX(CK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, 0x070, 0x074, ++ 0x078, 8, 2, 15, 0x1C0, 29), ++ TOP_MUX(CK_TOP_A_TUNER_SEL, "a_tuner_sel", a_tuner_parents, 0x070, ++ 0x074, 0x078, 16, 2, 23, 0x1C0, 30), ++ TOP_MUX(CK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents, 0x070, 0x074, ++ 0x078, 24, 1, 31, 0x1C4, 0), ++ /* CLK_CFG_8 */ ++ TOP_MUX(CK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", u2u3_sys_parents, 0x080, ++ 0x084, 0x088, 0, 1, 7, 0x1C4, 1), ++ TOP_MUX(CK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", u2u3_sys_parents, 0x080, ++ 0x084, 0x088, 8, 1, 15, 0x1C4, 2), ++ TOP_MUX(CK_TOP_DA_U2_REFSEL, "da_u2_refsel", da_u2_refsel_parents, ++ 0x080, 0x084, 0x088, 16, 1, 23, 0x1C4, 3), ++ TOP_MUX(CK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel", da_u2_refsel_parents, ++ 0x080, 0x084, 0x088, 24, 1, 31, 0x1C4, 4), ++ /* CLK_CFG_9 */ ++ TOP_MUX(CK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", sgm_reg_parents, ++ 0x090, 0x094, 0x098, 0, 1, 7, 0x1C4, 5), ++}; ++ ++/* INFRA FIXED DIV */ ++static const struct mtk_fixed_factor infra_fixed_divs[] = { ++ TOP_FACTOR(CK_INFRA_CK_F26M, "infra_ck_f26m", CK_TOP_F26M_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_UART, "infra_uart", CK_TOP_UART_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_ISPI0, "infra_ispi0", CK_TOP_SPI_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_I2C, "infra_i2c", CK_TOP_I2C_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_ISPI1, "infra_ispi1", CK_TOP_SPINFI_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_PWM, "infra_pwm", CK_TOP_PWM_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_66M_MCK, "infra_66m_mck", CK_TOP_SYSAXI_SEL, 1, 2), ++ TOP_FACTOR(CK_INFRA_CK_F32K, "infra_ck_f32k", CK_TOP_CB_RTC_32P7K, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_PCIE_CK, "infra_pcie", CK_TOP_PEXTP_TL_SEL, 1, 1), ++ INFRA_FACTOR(CK_INFRA_PWM_BCK, "infra_pwm_bck", CK_INFRA_PWM_BSEL, 1, ++ 1), ++ INFRA_FACTOR(CK_INFRA_PWM_CK1, "infra_pwm_ck1", CK_INFRA_PWM1_SEL, 1, ++ 1), ++ INFRA_FACTOR(CK_INFRA_PWM_CK2, "infra_pwm_ck2", CK_INFRA_PWM2_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_133M_HCK, "infra_133m_hck", CK_TOP_SYSAXI, 1, 1), ++ TOP_FACTOR(CK_INFRA_EIP_CK, "infra_eip", CK_TOP_EIP_B, 1, 1), ++ INFRA_FACTOR(CK_INFRA_66M_PHCK, "infra_66m_phck", CK_INFRA_133M_HCK, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_FAUD_L_CK, "infra_faud_l", CK_TOP_AUD_L, 1, 1), ++ TOP_FACTOR(CK_INFRA_FAUD_AUD_CK, "infra_faud_aud", CK_TOP_A1SYS, 1, 1), ++ TOP_FACTOR(CK_INFRA_FAUD_EG2_CK, "infra_faud_eg2", CK_TOP_A_TUNER, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_I2CS_CK, "infra_i2cs", CK_TOP_I2C_BCK, 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_UART0, "infra_mux_uart0", CK_INFRA_UART0_SEL, ++ 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_UART1, "infra_mux_uart1", CK_INFRA_UART1_SEL, ++ 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_UART2, "infra_mux_uart2", CK_INFRA_UART2_SEL, ++ 1, 1), ++ TOP_FACTOR(CK_INFRA_NFI_CK, "infra_nfi", CK_TOP_NFI1X, 1, 1), ++ TOP_FACTOR(CK_INFRA_SPINFI_CK, "infra_spinfi", CK_TOP_SPINFI_BCK, 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_SPI0, "infra_mux_spi0", CK_INFRA_SPI0_SEL, 1, ++ 1), ++ INFRA_FACTOR(CK_INFRA_MUX_SPI1, "infra_mux_spi1", CK_INFRA_SPI1_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_RTC_32K, "infra_rtc_32k", CK_TOP_CB_RTC_32K, 1, 1), ++ TOP_FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", CK_TOP_EMMC_416M, 1, 1), ++ TOP_FACTOR(CK_INFRA_FMSDC_HCK_CK, "infra_fmsdc_hck", CK_TOP_EMMC_250M, ++ 1, 1), ++ TOP_FACTOR(CK_INFRA_PERI_133M, "infra_peri_133m", CK_TOP_SYSAXI, 1, 1), ++ TOP_FACTOR(CK_INFRA_133M_PHCK, "infra_133m_phck", CK_TOP_SYSAXI, 1, 1), ++ TOP_FACTOR(CK_INFRA_USB_SYS_CK, "infra_usb_sys", CK_TOP_U2U3_SYS, 1, 1), ++ TOP_FACTOR(CK_INFRA_USB_CK, "infra_usb", CK_TOP_U2U3_REF, 1, 1), ++ TOP_FACTOR(CK_INFRA_USB_XHCI_CK, "infra_usb_xhci", CK_TOP_U2U3_XHCI, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_PCIE_GFMUX_TL_O_PRE, "infra_pcie_mux", ++ CK_TOP_PEXTP_TL, 1, 1), ++ TOP_FACTOR(CK_INFRA_F26M_CK0, "infra_f26m_ck0", CK_TOP_F26M, 1, 1), ++ TOP_FACTOR(CK_INFRA_HD_133M, "infra_hd_133m", CK_TOP_SYSAXI, 1, 1), ++}; ++ ++/* INFRASYS MUX PARENTS */ ++static const int infra_uart0_parents[] = { CK_INFRA_CK_F26M, CK_INFRA_UART }; ++ ++static const int infra_spi0_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI0 }; ++ ++static const int infra_spi1_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI1 }; ++ ++static const int infra_pwm_bsel_parents[] = { CK_INFRA_CK_F32K, ++ CK_INFRA_CK_F26M, ++ CK_INFRA_66M_MCK, CK_INFRA_PWM }; ++ ++static const int infra_pcie_parents[] = { CK_INFRA_CK_F32K, CK_INFRA_CK_F26M, ++ -1, CK_INFRA_PCIE_CK }; ++ ++#define INFRA_MUX(_id, _name, _parents, _reg, _shift, _width) \ ++ { \ ++ .id = _id, .mux_reg = (_reg) + 0x8, \ ++ .mux_set_reg = (_reg) + 0x0, .mux_clr_reg = (_reg) + 0x4, \ ++ .mux_shift = _shift, .mux_mask = BIT(_width) - 1, \ ++ .parent = _parents, .num_parents = ARRAY_SIZE(_parents), \ ++ .flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_INFRASYS, \ ++ } ++ ++/* INFRA MUX */ ++ ++static const struct mtk_composite infra_muxes[] = { ++ /* MODULE_CLK_SEL_0 */ ++ INFRA_MUX(CK_INFRA_UART0_SEL, "infra_uart0_sel", infra_uart0_parents, ++ 0x10, 0, 1), ++ INFRA_MUX(CK_INFRA_UART1_SEL, "infra_uart1_sel", infra_uart0_parents, ++ 0x10, 1, 1), ++ INFRA_MUX(CK_INFRA_UART2_SEL, "infra_uart2_sel", infra_uart0_parents, ++ 0x10, 2, 1), ++ INFRA_MUX(CK_INFRA_SPI0_SEL, "infra_spi0_sel", infra_spi0_parents, 0x10, ++ 4, 1), ++ INFRA_MUX(CK_INFRA_SPI1_SEL, "infra_spi1_sel", infra_spi1_parents, 0x10, ++ 5, 1), ++ INFRA_MUX(CK_INFRA_PWM1_SEL, "infra_pwm1_sel", infra_pwm_bsel_parents, ++ 0x10, 9, 2), ++ INFRA_MUX(CK_INFRA_PWM2_SEL, "infra_pwm2_sel", infra_pwm_bsel_parents, ++ 0x10, 11, 2), ++ INFRA_MUX(CK_INFRA_PWM_BSEL, "infra_pwm_bsel", infra_pwm_bsel_parents, ++ 0x10, 13, 2), ++ /* MODULE_CLK_SEL_1 */ ++ INFRA_MUX(CK_INFRA_PCIE_SEL, "infra_pcie_sel", infra_pcie_parents, 0x20, ++ 0, 2), ++}; ++ ++static const struct mtk_gate_regs infra_0_cg_regs = { ++ .set_ofs = 0x40, ++ .clr_ofs = 0x44, ++ .sta_ofs = 0x48, ++}; ++ ++static const struct mtk_gate_regs infra_1_cg_regs = { ++ .set_ofs = 0x50, ++ .clr_ofs = 0x54, ++ .sta_ofs = 0x58, ++}; ++ ++static const struct mtk_gate_regs infra_2_cg_regs = { ++ .set_ofs = 0x60, ++ .clr_ofs = 0x64, ++ .sta_ofs = 0x68, ++}; ++ ++#define GATE_INFRA0(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = &infra_0_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS, \ ++ } ++ ++#define GATE_INFRA1(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = &infra_1_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS, \ ++ } ++ ++#define GATE_INFRA2(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = &infra_2_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS, \ ++ } ++ ++/* INFRA GATE */ ++ ++static const struct mtk_gate infracfg_ao_gates[] = { ++ /* INFRA0 */ ++ GATE_INFRA0(CK_INFRA_GPT_STA, "infra_gpt_sta", CK_INFRA_66M_MCK, 0), ++ GATE_INFRA0(CK_INFRA_PWM_HCK, "infra_pwm_hck", CK_INFRA_66M_MCK, 1), ++ GATE_INFRA0(CK_INFRA_PWM_STA, "infra_pwm_sta", CK_INFRA_PWM_BCK, 2), ++ GATE_INFRA0(CK_INFRA_PWM1_CK, "infra_pwm1", CK_INFRA_PWM_CK1, 3), ++ GATE_INFRA0(CK_INFRA_PWM2_CK, "infra_pwm2", CK_INFRA_PWM_CK2, 4), ++ GATE_INFRA0(CK_INFRA_CQ_DMA_CK, "infra_cq_dma", CK_INFRA_133M_HCK, 6), ++ GATE_INFRA0(CK_INFRA_EIP97_CK, "infra_eip97", CK_INFRA_EIP_CK, 7), ++ GATE_INFRA0(CK_INFRA_AUD_BUS_CK, "infra_aud_bus", CK_INFRA_66M_PHCK, 8), ++ GATE_INFRA0(CK_INFRA_AUD_26M_CK, "infra_aud_26m", CK_INFRA_CK_F26M, 9), ++ GATE_INFRA0(CK_INFRA_AUD_L_CK, "infra_aud_l", CK_INFRA_FAUD_L_CK, 10), ++ GATE_INFRA0(CK_INFRA_AUD_AUD_CK, "infra_aud_aud", CK_INFRA_FAUD_AUD_CK, ++ 11), ++ GATE_INFRA0(CK_INFRA_AUD_EG2_CK, "infra_aud_eg2", CK_INFRA_FAUD_EG2_CK, ++ 13), ++ GATE_INFRA0(CK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", CK_INFRA_CK_F26M, ++ 14), ++ GATE_INFRA0(CK_INFRA_DBG_CK, "infra_dbg", CK_INFRA_66M_MCK, 15), ++ GATE_INFRA0(CK_INFRA_AP_DMA_CK, "infra_ap_dma", CK_INFRA_66M_MCK, 16), ++ GATE_INFRA0(CK_INFRA_SEJ_CK, "infra_sej", CK_INFRA_66M_MCK, 24), ++ GATE_INFRA0(CK_INFRA_SEJ_13M_CK, "infra_sej_13m", CK_INFRA_CK_F26M, 25), ++ GATE_INFRA0(CK_INFRA_TRNG_CK, "infra_trng", CK_INFRA_HD_133M, 26), ++ /* INFRA1 */ ++ GATE_INFRA1(CK_INFRA_THERM_CK, "infra_therm", CK_INFRA_CK_F26M, 0), ++ GATE_INFRA1(CK_INFRA_I2CO_CK, "infra_i2co", CK_INFRA_I2CS_CK, 1), ++ GATE_INFRA1(CK_INFRA_UART0_CK, "infra_uart0", CK_INFRA_MUX_UART0, 2), ++ GATE_INFRA1(CK_INFRA_UART1_CK, "infra_uart1", CK_INFRA_MUX_UART1, 3), ++ GATE_INFRA1(CK_INFRA_UART2_CK, "infra_uart2", CK_INFRA_MUX_UART2, 4), ++ GATE_INFRA1(CK_INFRA_NFI1_CK, "infra_nfi1", CK_INFRA_NFI_CK, 8), ++ GATE_INFRA1(CK_INFRA_SPINFI1_CK, "infra_spinfi1", CK_INFRA_SPINFI_CK, ++ 9), ++ GATE_INFRA1(CK_INFRA_NFI_HCK_CK, "infra_nfi_hck", CK_INFRA_66M_MCK, 10), ++ GATE_INFRA1(CK_INFRA_SPI0_CK, "infra_spi0", CK_INFRA_MUX_SPI0, 11), ++ GATE_INFRA1(CK_INFRA_SPI1_CK, "infra_spi1", CK_INFRA_MUX_SPI1, 12), ++ GATE_INFRA1(CK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", CK_INFRA_66M_MCK, ++ 13), ++ GATE_INFRA1(CK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", CK_INFRA_66M_MCK, ++ 14), ++ GATE_INFRA1(CK_INFRA_FRTC_CK, "infra_frtc", CK_INFRA_RTC_32K, 15), ++ GATE_INFRA1(CK_INFRA_MSDC_CK, "infra_msdc", CK_INFRA_FMSDC_CK, 16), ++ GATE_INFRA1(CK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", ++ CK_INFRA_FMSDC_HCK_CK, 17), ++ GATE_INFRA1(CK_INFRA_MSDC_133M_CK, "infra_msdc_133m", ++ CK_INFRA_PERI_133M, 18), ++ GATE_INFRA1(CK_INFRA_MSDC_66M_CK, "infra_msdc_66m", CK_INFRA_66M_PHCK, ++ 19), ++ GATE_INFRA1(CK_INFRA_ADC_26M_CK, "infra_adc_26m", CK_INFRA_CK_F26M, 20), ++ GATE_INFRA1(CK_INFRA_ADC_FRC_CK, "infra_adc_frc", CK_INFRA_CK_F26M, 21), ++ GATE_INFRA1(CK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", CK_INFRA_NFI_CK, ++ 23), ++ /* INFRA2 */ ++ GATE_INFRA2(CK_INFRA_IUSB_133_CK, "infra_iusb_133", CK_INFRA_133M_PHCK, ++ 0), ++ GATE_INFRA2(CK_INFRA_IUSB_66M_CK, "infra_iusb_66m", CK_INFRA_66M_PHCK, ++ 1), ++ GATE_INFRA2(CK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", CK_INFRA_USB_SYS_CK, ++ 2), ++ GATE_INFRA2(CK_INFRA_IUSB_CK, "infra_iusb", CK_INFRA_USB_CK, 3), ++ GATE_INFRA2(CK_INFRA_IPCIE_CK, "infra_ipcie", CK_INFRA_PCIE_CK, 13), ++ GATE_INFRA2(CK_INFRA_IPCIER_CK, "infra_ipcier", CK_INFRA_F26M_CK0, 15), ++ GATE_INFRA2(CK_INFRA_IPCIEB_CK, "infra_ipcieb", CK_INFRA_133M_PHCK, 15), ++}; ++ ++static const struct mtk_clk_tree mt7986_fixed_pll_clk_tree = { ++ .fdivs_offs = CLK_APMIXED_NR_CLK, ++ .xtal_rate = 40 * MHZ, ++ .fclks = fixed_pll_clks, ++}; ++ ++static const struct mtk_clk_tree mt7986_topckgen_clk_tree = { ++ .fdivs_offs = CK_TOP_CB_M_416M, ++ .muxes_offs = CK_TOP_NFI1X_SEL, ++ .fclks = top_fixed_clks, ++ .fdivs = top_fixed_divs, ++ .muxes = top_muxes, ++ .flags = CLK_BYPASS_XTAL, ++}; ++ ++static const struct mtk_clk_tree mt7986_infracfg_clk_tree = { ++ .fdivs_offs = CK_INFRA_CK_F26M, ++ .muxes_offs = CK_INFRA_UART0_SEL, ++ .fdivs = infra_fixed_divs, ++ .muxes = infra_muxes, ++}; ++ ++static const struct udevice_id mt7986_fixed_pll_compat[] = { ++ { .compatible = "mediatek,mt7986-fixed-plls" }, ++ {} ++}; ++ ++static const struct udevice_id mt7986_topckgen_compat[] = { ++ { .compatible = "mediatek,mt7986-topckgen" }, ++ {} ++}; ++ ++static int mt7986_fixed_pll_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_init(dev, &mt7986_fixed_pll_clk_tree); ++} ++ ++static int mt7986_topckgen_probe(struct udevice *dev) ++{ ++ struct mtk_clk_priv *priv = dev_get_priv(dev); ++ ++ priv->base = dev_read_addr_ptr(dev); ++ writel(MT7986_CLK_PDN_EN_WRITE, priv->base + MT7986_CLK_PDN); ++ ++ return mtk_common_clk_init(dev, &mt7986_topckgen_clk_tree); ++} ++ ++U_BOOT_DRIVER(mtk_clk_apmixedsys) = { ++ .name = "mt7986-clock-fixed-pll", ++ .id = UCLASS_CLK, ++ .of_match = mt7986_fixed_pll_compat, ++ .probe = mt7986_fixed_pll_probe, ++ .priv_auto = sizeof(struct mtk_clk_priv), ++ .ops = &mtk_clk_topckgen_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++U_BOOT_DRIVER(mtk_clk_topckgen) = { ++ .name = "mt7986-clock-topckgen", ++ .id = UCLASS_CLK, ++ .of_match = mt7986_topckgen_compat, ++ .probe = mt7986_topckgen_probe, ++ .priv_auto = sizeof(struct mtk_clk_priv), ++ .ops = &mtk_clk_topckgen_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++static const struct udevice_id mt7986_infracfg_compat[] = { ++ { .compatible = "mediatek,mt7986-infracfg" }, ++ {} ++}; ++ ++static const struct udevice_id mt7986_infracfg_ao_compat[] = { ++ { .compatible = "mediatek,mt7986-infracfg_ao" }, ++ {} ++}; ++ ++static int mt7986_infracfg_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_init(dev, &mt7986_infracfg_clk_tree); ++} ++ ++static int mt7986_infracfg_ao_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_gate_init(dev, &mt7986_infracfg_clk_tree, ++ infracfg_ao_gates); ++} ++ ++U_BOOT_DRIVER(mtk_clk_infracfg) = { ++ .name = "mt7986-clock-infracfg", ++ .id = UCLASS_CLK, ++ .of_match = mt7986_infracfg_compat, ++ .probe = mt7986_infracfg_probe, ++ .priv_auto = sizeof(struct mtk_clk_priv), ++ .ops = &mtk_clk_infrasys_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++U_BOOT_DRIVER(mtk_clk_infracfg_ao) = { ++ .name = "mt7986-clock-infracfg-ao", ++ .id = UCLASS_CLK, ++ .of_match = mt7986_infracfg_ao_compat, ++ .probe = mt7986_infracfg_ao_probe, ++ .priv_auto = sizeof(struct mtk_cg_priv), ++ .ops = &mtk_clk_gate_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++/* ethsys */ ++static const struct mtk_gate_regs eth_cg_regs = { ++ .sta_ofs = 0x30, ++}; ++ ++#define GATE_ETH(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = ð_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN, \ ++ } ++ ++static const struct mtk_gate eth_cgs[] = { ++ GATE_ETH(CK_ETH_FE_EN, "eth_fe_en", CK_TOP_NETSYS_2X, 7), ++ GATE_ETH(CK_ETH_GP2_EN, "eth_gp2_en", CK_TOP_SGM_325M, 8), ++ GATE_ETH(CK_ETH_GP1_EN, "eth_gp1_en", CK_TOP_SGM_325M, 8), ++ GATE_ETH(CK_ETH_WOCPU1_EN, "eth_wocpu1_en", CK_TOP_NETSYS_WED_MCU, 14), ++ GATE_ETH(CK_ETH_WOCPU0_EN, "eth_wocpu0_en", CK_TOP_NETSYS_WED_MCU, 15), ++}; ++ ++static int mt7986_ethsys_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_gate_init(dev, &mt7986_topckgen_clk_tree, ++ eth_cgs); ++} ++ ++static int mt7986_ethsys_bind(struct udevice *dev) ++{ ++ int ret = 0; ++ ++ if (CONFIG_IS_ENABLED(RESET_MEDIATEK)) { ++ ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1); ++ if (ret) ++ debug("Warning: failed to bind reset controller\n"); ++ } ++ ++ return ret; ++} ++ ++static const struct udevice_id mt7986_ethsys_compat[] = { ++ { .compatible = "mediatek,mt7986-ethsys" }, ++ { } ++}; ++ ++U_BOOT_DRIVER(mtk_clk_ethsys) = { ++ .name = "mt7986-clock-ethsys", ++ .id = UCLASS_CLK, ++ .of_match = mt7986_ethsys_compat, ++ .probe = mt7986_ethsys_probe, ++ .bind = mt7986_ethsys_bind, ++ .priv_auto = sizeof(struct mtk_cg_priv), ++ .ops = &mtk_clk_gate_ops, ++}; +--- /dev/null ++++ b/include/dt-bindings/clock/mt7986-clk.h +@@ -0,0 +1,249 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Sam Shih ++ */ ++ ++#ifndef _DT_BINDINGS_CLK_MT7986_H ++#define _DT_BINDINGS_CLK_MT7986_H ++ ++/* INFRACFG */ ++ ++#define CK_INFRA_CK_F26M 0 ++#define CK_INFRA_UART 1 ++#define CK_INFRA_ISPI0 2 ++#define CK_INFRA_I2C 3 ++#define CK_INFRA_ISPI1 4 ++#define CK_INFRA_PWM 5 ++#define CK_INFRA_66M_MCK 6 ++#define CK_INFRA_CK_F32K 7 ++#define CK_INFRA_PCIE_CK 8 ++#define CK_INFRA_PWM_BCK 9 ++#define CK_INFRA_PWM_CK1 10 ++#define CK_INFRA_PWM_CK2 11 ++#define CK_INFRA_133M_HCK 12 ++#define CK_INFRA_EIP_CK 13 ++#define CK_INFRA_66M_PHCK 14 ++#define CK_INFRA_FAUD_L_CK 15 ++#define CK_INFRA_FAUD_AUD_CK 17 ++#define CK_INFRA_FAUD_EG2_CK 17 ++#define CK_INFRA_I2CS_CK 18 ++#define CK_INFRA_MUX_UART0 19 ++#define CK_INFRA_MUX_UART1 20 ++#define CK_INFRA_MUX_UART2 21 ++#define CK_INFRA_NFI_CK 22 ++#define CK_INFRA_SPINFI_CK 23 ++#define CK_INFRA_MUX_SPI0 24 ++#define CK_INFRA_MUX_SPI1 25 ++#define CK_INFRA_RTC_32K 26 ++#define CK_INFRA_FMSDC_CK 27 ++#define CK_INFRA_FMSDC_HCK_CK 28 ++#define CK_INFRA_PERI_133M 29 ++#define CK_INFRA_133M_PHCK 30 ++#define CK_INFRA_USB_SYS_CK 31 ++#define CK_INFRA_USB_CK 32 ++#define CK_INFRA_USB_XHCI_CK 33 ++#define CK_INFRA_PCIE_GFMUX_TL_O_PRE 34 ++#define CK_INFRA_F26M_CK0 35 ++#define CK_INFRA_HD_133M 36 ++#define CLK_INFRA_NR_CLK 37 ++ ++/* TOPCKGEN */ ++ ++#define CK_TOP_CB_CKSQ_40M 0 ++#define CK_TOP_CB_M_416M 1 ++#define CK_TOP_CB_M_D2 2 ++#define CK_TOP_CB_M_D4 3 ++#define CK_TOP_CB_M_D8 4 ++#define CK_TOP_M_D8_D2 5 ++#define CK_TOP_M_D3_D2 6 ++#define CK_TOP_CB_MM_D2 7 ++#define CK_TOP_CB_MM_D4 8 ++#define CK_TOP_CB_MM_D8 9 ++#define CK_TOP_MM_D8_D2 10 ++#define CK_TOP_MM_D3_D8 11 ++#define CK_TOP_CB_U2_PHYD_CK 12 ++#define CK_TOP_CB_APLL2_196M 13 ++#define CK_TOP_APLL2_D4 14 ++#define CK_TOP_CB_NET1_D4 15 ++#define CK_TOP_CB_NET1_D5 16 ++#define CK_TOP_NET1_D5_D2 17 ++#define CK_TOP_NET1_D5_D4 18 ++#define CK_TOP_NET1_D8_D2 19 ++#define CK_TOP_NET1_D8_D4 20 ++#define CK_TOP_CB_NET2_800M 21 ++#define CK_TOP_CB_NET2_D4 22 ++#define CK_TOP_NET2_D4_D2 23 ++#define CK_TOP_NET2_D3_D2 24 ++#define CK_TOP_CB_WEDMCU_760M 25 ++#define CK_TOP_WEDMCU_D5_D2 26 ++#define CK_TOP_CB_SGM_325M 27 ++#define CK_TOP_CB_CKSQ_40M_D2 28 ++#define CK_TOP_CB_RTC_32K 29 ++#define CK_TOP_CB_RTC_32P7K 30 ++#define CK_TOP_NFI1X 31 ++#define CK_TOP_USB_EQ_RX250M 32 ++#define CK_TOP_USB_TX250M 33 ++#define CK_TOP_USB_LN0_CK 34 ++#define CK_TOP_USB_CDR_CK 35 ++#define CK_TOP_SPINFI_BCK 36 ++#define CK_TOP_I2C_BCK 37 ++#define CK_TOP_PEXTP_TL 38 ++#define CK_TOP_EMMC_250M 39 ++#define CK_TOP_EMMC_416M 40 ++#define CK_TOP_F_26M_ADC_CK 41 ++#define CK_TOP_SYSAXI 42 ++#define CK_TOP_NETSYS_WED_MCU 43 ++#define CK_TOP_NETSYS_2X 44 ++#define CK_TOP_SGM_325M 45 ++#define CK_TOP_A1SYS 46 ++#define CK_TOP_EIP_B 47 ++#define CK_TOP_F26M 48 ++#define CK_TOP_AUD_L 49 ++#define CK_TOP_A_TUNER 50 ++#define CK_TOP_U2U3_REF 51 ++#define CK_TOP_U2U3_SYS 52 ++#define CK_TOP_U2U3_XHCI 53 ++#define CK_TOP_AP2CNN_HOST 54 ++#define CK_TOP_NFI1X_SEL 55 ++#define CK_TOP_SPINFI_SEL 56 ++#define CK_TOP_SPI_SEL 57 ++#define CK_TOP_SPIM_MST_SEL 58 ++#define CK_TOP_UART_SEL 59 ++#define CK_TOP_PWM_SEL 60 ++#define CK_TOP_I2C_SEL 61 ++#define CK_TOP_PEXTP_TL_SEL 62 ++#define CK_TOP_EMMC_250M_SEL 63 ++#define CK_TOP_EMMC_416M_SEL 64 ++#define CK_TOP_F_26M_ADC_SEL 65 ++#define CK_TOP_DRAMC_SEL 66 ++#define CK_TOP_DRAMC_MD32_SEL 67 ++#define CK_TOP_SYSAXI_SEL 68 ++#define CK_TOP_SYSAPB_SEL 69 ++#define CK_TOP_ARM_DB_MAIN_SEL 70 ++#define CK_TOP_ARM_DB_JTSEL 71 ++#define CK_TOP_NETSYS_SEL 72 ++#define CK_TOP_NETSYS_500M_SEL 73 ++#define CK_TOP_NETSYS_MCU_SEL 74 ++#define CK_TOP_NETSYS_2X_SEL 75 ++#define CK_TOP_SGM_325M_SEL 76 ++#define CK_TOP_SGM_REG_SEL 77 ++#define CK_TOP_A1SYS_SEL 78 ++#define CK_TOP_CONN_MCUSYS_SEL 79 ++#define CK_TOP_EIP_B_SEL 80 ++#define CK_TOP_PCIE_PHY_SEL 81 ++#define CK_TOP_USB3_PHY_SEL 82 ++#define CK_TOP_F26M_SEL 83 ++#define CK_TOP_AUD_L_SEL 84 ++#define CK_TOP_A_TUNER_SEL 85 ++#define CK_TOP_U2U3_SEL 86 ++#define CK_TOP_U2U3_SYS_SEL 87 ++#define CK_TOP_U2U3_XHCI_SEL 88 ++#define CK_TOP_DA_U2_REFSEL 89 ++#define CK_TOP_DA_U2_CK_1P_SEL 90 ++#define CK_TOP_AP2CNN_HOST_SEL 91 ++#define CLK_TOP_NR_CLK 92 ++ ++/* ++ * INFRACFG_AO ++ * clock muxes need to be append to infracfg domain, and clock gates ++ * need to be keep in infracgh_ao domain ++ */ ++ ++#define CK_INFRA_UART0_SEL (0 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_UART1_SEL (1 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_UART2_SEL (2 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_SPI0_SEL (3 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_SPI1_SEL (4 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PWM1_SEL (5 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PWM2_SEL (6 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PWM_BSEL (7 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PCIE_SEL (8 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_GPT_STA 0 ++#define CK_INFRA_PWM_HCK 1 ++#define CK_INFRA_PWM_STA 2 ++#define CK_INFRA_PWM1_CK 3 ++#define CK_INFRA_PWM2_CK 4 ++#define CK_INFRA_CQ_DMA_CK 5 ++#define CK_INFRA_EIP97_CK 6 ++#define CK_INFRA_AUD_BUS_CK 7 ++#define CK_INFRA_AUD_26M_CK 8 ++#define CK_INFRA_AUD_L_CK 9 ++#define CK_INFRA_AUD_AUD_CK 10 ++#define CK_INFRA_AUD_EG2_CK 11 ++#define CK_INFRA_DRAMC_26M_CK 12 ++#define CK_INFRA_DBG_CK 13 ++#define CK_INFRA_AP_DMA_CK 14 ++#define CK_INFRA_SEJ_CK 15 ++#define CK_INFRA_SEJ_13M_CK 16 ++#define CK_INFRA_THERM_CK 17 ++#define CK_INFRA_I2CO_CK 18 ++#define CK_INFRA_TRNG_CK 19 ++#define CK_INFRA_UART0_CK 20 ++#define CK_INFRA_UART1_CK 21 ++#define CK_INFRA_UART2_CK 22 ++#define CK_INFRA_NFI1_CK 23 ++#define CK_INFRA_SPINFI1_CK 24 ++#define CK_INFRA_NFI_HCK_CK 25 ++#define CK_INFRA_SPI0_CK 26 ++#define CK_INFRA_SPI1_CK 27 ++#define CK_INFRA_SPI0_HCK_CK 28 ++#define CK_INFRA_SPI1_HCK_CK 29 ++#define CK_INFRA_FRTC_CK 30 ++#define CK_INFRA_MSDC_CK 31 ++#define CK_INFRA_MSDC_HCK_CK 32 ++#define CK_INFRA_MSDC_133M_CK 33 ++#define CK_INFRA_MSDC_66M_CK 34 ++#define CK_INFRA_ADC_26M_CK 35 ++#define CK_INFRA_ADC_FRC_CK 36 ++#define CK_INFRA_FBIST2FPC_CK 37 ++#define CK_INFRA_IUSB_133_CK 38 ++#define CK_INFRA_IUSB_66M_CK 39 ++#define CK_INFRA_IUSB_SYS_CK 40 ++#define CK_INFRA_IUSB_CK 41 ++#define CK_INFRA_IPCIE_CK 42 ++#define CK_INFRA_IPCIER_CK 43 ++#define CK_INFRA_IPCIEB_CK 44 ++#define CLK_INFRA_AO_NR_CLK 45 ++ ++/* APMIXEDSYS */ ++ ++#define CK_APMIXED_ARMPLL 0 ++#define CK_APMIXED_NET2PLL 1 ++#define CK_APMIXED_MMPLL 2 ++#define CK_APMIXED_SGMPLL 3 ++#define CK_APMIXED_WEDMCUPLL 4 ++#define CK_APMIXED_NET1PLL 5 ++#define CK_APMIXED_MPLL 6 ++#define CK_APMIXED_APLL2 7 ++#define CLK_APMIXED_NR_CLK 8 ++ ++/* SGMIISYS_0 */ ++ ++#define CK_SGM0_TX_EN 0 ++#define CK_SGM0_RX_EN 1 ++#define CK_SGM0_CK0_EN 2 ++#define CK_SGM0_CDR_CK0_EN 3 ++#define CLK_SGMII0_NR_CLK 4 ++ ++/* SGMIISYS_1 */ ++ ++#define CK_SGM1_TX_EN 0 ++#define CK_SGM1_RX_EN 1 ++#define CK_SGM1_CK1_EN 2 ++#define CK_SGM1_CDR_CK1_EN 3 ++#define CLK_SGMII1_NR_CLK 4 ++ ++/* ETHSYS */ ++ ++#define CK_ETH_FE_EN 0 ++#define CK_ETH_GP2_EN 1 ++#define CK_ETH_GP1_EN 2 ++#define CK_ETH_WOCPU1_EN 3 ++#define CK_ETH_WOCPU0_EN 4 ++#define CLK_ETH_NR_CLK 5 ++ ++#endif ++ ++/* _DT_BINDINGS_CLK_MT7986_H */ diff --git a/package/boot/uboot-mediatek/patches/002-0027-clk-mediatek-add-clock-driver-support-for-MediaTek-M.patch b/package/boot/uboot-mediatek/patches/002-0027-clk-mediatek-add-clock-driver-support-for-MediaTek-M.patch new file mode 100644 index 0000000000..26084a6535 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0027-clk-mediatek-add-clock-driver-support-for-MediaTek-M.patch @@ -0,0 +1,984 @@ +From 79bca945dbfafcd08d71437b11e8ee57d64b4305 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 11:22:51 +0800 +Subject: [PATCH 27/31] clk: mediatek: add clock driver support for MediaTek + MT7981 SoC + +This patch adds clock driver support for MediaTek MT7981 SoC + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + drivers/clk/mediatek/Makefile | 1 + + drivers/clk/mediatek/clk-mt7981.c | 683 +++++++++++++++++++++++++ + include/dt-bindings/clock/mt7981-clk.h | 267 ++++++++++ + 3 files changed, 951 insertions(+) + create mode 100644 drivers/clk/mediatek/clk-mt7981.c + create mode 100644 include/dt-bindings/clock/mt7981-clk.h + +--- a/drivers/clk/mediatek/Makefile ++++ b/drivers/clk/mediatek/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_TARGET_MT7623) += clk-mt762 + obj-$(CONFIG_TARGET_MT7622) += clk-mt7622.o + obj-$(CONFIG_TARGET_MT7629) += clk-mt7629.o + obj-$(CONFIG_TARGET_MT7986) += clk-mt7986.o ++obj-$(CONFIG_TARGET_MT7981) += clk-mt7981.o + obj-$(CONFIG_TARGET_MT8183) += clk-mt8183.o + obj-$(CONFIG_TARGET_MT8516) += clk-mt8516.o + obj-$(CONFIG_TARGET_MT8518) += clk-mt8518.o +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7981.c +@@ -0,0 +1,683 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * MediaTek clock driver for MT7981 SoC ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk-mtk.h" ++ ++#define MT7981_CLK_PDN 0x250 ++#define MT7981_CLK_PDN_EN_WRITE BIT(31) ++ ++#define PLL_FACTOR(_id, _name, _parent, _mult, _div) \ ++ FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED) ++ ++#define TOP_FACTOR(_id, _name, _parent, _mult, _div) \ ++ FACTOR(_id, _parent, _mult, _div, CLK_PARENT_TOPCKGEN) ++ ++#define INFRA_FACTOR(_id, _name, _parent, _mult, _div) \ ++ FACTOR(_id, _parent, _mult, _div, CLK_PARENT_INFRASYS) ++ ++/* FIXED PLLS */ ++static const struct mtk_fixed_clk fixed_pll_clks[] = { ++ FIXED_CLK(CK_APMIXED_ARMPLL, CLK_XTAL, 1300000000), ++ FIXED_CLK(CK_APMIXED_NET2PLL, CLK_XTAL, 800000000), ++ FIXED_CLK(CK_APMIXED_MMPLL, CLK_XTAL, 720000000), ++ FIXED_CLK(CK_APMIXED_SGMPLL, CLK_XTAL, 325000000), ++ FIXED_CLK(CK_APMIXED_WEDMCUPLL, CLK_XTAL, 208000000), ++ FIXED_CLK(CK_APMIXED_NET1PLL, CLK_XTAL, 2500000000), ++ FIXED_CLK(CK_APMIXED_MPLL, CLK_XTAL, 416000000), ++ FIXED_CLK(CK_APMIXED_APLL2, CLK_XTAL, 196608000), ++}; ++ ++/* TOPCKGEN FIXED CLK */ ++static const struct mtk_fixed_clk top_fixed_clks[] = { ++ FIXED_CLK(CK_TOP_CB_CKSQ_40M, CLK_XTAL, 40000000), ++}; ++ ++/* TOPCKGEN FIXED DIV */ ++static const struct mtk_fixed_factor top_fixed_divs[] = { ++ PLL_FACTOR(CK_TOP_CB_M_416M, "cb_m_416m", CK_APMIXED_MPLL, 1, 1), ++ PLL_FACTOR(CK_TOP_CB_M_D2, "cb_m_d2", CK_APMIXED_MPLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_M_D3, "cb_m_d3", CK_APMIXED_MPLL, 1, 3), ++ PLL_FACTOR(CK_TOP_M_D3_D2, "m_d3_d2", CK_APMIXED_MPLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_M_D4, "cb_m_d4", CK_APMIXED_MPLL, 1, 4), ++ PLL_FACTOR(CK_TOP_CB_M_D8, "cb_m_d8", CK_APMIXED_MPLL, 1, 8), ++ PLL_FACTOR(CK_TOP_M_D8_D2, "m_d8_d2", CK_APMIXED_MPLL, 1, 16), ++ PLL_FACTOR(CK_TOP_CB_MM_720M, "cb_mm_720m", CK_APMIXED_MMPLL, 1, 1), ++ PLL_FACTOR(CK_TOP_CB_MM_D2, "cb_mm_d2", CK_APMIXED_MMPLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_MM_D3, "cb_mm_d3", CK_APMIXED_MMPLL, 1, 3), ++ PLL_FACTOR(CK_TOP_CB_MM_D3_D5, "cb_mm_d3_d5", CK_APMIXED_MMPLL, 1, 15), ++ PLL_FACTOR(CK_TOP_CB_MM_D4, "cb_mm_d4", CK_APMIXED_MMPLL, 1, 4), ++ PLL_FACTOR(CK_TOP_CB_MM_D6, "cb_mm_d6", CK_APMIXED_MMPLL, 1, 6), ++ PLL_FACTOR(CK_TOP_MM_D6_D2, "mm_d6_d2", CK_APMIXED_MMPLL, 1, 12), ++ PLL_FACTOR(CK_TOP_CB_MM_D8, "cb_mm_d8", CK_APMIXED_MMPLL, 1, 8), ++ PLL_FACTOR(CK_TOP_CB_APLL2_196M, "cb_apll2_196m", CK_APMIXED_APLL2, 1, ++ 1), ++ PLL_FACTOR(CK_TOP_APLL2_D2, "apll2_d2", CK_APMIXED_APLL2, 1, 2), ++ PLL_FACTOR(CK_TOP_APLL2_D4, "apll2_d4", CK_APMIXED_APLL2, 1, 4), ++ PLL_FACTOR(CK_TOP_NET1_2500M, "net1_2500m", CK_APMIXED_NET1PLL, 1, 1), ++ PLL_FACTOR(CK_TOP_CB_NET1_D4, "cb_net1_d4", CK_APMIXED_NET1PLL, 1, 4), ++ PLL_FACTOR(CK_TOP_CB_NET1_D5, "cb_net1_d5", CK_APMIXED_NET1PLL, 1, 5), ++ PLL_FACTOR(CK_TOP_NET1_D5_D2, "net1_d5_d2", CK_APMIXED_NET1PLL, 1, 10), ++ PLL_FACTOR(CK_TOP_NET1_D5_D4, "net1_d5_d4", CK_APMIXED_NET1PLL, 1, 20), ++ PLL_FACTOR(CK_TOP_CB_NET1_D8, "cb_net1_d8", CK_APMIXED_NET1PLL, 1, 8), ++ PLL_FACTOR(CK_TOP_NET1_D8_D2, "net1_d8_d2", CK_APMIXED_NET1PLL, 1, 16), ++ PLL_FACTOR(CK_TOP_NET1_D8_D4, "net1_d8_d4", CK_APMIXED_NET1PLL, 1, 32), ++ PLL_FACTOR(CK_TOP_CB_NET2_800M, "cb_net2_800m", CK_APMIXED_NET2PLL, 1, ++ 1), ++ PLL_FACTOR(CK_TOP_CB_NET2_D2, "cb_net2_d2", CK_APMIXED_NET2PLL, 1, 2), ++ PLL_FACTOR(CK_TOP_CB_NET2_D4, "cb_net2_d4", CK_APMIXED_NET2PLL, 1, 4), ++ PLL_FACTOR(CK_TOP_NET2_D4_D2, "net2_d4_d2", CK_APMIXED_NET2PLL, 1, 8), ++ PLL_FACTOR(CK_TOP_NET2_D4_D4, "net2_d4_d4", CK_APMIXED_NET2PLL, 1, 16), ++ PLL_FACTOR(CK_TOP_CB_NET2_D6, "cb_net2_d6", CK_APMIXED_NET2PLL, 1, 6), ++ PLL_FACTOR(CK_TOP_CB_WEDMCU_208M, "cb_wedmcu_208m", ++ CK_APMIXED_WEDMCUPLL, 1, 1), ++ PLL_FACTOR(CK_TOP_CB_SGM_325M, "cb_sgm_325m", CK_APMIXED_SGMPLL, 1, 1), ++ TOP_FACTOR(CK_TOP_CKSQ_40M_D2, "cksq_40m_d2", CK_TOP_CB_CKSQ_40M, 1, 2), ++ TOP_FACTOR(CK_TOP_CB_RTC_32K, "cb_rtc_32k", CK_TOP_CB_CKSQ_40M, 1, ++ 1250), ++ TOP_FACTOR(CK_TOP_CB_RTC_32P7K, "cb_rtc_32p7k", CK_TOP_CB_CKSQ_40M, 1, ++ 1220), ++ TOP_FACTOR(CK_TOP_USB_TX250M, "usb_tx250m", CK_TOP_CB_CKSQ_40M, 1, 1), ++ TOP_FACTOR(CK_TOP_FAUD, "faud", CK_TOP_CB_CKSQ_40M, 1, 1), ++ TOP_FACTOR(CK_TOP_NFI1X, "nfi1x", CK_TOP_NFI1X_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_USB_EQ_RX250M, "usb_eq_rx250m", CK_TOP_CB_CKSQ_40M, 1, ++ 1), ++ TOP_FACTOR(CK_TOP_USB_CDR_CK, "usb_cdr", CK_TOP_CB_CKSQ_40M, 1, 1), ++ TOP_FACTOR(CK_TOP_USB_LN0_CK, "usb_ln0", CK_TOP_CB_CKSQ_40M, 1, 1), ++ TOP_FACTOR(CK_TOP_SPINFI_BCK, "spinfi_bck", CK_TOP_SPINFI_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_SPI, "spi", CK_TOP_SPI_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_SPIM_MST, "spim_mst", CK_TOP_SPIM_MST_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_UART_BCK, "uart_bck", CK_TOP_UART_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_PWM_BCK, "pwm_bck", CK_TOP_PWM_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_I2C_BCK, "i2c_bck", CK_TOP_I2C_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_PEXTP_TL, "pextp_tl", CK_TOP_PEXTP_TL_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_EMMC_208M, "emmc_208m", CK_TOP_EMMC_208M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_EMMC_400M, "emmc_400m", CK_TOP_EMMC_400M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_DRAMC_REF, "dramc_ref", CK_TOP_DRAMC_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_DRAMC_MD32, "dramc_md32", CK_TOP_DRAMC_MD32_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_TOP_SYSAXI, "sysaxi", CK_TOP_SYSAXI_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_SYSAPB, "sysapb", CK_TOP_SYSAPB_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_ARM_DB_MAIN, "arm_db_main", CK_TOP_ARM_DB_MAIN_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_TOP_AP2CNN_HOST, "ap2cnn_host", CK_TOP_AP2CNN_HOST_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_TOP_NETSYS, "netsys", CK_TOP_NETSYS_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_NETSYS_500M, "netsys_500m", CK_TOP_NETSYS_500M_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_TOP_NETSYS_WED_MCU, "netsys_wed_mcu", ++ CK_TOP_NETSYS_MCU_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_NETSYS_2X, "netsys_2x", CK_TOP_NETSYS_2X_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_SGM_325M, "sgm_325m", CK_TOP_SGM_325M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_SGM_REG, "sgm_reg", CK_TOP_SGM_REG_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_F26M, "csw_f26m", CK_TOP_F26M_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_EIP97B, "eip97b", CK_TOP_EIP97B_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_USB3_PHY, "usb3_phy", CK_TOP_USB3_PHY_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_AUD, "aud", CK_TOP_FAUD, 1, 1), ++ TOP_FACTOR(CK_TOP_A1SYS, "a1sys", CK_TOP_A1SYS_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_AUD_L, "aud_l", CK_TOP_AUD_L_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_A_TUNER, "a_tuner", CK_TOP_A_TUNER_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_U2U3_REF, "u2u3_ref", CK_TOP_U2U3_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_U2U3_SYS, "u2u3_sys", CK_TOP_U2U3_SYS_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_U2U3_XHCI, "u2u3_xhci", CK_TOP_U2U3_XHCI_SEL, 1, 1), ++ TOP_FACTOR(CK_TOP_USB_FRMCNT, "usb_frmcnt", CK_TOP_USB_FRMCNT_SEL, 1, ++ 1), ++}; ++ ++/* TOPCKGEN MUX PARENTS */ ++static const int nfi1x_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D4, ++ CK_TOP_NET1_D8_D2, CK_TOP_CB_NET2_D6, ++ CK_TOP_CB_M_D4, CK_TOP_CB_MM_D8, ++ CK_TOP_NET1_D8_D4, CK_TOP_CB_M_D8 }; ++ ++static const int spinfi_parents[] = { CK_TOP_CKSQ_40M_D2, CK_TOP_CB_CKSQ_40M, ++ CK_TOP_NET1_D5_D4, CK_TOP_CB_M_D4, ++ CK_TOP_CB_MM_D8, CK_TOP_NET1_D8_D4, ++ CK_TOP_MM_D6_D2, CK_TOP_CB_M_D8 }; ++ ++static const int spi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2, ++ CK_TOP_CB_MM_D4, CK_TOP_NET1_D8_D2, ++ CK_TOP_CB_NET2_D6, CK_TOP_NET1_D5_D4, ++ CK_TOP_CB_M_D4, CK_TOP_NET1_D8_D4 }; ++ ++static const int uart_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D8, ++ CK_TOP_M_D8_D2 }; ++ ++static const int pwm_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2, ++ CK_TOP_NET1_D5_D4, CK_TOP_CB_M_D4, ++ CK_TOP_M_D8_D2, CK_TOP_CB_RTC_32K }; ++ ++static const int i2c_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4, ++ CK_TOP_CB_M_D4, CK_TOP_NET1_D8_D4 }; ++ ++static const int pextp_tl_ck_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_NET1_D5_D4, CK_TOP_CB_M_D4, ++ CK_TOP_CB_RTC_32K }; ++ ++static const int emmc_208m_parents[] = { ++ CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2, CK_TOP_CB_NET2_D4, ++ CK_TOP_CB_APLL2_196M, CK_TOP_CB_MM_D4, CK_TOP_NET1_D8_D2, ++ CK_TOP_CB_MM_D6 ++}; ++ ++static const int emmc_400m_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET2_D2, ++ CK_TOP_CB_MM_D2, CK_TOP_CB_NET2_D2 }; ++ ++static const int csw_f26m_parents[] = { CK_TOP_CKSQ_40M_D2, CK_TOP_M_D8_D2 }; ++ ++static const int dramc_md32_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_M_D2, ++ CK_TOP_CB_WEDMCU_208M }; ++ ++static const int sysaxi_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D8_D2 }; ++ ++static const int sysapb_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D3_D2 }; ++ ++static const int arm_db_main_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_NET2_D6 }; ++ ++static const int ap2cnn_host_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_NET1_D8_D4 }; ++ ++static const int netsys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_D2 }; ++ ++static const int netsys_500m_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_NET1_D5 }; ++ ++static const int netsys_mcu_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_MM_720M, ++ CK_TOP_CB_NET1_D4, CK_TOP_CB_NET1_D5, ++ CK_TOP_CB_M_416M }; ++ ++static const int netsys_2x_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_NET2_800M, ++ CK_TOP_CB_MM_720M }; ++ ++static const int sgm_325m_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_SGM_325M }; ++ ++static const int sgm_reg_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET2_D4 }; ++ ++static const int eip97b_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_NET1_D5, ++ CK_TOP_CB_M_416M, CK_TOP_CB_MM_D2, ++ CK_TOP_NET1_D5_D2 }; ++ ++static const int aud_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_APLL2_196M }; ++ ++static const int a1sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4 }; ++ ++static const int aud_l_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_CB_APLL2_196M, ++ CK_TOP_M_D8_D2 }; ++ ++static const int a_tuner_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_APLL2_D4, ++ CK_TOP_M_D8_D2 }; ++ ++static const int u2u3_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_M_D8_D2 }; ++ ++static const int u2u3_sys_parents[] = { CK_TOP_CB_CKSQ_40M, CK_TOP_NET1_D5_D4 }; ++ ++static const int usb_frmcnt_parents[] = { CK_TOP_CB_CKSQ_40M, ++ CK_TOP_CB_MM_D3_D5 }; ++ ++#define TOP_MUX(_id, _name, _parents, _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \ ++ _shift, _width, _gate, _upd_ofs, _upd) \ ++ { \ ++ .id = _id, .mux_reg = _mux_ofs, .mux_set_reg = _mux_set_ofs, \ ++ .mux_clr_reg = _mux_clr_ofs, .upd_reg = _upd_ofs, \ ++ .upd_shift = _upd, .mux_shift = _shift, \ ++ .mux_mask = BIT(_width) - 1, .gate_reg = _mux_ofs, \ ++ .gate_shift = _gate, .parent = _parents, \ ++ .num_parents = ARRAY_SIZE(_parents), \ ++ .flags = CLK_MUX_SETCLR_UPD, \ ++ } ++ ++/* TOPCKGEN MUX_GATE */ ++static const struct mtk_composite top_muxes[] = { ++ TOP_MUX(CK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, 0x0, 0x4, 0x8, 0, ++ 3, 7, 0x1c0, 0), ++ TOP_MUX(CK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, 0x0, 0x4, 0x8, ++ 8, 3, 15, 0x1c0, 1), ++ TOP_MUX(CK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0, 0x4, 0x8, 16, 3, ++ 23, 0x1c0, 2), ++ TOP_MUX(CK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, 0x0, 0x4, 0x8, ++ 24, 3, 31, 0x1c0, 3), ++ TOP_MUX(CK_TOP_UART_SEL, "uart_sel", uart_parents, 0x10, 0x14, 0x18, 0, ++ 2, 7, 0x1c0, 4), ++ TOP_MUX(CK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x10, 0x14, 0x18, 8, 3, ++ 15, 0x1c0, 5), ++ TOP_MUX(CK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x10, 0x14, 0x18, 16, 2, ++ 23, 0x1c0, 6), ++ TOP_MUX(CK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", pextp_tl_ck_parents, ++ 0x10, 0x14, 0x18, 24, 2, 31, 0x1c0, 7), ++ TOP_MUX(CK_TOP_EMMC_208M_SEL, "emmc_208m_sel", emmc_208m_parents, 0x20, ++ 0x24, 0x28, 0, 3, 7, 0x1c0, 8), ++ TOP_MUX(CK_TOP_EMMC_400M_SEL, "emmc_400m_sel", emmc_400m_parents, 0x20, ++ 0x24, 0x28, 8, 2, 15, 0x1c0, 9), ++ TOP_MUX(CK_TOP_F26M_SEL, "csw_f26m_sel", csw_f26m_parents, 0x20, 0x24, ++ 0x28, 16, 1, 23, 0x1c0, 10), ++ TOP_MUX(CK_TOP_DRAMC_SEL, "dramc_sel", csw_f26m_parents, 0x20, 0x24, ++ 0x28, 24, 1, 31, 0x1c0, 11), ++ TOP_MUX(CK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", dramc_md32_parents, ++ 0x30, 0x34, 0x38, 0, 2, 7, 0x1c0, 12), ++ TOP_MUX(CK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, 0x30, 0x34, ++ 0x38, 8, 1, 15, 0x1c0, 13), ++ TOP_MUX(CK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, 0x30, 0x34, ++ 0x38, 16, 1, 23, 0x1c0, 14), ++ TOP_MUX(CK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", arm_db_main_parents, ++ 0x30, 0x34, 0x38, 24, 1, 31, 0x1c0, 15), ++ TOP_MUX(CK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", ap2cnn_host_parents, ++ 0x40, 0x44, 0x48, 0, 1, 7, 0x1c0, 16), ++ TOP_MUX(CK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, 0x40, 0x44, ++ 0x48, 8, 1, 15, 0x1c0, 17), ++ TOP_MUX(CK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", netsys_500m_parents, ++ 0x40, 0x44, 0x48, 16, 1, 23, 0x1c0, 18), ++ TOP_MUX(CK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", netsys_mcu_parents, ++ 0x40, 0x44, 0x48, 24, 3, 31, 0x1c0, 19), ++ TOP_MUX(CK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", netsys_2x_parents, 0x50, ++ 0x54, 0x58, 0, 2, 7, 0x1c0, 20), ++ TOP_MUX(CK_TOP_SGM_325M_SEL, "sgm_325m_sel", sgm_325m_parents, 0x50, ++ 0x54, 0x58, 8, 1, 15, 0x1c0, 21), ++ TOP_MUX(CK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents, 0x50, 0x54, ++ 0x58, 16, 1, 23, 0x1c0, 22), ++ TOP_MUX(CK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents, 0x50, 0x54, ++ 0x58, 24, 3, 31, 0x1c0, 23), ++ TOP_MUX(CK_TOP_USB3_PHY_SEL, "usb3_phy_sel", csw_f26m_parents, 0x60, ++ 0x64, 0x68, 0, 1, 7, 0x1c0, 24), ++ TOP_MUX(CK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x60, 0x64, 0x68, 8, 1, ++ 15, 0x1c0, 25), ++ TOP_MUX(CK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, 0x60, 0x64, 0x68, ++ 16, 1, 23, 0x1c0, 26), ++ TOP_MUX(CK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, 0x60, 0x64, 0x68, ++ 24, 2, 31, 0x1c0, 27), ++ TOP_MUX(CK_TOP_A_TUNER_SEL, "a_tuner_sel", a_tuner_parents, 0x70, 0x74, ++ 0x78, 0, 2, 7, 0x1c0, 28), ++ TOP_MUX(CK_TOP_U2U3_SEL, "u2u3_sel", u2u3_parents, 0x70, 0x74, 0x78, 8, ++ 1, 15, 0x1c0, 29), ++ TOP_MUX(CK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", u2u3_sys_parents, 0x70, ++ 0x74, 0x78, 16, 1, 23, 0x1c0, 30), ++ TOP_MUX(CK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", u2u3_sys_parents, 0x70, ++ 0x74, 0x78, 24, 1, 31, 0x1c4, 0), ++ TOP_MUX(CK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", usb_frmcnt_parents, ++ 0x80, 0x84, 0x88, 0, 1, 7, 0x1c4, 1), ++}; ++ ++/* INFRA FIXED DIV */ ++static const struct mtk_fixed_factor infra_fixed_divs[] = { ++ TOP_FACTOR(CK_INFRA_CK_F26M, "infra_ck_f26m", CK_TOP_F26M_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_UART, "infra_uart", CK_TOP_UART_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_ISPI0, "infra_ispi0", CK_TOP_SPI_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_I2C, "infra_i2c", CK_TOP_I2C_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_ISPI1, "infra_ispi1", CK_TOP_SPIM_MST_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_PWM, "infra_pwm", CK_TOP_PWM_SEL, 1, 1), ++ TOP_FACTOR(CK_INFRA_66M_MCK, "infra_66m_mck", CK_TOP_SYSAXI_SEL, 1, 2), ++ TOP_FACTOR(CK_INFRA_CK_F32K, "infra_ck_f32k", CK_TOP_CB_RTC_32P7K, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_PCIE_CK, "infra_pcie", CK_TOP_PEXTP_TL_SEL, 1, 1), ++ INFRA_FACTOR(CK_INFRA_PWM_BCK, "infra_pwm_bck", CK_INFRA_PWM_BSEL, 1, ++ 1), ++ INFRA_FACTOR(CK_INFRA_PWM_CK1, "infra_pwm_ck1", CK_INFRA_PWM1_SEL, 1, ++ 1), ++ INFRA_FACTOR(CK_INFRA_PWM_CK2, "infra_pwm_ck2", CK_INFRA_PWM2_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_133M_HCK, "infra_133m_hck", CK_TOP_SYSAXI, 1, 1), ++ INFRA_FACTOR(CK_INFRA_66M_PHCK, "infra_66m_phck", CK_INFRA_133M_HCK, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_FAUD_L_CK, "infra_faud_l", CK_TOP_AUD_L, 1, 1), ++ TOP_FACTOR(CK_INFRA_FAUD_AUD_CK, "infra_faud_aud", CK_TOP_A1SYS, 1, 1), ++ TOP_FACTOR(CK_INFRA_FAUD_EG2_CK, "infra_faud_eg2", CK_TOP_A_TUNER, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_I2CS_CK, "infra_i2cs", CK_TOP_I2C_BCK, 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_UART0, "infra_mux_uart0", CK_INFRA_UART0_SEL, ++ 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_UART1, "infra_mux_uart1", CK_INFRA_UART1_SEL, ++ 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_UART2, "infra_mux_uart2", CK_INFRA_UART2_SEL, ++ 1, 1), ++ TOP_FACTOR(CK_INFRA_NFI_CK, "infra_nfi", CK_TOP_NFI1X, 1, 1), ++ TOP_FACTOR(CK_INFRA_SPINFI_CK, "infra_spinfi", CK_TOP_SPINFI_BCK, 1, 1), ++ INFRA_FACTOR(CK_INFRA_MUX_SPI0, "infra_mux_spi0", CK_INFRA_SPI0_SEL, 1, ++ 1), ++ INFRA_FACTOR(CK_INFRA_MUX_SPI1, "infra_mux_spi1", CK_INFRA_SPI1_SEL, 1, ++ 1), ++ INFRA_FACTOR(CK_INFRA_MUX_SPI2, "infra_mux_spi2", CK_INFRA_SPI2_SEL, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_RTC_32K, "infra_rtc_32k", CK_TOP_CB_RTC_32K, 1, 1), ++ TOP_FACTOR(CK_INFRA_FMSDC_CK, "infra_fmsdc", CK_TOP_EMMC_400M, 1, 1), ++ TOP_FACTOR(CK_INFRA_FMSDC_HCK_CK, "infra_fmsdc_hck", CK_TOP_EMMC_208M, ++ 1, 1), ++ TOP_FACTOR(CK_INFRA_PERI_133M, "infra_peri_133m", CK_TOP_SYSAXI, 1, 1), ++ TOP_FACTOR(CK_INFRA_133M_PHCK, "infra_133m_phck", CK_TOP_SYSAXI, 1, 1), ++ TOP_FACTOR(CK_INFRA_USB_SYS_CK, "infra_usb_sys", CK_TOP_U2U3_SYS, 1, 1), ++ TOP_FACTOR(CK_INFRA_USB_CK, "infra_usb", CK_TOP_U2U3_REF, 1, 1), ++ TOP_FACTOR(CK_INFRA_USB_XHCI_CK, "infra_usb_xhci", CK_TOP_U2U3_XHCI, 1, ++ 1), ++ TOP_FACTOR(CK_INFRA_PCIE_GFMUX_TL_O_PRE, "infra_pcie_mux", ++ CK_TOP_PEXTP_TL, 1, 1), ++ TOP_FACTOR(CK_INFRA_F26M_CK0, "infra_f26m_ck0", CK_TOP_F26M, 1, 1), ++ TOP_FACTOR(CK_INFRA_133M_MCK, "infra_133m_mck", CK_TOP_SYSAXI, 1, 1), ++}; ++ ++/* INFRASYS MUX PARENTS */ ++static const int infra_uart0_parents[] = { CK_INFRA_CK_F26M, CK_INFRA_UART }; ++ ++static const int infra_spi0_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI0 }; ++ ++static const int infra_spi1_parents[] = { CK_INFRA_I2C, CK_INFRA_ISPI1 }; ++ ++static const int infra_pwm1_parents[] = { -1, -1, -1, CK_INFRA_PWM }; ++ ++static const int infra_pwm_bsel_parents[] = { -1, -1, -1, CK_INFRA_PWM }; ++ ++static const int infra_pcie_parents[] = { CK_INFRA_CK_F32K, CK_INFRA_CK_F26M, ++ CK_TOP_CB_CKSQ_40M, CK_INFRA_PCIE_CK}; ++ ++#define INFRA_MUX(_id, _name, _parents, _reg, _shift, _width) \ ++ { \ ++ .id = _id, .mux_reg = (_reg) + 0x8, \ ++ .mux_set_reg = (_reg) + 0x0, .mux_clr_reg = (_reg) + 0x4, \ ++ .mux_shift = _shift, .mux_mask = BIT(_width) - 1, \ ++ .parent = _parents, .num_parents = ARRAY_SIZE(_parents), \ ++ .flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_INFRASYS, \ ++ } ++ ++/* INFRA MUX */ ++static const struct mtk_composite infra_muxes[] = { ++ INFRA_MUX(CK_INFRA_UART0_SEL, "infra_uart0_sel", infra_uart0_parents, ++ 0x10, 0, 1), ++ INFRA_MUX(CK_INFRA_UART1_SEL, "infra_uart1_sel", infra_uart0_parents, ++ 0x10, 1, 1), ++ INFRA_MUX(CK_INFRA_UART2_SEL, "infra_uart2_sel", infra_uart0_parents, ++ 0x10, 2, 1), ++ INFRA_MUX(CK_INFRA_SPI0_SEL, "infra_spi0_sel", infra_spi0_parents, 0x10, ++ 4, 1), ++ INFRA_MUX(CK_INFRA_SPI1_SEL, "infra_spi1_sel", infra_spi1_parents, 0x10, ++ 5, 1), ++ INFRA_MUX(CK_INFRA_SPI2_SEL, "infra_spi2_sel", infra_spi0_parents, 0x10, ++ 6, 1), ++ INFRA_MUX(CK_INFRA_PWM1_SEL, "infra_pwm1_sel", infra_pwm1_parents, 0x10, ++ 9, 2), ++ INFRA_MUX(CK_INFRA_PWM2_SEL, "infra_pwm2_sel", infra_pwm1_parents, 0x10, ++ 11, 2), ++ INFRA_MUX(CK_INFRA_PWM_BSEL, "infra_pwm_bsel", infra_pwm_bsel_parents, ++ 0x10, 13, 2), ++ INFRA_MUX(CK_INFRA_PCIE_SEL, "infra_pcie_sel", infra_pcie_parents, 0x20, ++ 0, 2), ++}; ++ ++static const struct mtk_gate_regs infra_0_cg_regs = { ++ .set_ofs = 0x40, ++ .clr_ofs = 0x44, ++ .sta_ofs = 0x48, ++}; ++ ++static const struct mtk_gate_regs infra_1_cg_regs = { ++ .set_ofs = 0x50, ++ .clr_ofs = 0x54, ++ .sta_ofs = 0x58, ++}; ++ ++static const struct mtk_gate_regs infra_2_cg_regs = { ++ .set_ofs = 0x60, ++ .clr_ofs = 0x64, ++ .sta_ofs = 0x68, ++}; ++ ++#define GATE_INFRA0(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = &infra_0_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS, \ ++ } ++ ++#define GATE_INFRA1(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = &infra_1_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS, \ ++ } ++ ++#define GATE_INFRA2(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = &infra_2_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_SETCLR | CLK_PARENT_INFRASYS, \ ++ } ++ ++/* INFRA GATE */ ++static const struct mtk_gate infracfg_ao_gates[] = { ++ GATE_INFRA0(CK_INFRA_GPT_STA, "infra_gpt_sta", CK_INFRA_66M_MCK, 0), ++ GATE_INFRA0(CK_INFRA_PWM_HCK, "infra_pwm_hck", CK_INFRA_66M_MCK, 1), ++ GATE_INFRA0(CK_INFRA_PWM_STA, "infra_pwm_sta", CK_INFRA_PWM_BCK, 2), ++ GATE_INFRA0(CK_INFRA_PWM1_CK, "infra_pwm1", CK_INFRA_PWM_CK1, 3), ++ GATE_INFRA0(CK_INFRA_PWM2_CK, "infra_pwm2", CK_INFRA_PWM_CK2, 4), ++ GATE_INFRA0(CK_INFRA_CQ_DMA_CK, "infra_cq_dma", CK_INFRA_133M_HCK, 6), ++ GATE_INFRA0(CK_INFRA_AUD_BUS_CK, "infra_aud_bus", CK_INFRA_66M_PHCK, 8), ++ GATE_INFRA0(CK_INFRA_AUD_26M_CK, "infra_aud_26m", CK_INFRA_CK_F26M, 9), ++ GATE_INFRA0(CK_INFRA_AUD_L_CK, "infra_aud_l", CK_INFRA_FAUD_L_CK, 10), ++ GATE_INFRA0(CK_INFRA_AUD_AUD_CK, "infra_aud_aud", CK_INFRA_FAUD_AUD_CK, ++ 11), ++ GATE_INFRA0(CK_INFRA_AUD_EG2_CK, "infra_aud_eg2", CK_INFRA_FAUD_EG2_CK, ++ 13), ++ GATE_INFRA0(CK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", CK_INFRA_CK_F26M, ++ 14), ++ GATE_INFRA0(CK_INFRA_DBG_CK, "infra_dbg", CK_INFRA_66M_MCK, 15), ++ GATE_INFRA0(CK_INFRA_AP_DMA_CK, "infra_ap_dma", CK_INFRA_66M_MCK, 16), ++ GATE_INFRA0(CK_INFRA_SEJ_CK, "infra_sej", CK_INFRA_66M_MCK, 24), ++ GATE_INFRA0(CK_INFRA_SEJ_13M_CK, "infra_sej_13m", CK_INFRA_CK_F26M, 25), ++ GATE_INFRA1(CK_INFRA_THERM_CK, "infra_therm", CK_INFRA_CK_F26M, 0), ++ GATE_INFRA1(CK_INFRA_I2CO_CK, "infra_i2co", CK_INFRA_I2CS_CK, 1), ++ GATE_INFRA1(CK_INFRA_UART0_CK, "infra_uart0", CK_INFRA_MUX_UART0, 2), ++ GATE_INFRA1(CK_INFRA_UART1_CK, "infra_uart1", CK_INFRA_MUX_UART1, 3), ++ GATE_INFRA1(CK_INFRA_UART2_CK, "infra_uart2", CK_INFRA_MUX_UART2, 4), ++ GATE_INFRA1(CK_INFRA_SPI2_CK, "infra_spi2", CK_INFRA_MUX_SPI2, 6), ++ GATE_INFRA1(CK_INFRA_SPI2_HCK_CK, "infra_spi2_hck", CK_INFRA_66M_MCK, ++ 7), ++ GATE_INFRA1(CK_INFRA_NFI1_CK, "infra_nfi1", CK_INFRA_NFI_CK, 8), ++ GATE_INFRA1(CK_INFRA_SPINFI1_CK, "infra_spinfi1", CK_INFRA_SPINFI_CK, ++ 9), ++ GATE_INFRA1(CK_INFRA_NFI_HCK_CK, "infra_nfi_hck", CK_INFRA_66M_MCK, 10), ++ GATE_INFRA1(CK_INFRA_SPI0_CK, "infra_spi0", CK_INFRA_MUX_SPI0, 11), ++ GATE_INFRA1(CK_INFRA_SPI1_CK, "infra_spi1", CK_INFRA_MUX_SPI1, 12), ++ GATE_INFRA1(CK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", CK_INFRA_66M_MCK, ++ 13), ++ GATE_INFRA1(CK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", CK_INFRA_66M_MCK, ++ 14), ++ GATE_INFRA1(CK_INFRA_FRTC_CK, "infra_frtc", CK_INFRA_RTC_32K, 15), ++ GATE_INFRA1(CK_INFRA_MSDC_CK, "infra_msdc", CK_INFRA_FMSDC_CK, 16), ++ GATE_INFRA1(CK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", ++ CK_INFRA_FMSDC_HCK_CK, 17), ++ GATE_INFRA1(CK_INFRA_MSDC_133M_CK, "infra_msdc_133m", ++ CK_INFRA_PERI_133M, 18), ++ GATE_INFRA1(CK_INFRA_MSDC_66M_CK, "infra_msdc_66m", CK_INFRA_66M_PHCK, ++ 19), ++ GATE_INFRA1(CK_INFRA_ADC_26M_CK, "infra_adc_26m", CK_TOP_F26M, 20), ++ GATE_INFRA1(CK_INFRA_ADC_FRC_CK, "infra_adc_frc", CK_TOP_F26M, 21), ++ GATE_INFRA1(CK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", CK_INFRA_NFI_CK, ++ 23), ++ GATE_INFRA1(CK_INFRA_I2C_MCK_CK, "infra_i2c_mck", CK_INFRA_133M_MCK, ++ 25), ++ GATE_INFRA1(CK_INFRA_I2C_PCK_CK, "infra_i2c_pck", CK_INFRA_66M_MCK, 26), ++ GATE_INFRA2(CK_INFRA_IUSB_133_CK, "infra_iusb_133", CK_INFRA_133M_PHCK, ++ 0), ++ GATE_INFRA2(CK_INFRA_IUSB_66M_CK, "infra_iusb_66m", CK_INFRA_66M_PHCK, ++ 1), ++ GATE_INFRA2(CK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", CK_INFRA_USB_SYS_CK, ++ 2), ++ GATE_INFRA2(CK_INFRA_IUSB_CK, "infra_iusb", CK_INFRA_USB_CK, 3), ++ GATE_INFRA2(CK_INFRA_IPCIE_CK, "infra_ipcie", ++ CK_INFRA_PCIE_GFMUX_TL_O_PRE, 12), ++ GATE_INFRA2(CK_INFRA_IPCIER_CK, "infra_ipcier", CK_INFRA_F26M_CK0, 14), ++ GATE_INFRA2(CK_INFRA_IPCIEB_CK, "infra_ipcieb", CK_INFRA_133M_PHCK, 15), ++}; ++ ++static const struct mtk_clk_tree mt7981_fixed_pll_clk_tree = { ++ .fdivs_offs = CLK_APMIXED_NR_CLK, ++ .xtal_rate = 40 * MHZ, ++ .fclks = fixed_pll_clks, ++}; ++ ++static const struct mtk_clk_tree mt7981_topckgen_clk_tree = { ++ .fdivs_offs = CK_TOP_CB_M_416M, ++ .muxes_offs = CK_TOP_NFI1X_SEL, ++ .fclks = top_fixed_clks, ++ .fdivs = top_fixed_divs, ++ .muxes = top_muxes, ++ .flags = CLK_BYPASS_XTAL, ++}; ++ ++static const struct mtk_clk_tree mt7981_infracfg_clk_tree = { ++ .fdivs_offs = CK_INFRA_CK_F26M, ++ .muxes_offs = CK_INFRA_UART0_SEL, ++ .fdivs = infra_fixed_divs, ++ .muxes = infra_muxes, ++}; ++ ++static const struct udevice_id mt7981_fixed_pll_compat[] = { ++ { .compatible = "mediatek,mt7981-fixed-plls" }, ++ {} ++}; ++ ++static const struct udevice_id mt7981_topckgen_compat[] = { ++ { .compatible = "mediatek,mt7981-topckgen" }, ++ {} ++}; ++ ++static int mt7981_fixed_pll_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_init(dev, &mt7981_fixed_pll_clk_tree); ++} ++ ++static int mt7981_topckgen_probe(struct udevice *dev) ++{ ++ struct mtk_clk_priv *priv = dev_get_priv(dev); ++ ++ priv->base = dev_read_addr_ptr(dev); ++ writel(MT7981_CLK_PDN_EN_WRITE, priv->base + MT7981_CLK_PDN); ++ ++ return mtk_common_clk_init(dev, &mt7981_topckgen_clk_tree); ++} ++ ++U_BOOT_DRIVER(mtk_clk_apmixedsys) = { ++ .name = "mt7981-clock-fixed-pll", ++ .id = UCLASS_CLK, ++ .of_match = mt7981_fixed_pll_compat, ++ .probe = mt7981_fixed_pll_probe, ++ .priv_auto = sizeof(struct mtk_clk_priv), ++ .ops = &mtk_clk_topckgen_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++U_BOOT_DRIVER(mtk_clk_topckgen) = { ++ .name = "mt7981-clock-topckgen", ++ .id = UCLASS_CLK, ++ .of_match = mt7981_topckgen_compat, ++ .probe = mt7981_topckgen_probe, ++ .priv_auto = sizeof(struct mtk_clk_priv), ++ .ops = &mtk_clk_topckgen_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++static const struct udevice_id mt7981_infracfg_compat[] = { ++ { .compatible = "mediatek,mt7981-infracfg" }, ++ {} ++}; ++ ++static const struct udevice_id mt7981_infracfg_ao_compat[] = { ++ { .compatible = "mediatek,mt7981-infracfg_ao" }, ++ {} ++}; ++ ++static int mt7981_infracfg_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_init(dev, &mt7981_infracfg_clk_tree); ++} ++ ++static int mt7981_infracfg_ao_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_gate_init(dev, &mt7981_infracfg_clk_tree, ++ infracfg_ao_gates); ++} ++ ++U_BOOT_DRIVER(mtk_clk_infracfg) = { ++ .name = "mt7981-clock-infracfg", ++ .id = UCLASS_CLK, ++ .of_match = mt7981_infracfg_compat, ++ .probe = mt7981_infracfg_probe, ++ .priv_auto = sizeof(struct mtk_clk_priv), ++ .ops = &mtk_clk_infrasys_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++U_BOOT_DRIVER(mtk_clk_infracfg_ao) = { ++ .name = "mt7981-clock-infracfg-ao", ++ .id = UCLASS_CLK, ++ .of_match = mt7981_infracfg_ao_compat, ++ .probe = mt7981_infracfg_ao_probe, ++ .priv_auto = sizeof(struct mtk_cg_priv), ++ .ops = &mtk_clk_gate_ops, ++ .flags = DM_FLAG_PRE_RELOC, ++}; ++ ++/* ethsys */ ++static const struct mtk_gate_regs eth_cg_regs = { ++ .set_ofs = 0x30, ++ .clr_ofs = 0x30, ++ .sta_ofs = 0x30, ++}; ++ ++#define GATE_ETH(_id, _name, _parent, _shift) \ ++ { \ ++ .id = _id, .parent = _parent, .regs = ð_cg_regs, \ ++ .shift = _shift, \ ++ .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN, \ ++ } ++ ++static const struct mtk_gate eth_cgs[] = { ++ GATE_ETH(CK_ETH_FE_EN, "eth_fe_en", CK_TOP_NETSYS_2X, 6), ++ GATE_ETH(CK_ETH_GP2_EN, "eth_gp2_en", CK_TOP_SGM_325M, 7), ++ GATE_ETH(CK_ETH_GP1_EN, "eth_gp1_en", CK_TOP_SGM_325M, 8), ++ GATE_ETH(CK_ETH_WOCPU0_EN, "eth_wocpu0_en", CK_TOP_NETSYS_WED_MCU, 15), ++}; ++ ++static int mt7981_ethsys_probe(struct udevice *dev) ++{ ++ return mtk_common_clk_gate_init(dev, &mt7981_topckgen_clk_tree, ++ eth_cgs); ++} ++ ++static int mt7981_ethsys_bind(struct udevice *dev) ++{ ++ int ret = 0; ++ ++ if (CONFIG_IS_ENABLED(RESET_MEDIATEK)) { ++ ret = mediatek_reset_bind(dev, ETHSYS_HIFSYS_RST_CTRL_OFS, 1); ++ if (ret) ++ debug("Warning: failed to bind reset controller\n"); ++ } ++ ++ return ret; ++} ++ ++static const struct udevice_id mt7981_ethsys_compat[] = { ++ { .compatible = "mediatek,mt7981-ethsys", }, ++ {} ++}; ++ ++U_BOOT_DRIVER(mtk_clk_ethsys) = { ++ .name = "mt7981-clock-ethsys", ++ .id = UCLASS_CLK, ++ .of_match = mt7981_ethsys_compat, ++ .probe = mt7981_ethsys_probe, ++ .bind = mt7981_ethsys_bind, ++ .priv_auto = sizeof(struct mtk_cg_priv), ++ .ops = &mtk_clk_gate_ops, ++}; +--- /dev/null ++++ b/include/dt-bindings/clock/mt7981-clk.h +@@ -0,0 +1,267 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 MediaTek Inc. All rights reserved. ++ * ++ * Author: Sam Shih ++ */ ++ ++#ifndef _DT_BINDINGS_CLK_MT7981_H ++#define _DT_BINDINGS_CLK_MT7981_H ++ ++/* INFRACFG */ ++ ++#define CK_INFRA_CK_F26M 0 ++#define CK_INFRA_UART 1 ++#define CK_INFRA_ISPI0 2 ++#define CK_INFRA_I2C 3 ++#define CK_INFRA_ISPI1 4 ++#define CK_INFRA_PWM 5 ++#define CK_INFRA_66M_MCK 6 ++#define CK_INFRA_CK_F32K 7 ++#define CK_INFRA_PCIE_CK 8 ++#define CK_INFRA_PWM_BCK 9 ++#define CK_INFRA_PWM_CK1 10 ++#define CK_INFRA_PWM_CK2 11 ++#define CK_INFRA_133M_HCK 12 ++#define CK_INFRA_66M_PHCK 13 ++#define CK_INFRA_FAUD_L_CK 14 ++#define CK_INFRA_FAUD_AUD_CK 15 ++#define CK_INFRA_FAUD_EG2_CK 16 ++#define CK_INFRA_I2CS_CK 17 ++#define CK_INFRA_MUX_UART0 18 ++#define CK_INFRA_MUX_UART1 19 ++#define CK_INFRA_MUX_UART2 20 ++#define CK_INFRA_NFI_CK 21 ++#define CK_INFRA_SPINFI_CK 22 ++#define CK_INFRA_MUX_SPI0 23 ++#define CK_INFRA_MUX_SPI1 24 ++#define CK_INFRA_MUX_SPI2 25 ++#define CK_INFRA_RTC_32K 26 ++#define CK_INFRA_FMSDC_CK 27 ++#define CK_INFRA_FMSDC_HCK_CK 28 ++#define CK_INFRA_PERI_133M 29 ++#define CK_INFRA_133M_PHCK 30 ++#define CK_INFRA_USB_SYS_CK 31 ++#define CK_INFRA_USB_CK 32 ++#define CK_INFRA_USB_XHCI_CK 33 ++#define CK_INFRA_PCIE_GFMUX_TL_O_PRE 34 ++#define CK_INFRA_F26M_CK0 35 ++#define CK_INFRA_133M_MCK 36 ++#define CLK_INFRA_NR_CLK 37 ++ ++/* TOPCKGEN */ ++ ++#define CK_TOP_CB_CKSQ_40M 0 ++#define CK_TOP_CB_M_416M 1 ++#define CK_TOP_CB_M_D2 2 ++#define CK_TOP_CB_M_D3 3 ++#define CK_TOP_M_D3_D2 4 ++#define CK_TOP_CB_M_D4 5 ++#define CK_TOP_CB_M_D8 6 ++#define CK_TOP_M_D8_D2 7 ++#define CK_TOP_CB_MM_720M 8 ++#define CK_TOP_CB_MM_D2 9 ++#define CK_TOP_CB_MM_D3 10 ++#define CK_TOP_CB_MM_D3_D5 11 ++#define CK_TOP_CB_MM_D4 12 ++#define CK_TOP_CB_MM_D6 13 ++#define CK_TOP_MM_D6_D2 14 ++#define CK_TOP_CB_MM_D8 15 ++#define CK_TOP_CB_APLL2_196M 16 ++#define CK_TOP_APLL2_D2 17 ++#define CK_TOP_APLL2_D4 18 ++#define CK_TOP_NET1_2500M 19 ++#define CK_TOP_CB_NET1_D4 20 ++#define CK_TOP_CB_NET1_D5 21 ++#define CK_TOP_NET1_D5_D2 22 ++#define CK_TOP_NET1_D5_D4 23 ++#define CK_TOP_CB_NET1_D8 24 ++#define CK_TOP_NET1_D8_D2 25 ++#define CK_TOP_NET1_D8_D4 26 ++#define CK_TOP_CB_NET2_800M 27 ++#define CK_TOP_CB_NET2_D2 28 ++#define CK_TOP_CB_NET2_D4 29 ++#define CK_TOP_NET2_D4_D2 30 ++#define CK_TOP_NET2_D4_D4 31 ++#define CK_TOP_CB_NET2_D6 32 ++#define CK_TOP_CB_WEDMCU_208M 33 ++#define CK_TOP_CB_SGM_325M 34 ++#define CK_TOP_CKSQ_40M_D2 35 ++#define CK_TOP_CB_RTC_32K 36 ++#define CK_TOP_CB_RTC_32P7K 37 ++#define CK_TOP_USB_TX250M 38 ++#define CK_TOP_FAUD 39 ++#define CK_TOP_NFI1X 40 ++#define CK_TOP_USB_EQ_RX250M 41 ++#define CK_TOP_USB_CDR_CK 42 ++#define CK_TOP_USB_LN0_CK 43 ++#define CK_TOP_SPINFI_BCK 44 ++#define CK_TOP_SPI 45 ++#define CK_TOP_SPIM_MST 46 ++#define CK_TOP_UART_BCK 47 ++#define CK_TOP_PWM_BCK 48 ++#define CK_TOP_I2C_BCK 49 ++#define CK_TOP_PEXTP_TL 50 ++#define CK_TOP_EMMC_208M 51 ++#define CK_TOP_EMMC_400M 52 ++#define CK_TOP_DRAMC_REF 53 ++#define CK_TOP_DRAMC_MD32 54 ++#define CK_TOP_SYSAXI 55 ++#define CK_TOP_SYSAPB 56 ++#define CK_TOP_ARM_DB_MAIN 57 ++#define CK_TOP_AP2CNN_HOST 58 ++#define CK_TOP_NETSYS 59 ++#define CK_TOP_NETSYS_500M 60 ++#define CK_TOP_NETSYS_WED_MCU 61 ++#define CK_TOP_NETSYS_2X 62 ++#define CK_TOP_SGM_325M 63 ++#define CK_TOP_SGM_REG 64 ++#define CK_TOP_F26M 65 ++#define CK_TOP_EIP97B 66 ++#define CK_TOP_USB3_PHY 67 ++#define CK_TOP_AUD 68 ++#define CK_TOP_A1SYS 69 ++#define CK_TOP_AUD_L 70 ++#define CK_TOP_A_TUNER 71 ++#define CK_TOP_U2U3_REF 72 ++#define CK_TOP_U2U3_SYS 73 ++#define CK_TOP_U2U3_XHCI 74 ++#define CK_TOP_USB_FRMCNT 75 ++#define CK_TOP_NFI1X_SEL 76 ++#define CK_TOP_SPINFI_SEL 77 ++#define CK_TOP_SPI_SEL 78 ++#define CK_TOP_SPIM_MST_SEL 79 ++#define CK_TOP_UART_SEL 80 ++#define CK_TOP_PWM_SEL 81 ++#define CK_TOP_I2C_SEL 82 ++#define CK_TOP_PEXTP_TL_SEL 83 ++#define CK_TOP_EMMC_208M_SEL 84 ++#define CK_TOP_EMMC_400M_SEL 85 ++#define CK_TOP_F26M_SEL 86 ++#define CK_TOP_DRAMC_SEL 87 ++#define CK_TOP_DRAMC_MD32_SEL 88 ++#define CK_TOP_SYSAXI_SEL 89 ++#define CK_TOP_SYSAPB_SEL 90 ++#define CK_TOP_ARM_DB_MAIN_SEL 91 ++#define CK_TOP_AP2CNN_HOST_SEL 92 ++#define CK_TOP_NETSYS_SEL 93 ++#define CK_TOP_NETSYS_500M_SEL 94 ++#define CK_TOP_NETSYS_MCU_SEL 95 ++#define CK_TOP_NETSYS_2X_SEL 96 ++#define CK_TOP_SGM_325M_SEL 97 ++#define CK_TOP_SGM_REG_SEL 98 ++#define CK_TOP_EIP97B_SEL 99 ++#define CK_TOP_USB3_PHY_SEL 100 ++#define CK_TOP_AUD_SEL 101 ++#define CK_TOP_A1SYS_SEL 102 ++#define CK_TOP_AUD_L_SEL 103 ++#define CK_TOP_A_TUNER_SEL 104 ++#define CK_TOP_U2U3_SEL 105 ++#define CK_TOP_U2U3_SYS_SEL 106 ++#define CK_TOP_U2U3_XHCI_SEL 107 ++#define CK_TOP_USB_FRMCNT_SEL 108 ++#define CLK_TOP_NR_CLK 109 ++ ++/* ++ * INFRACFG_AO ++ * clock muxes need to be append to infracfg domain, and clock gates ++ * need to be keep in infracgh_ao domain ++ */ ++#define INFRACFG_AO_OFFSET 10 ++ ++#define CK_INFRA_UART0_SEL (0 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_UART1_SEL (1 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_UART2_SEL (2 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_SPI0_SEL (3 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_SPI1_SEL (4 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_SPI2_SEL (5 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PWM1_SEL (6 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PWM2_SEL (7 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PWM_BSEL (8 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_PCIE_SEL (9 + CLK_INFRA_NR_CLK) ++#define CK_INFRA_GPT_STA (10 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_PWM_HCK (11 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_PWM_STA (12 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_PWM1_CK (13 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_PWM2_CK (14 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_CQ_DMA_CK (15 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_AUD_BUS_CK (16 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_AUD_26M_CK (17 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_AUD_L_CK (18 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_AUD_AUD_CK (19 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_AUD_EG2_CK (20 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_DRAMC_26M_CK (21 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_DBG_CK (22 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_AP_DMA_CK (23 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SEJ_CK (24 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SEJ_13M_CK (25 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_THERM_CK (26 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_I2CO_CK (27 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_UART0_CK (28 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_UART1_CK (29 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_UART2_CK (30 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SPI2_CK (31 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SPI2_HCK_CK (32 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_NFI1_CK (33 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SPINFI1_CK (34 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_NFI_HCK_CK (35 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SPI0_CK (36 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SPI1_CK (37 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SPI0_HCK_CK (38 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_SPI1_HCK_CK (39 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_FRTC_CK (40 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_MSDC_CK (41 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_MSDC_HCK_CK (42 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_MSDC_133M_CK (43 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_MSDC_66M_CK (44 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_ADC_26M_CK (45 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_ADC_FRC_CK (46 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_FBIST2FPC_CK (47 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_I2C_MCK_CK (48 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_I2C_PCK_CK (49 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_IUSB_133_CK (50 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_IUSB_66M_CK (51 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_IUSB_SYS_CK (52 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_IUSB_CK (53 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_IPCIE_CK (54 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_IPCIER_CK (55 - INFRACFG_AO_OFFSET) ++#define CK_INFRA_IPCIEB_CK (56 - INFRACFG_AO_OFFSET) ++#define CLK_INFRA_AO_NR_CLK (57 - INFRACFG_AO_OFFSET) ++ ++/* APMIXEDSYS */ ++ ++#define CK_APMIXED_ARMPLL 0 ++#define CK_APMIXED_NET2PLL 1 ++#define CK_APMIXED_MMPLL 2 ++#define CK_APMIXED_SGMPLL 3 ++#define CK_APMIXED_WEDMCUPLL 4 ++#define CK_APMIXED_NET1PLL 5 ++#define CK_APMIXED_MPLL 6 ++#define CK_APMIXED_APLL2 7 ++#define CLK_APMIXED_NR_CLK 8 ++ ++/* SGMIISYS_0 */ ++ ++#define CK_SGM0_TX_EN 0 ++#define CK_SGM0_RX_EN 1 ++#define CK_SGM0_CK0_EN 2 ++#define CK_SGM0_CDR_CK0_EN 3 ++#define CLK_SGMII0_NR_CLK 4 ++ ++/* SGMIISYS_1 */ ++ ++#define CK_SGM1_TX_EN 0 ++#define CK_SGM1_RX_EN 1 ++#define CK_SGM1_CK1_EN 2 ++#define CK_SGM1_CDR_CK1_EN 3 ++#define CLK_SGMII1_NR_CLK 4 ++ ++/* ETHSYS */ ++ ++#define CK_ETH_FE_EN 0 ++#define CK_ETH_GP2_EN 1 ++#define CK_ETH_GP1_EN 2 ++#define CK_ETH_WOCPU0_EN 3 ++#define CLK_ETH_NR_CLK 4 ++ ++#endif /* _DT_BINDINGS_CLK_MT7981_H */ diff --git a/package/boot/uboot-mediatek/patches/002-0028-tools-mtk_image-split-gfh-header-verification-into-a.patch b/package/boot/uboot-mediatek/patches/002-0028-tools-mtk_image-split-gfh-header-verification-into-a.patch new file mode 100644 index 0000000000..c8747ae154 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0028-tools-mtk_image-split-gfh-header-verification-into-a.patch @@ -0,0 +1,89 @@ +From b6bb61fd3818f4a3025fedbe4d15dbeeaef6ee82 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Tue, 2 Aug 2022 17:21:34 +0800 +Subject: [PATCH 28/31] tools: mtk_image: split gfh header verification into a + new function + +The verification code of gfh header for NAND and non-NAND are identical. +It's better to define a individual function to reduce redundancy. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + tools/mtk_image.c | 51 +++++++++++++++++++---------------------------- + 1 file changed, 21 insertions(+), 30 deletions(-) + +--- a/tools/mtk_image.c ++++ b/tools/mtk_image.c +@@ -480,6 +480,25 @@ static int mtk_image_vrec_header(struct + return SHA256_SUM_LEN; + } + ++static int mtk_image_verify_gfh(struct gfh_header *gfh, uint32_t type, int print) ++{ ++ if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME)) ++ return -1; ++ ++ if (le32_to_cpu(gfh->file_info.flash_type) != type) ++ return -1; ++ ++ if (print) ++ printf("Load Address: %08x\n", ++ le32_to_cpu(gfh->file_info.load_addr) + ++ le32_to_cpu(gfh->file_info.jump_offset)); ++ ++ if (print) ++ printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM"); ++ ++ return 0; ++} ++ + static int mtk_image_verify_gen_header(const uint8_t *ptr, int print) + { + union gen_boot_header *gbh = (union gen_boot_header *)ptr; +@@ -542,21 +561,7 @@ static int mtk_image_verify_gen_header(c + + gfh = (struct gfh_header *)(ptr + gfh_offset); + +- if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME)) +- return -1; +- +- if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN) +- return -1; +- +- if (print) +- printf("Load Address: %08x\n", +- le32_to_cpu(gfh->file_info.load_addr) + +- le32_to_cpu(gfh->file_info.jump_offset)); +- +- if (print) +- printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM"); +- +- return 0; ++ return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print); + } + + static int mtk_image_verify_nand_header(const uint8_t *ptr, int print) +@@ -610,21 +615,7 @@ static int mtk_image_verify_nand_header( + + gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize)); + +- if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME)) +- return -1; +- +- if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND) +- return -1; +- +- if (print) +- printf("Load Address: %08x\n", +- le32_to_cpu(gfh->file_info.load_addr) + +- le32_to_cpu(gfh->file_info.jump_offset)); +- +- if (print) +- printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM"); +- +- return 0; ++ return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print); + } + + static uint32_t crc32be_cal(const void *data, size_t length) diff --git a/package/boot/uboot-mediatek/patches/002-0029-tools-mtk_image-split-the-code-of-generating-NAND-he.patch b/package/boot/uboot-mediatek/patches/002-0029-tools-mtk_image-split-the-code-of-generating-NAND-he.patch new file mode 100644 index 0000000000..9a5332f695 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0029-tools-mtk_image-split-the-code-of-generating-NAND-he.patch @@ -0,0 +1,821 @@ +From 20ebf03eab571b25e9f62b2764ab84932111dcd6 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Tue, 2 Aug 2022 17:23:57 +0800 +Subject: [PATCH 29/31] tools: mtk_image: split the code of generating NAND + header into a new file + +The predefined NAND headers take too much spaces in the mtk_image.c. +Moving them into a new file can significantly improve the readability of +both mtk_image.c and the new mtk_nand_headers.c. + +This is a preparation for adding more NAND headers. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + tools/Makefile | 1 + + tools/mtk_image.c | 305 ++++++--------------------------------- + tools/mtk_image.h | 25 ---- + tools/mtk_nand_headers.c | 286 ++++++++++++++++++++++++++++++++++++ + tools/mtk_nand_headers.h | 61 ++++++++ + 5 files changed, 389 insertions(+), 289 deletions(-) + create mode 100644 tools/mtk_nand_headers.c + create mode 100644 tools/mtk_nand_headers.h + +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -147,6 +147,7 @@ dumpimage-mkimage-objs := aisimage.o \ + gpimage.o \ + gpimage-common.o \ + mtk_image.o \ ++ mtk_nand_headers.o \ + $(ECDSA_OBJS-y) \ + $(RSA_OBJS-y) \ + $(AES_OBJS-y) +--- a/tools/mtk_image.c ++++ b/tools/mtk_image.c +@@ -12,216 +12,7 @@ + #include + #include "imagetool.h" + #include "mtk_image.h" +- +-/* NAND header for SPI-NAND with 2KB page + 64B spare */ +-static const union nand_boot_header snand_hdr_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D, +- 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7, +- 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8, +- 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00 +- } +-}; +- +-/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */ +-static const union nand_boot_header snand_hdr_2k_128_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13, +- 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3, +- 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7, +- 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00 +- } +-}; +- +-/* NAND header for SPI-NAND with 4KB page + 256B spare */ +-static const union nand_boot_header snand_hdr_4k_256_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3, +- 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57, +- 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F, +- 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */ +-static const union nand_boot_header nand_hdr_1gb_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12, +- 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C, +- 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82, +- 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */ +-static const union nand_boot_header nand_hdr_2gb_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D, +- 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1, +- 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95, +- 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */ +-static const union nand_boot_header nand_hdr_4gb_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32, +- 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B, +- 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87, +- 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */ +-static const union nand_boot_header nand_hdr_2gb_2k_128_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A, +- 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC, +- 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0, +- 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */ +-static const union nand_boot_header nand_hdr_4gb_2k_128_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, +- 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45, +- 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46, +- 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2, +- 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00 +- } +-}; +- +-static const struct nand_header_type { +- const char *name; +- const union nand_boot_header *data; +-} nand_headers[] = { +- { +- .name = "2k+64", +- .data = &snand_hdr_2k_64_data +- }, { +- .name = "2k+120", +- .data = &snand_hdr_2k_128_data +- }, { +- .name = "2k+128", +- .data = &snand_hdr_2k_128_data +- }, { +- .name = "4k+256", +- .data = &snand_hdr_4k_256_data +- }, { +- .name = "1g:2k+64", +- .data = &nand_hdr_1gb_2k_64_data +- }, { +- .name = "2g:2k+64", +- .data = &nand_hdr_2gb_2k_64_data +- }, { +- .name = "4g:2k+64", +- .data = &nand_hdr_4gb_2k_64_data +- }, { +- .name = "2g:2k+128", +- .data = &nand_hdr_2gb_2k_128_data +- }, { +- .name = "4g:2k+128", +- .data = &nand_hdr_4gb_2k_128_data +- } +-}; ++#include "mtk_nand_headers.h" + + static const struct brom_img_type { + const char *name; +@@ -264,6 +55,7 @@ static uint32_t crc32tbl[256]; + + /* NAND header selected by user */ + static const union nand_boot_header *hdr_nand; ++static uint32_t hdr_nand_size; + + /* GFH header + 2 * 4KB pages of NAND */ + static char hdr_tmp[sizeof(struct gfh_header) + 0x2000]; +@@ -402,12 +194,7 @@ static int mtk_brom_parse_imagename(cons + } + + /* parse nand header type */ +- for (i = 0; i < ARRAY_SIZE(nand_headers); i++) { +- if (!strcmp(nand_headers[i].name, nandinfo)) { +- hdr_nand = nand_headers[i].data; +- break; +- } +- } ++ hdr_nand = mtk_nand_header_find(nandinfo); + + /* parse device header offset */ + if (hdr_offs && hdr_offs[0]) +@@ -432,6 +219,9 @@ static int mtk_brom_parse_imagename(cons + return -EINVAL; + } + ++ if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) ++ hdr_nand_size = mtk_nand_header_size(hdr_nand); ++ + return 0; + } + +@@ -468,7 +258,7 @@ static int mtk_image_vrec_header(struct + } + + if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) +- tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize); ++ tparams->header_size = hdr_nand_size; + else + tparams->header_size = sizeof(struct gen_device_header); + +@@ -566,16 +356,17 @@ static int mtk_image_verify_gen_header(c + + static int mtk_image_verify_nand_header(const uint8_t *ptr, int print) + { +- union nand_boot_header *nh = (union nand_boot_header *)ptr; + struct brom_layout_header *bh; ++ struct nand_header_info info; + struct gfh_header *gfh; + const char *bootmedia; ++ int ret; + +- if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) || +- strcmp(nh->id, NAND_BOOT_ID)) +- return -1; ++ ret = mtk_nand_header_info(ptr, &info); ++ if (ret < 0) ++ return ret; + +- bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize)); ++ bh = (struct brom_layout_header *)(ptr + info.page_size); + + if (strcmp(bh->name, BRLYT_NAME)) + return -1; +@@ -586,34 +377,23 @@ static int mtk_image_verify_nand_header( + if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) + bootmedia = "Parallel NAND"; + else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND) +- bootmedia = "Serial NAND"; ++ bootmedia = "Serial NAND (SNFI/AP)"; + else + return -1; + } + + if (print) { +- printf("Boot Media: %s\n", bootmedia); +- +- if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) { +- uint64_t capacity = +- (uint64_t)le16_to_cpu(nh->numblocks) * +- (uint64_t)le16_to_cpu(nh->pages_of_block) * +- (uint64_t)le16_to_cpu(nh->pagesize) * 8; +- printf("Capacity: %dGb\n", +- (uint32_t)(capacity >> 30)); +- } ++ printf("Boot Media: %s\n", bootmedia); + +- if (le16_to_cpu(nh->pagesize) >= 1024) +- printf("Page Size: %dKB\n", +- le16_to_cpu(nh->pagesize) >> 10); ++ if (info.page_size >= 1024) ++ printf("Page Size: %dKB\n", info.page_size >> 10); + else +- printf("Page Size: %dB\n", +- le16_to_cpu(nh->pagesize)); ++ printf("Page Size: %dB\n", info.page_size); + +- printf("Spare Size: %dB\n", le16_to_cpu(nh->oobsize)); ++ printf("Spare Size: %dB\n", info.spare_size); + } + +- gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize)); ++ gfh = (struct gfh_header *)(ptr + info.gfh_offset); + + return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print); + } +@@ -713,7 +493,7 @@ static int mtk_image_verify_header(unsig + if (image_get_magic(hdr) == IH_MAGIC) + return mtk_image_verify_mt7621_header(ptr, 0); + +- if (!strcmp((char *)ptr, NAND_BOOT_NAME)) ++ if (is_mtk_nand_header(ptr)) + return mtk_image_verify_nand_header(ptr, 0); + else + return mtk_image_verify_gen_header(ptr, 0); +@@ -739,7 +519,7 @@ static void mtk_image_print_header(const + return; + } + +- if (!strcmp((char *)ptr, NAND_BOOT_NAME)) ++ if (is_mtk_nand_header(ptr)) + mtk_image_verify_nand_header(ptr, 1); + else + mtk_image_verify_gen_header(ptr, 1); +@@ -870,36 +650,33 @@ static void mtk_image_set_gen_header(voi + static void mtk_image_set_nand_header(void *ptr, off_t filesize, + uint32_t loadaddr) + { +- union nand_boot_header *nh = (union nand_boot_header *)ptr; + struct brom_layout_header *brlyt; + struct gfh_header *gfh; +- uint32_t payload_pages; +- int i; ++ uint32_t payload_pages, nand_page_size; + +- /* NAND device header, repeat 4 times */ +- for (i = 0; i < 4; i++) +- memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header)); ++ /* NAND header */ ++ nand_page_size = mtk_nand_header_put(hdr_nand, ptr); + +- /* BRLYT header */ +- payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) / +- le16_to_cpu(hdr_nand->pagesize); +- brlyt = (struct brom_layout_header *) +- (ptr + le16_to_cpu(hdr_nand->pagesize)); +- put_brom_layout_header(brlyt, hdr_media); +- brlyt->header_size = cpu_to_le32(2); +- brlyt->total_size = cpu_to_le32(payload_pages); +- brlyt->header_size_2 = brlyt->header_size; +- brlyt->total_size_2 = brlyt->total_size; +- brlyt->unused = cpu_to_le32(1); ++ if (nand_page_size) { ++ /* BRLYT header */ ++ payload_pages = (filesize + nand_page_size - 1) / ++ nand_page_size; ++ brlyt = (struct brom_layout_header *)(ptr + nand_page_size); ++ put_brom_layout_header(brlyt, hdr_media); ++ brlyt->header_size = cpu_to_le32(2); ++ brlyt->total_size = cpu_to_le32(payload_pages); ++ brlyt->header_size_2 = brlyt->header_size; ++ brlyt->total_size_2 = brlyt->total_size; ++ brlyt->unused = cpu_to_le32(1); ++ } + + /* GFH header */ +- gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize)); +- put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize), +- loadaddr, GFH_FLASH_TYPE_NAND); ++ gfh = (struct gfh_header *)(ptr + hdr_nand_size); ++ put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr, ++ GFH_FLASH_TYPE_NAND); + + /* Generate SHA256 hash */ +- put_hash((uint8_t *)gfh, +- filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN); ++ put_hash((uint8_t *)gfh, filesize - hdr_nand_size - SHA256_SUM_LEN); + } + + static void mtk_image_set_mt7621_header(void *ptr, off_t filesize, +--- a/tools/mtk_image.h ++++ b/tools/mtk_image.h +@@ -26,31 +26,6 @@ union gen_boot_header { + #define SF_BOOT_NAME "SF_BOOT" + #define SDMMC_BOOT_NAME "SDMMC_BOOT" + +-/* Header for NAND */ +-union nand_boot_header { +- struct { +- char name[12]; +- char version[4]; +- char id[8]; +- uint16_t ioif; +- uint16_t pagesize; +- uint16_t addrcycles; +- uint16_t oobsize; +- uint16_t pages_of_block; +- uint16_t numblocks; +- uint16_t writesize_shift; +- uint16_t erasesize_shift; +- uint8_t dummy[60]; +- uint8_t ecc_parity[28]; +- }; +- +- uint8_t data[0x80]; +-}; +- +-#define NAND_BOOT_NAME "BOOTLOADER!" +-#define NAND_BOOT_VERSION "V006" +-#define NAND_BOOT_ID "NFIINFO" +- + /* BootROM layout header */ + struct brom_layout_header { + char name[8]; +--- /dev/null ++++ b/tools/mtk_nand_headers.c +@@ -0,0 +1,286 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * MediaTek BootROM NAND header definitions ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Weijie Gao ++ */ ++ ++#include ++#include ++#include "imagetool.h" ++#include "mtk_image.h" ++#include "mtk_nand_headers.h" ++ ++/* NAND header for SPI-NAND with 2KB page + 64B spare */ ++static const union nand_boot_header snand_hdr_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D, ++ 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7, ++ 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8, ++ 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */ ++static const union nand_boot_header snand_hdr_2k_128_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13, ++ 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3, ++ 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7, ++ 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for SPI-NAND with 4KB page + 256B spare */ ++static const union nand_boot_header snand_hdr_4k_256_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3, ++ 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57, ++ 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F, ++ 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */ ++static const union nand_boot_header nand_hdr_1gb_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12, ++ 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C, ++ 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82, ++ 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */ ++static const union nand_boot_header nand_hdr_2gb_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D, ++ 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1, ++ 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95, ++ 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */ ++static const union nand_boot_header nand_hdr_4gb_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32, ++ 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B, ++ 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87, ++ 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */ ++static const union nand_boot_header nand_hdr_2gb_2k_128_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A, ++ 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC, ++ 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0, ++ 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */ ++static const union nand_boot_header nand_hdr_4gb_2k_128_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, ++ 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45, ++ 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46, ++ 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2, ++ 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00 ++ } ++}; ++ ++static const struct nand_header_type { ++ const char *name; ++ const union nand_boot_header *data; ++} nand_headers[] = { ++ { ++ .name = "2k+64", ++ .data = &snand_hdr_2k_64_data ++ }, { ++ .name = "2k+120", ++ .data = &snand_hdr_2k_128_data ++ }, { ++ .name = "2k+128", ++ .data = &snand_hdr_2k_128_data ++ }, { ++ .name = "4k+256", ++ .data = &snand_hdr_4k_256_data ++ }, { ++ .name = "1g:2k+64", ++ .data = &nand_hdr_1gb_2k_64_data ++ }, { ++ .name = "2g:2k+64", ++ .data = &nand_hdr_2gb_2k_64_data ++ }, { ++ .name = "4g:2k+64", ++ .data = &nand_hdr_4gb_2k_64_data ++ }, { ++ .name = "2g:2k+128", ++ .data = &nand_hdr_2gb_2k_128_data ++ }, { ++ .name = "4g:2k+128", ++ .data = &nand_hdr_4gb_2k_128_data ++ } ++}; ++ ++const union nand_boot_header *mtk_nand_header_find(const char *name) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(nand_headers); i++) { ++ if (!strcmp(nand_headers[i].name, name)) ++ return nand_headers[i].data; ++ } ++ ++ return NULL; ++} ++ ++uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand) ++{ ++ return 2 * le16_to_cpu(hdr_nand->pagesize); ++} ++ ++static int mtk_nand_header_ap_info(const void *ptr, ++ struct nand_header_info *info) ++{ ++ union nand_boot_header *nh = (union nand_boot_header *)ptr; ++ ++ if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) || ++ strcmp(nh->id, NAND_BOOT_ID)) ++ return -1; ++ ++ info->page_size = le16_to_cpu(nh->pagesize); ++ info->spare_size = le16_to_cpu(nh->oobsize); ++ info->gfh_offset = 2 * info->page_size; ++ ++ return 0; ++} ++ ++int mtk_nand_header_info(const void *ptr, struct nand_header_info *info) ++{ ++ if (!strcmp((char *)ptr, NAND_BOOT_NAME)) ++ return mtk_nand_header_ap_info(ptr, info); ++ ++ return -1; ++} ++ ++bool is_mtk_nand_header(const void *ptr) ++{ ++ struct nand_header_info info; ++ ++ if (mtk_nand_header_info(ptr, &info) >= 0) ++ return true; ++ ++ return false; ++} ++ ++uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr) ++{ ++ union nand_boot_header *nh = (union nand_boot_header *)ptr; ++ int i; ++ ++ /* NAND device header, repeat 4 times */ ++ for (i = 0; i < 4; i++) ++ memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header)); ++ ++ return le16_to_cpu(hdr_nand->pagesize); ++} +--- /dev/null ++++ b/tools/mtk_nand_headers.h +@@ -0,0 +1,61 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * MediaTek BootROM NAND header definitions ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Weijie Gao ++ */ ++ ++#ifndef _MTK_NAND_HEADERS_H ++#define _MTK_NAND_HEADERS_H ++ ++#include ++#include ++ ++struct nand_header_info { ++ uint32_t page_size; ++ uint32_t spare_size; ++ uint32_t gfh_offset; ++}; ++ ++/* AP BROM Header for NAND */ ++union nand_boot_header { ++ struct { ++ char name[12]; ++ char version[4]; ++ char id[8]; ++ uint16_t ioif; /* I/O interface */ ++ uint16_t pagesize; /* NAND page size */ ++ uint16_t addrcycles; /* Address cycles */ ++ uint16_t oobsize; /* NAND page spare size */ ++ uint16_t pages_of_block; /* Pages of one block */ ++ uint16_t numblocks; /* Total blocks of NAND chip */ ++ uint16_t writesize_shift; ++ uint16_t erasesize_shift; ++ uint8_t dummy[60]; ++ uint8_t ecc_parity[28]; /* ECC parity of this header */ ++ }; ++ ++ uint8_t data[0x80]; ++}; ++ ++#define NAND_BOOT_NAME "BOOTLOADER!" ++#define NAND_BOOT_VERSION "V006" ++#define NAND_BOOT_ID "NFIINFO" ++ ++/* Find nand header data by name */ ++const union nand_boot_header *mtk_nand_header_find(const char *name); ++ ++/* Device header size using this nand header */ ++uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand); ++ ++/* Get nand info from nand header (page size, spare size, ...) */ ++int mtk_nand_header_info(const void *ptr, struct nand_header_info *info); ++ ++/* Whether given header data is valid */ ++bool is_mtk_nand_header(const void *ptr); ++ ++/* Generate Device header using give nand header */ ++uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr); ++ ++#endif /* _MTK_NAND_HEADERS_H */ diff --git a/package/boot/uboot-mediatek/patches/002-0030-tools-mtk_image-add-support-for-nand-headers-used-by.patch b/package/boot/uboot-mediatek/patches/002-0030-tools-mtk_image-add-support-for-nand-headers-used-by.patch new file mode 100644 index 0000000000..0ce095998f --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0030-tools-mtk_image-add-support-for-nand-headers-used-by.patch @@ -0,0 +1,702 @@ +From fbf296f9ed5daab70020686e9ba072efe663bbab Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 3 Aug 2022 11:14:36 +0800 +Subject: [PATCH 30/31] tools: mtk_image: add support for nand headers used by + newer chips + +This patch adds more nand headers in two new types: +1. HSM header, used for spi-nand thru SNFI interface +2. SPIM header, used for spi-nand thru spi-mem interface + +The original nand header is renamed to AP header. + +Signed-off-by: Weijie Gao +--- + tools/mtk_image.c | 23 ++- + tools/mtk_nand_headers.c | 422 +++++++++++++++++++++++++++++++++++++-- + tools/mtk_nand_headers.h | 110 +++++++++- + 3 files changed, 525 insertions(+), 30 deletions(-) + +--- a/tools/mtk_image.c ++++ b/tools/mtk_image.c +@@ -33,6 +33,9 @@ static const struct brom_img_type { + }, { + .name = "snand", + .type = BRLYT_TYPE_SNAND ++ }, { ++ .name = "spim-nand", ++ .type = BRLYT_TYPE_SNAND + } + }; + +@@ -54,7 +57,7 @@ static char lk_name[32] = "U-Boot"; + static uint32_t crc32tbl[256]; + + /* NAND header selected by user */ +-static const union nand_boot_header *hdr_nand; ++static const struct nand_header_type *hdr_nand; + static uint32_t hdr_nand_size; + + /* GFH header + 2 * 4KB pages of NAND */ +@@ -366,20 +369,26 @@ static int mtk_image_verify_nand_header( + if (ret < 0) + return ret; + +- bh = (struct brom_layout_header *)(ptr + info.page_size); ++ if (!ret) { ++ bh = (struct brom_layout_header *)(ptr + info.page_size); + +- if (strcmp(bh->name, BRLYT_NAME)) +- return -1; ++ if (strcmp(bh->name, BRLYT_NAME)) ++ return -1; ++ ++ if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) ++ return -1; + +- if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) { +- return -1; +- } else { + if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) + bootmedia = "Parallel NAND"; + else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND) + bootmedia = "Serial NAND (SNFI/AP)"; + else + return -1; ++ } else { ++ if (info.snfi) ++ bootmedia = "Serial NAND (SNFI/HSM)"; ++ else ++ bootmedia = "Serial NAND (SPIM)"; + } + + if (print) { +--- a/tools/mtk_nand_headers.c ++++ b/tools/mtk_nand_headers.c +@@ -188,55 +188,346 @@ static const union nand_boot_header nand + } + }; + +-static const struct nand_header_type { ++/* HSM BROM NAND header for SPI NAND with 2KB page + 64B spare */ ++static const union hsm_nand_boot_header hsm_nand_hdr_2k_64_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0xFF, 0x00, 0x00, 0x00, 0x21, 0xD2, 0xEE, 0xF6, ++ 0xAE, 0xDD, 0x5E, 0xC2, 0x82, 0x8E, 0x9A, 0x62, ++ 0x09, 0x8E, 0x80, 0xE2, 0x37, 0x0D, 0xC9, 0xFA, ++ 0xA9, 0xDD, 0xFC, 0x92, 0x34, 0x2A, 0xED, 0x51, ++ 0xA4, 0x1B, 0xF7, 0x63, 0xCC, 0x5A, 0xC7, 0xFB, ++ 0xED, 0x21, 0x02, 0x23, 0x51, 0x31 ++ } ++}; ++ ++/* HSM BROM NAND header for SPI NAND with 2KB page + 128B spare */ ++static const union hsm_nand_boot_header hsm_nand_hdr_2k_128_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0xFF, 0x00, 0x00, 0x00, 0x71, 0x7f, 0x71, 0xAC, ++ 0x42, 0xD0, 0x5B, 0xD2, 0x12, 0x81, 0x15, 0x0A, ++ 0x0C, 0xD4, 0xF6, 0x32, 0x1E, 0x63, 0xE7, 0x81, ++ 0x8A, 0x7F, 0xDE, 0xF9, 0x4B, 0x91, 0xEC, 0xC2, ++ 0x70, 0x00, 0x7F, 0x57, 0xAF, 0xDC, 0xE4, 0x24, ++ 0x57, 0x09, 0xBC, 0xC5, 0x35, 0xDC ++ } ++}; ++ ++/* HSM BROM NAND header for SPI NAND with 4KB page + 256B spare */ ++static const union hsm_nand_boot_header hsm_nand_hdr_4k_256_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0xFF, 0x00, 0x00, 0x00, 0x62, 0x04, 0xD6, 0x1F, ++ 0x2B, 0x57, 0x7A, 0x2D, 0xFE, 0xBB, 0x4A, 0x50, ++ 0xEC, 0xF8, 0x70, 0x1A, 0x44, 0x15, 0xF6, 0xA2, ++ 0x8E, 0xB0, 0xFD, 0xFA, 0xDC, 0xAA, 0x5A, 0x4E, ++ 0xCB, 0x8E, 0xC9, 0x72, 0x08, 0xDC, 0x20, 0xB9, ++ 0x98, 0xC8, 0x82, 0xD8, 0xBE, 0x44 ++ } ++}; ++ ++/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 64B spare */ ++static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_64_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x5F, 0x4B, 0xB2, 0x5B, 0x8B, 0x1C, 0x35, 0xDA, ++ 0x83, 0xE6, 0x6C, 0xC3, 0xFB, 0x8C, 0x78, 0x23, ++ 0xD0, 0x89, 0x24, 0xD9, 0x6C, 0x35, 0x2C, 0x5D, ++ 0x8F, 0xBB, 0xFC, 0x10, 0xD0, 0xE2, 0x22, 0x7D, ++ 0xC8, 0x97, 0x9A, 0xEF, 0xC6, 0xB5, 0xA7, 0x4E, ++ 0x4E, 0x0E ++ } ++}; ++ ++/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 128B spare */ ++static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_128_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xF8, 0x7E, 0xC1, 0x5D, 0x61, 0x54, 0xEA, 0x9F, ++ 0x5E, 0x66, 0x39, 0x66, 0x21, 0xFF, 0x8C, 0x3B, ++ 0xBE, 0xA7, 0x5A, 0x9E, 0xD7, 0xBD, 0x9E, 0x89, ++ 0xEE, 0x7E, 0x10, 0x31, 0x9A, 0x1D, 0x82, 0x49, ++ 0xA3, 0x4E, 0xD8, 0x47, 0xD7, 0x19, 0xF4, 0x2D, ++ 0x8E, 0x53 ++ } ++}; ++ ++/* HSM2.0 BROM NAND header for SPI NAND with 4KB page + 256B spare */ ++static const union hsm20_nand_boot_header hsm20_nand_hdr_4k_256_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x79, 0x01, 0x1F, 0x86, 0x62, 0x6A, 0x43, 0xAE, ++ 0xE6, 0xF8, 0xDD, 0x5B, 0x29, 0xB7, 0xA2, 0x7F, ++ 0x29, 0x72, 0x54, 0x37, 0xBE, 0x50, 0xD4, 0x24, ++ 0xAB, 0x60, 0xF4, 0x44, 0x97, 0x3B, 0x65, 0x21, ++ 0x73, 0x24, 0x1F, 0x93, 0x0E, 0x9E, 0x96, 0x88, ++ 0x78, 0x6C ++ } ++}; ++ ++/* SPIM-NAND header for SPI NAND with 2KB page + 64B spare */ ++static const union spim_nand_boot_header spim_nand_hdr_2k_64_data = { ++ .data = { ++ 0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30, ++ 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ } ++}; ++ ++/* SPIM-NAND header for SPI NAND with 2KB page + 128B spare */ ++static const union spim_nand_boot_header spim_nand_hdr_2k_128_data = { ++ .data = { ++ 0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30, ++ 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ } ++}; ++ ++/* SPIM-NAND header for SPI NAND with 4KB page + 256B spare */ ++static const union spim_nand_boot_header spim_nand_hdr_4k_256_data = { ++ .data = { ++ 0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x40, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x30, ++ 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ } ++}; ++ ++struct nand_header_type { + const char *name; +- const union nand_boot_header *data; ++ enum nand_boot_header_type type; ++ union { ++ const union nand_boot_header *ap; ++ const union hsm_nand_boot_header *hsm; ++ const union hsm20_nand_boot_header *hsm20; ++ const union spim_nand_boot_header *spim; ++ }; + } nand_headers[] = { + { + .name = "2k+64", +- .data = &snand_hdr_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_2k_64_data, + }, { + .name = "2k+120", +- .data = &snand_hdr_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_2k_128_data, + }, { + .name = "2k+128", +- .data = &snand_hdr_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_2k_128_data, + }, { + .name = "4k+256", +- .data = &snand_hdr_4k_256_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_4k_256_data, + }, { + .name = "1g:2k+64", +- .data = &nand_hdr_1gb_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_1gb_2k_64_data, + }, { + .name = "2g:2k+64", +- .data = &nand_hdr_2gb_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_2gb_2k_64_data, + }, { + .name = "4g:2k+64", +- .data = &nand_hdr_4gb_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_4gb_2k_64_data, + }, { + .name = "2g:2k+128", +- .data = &nand_hdr_2gb_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_2gb_2k_128_data, + }, { + .name = "4g:2k+128", +- .data = &nand_hdr_4gb_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_4gb_2k_128_data, ++ }, { ++ .name = "hsm:2k+64", ++ .type = NAND_BOOT_HSM_HEADER, ++ .hsm = &hsm_nand_hdr_2k_64_data, ++ }, { ++ .name = "hsm:2k+128", ++ .type = NAND_BOOT_HSM_HEADER, ++ .hsm = &hsm_nand_hdr_2k_128_data, ++ }, { ++ .name = "hsm:4k+256", ++ .type = NAND_BOOT_HSM_HEADER, ++ .hsm = &hsm_nand_hdr_4k_256_data, ++ }, { ++ .name = "hsm20:2k+64", ++ .type = NAND_BOOT_HSM20_HEADER, ++ .hsm20 = &hsm20_nand_hdr_2k_64_data, ++ }, { ++ .name = "hsm20:2k+128", ++ .type = NAND_BOOT_HSM20_HEADER, ++ .hsm20 = &hsm20_nand_hdr_2k_128_data, ++ }, { ++ .name = "hsm20:4k+256", ++ .type = NAND_BOOT_HSM20_HEADER, ++ .hsm20 = &hsm20_nand_hdr_4k_256_data, ++ }, { ++ .name = "spim:2k+64", ++ .type = NAND_BOOT_SPIM_HEADER, ++ .spim = &spim_nand_hdr_2k_64_data, ++ }, { ++ .name = "spim:2k+128", ++ .type = NAND_BOOT_SPIM_HEADER, ++ .spim = &spim_nand_hdr_2k_128_data, ++ }, { ++ .name = "spim:4k+256", ++ .type = NAND_BOOT_SPIM_HEADER, ++ .spim = &spim_nand_hdr_4k_256_data, + } + }; + +-const union nand_boot_header *mtk_nand_header_find(const char *name) ++const struct nand_header_type *mtk_nand_header_find(const char *name) + { + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(nand_headers); i++) { + if (!strcmp(nand_headers[i].name, name)) +- return nand_headers[i].data; ++ return &nand_headers[i]; + } + + return NULL; + } + +-uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand) ++uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand) + { +- return 2 * le16_to_cpu(hdr_nand->pagesize); ++ switch (hdr_nand->type) { ++ case NAND_BOOT_HSM_HEADER: ++ return le32_to_cpu(hdr_nand->hsm->page_size); ++ ++ case NAND_BOOT_HSM20_HEADER: ++ return le32_to_cpu(hdr_nand->hsm20->page_size); ++ ++ case NAND_BOOT_SPIM_HEADER: ++ return le32_to_cpu(hdr_nand->spim->page_size); ++ ++ default: ++ return 2 * le16_to_cpu(hdr_nand->ap->pagesize); ++ } + } + + static int mtk_nand_header_ap_info(const void *ptr, +@@ -251,14 +542,45 @@ static int mtk_nand_header_ap_info(const + info->page_size = le16_to_cpu(nh->pagesize); + info->spare_size = le16_to_cpu(nh->oobsize); + info->gfh_offset = 2 * info->page_size; ++ info->snfi = true; + + return 0; + } + ++static int mtk_nand_header_hsm_info(const void *ptr, ++ struct nand_header_info *info) ++{ ++ union hsm_nand_boot_header *nh = (union hsm_nand_boot_header *)ptr; ++ ++ info->page_size = le16_to_cpu(nh->page_size); ++ info->spare_size = le16_to_cpu(nh->spare_size); ++ info->gfh_offset = info->page_size; ++ info->snfi = true; ++ ++ return 1; ++} ++ ++static int mtk_nand_header_spim_info(const void *ptr, ++ struct nand_header_info *info) ++{ ++ union spim_nand_boot_header *nh = (union spim_nand_boot_header *)ptr; ++ ++ info->page_size = le16_to_cpu(nh->page_size); ++ info->spare_size = le16_to_cpu(nh->spare_size); ++ info->gfh_offset = info->page_size; ++ info->snfi = false; ++ ++ return 1; ++} ++ + int mtk_nand_header_info(const void *ptr, struct nand_header_info *info) + { + if (!strcmp((char *)ptr, NAND_BOOT_NAME)) + return mtk_nand_header_ap_info(ptr, info); ++ else if (!strncmp((char *)ptr, HSM_NAND_BOOT_NAME, 8)) ++ return mtk_nand_header_hsm_info(ptr, info); ++ else if (!strncmp((char *)ptr, SPIM_NAND_BOOT_NAME, 8)) ++ return mtk_nand_header_spim_info(ptr, info); + + return -1; + } +@@ -273,14 +595,74 @@ bool is_mtk_nand_header(const void *ptr) + return false; + } + +-uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr) ++static uint16_t crc16(const uint8_t *p, uint32_t len) ++{ ++ uint16_t crc = 0x4f4e; ++ uint32_t i; ++ ++ while (len--) { ++ crc ^= *p++ << 8; ++ for (i = 0; i < 8; i++) ++ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); ++ } ++ ++ return crc; ++} ++ ++static uint32_t mtk_nand_header_put_ap(const struct nand_header_type *hdr_nand, ++ void *ptr) + { +- union nand_boot_header *nh = (union nand_boot_header *)ptr; + int i; + + /* NAND device header, repeat 4 times */ +- for (i = 0; i < 4; i++) +- memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header)); ++ for (i = 0; i < 4; i++) { ++ memcpy(ptr, hdr_nand->ap, sizeof(*hdr_nand->ap)); ++ ptr += sizeof(*hdr_nand->ap); ++ } ++ ++ return le16_to_cpu(hdr_nand->ap->pagesize); ++} + +- return le16_to_cpu(hdr_nand->pagesize); ++static uint32_t mtk_nand_header_put_hsm(const struct nand_header_type *hdr_nand, ++ void *ptr) ++{ ++ memcpy(ptr, hdr_nand->hsm, sizeof(*hdr_nand->hsm)); ++ return 0; ++} ++ ++static uint32_t mtk_nand_header_put_hsm20(const struct nand_header_type *hdr_nand, ++ void *ptr) ++{ ++ memcpy(ptr, hdr_nand->hsm20, sizeof(*hdr_nand->hsm20)); ++ return 0; ++} ++ ++static uint32_t mtk_nand_header_put_spim(const struct nand_header_type *hdr_nand, ++ void *ptr) ++{ ++ uint16_t crc; ++ ++ memcpy(ptr, hdr_nand->spim, sizeof(*hdr_nand->spim)); ++ ++ crc = crc16(ptr, 0x4e); ++ memcpy(ptr + 0x4e, &crc, sizeof(uint16_t)); ++ ++ return 0; ++} ++ ++uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand, void *ptr) ++{ ++ switch (hdr_nand->type) { ++ case NAND_BOOT_HSM_HEADER: ++ return mtk_nand_header_put_hsm(hdr_nand, ptr); ++ ++ case NAND_BOOT_HSM20_HEADER: ++ return mtk_nand_header_put_hsm20(hdr_nand, ptr); ++ ++ case NAND_BOOT_SPIM_HEADER: ++ return mtk_nand_header_put_spim(hdr_nand, ptr); ++ ++ default: ++ return mtk_nand_header_put_ap(hdr_nand, ptr); ++ } + } +--- a/tools/mtk_nand_headers.h ++++ b/tools/mtk_nand_headers.h +@@ -16,6 +16,7 @@ struct nand_header_info { + uint32_t page_size; + uint32_t spare_size; + uint32_t gfh_offset; ++ bool snfi; + }; + + /* AP BROM Header for NAND */ +@@ -39,15 +40,117 @@ union nand_boot_header { + uint8_t data[0x80]; + }; + ++/* HSM BROM Header for NAND */ ++union hsm_nand_boot_header { ++ struct { ++ char id[8]; ++ uint32_t version; /* Header version */ ++ uint32_t config; /* Header config */ ++ uint32_t sector_size; /* ECC step size */ ++ uint32_t fdm_size; /* User OOB size of a step */ ++ uint32_t fdm_ecc_size; /* ECC parity size of a step */ ++ uint32_t lbs; ++ uint32_t page_size; /* NAND page size */ ++ uint32_t spare_size; /* NAND page spare size */ ++ uint32_t page_per_block; /* Pages of one block */ ++ uint32_t blocks; /* Total blocks of NAND chip */ ++ uint32_t plane_sel_position; /* Plane bit position */ ++ uint32_t pll; /* Value of pll reg */ ++ uint32_t acccon; /* Value of access timing reg */ ++ uint32_t strobe_sel; /* Value of DQS selection reg*/ ++ uint32_t acccon1; /* Value of access timing reg */ ++ uint32_t dqs_mux; /* Value of DQS mux reg */ ++ uint32_t dqs_ctrl; /* Value of DQS control reg */ ++ uint32_t delay_ctrl; /* Value of delay ctrl reg */ ++ uint32_t latch_lat; /* Value of latch latency reg */ ++ uint32_t sample_delay; /* Value of sample delay reg */ ++ uint32_t driving; /* Value of driving reg */ ++ uint32_t bl_start; /* Bootloader start addr */ ++ uint32_t bl_end; /* Bootloader end addr */ ++ uint8_t ecc_parity[42]; /* ECC parity of this header */ ++ }; ++ ++ uint8_t data[0x8E]; ++}; ++ ++/* HSM2.0 BROM Header for NAND */ ++union hsm20_nand_boot_header { ++ struct { ++ char id[8]; ++ uint32_t version; /* Header version */ ++ uint32_t config; /* Header config */ ++ uint32_t sector_size; /* ECC step size */ ++ uint32_t fdm_size; /* User OOB size of a step */ ++ uint32_t fdm_ecc_size; /* ECC parity size of a step */ ++ uint32_t lbs; ++ uint32_t page_size; /* NAND page size */ ++ uint32_t spare_size; /* NAND page spare size */ ++ uint32_t page_per_block; /* Pages of one block */ ++ uint32_t blocks; /* Total blocks of NAND chip */ ++ uint32_t plane_sel_position; /* Plane bit position */ ++ uint32_t pll; /* Value of pll reg */ ++ uint32_t acccon; /* Value of access timing reg */ ++ uint32_t strobe_sel; /* Value of DQS selection reg*/ ++ uint32_t acccon1; /* Value of access timing reg */ ++ uint32_t dqs_mux; /* Value of DQS mux reg */ ++ uint32_t dqs_ctrl; /* Value of DQS control reg */ ++ uint32_t delay_ctrl; /* Value of delay ctrl reg */ ++ uint32_t latch_lat; /* Value of latch latency reg */ ++ uint32_t sample_delay; /* Value of sample delay reg */ ++ uint32_t driving; /* Value of driving reg */ ++ uint32_t reserved; ++ uint32_t bl0_start; /* Bootloader start addr */ ++ uint32_t bl0_end; /* Bootloader end addr */ ++ uint32_t bl0_type; /* Bootloader type */ ++ uint8_t bl_reserve[84]; ++ uint8_t ecc_parity[42]; /* ECC parity of this header */ ++ }; ++ ++ uint8_t data[0xEA]; ++}; ++ ++/* SPIM BROM Header for SPI-NAND */ ++union spim_nand_boot_header { ++ struct { ++ char id[8]; ++ uint32_t version; /* Header version */ ++ uint32_t config; /* Header config */ ++ uint32_t page_size; /* NAND page size */ ++ uint32_t spare_size; /* NAND page spare size */ ++ uint16_t page_per_block; /* Pages of one block */ ++ uint16_t plane_sel_position; /* Plane bit position */ ++ uint16_t reserve_reg; ++ uint16_t reserve_val; ++ uint16_t ecc_error; /* ECC error reg addr */ ++ uint16_t ecc_mask; /* ECC error bit mask */ ++ uint32_t bl_start; /* Bootloader start addr */ ++ uint32_t bl_end; /* Bootloader end addr */ ++ uint8_t ecc_parity[32]; /* ECC parity of this header */ ++ uint32_t integrity_crc; /* CRC of this header */ ++ }; ++ ++ uint8_t data[0x50]; ++}; ++ ++enum nand_boot_header_type { ++ NAND_BOOT_AP_HEADER, ++ NAND_BOOT_HSM_HEADER, ++ NAND_BOOT_HSM20_HEADER, ++ NAND_BOOT_SPIM_HEADER ++}; ++ + #define NAND_BOOT_NAME "BOOTLOADER!" + #define NAND_BOOT_VERSION "V006" + #define NAND_BOOT_ID "NFIINFO" + ++#define HSM_NAND_BOOT_NAME "NANDCFG!" ++#define SPIM_NAND_BOOT_NAME "SPINAND!" ++ + /* Find nand header data by name */ +-const union nand_boot_header *mtk_nand_header_find(const char *name); ++const struct nand_header_type *mtk_nand_header_find(const char *name); + + /* Device header size using this nand header */ +-uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand); ++uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand); + + /* Get nand info from nand header (page size, spare size, ...) */ + int mtk_nand_header_info(const void *ptr, struct nand_header_info *info); +@@ -56,6 +159,7 @@ int mtk_nand_header_info(const void *ptr + bool is_mtk_nand_header(const void *ptr); + + /* Generate Device header using give nand header */ +-uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr); ++uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand, ++ void *ptr); + + #endif /* _MTK_NAND_HEADERS_H */ diff --git a/package/boot/uboot-mediatek/patches/002-0031-MAINTAINERS-update-maintainer-for-MediaTek-ARM-platf.patch b/package/boot/uboot-mediatek/patches/002-0031-MAINTAINERS-update-maintainer-for-MediaTek-ARM-platf.patch new file mode 100644 index 0000000000..227fa07527 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/002-0031-MAINTAINERS-update-maintainer-for-MediaTek-ARM-platf.patch @@ -0,0 +1,42 @@ +From ca90c165157c19af9bf46a69dcf719b8aab636b1 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Thu, 4 Aug 2022 09:50:40 +0800 +Subject: [PATCH 31/31] MAINTAINERS: update maintainer for MediaTek ARM + platform + +Add new files for MediaTek ARM platform + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + MAINTAINERS | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -340,20 +340,25 @@ F: doc/device-tree-bindings/phy/phy-mtk- + F: doc/device-tree-bindings/usb/mediatek,* + F: doc/README.mediatek + F: drivers/clk/mediatek/ ++F: drivers/i2c/mtk_i2c.c + F: drivers/mmc/mtk-sd.c + F: drivers/phy/phy-mtk-* + F: drivers/pinctrl/mediatek/ + F: drivers/power/domain/mtk-power-domain.c + F: drivers/ram/mediatek/ + F: drivers/spi/mtk_snfi_spi.c ++F: drivers/spi/mtk_spim.c + F: drivers/timer/mtk_timer.c + F: drivers/usb/host/xhci-mtk.c + F: drivers/usb/mtu3/ + F: drivers/watchdog/mtk_wdt.c + F: drivers/net/mtk_eth.c ++F: drivers/net/mtk_eth.h + F: drivers/reset/reset-mediatek.c + F: tools/mtk_image.c + F: tools/mtk_image.h ++F: tools/mtk_nand_headers.c ++F: tools/mtk_nand_headers.h + N: mediatek + + ARM MICROCHIP/ATMEL AT91 diff --git a/package/boot/uboot-mediatek/patches/003-mtd-spi-nor-ids-Add-support-for-flashes-tested-by-xi.patch b/package/boot/uboot-mediatek/patches/003-mtd-spi-nor-ids-Add-support-for-flashes-tested-by-xi.patch new file mode 100644 index 0000000000..e54b46f5e4 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/003-mtd-spi-nor-ids-Add-support-for-flashes-tested-by-xi.patch @@ -0,0 +1,182 @@ +From baef13ec9d592a27b5d3bf03967bfd2bebd65157 Mon Sep 17 00:00:00 2001 +From: Ashok Reddy Soma +Date: Wed, 25 May 2022 10:47:12 +0530 +Subject: [PATCH] mtd: spi-nor-ids: Add support for flashes tested by xilinx + +Add support for various flashes from below manufacturers which are tested +by xilinx for years. + +EON: + en25q128b +GIGA: + gd25lx256e +ISSI: + is25lp008 + is25lp016 + is25lp01g + is25wp008 + is25wp016 + is25wp01g + is25wx256 +MACRONIX: + mx25u51245f + mx66u1g45g + mx66l2g45g +MICRON: + mt35xl512aba + mt35xu01g +SPANSION: + s70fs01gs_256k +SST: + sst26wf016b +WINBOND: + w25q16dw + w25q16jv + w25q512jv + w25q32bv + w25h02jv + +Signed-off-by: Ashok Reddy Soma +Link: https://lore.kernel.org/r/1653455832-14763-1-git-send-email-ashok.reddy.soma@xilinx.com +Signed-off-by: Michal Simek +--- + drivers/mtd/spi/spi-nor-ids.c | 37 +++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +--- a/drivers/mtd/spi/spi-nor-ids.c ++++ b/drivers/mtd/spi/spi-nor-ids.c +@@ -82,6 +82,7 @@ const struct flash_info spi_nor_ids[] = + /* EON -- en25xxx */ + { INFO("en25q32b", 0x1c3016, 0, 64 * 1024, 64, 0) }, + { INFO("en25q64", 0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, ++ { INFO("en25q128b", 0x1c3018, 0, 64 * 1024, 256, 0) }, + { INFO("en25qh128", 0x1c7018, 0, 64 * 1024, 256, 0) }, + { INFO("en25s64", 0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, + #endif +@@ -127,11 +128,17 @@ const struct flash_info spi_nor_ids[] = + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, ++ { ++ INFO("gd25lx256e", 0xc86819, 0, 64 * 1024, 512, ++ SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) ++ }, + #endif + #ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ + /* ISSI */ + { INFO("is25lq040b", 0x9d4013, 0, 64 * 1024, 8, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("is25lp008", 0x9d6014, 0, 64 * 1024, 16, SPI_NOR_QUAD_READ) }, ++ { INFO("is25lp016", 0x9d6015, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ) }, + { INFO("is25lp032", 0x9d6016, 0, 64 * 1024, 64, 0) }, + { INFO("is25lp064", 0x9d6017, 0, 64 * 1024, 128, 0) }, + { INFO("is25lp128", 0x9d6018, 0, 64 * 1024, 256, +@@ -140,6 +147,10 @@ const struct flash_info spi_nor_ids[] = + SECT_4K | SPI_NOR_DUAL_READ) }, + { INFO("is25lp512", 0x9d601a, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("is25lp01g", 0x9d601b, 0, 64 * 1024, 2048, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("is25wp008", 0x9d7014, 0, 64 * 1024, 16, SPI_NOR_QUAD_READ) }, ++ { INFO("is25wp016", 0x9d7015, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ) }, + { INFO("is25wp032", 0x9d7016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25wp064", 0x9d7017, 0, 64 * 1024, 128, +@@ -151,6 +162,10 @@ const struct flash_info spi_nor_ids[] = + SPI_NOR_4B_OPCODES) }, + { INFO("is25wp512", 0x9d701a, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("is25wp01g", 0x9d701b, 0, 64 * 1024, 2048, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("is25wx256", 0x9d5b19, 0, 128 * 1024, 256, ++ SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, + #endif + #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ + /* Macronix */ +@@ -176,8 +191,11 @@ const struct flash_info spi_nor_ids[] = + { INFO("mx25l25655e", 0xc22619, 0, 64 * 1024, 512, 0) }, + { INFO("mx66l51235l", 0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66u51235f", 0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25u51245f", 0xc2953a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx66u1g45g", 0xc2253b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66u2g45g", 0xc2253c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66l1g45g", 0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("mx66l2g45g", 0xc2201c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25l1633e", 0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, + { INFO("mx25r6435f", 0xc22817, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("mx66uw2g345g", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, +@@ -208,8 +226,10 @@ const struct flash_info spi_nor_ids[] = + { INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, + { INFO("mt25ql02g", 0x20ba22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE | SPI_NOR_4B_OPCODES) }, + #ifdef CONFIG_SPI_FLASH_MT35XU ++ { INFO("mt35xl512aba", 0x2c5a1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ) }, + { INFO("mt35xu512aba", 0x2c5b1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ) }, + #endif /* CONFIG_SPI_FLASH_MT35XU */ ++ { INFO6("mt35xu01g", 0x2c5b1b, 0x104100, 128 * 1024, 1024, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mt35xu02g", 0x2c5b1c, 0, 128 * 1024, 2048, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, + #endif + #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ +@@ -225,6 +245,7 @@ const struct flash_info spi_nor_ids[] = + { INFO("s25fl512s_256k", 0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25fl512s_64k", 0x010220, 0x4d01, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s25fl512s_512k", 0x010220, 0x4f00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, ++ { INFO("s70fs01gs_256k", 0x010221, 0x4d00, 256 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, 0) }, + { INFO("s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, 0) }, + { INFO6("s25fl128s", 0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, +@@ -275,6 +296,7 @@ const struct flash_info spi_nor_ids[] = + { INFO("sst25wf040", 0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, + { INFO("sst25wf080", 0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, + { INFO("sst26vf064b", 0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_SST26LOCK | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("sst26wf016b", 0xbf2641, 0, 64 * 1024, 32, SECT_4K) }, + { INFO("sst26wf016", 0xbf2651, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_HAS_SST26LOCK) }, + { INFO("sst26wf032", 0xbf2622, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_SST26LOCK) }, + { INFO("sst26wf064", 0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_SST26LOCK) }, +@@ -312,11 +334,19 @@ const struct flash_info spi_nor_ids[] = + { INFO("w25q20ew", 0xef6012, 0, 64 * 1024, 4, SECT_4K) }, + { INFO("w25q32", 0xef4016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { ++ INFO("w25q16dw", 0xef6015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) ++ }, ++ { + INFO("w25q32dw", 0xef6016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { ++ INFO("w25q16jv", 0xef7015, 0, 64 * 1024, 32, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) ++ }, ++ { + INFO("w25q32jv", 0xef7016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +@@ -363,6 +393,11 @@ const struct flash_info spi_nor_ids[] = + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { ++ INFO("w25q512jv", 0xef7119, 0, 64 * 1024, 512, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, ++ { + INFO("w25q01jv", 0xef4021, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +@@ -370,6 +405,7 @@ const struct flash_info spi_nor_ids[] = + { INFO("w25q80", 0xef5014, 0, 64 * 1024, 16, SECT_4K) }, + { INFO("w25q80bl", 0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q16cl", 0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("w25q32bv", 0xef4016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q64cv", 0xef4017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q128", 0xef4018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | +@@ -378,6 +414,7 @@ const struct flash_info spi_nor_ids[] = + { INFO("w25q256", 0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25m512jw", 0xef6119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25m512jv", 0xef7119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("w25h02jv", 0xef9022, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + #endif + #ifdef CONFIG_SPI_FLASH_XMC + /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ diff --git a/package/boot/uboot-mediatek/patches/004-mtd-spi-nor-core-Add-support-for-Macronix-Octal-flas.patch b/package/boot/uboot-mediatek/patches/004-mtd-spi-nor-core-Add-support-for-Macronix-Octal-flas.patch new file mode 100644 index 0000000000..b0299ac6d8 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/004-mtd-spi-nor-core-Add-support-for-Macronix-Octal-flas.patch @@ -0,0 +1,614 @@ +From 4290ed7835e0a76792b8e554ae79e3f6d52ac800 Mon Sep 17 00:00:00 2001 +From: JaimeLiao +Date: Mon, 18 Jul 2022 14:49:22 +0800 +Subject: [PATCH] mtd: spi-nor-core: Add support for Macronix Octal flash + +Adding Macronix Octal flash for Octal DTR support. + +The octaflash series can be divided into the following types: + +MX25 series : Serial NOR Flash. +MX66 series : Serial NOR Flash with stacked die.(Size larger than 1Gb) +LM/UM series : Up to 250MHz clock frequency with both DTR/STR operation. +LW/UW series : Support simultaneous Read-while-Write operation in multiple + bank architecture. Read-while-write feature which means read + data one bank while another bank is programing or erasing. + +MX25LM : 3.0V Octal I/O + -https://www.mxic.com.tw/Lists/Datasheet/Attachments/7841/MX25LM51245G,%203V,%20512Mb,%20v1.1.pdf + +MX25UM : 1.8V Octal I/O + -https://www.mxic.com.tw/Lists/Datasheet/Attachments/7525/MX25UM51245G%20Extreme%20Speed,%201.8V,%20512Mb,%20v1.0.pdf + +MX66LM : 3.0V Octal I/O with stacked die + -https://www.mxic.com.tw/Lists/Datasheet/Attachments/7929/MX66LM1G45G,%203V,%201Gb,%20v1.1.pdf + +MX66UM : 1.8V Octal I/O with stacked die + -https://www.mxic.com.tw/Lists/Datasheet/Attachments/7721/MX66UM1G45G,%201.8V,%201Gb,%20v1.1.pdf + +MX25LW : 3.0V Octal I/O with Read-while-Write +MX25UW : 1.8V Octal I/O with Read-while-Write +MX66LW : 3.0V Octal I/O with Read-while-Write and stack die +MX66UW : 1.8V Octal I/O with Read-while-Write and stack die + +About LW/UW series, please contact us freely if you have any +questions. For adding Octal NOR Flash IDs, we have validated +each Flash on plateform zynq-picozed. + +As below are the SFDP table dump. + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2943c +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx66uw2g345gx0 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx66uw2g345gx0 +zynq> hexdump mx66uw2g345gx0 +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 7fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7987 0001 1284 e200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 237c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 001f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2853b +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx66lm1g45g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx66lm1g45g +zynq> hexdump mx66lm1g45g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 3fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 6987 0001 1282 e200 02cc 3867 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 6666 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0000 0000 +0000130 3514 001c 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2853a +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25lm51245g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25lm51245g +zynq> hexdump mx25lm51245g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 1fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7989 0001 128d e200 02cc 4467 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 6666 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0000 0000 +0000130 3514 001c 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2863a +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25lw51245g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25lw51245g +zynq> hexdump mx25lw51245g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 0000 0000 0000 0000 +0000040 20e5 ff8a ffff 1fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 798b 0001 128f e200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 6666 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0000 0000 +0000130 3514 001c 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28539 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25lm25645g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25lm25645g +zynq> hexdump mx25lm25645g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 0fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 6987 0001 1282 d200 02cc 3867 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 6666 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0000 0000 +0000130 3514 001c 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2843c +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx66uw2g345g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx66uw2g345g +zynq> hexdump mx66uw2g345g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 7fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7987 0001 1284 e200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 237c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 001f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2803b +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx66um1g45g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx66um1g45g +zynq> hexdump mx66um1g45g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 3fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7989 0001 128d e200 02cc 4467 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 3514 809c 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2813b +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx66uw1g45g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx66uw1g45g +zynq> hexdump mx66uw1g45g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 3fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 798b 0001 128f e200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2813a +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw51245g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw51245g +zynq> hexdump mx25uw51245g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 1fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 798b 0001 128f e200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 7777 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0000 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c2843a +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw51345g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw51345g +zynq> hexdump mx25uw51345g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 1fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 798b 0001 128f e200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 237c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28039 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25um25645g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25um25645g +zynq> random: fast init done +zynq> hexdump mx25um25645g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 0fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7987 0001 1284 d200 02cc 3867 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 3514 809c 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28139 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw25645g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw25645g +zynq> hexdump mx25uw25645g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 0fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7989 0001 128d d200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28339 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25um25345g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25um25345g +zynq> hexdump mx25um25345g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 0fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 6987 0001 1282 d200 02cc 3867 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 237c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0904 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28439 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw25345g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw25345g +zynq> hexdump mx25uw25345g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 0fff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7987 0001 1284 d200 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 237c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28138 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw12845g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw12845g +zynq> hexdump mx25uw12845g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 0000 0000 0000 0000 +0000040 20e5 ff8a ffff 07ff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 798b 0001 128f c900 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28438 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw12345g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw12345g +zynq> hexdump mx25uw12345g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 07ff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 798b 0001 128f c900 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 237c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28137 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw6445g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw6445g +zynq> hexdump mx25uw6445g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 03ff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 7989 0001 128d c400 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 a37c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id +c28437 +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer +macronix +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/partname +mx25uw6345g +zynq> cat /sys/bus/spi/devices/spi0.0/spi-nor/sfdp > mx25uw6345g +zynq> hexdump mx25uw6345g +0000000 4653 5044 0108 fd04 0700 1401 0040 ff00 +0000010 0187 1c01 0090 ff00 000a 0801 0100 ff00 +0000020 0005 0501 0120 ff00 0084 0201 0134 ff00 +0000030 0000 0000 0000 0000 ffff ffff ffff ffff +0000040 20e5 ff8a ffff 03ff ff00 ff00 ff00 ff00 +0000050 ffee ffff ffff ff00 ffff ff00 200c d810 +0000060 ff00 ff00 798b 0001 128f c400 04cc 4667 +0000070 b030 b030 bdf4 5cd5 0000 ff00 1010 2000 +0000080 0000 0000 0000 237c 0048 0000 0000 8888 +0000090 0000 0000 0000 4000 d10f f3ff d10f f3ff +00000a0 0500 9000 0500 b100 2b00 9500 2b00 9600 +00000b0 7172 b803 7172 b803 0000 0000 a390 8218 +00000c0 c000 9669 0000 0000 0000 0000 7172 9800 +00000d0 7172 b800 7172 9900 0000 0000 7172 9800 +00000e0 7172 f800 7172 9900 7172 f900 0000 0000 +00000f0 0000 0000 1501 d001 7172 d806 0000 5086 +0000100 0000 0106 0000 0000 0002 0301 0200 0000 +0000110 0000 0106 0000 0000 0000 0672 0200 0000 +0000120 ee00 69c0 7272 7171 d800 f6f7 0a00 0000 +0000130 4514 8098 0643 000f dc21 ffff ffff ffff +0000140 ffff ffff ffff ffff ffff ffff ffff ffff + +Signed-off-by: JaimeLiao +Reviewed-by: Jagan Teki +--- + drivers/mtd/spi/spi-nor-ids.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi/spi-nor-ids.c ++++ b/drivers/mtd/spi/spi-nor-ids.c +@@ -198,7 +198,24 @@ const struct flash_info spi_nor_ids[] = + { INFO("mx66l2g45g", 0xc2201c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25l1633e", 0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, + { INFO("mx25r6435f", 0xc22817, 0, 64 * 1024, 128, SECT_4K) }, +- { INFO("mx66uw2g345g", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx66uw2g345gx0", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx66lm1g45g", 0xc2853b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25lm51245g", 0xc2853a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25lw51245g", 0xc2863a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25lm25645g", 0xc28539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx66uw2g345g", 0xc2843c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx66um1g45g", 0xc2803b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx66uw1g45g", 0xc2813b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw51245g", 0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw51345g", 0xc2843a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25um25645g", 0xc28039, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw25645g", 0xc28139, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25um25345g", 0xc28339, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw25345g", 0xc28439, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw12845g", 0xc28138, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw12345g", 0xc28438, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw6445g", 0xc28137, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, ++ { INFO("mx25uw6345g", 0xc28437, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, + #endif + + #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ diff --git a/package/boot/uboot-mediatek/patches/004-mtd-spi-nor-ids-add-winbond-w25q512nw-family-support.patch b/package/boot/uboot-mediatek/patches/004-mtd-spi-nor-ids-add-winbond-w25q512nw-family-support.patch new file mode 100644 index 0000000000..b88120052c --- /dev/null +++ b/package/boot/uboot-mediatek/patches/004-mtd-spi-nor-ids-add-winbond-w25q512nw-family-support.patch @@ -0,0 +1,39 @@ +From 47ed8b22fd561b65e8541919becc76ab3d86f7a3 Mon Sep 17 00:00:00 2001 +From: Jae Hyun Yoo +Date: Fri, 8 Jul 2022 12:03:19 -0700 +Subject: [PATCH] mtd: spi-nor-ids: add winbond w25q512nw family support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add Winbond w25q512nwq/n and w25q512nwm support. + +datasheet: +https://www.winbond.com/resource-files/W25Q512NW%20RevB%2007192021.pdf + +Signed-off-by: Jae Hyun Yoo +Reviewed-by: Cédric Le Goater +Reviewed-by: Jagan Teki +--- + drivers/mtd/spi/spi-nor-ids.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/mtd/spi/spi-nor-ids.c ++++ b/drivers/mtd/spi/spi-nor-ids.c +@@ -415,6 +415,16 @@ const struct flash_info spi_nor_ids[] = + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { ++ INFO("w25q512nwq", 0xef6020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, ++ { ++ INFO("w25q512nwm", 0xef8020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, ++ { + INFO("w25q01jv", 0xef4021, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) diff --git a/package/boot/uboot-mediatek/patches/051-mt7986-enable-pstore.patch b/package/boot/uboot-mediatek/patches/051-mt7986-enable-pstore.patch new file mode 100644 index 0000000000..15484bef55 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/051-mt7986-enable-pstore.patch @@ -0,0 +1,38 @@ +--- a/arch/arm/dts/mt7986.dtsi ++++ b/arch/arm/dts/mt7986.dtsi +@@ -46,6 +46,35 @@ + }; + }; + ++ psci { ++ compatible = "arm,psci-0.2"; ++ method = "smc"; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* 64 KiB reserved for ramoops/pstore */ ++ ramoops@42ff0000 { ++ compatible = "ramoops"; ++ reg = <0 0x42ff0000 0 0x10000>; ++ record-size = <0x1000>; ++ }; ++ ++ /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ ++ secmon_reserved: secmon@43000000 { ++ reg = <0 0x43000000 0 0x30000>; ++ no-map; ++ }; ++ ++ wmcpu_emi: wmcpu-reserved@4fc00000 { ++ no-map; ++ reg = <0 0x4fc00000 0 0x00100000>; ++ }; ++ }; ++ + dummy_clk: dummy12m { + compatible = "fixed-clock"; + clock-frequency = <12000000>; diff --git a/package/boot/uboot-mediatek/patches/060-bootm-fix-typo-imape_comp-image_comp.patch b/package/boot/uboot-mediatek/patches/060-bootm-fix-typo-imape_comp-image_comp.patch new file mode 100644 index 0000000000..e9777db9c3 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/060-bootm-fix-typo-imape_comp-image_comp.patch @@ -0,0 +1,48 @@ +From 22832a0a15227e3fcc364b356247d8aeb9ce45b3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 27 Aug 2022 04:05:31 +0100 +Subject: [PATCH 1/2] bootm: fix typo imape_comp -> image_comp + +Chage variable name 'imape_comp' to the supposedly intended name +'image_comp'. + +Signed-off-by: Daniel Golle +--- + boot/bootm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/boot/bootm.c ++++ b/boot/bootm.c +@@ -1006,7 +1006,7 @@ static int bootm_host_load_image(const v + int noffset; + ulong load_end; + uint8_t image_type; +- uint8_t imape_comp; ++ uint8_t image_comp; + void *load_buf; + int ret; + +@@ -1024,20 +1024,20 @@ static int bootm_host_load_image(const v + return -EINVAL; + } + +- if (fit_image_get_comp(fit, noffset, &imape_comp)) { ++ if (fit_image_get_comp(fit, noffset, &image_comp)) { + puts("Can't get image compression!\n"); + return -EINVAL; + } + + /* Allow the image to expand by a factor of 4, should be safe */ + load_buf = malloc((1 << 20) + len * 4); +- ret = image_decomp(imape_comp, 0, data, image_type, load_buf, ++ ret = image_decomp(image_comp, 0, data, image_type, load_buf, + (void *)data, len, CONFIG_SYS_BOOTM_LEN, + &load_end); + free(load_buf); + + if (ret) { +- ret = handle_decomp_error(imape_comp, load_end - 0, ret); ++ ret = handle_decomp_error(image_comp, load_end - 0, ret); + if (ret != BOOTM_ERR_UNIMPLEMENTED) + return ret; + } diff --git a/package/boot/uboot-mediatek/patches/061-image-fit-don-t-set-compression-if-it-can-t-be-read.patch b/package/boot/uboot-mediatek/patches/061-image-fit-don-t-set-compression-if-it-can-t-be-read.patch new file mode 100644 index 0000000000..2eed6ae9b1 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/061-image-fit-don-t-set-compression-if-it-can-t-be-read.patch @@ -0,0 +1,71 @@ +From b2c109c012ca946baebbb23e7f4301f6eee4c6f3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 15 Aug 2022 12:15:50 +0200 +Subject: [PATCH 2/2] image-fit: don't set compression if it can't be read + +fit_image_get_comp() should not set value -1 in case it can't read +the compression node. Instead, leave the value untouched in that case +as it can be absent and a default value previously defined by the +caller of fit_image_get_comp() should be used. + +As a result the warning message +WARNING: 'compression' nodes for ramdisks are deprecated, please fix your .its file! +no longer shows if the compression node is actually absent. + +Signed-off-by: Daniel Golle +--- + boot/bootm.c | 6 ++---- + boot/image-fit.c | 3 +-- + cmd/ximg.c | 7 ++----- + 3 files changed, 5 insertions(+), 11 deletions(-) + +--- a/boot/bootm.c ++++ b/boot/bootm.c +@@ -1024,10 +1024,8 @@ static int bootm_host_load_image(const v + return -EINVAL; + } + +- if (fit_image_get_comp(fit, noffset, &image_comp)) { +- puts("Can't get image compression!\n"); +- return -EINVAL; +- } ++ if (fit_image_get_comp(fit, noffset, &image_comp)) ++ image_comp = IH_COMP_NONE; + + /* Allow the image to expand by a factor of 4, should be safe */ + load_buf = malloc((1 << 20) + len * 4); +--- a/boot/image-fit.c ++++ b/boot/image-fit.c +@@ -477,7 +477,7 @@ void fit_print_contents(const void *fit) + void fit_image_print(const void *fit, int image_noffset, const char *p) + { + char *desc; +- uint8_t type, arch, os, comp; ++ uint8_t type, arch, os, comp = IH_COMP_NONE; + size_t size; + ulong load, entry; + const void *data; +@@ -794,7 +794,6 @@ int fit_image_get_comp(const void *fit, + data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len); + if (data == NULL) { + fit_get_debug(fit, noffset, FIT_COMP_PROP, len); +- *comp = -1; + return -1; + } + +--- a/cmd/ximg.c ++++ b/cmd/ximg.c +@@ -171,11 +171,8 @@ do_imgextract(struct cmd_tbl *cmdtp, int + return 1; + } + +- if (fit_image_get_comp(fit_hdr, noffset, &comp)) { +- puts("Could not find script subimage " +- "compression type\n"); +- return 1; +- } ++ if (fit_image_get_comp(fit_hdr, noffset, &comp)) ++ comp = IH_COMP_NONE; + + data = (ulong)fit_data; + len = (ulong)fit_len; diff --git a/package/boot/uboot-mediatek/patches/100-00-clk-remove-log_ret-from-clk_get_rate.patch b/package/boot/uboot-mediatek/patches/100-00-clk-remove-log_ret-from-clk_get_rate.patch new file mode 100644 index 0000000000..30dcffd59e --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-00-clk-remove-log_ret-from-clk_get_rate.patch @@ -0,0 +1,43 @@ +From 19f2aa053d5531a9ca0ece04dca172a522d58b90 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 11:32:28 +0800 +Subject: [PATCH 32/71] clk: remove log_ret from clk_get_rate + +The return value of clk_get_rate is ulong, an unsigned type. The size of +ulong depends on the cpu architecture, i.e. 4 bytes on 32-bit CPUs and +8 bytes on 64-bit CPUs. + +However log_ret only accepts and returns value in int type, a fixed 4-byte +type. This may truncate the real clock value and cause unexpected error on +64-bit platforms. + +This patch removes log_ret to solve this issue. + +Signed-off-by: Weijie Gao +--- + drivers/clk/clk-uclass.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/clk/clk-uclass.c ++++ b/drivers/clk/clk-uclass.c +@@ -469,7 +469,6 @@ void clk_free(struct clk *clk) + ulong clk_get_rate(struct clk *clk) + { + const struct clk_ops *ops; +- int ret; + + debug("%s(clk=%p)\n", __func__, clk); + if (!clk_valid(clk)) +@@ -479,11 +478,7 @@ ulong clk_get_rate(struct clk *clk) + if (!ops->get_rate) + return -ENOSYS; + +- ret = ops->get_rate(clk); +- if (ret) +- return log_ret(ret); +- +- return 0; ++ return ops->get_rate(clk); + } + + struct clk *clk_get_parent(struct clk *clk) diff --git a/package/boot/uboot-mediatek/patches/000-mtk-09-board-mediatek-add-more-network-configurations.patch b/package/boot/uboot-mediatek/patches/100-01-board-mediatek-add-more-network-configurations.patch similarity index 56% rename from package/boot/uboot-mediatek/patches/000-mtk-09-board-mediatek-add-more-network-configurations.patch rename to package/boot/uboot-mediatek/patches/100-01-board-mediatek-add-more-network-configurations.patch index 50c2ac2e42..9591463373 100644 --- a/package/boot/uboot-mediatek/patches/000-mtk-09-board-mediatek-add-more-network-configurations.patch +++ b/package/boot/uboot-mediatek/patches/100-01-board-mediatek-add-more-network-configurations.patch @@ -1,7 +1,7 @@ -From 938ba7ed996a86c9cc7af08b69df57b8b4c09510 Mon Sep 17 00:00:00 2001 +From 97df847f8f895cc2692bb0e4e933269c275da378 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Tue, 2 Mar 2021 15:47:45 +0800 -Subject: [PATCH 02/12] board: mediatek: add more network configurations +Subject: [PATCH 35/71] board: mediatek: add more network configurations Make the network configurations uniform for mediatek boards @@ -10,7 +10,9 @@ Signed-off-by: Weijie Gao include/configs/mt7622.h | 3 ++- include/configs/mt7623.h | 1 + include/configs/mt7629.h | 1 + - 3 files changed, 4 insertions(+), 1 deletion(-) + include/configs/mt7981.h | 5 +++++ + include/configs/mt7986.h | 5 +++++ + 5 files changed, 14 insertions(+), 1 deletion(-) --- a/include/configs/mt7622.h +++ b/include/configs/mt7622.h @@ -42,3 +44,27 @@ Signed-off-by: Weijie Gao +#define CONFIG_NETMASK 255.255.255.0 #endif +--- a/include/configs/mt7981.h ++++ b/include/configs/mt7981.h +@@ -23,4 +23,9 @@ + /* DRAM */ + #define CONFIG_SYS_SDRAM_BASE 0x40000000 + ++/* Ethernet */ ++#define CONFIG_IPADDR 192.168.1.1 ++#define CONFIG_SERVERIP 192.168.1.2 ++#define CONFIG_NETMASK 255.255.255.0 ++ + #endif +--- a/include/configs/mt7986.h ++++ b/include/configs/mt7986.h +@@ -23,4 +23,9 @@ + /* DRAM */ + #define CONFIG_SYS_SDRAM_BASE 0x40000000 + ++/* Ethernet */ ++#define CONFIG_IPADDR 192.168.1.1 ++#define CONFIG_SERVERIP 192.168.1.2 ++#define CONFIG_NETMASK 255.255.255.0 ++ + #endif diff --git a/package/boot/uboot-mediatek/patches/000-mtk-14-drivers-mtd-add-support-for-MediaTek-SPI-NAND-flash-.patch b/package/boot/uboot-mediatek/patches/100-02-drivers-mtd-add-support-for-MediaTek-SPI-NAND-flash-.patch similarity index 90% rename from package/boot/uboot-mediatek/patches/000-mtk-14-drivers-mtd-add-support-for-MediaTek-SPI-NAND-flash-.patch rename to package/boot/uboot-mediatek/patches/100-02-drivers-mtd-add-support-for-MediaTek-SPI-NAND-flash-.patch index 1caa7ffd24..e2316c62c4 100644 --- a/package/boot/uboot-mediatek/patches/000-mtk-14-drivers-mtd-add-support-for-MediaTek-SPI-NAND-flash-.patch +++ b/package/boot/uboot-mediatek/patches/100-02-drivers-mtd-add-support-for-MediaTek-SPI-NAND-flash-.patch @@ -1,7 +1,7 @@ -From d6c5309185aae3d9ecf80eae8b248522d11a6136 Mon Sep 17 00:00:00 2001 +From f7704275957852cd4c4632d6da126979ef24b83a Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Tue, 2 Mar 2021 16:58:01 +0800 -Subject: [PATCH 04/12] drivers: mtd: add support for MediaTek SPI-NAND flash +Subject: [PATCH 36/71] drivers: mtd: add support for MediaTek SPI-NAND flash controller Add mtd driver for MediaTek SPI-NAND flash controller @@ -16,15 +16,15 @@ Signed-off-by: Weijie Gao drivers/mtd/Makefile | 2 + drivers/mtd/mtk-snand/Kconfig | 21 + drivers/mtd/mtk-snand/Makefile | 11 + - drivers/mtd/mtk-snand/mtk-snand-def.h | 266 ++++ - drivers/mtd/mtk-snand/mtk-snand-ecc.c | 264 ++++ + drivers/mtd/mtk-snand/mtk-snand-def.h | 271 ++++ + drivers/mtd/mtk-snand/mtk-snand-ecc.c | 395 +++++ drivers/mtd/mtk-snand/mtk-snand-ids.c | 511 +++++++ - drivers/mtd/mtk-snand/mtk-snand-mtd.c | 526 ++++++++ + drivers/mtd/mtk-snand/mtk-snand-mtd.c | 535 +++++++ drivers/mtd/mtk-snand/mtk-snand-os.c | 39 + drivers/mtd/mtk-snand/mtk-snand-os.h | 120 ++ - drivers/mtd/mtk-snand/mtk-snand.c | 1776 +++++++++++++++++++++++++ - drivers/mtd/mtk-snand/mtk-snand.h | 77 ++ - 12 files changed, 3615 insertions(+) + drivers/mtd/mtk-snand/mtk-snand.c | 1933 +++++++++++++++++++++++++ + drivers/mtd/mtk-snand/mtk-snand.h | 77 + + 12 files changed, 3917 insertions(+) create mode 100644 drivers/mtd/mtk-snand/Kconfig create mode 100644 drivers/mtd/mtk-snand/Makefile create mode 100644 drivers/mtd/mtk-snand/mtk-snand-def.h @@ -95,7 +95,7 @@ Signed-off-by: Weijie Gao +ccflags-y += -DPRIVATE_MTK_SNAND_HEADER --- /dev/null +++ b/drivers/mtd/mtk-snand/mtk-snand-def.h -@@ -0,0 +1,266 @@ +@@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. @@ -213,6 +213,9 @@ Signed-off-by: Weijie Gao + + const uint8_t *spare_sizes; + uint32_t num_spare_size; ++ ++ uint16_t latch_lat; ++ uint16_t sample_delay; +}; + +enum mtk_ecc_regs { @@ -272,6 +275,7 @@ Signed-off-by: Weijie Gao + + uint8_t *page_cache; /* Used by read/write page */ + uint8_t *buf_cache; /* Used by block bad/markbad & auto_oob */ ++ int *sect_bf; /* Used by ECC correction */ +}; + +enum mtk_snand_log_category { @@ -290,7 +294,8 @@ Signed-off-by: Weijie Gao +int mtk_snand_ecc_decoder_start(struct mtk_snand *snf); +void mtk_snand_ecc_decoder_stop(struct mtk_snand *snf); +int mtk_ecc_wait_decoder_done(struct mtk_snand *snf); -+int mtk_ecc_check_decode_error(struct mtk_snand *snf, uint32_t page); ++int mtk_ecc_check_decode_error(struct mtk_snand *snf); ++int mtk_ecc_fixup_empty_sector(struct mtk_snand *snf, uint32_t sect); + +int mtk_snand_mac_io(struct mtk_snand *snf, const uint8_t *out, uint32_t outlen, + uint8_t *in, uint32_t inlen); @@ -364,7 +369,7 @@ Signed-off-by: Weijie Gao +#endif /* _MTK_SNAND_DEF_H_ */ --- /dev/null +++ b/drivers/mtd/mtk-snand/mtk-snand-ecc.c -@@ -0,0 +1,264 @@ +@@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. @@ -599,7 +604,7 @@ Signed-off-by: Weijie Gao + return ret; +} + -+int mtk_ecc_check_decode_error(struct mtk_snand *snf, uint32_t page) ++int mtk_ecc_check_decode_error(struct mtk_snand *snf) +{ + uint32_t i, regi, fi, errnum; + uint32_t errnum_shift = snf->ecc_soc->errnum_shift; @@ -612,23 +617,154 @@ Signed-off-by: Weijie Gao + + errnum = ecc_read32(snf, ECC_DECENUM(regi)); + errnum = (errnum >> (fi * errnum_shift)) & errnum_mask; -+ if (!errnum) -+ continue; + + if (errnum <= snf->ecc_strength) { -+ if (ret >= 0) -+ ret += errnum; -+ continue; ++ snf->sect_bf[i] = errnum; ++ } else { ++ snf->sect_bf[i] = -1; ++ ret = -EBADMSG; + } -+ -+ snand_log_ecc(snf->pdev, -+ "Uncorrectable bitflips in page %u sect %u\n", -+ page, i); -+ ret = -EBADMSG; + } + + return ret; +} ++ ++static int mtk_ecc_check_buf_bitflips(struct mtk_snand *snf, const void *buf, ++ size_t len, uint32_t bitflips) ++{ ++ const uint8_t *buf8 = buf; ++ const uint32_t *buf32; ++ uint32_t d, weight; ++ ++ while (len && ((uintptr_t)buf8) % sizeof(uint32_t)) { ++ weight = hweight8(*buf8); ++ bitflips += BITS_PER_BYTE - weight; ++ buf8++; ++ len--; ++ ++ if (bitflips > snf->ecc_strength) ++ return -EBADMSG; ++ } ++ ++ buf32 = (const uint32_t *)buf8; ++ while (len >= sizeof(uint32_t)) { ++ d = *buf32; ++ ++ if (d != ~0) { ++ weight = hweight32(d); ++ bitflips += sizeof(uint32_t) * BITS_PER_BYTE - weight; ++ } ++ ++ buf32++; ++ len -= sizeof(uint32_t); ++ ++ if (bitflips > snf->ecc_strength) ++ return -EBADMSG; ++ } ++ ++ buf8 = (const uint8_t *)buf32; ++ while (len) { ++ weight = hweight8(*buf8); ++ bitflips += BITS_PER_BYTE - weight; ++ buf8++; ++ len--; ++ ++ if (bitflips > snf->ecc_strength) ++ return -EBADMSG; ++ } ++ ++ return bitflips; ++} ++ ++static int mtk_ecc_check_parity_bitflips(struct mtk_snand *snf, const void *buf, ++ uint32_t bits, uint32_t bitflips) ++{ ++ uint32_t len, i; ++ uint8_t b; ++ int rc; ++ ++ len = bits >> 3; ++ bits &= 7; ++ ++ rc = mtk_ecc_check_buf_bitflips(snf, buf, len, bitflips); ++ if (!bits || rc < 0) ++ return rc; ++ ++ bitflips = rc; ++ ++ /* We want a precise count of bits */ ++ b = ((const uint8_t *)buf)[len]; ++ for (i = 0; i < bits; i++) { ++ if (!(b & BIT(i))) ++ bitflips++; ++ } ++ ++ if (bitflips > snf->ecc_strength) ++ return -EBADMSG; ++ ++ return bitflips; ++} ++ ++static void mtk_ecc_reset_parity(void *buf, uint32_t bits) ++{ ++ uint32_t len; ++ ++ len = bits >> 3; ++ bits &= 7; ++ ++ memset(buf, 0xff, len); ++ ++ /* Only reset bits protected by ECC to 1 */ ++ if (bits) ++ ((uint8_t *)buf)[len] |= GENMASK(bits - 1, 0); ++} ++ ++int mtk_ecc_fixup_empty_sector(struct mtk_snand *snf, uint32_t sect) ++{ ++ uint32_t ecc_bytes = snf->spare_per_sector - snf->nfi_soc->fdm_size; ++ uint8_t *oob = snf->page_cache + snf->writesize; ++ uint8_t *data_ptr, *fdm_ptr, *ecc_ptr; ++ int bitflips = 0, ecc_bits, parity_bits; ++ ++ parity_bits = fls(snf->nfi_soc->sector_size * 8); ++ ecc_bits = snf->ecc_strength * parity_bits; ++ ++ data_ptr = snf->page_cache + sect * snf->nfi_soc->sector_size; ++ fdm_ptr = oob + sect * snf->nfi_soc->fdm_size; ++ ecc_ptr = oob + snf->ecc_steps * snf->nfi_soc->fdm_size + ++ sect * ecc_bytes; ++ ++ /* ++ * Check whether DATA + FDM + ECC of a sector contains correctable ++ * bitflips ++ */ ++ bitflips = mtk_ecc_check_buf_bitflips(snf, data_ptr, ++ snf->nfi_soc->sector_size, ++ bitflips); ++ if (bitflips < 0) ++ return -EBADMSG; ++ ++ bitflips = mtk_ecc_check_buf_bitflips(snf, fdm_ptr, ++ snf->nfi_soc->fdm_ecc_size, ++ bitflips); ++ if (bitflips < 0) ++ return -EBADMSG; ++ ++ bitflips = mtk_ecc_check_parity_bitflips(snf, ecc_ptr, ecc_bits, ++ bitflips); ++ if (bitflips < 0) ++ return -EBADMSG; ++ ++ if (!bitflips) ++ return 0; ++ ++ /* Reset the data of this sector to 0xff */ ++ memset(data_ptr, 0xff, snf->nfi_soc->sector_size); ++ memset(fdm_ptr, 0xff, snf->nfi_soc->fdm_ecc_size); ++ mtk_ecc_reset_parity(ecc_ptr, ecc_bits); ++ ++ return bitflips; ++} --- /dev/null +++ b/drivers/mtd/mtk-snand/mtk-snand-ids.c @@ -0,0 +1,511 @@ @@ -1145,7 +1281,7 @@ Signed-off-by: Weijie Gao +} --- /dev/null +++ b/drivers/mtd/mtk-snand/mtk-snand-mtd.c -@@ -0,0 +1,524 @@ +@@ -0,0 +1,535 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. @@ -1220,13 +1356,12 @@ Signed-off-by: Weijie Gao + start_addr += mtd->erasesize; + } + -+ if (ret) -+ instr->state = MTD_ERASE_FAILED; -+ else ++ if (!ret) { + instr->state = MTD_ERASE_DONE; -+ -+ if (ret) ++ } else { ++ instr->state = MTD_ERASE_FAILED; + ret = -EIO; ++ } + + return ret; +} @@ -1238,8 +1373,8 @@ Signed-off-by: Weijie Gao + size_t len, ooblen, maxooblen, chklen; + uint32_t col, ooboffs; + uint8_t *datcache, *oobcache; -+ bool raw = ops->mode == MTD_OPS_RAW ? true : false; -+ int ret; ++ bool ecc_failed = false, raw = ops->mode == MTD_OPS_RAW ? true : false; ++ int ret, max_bitflips = 0; + + col = addr & mtd->writesize_mask; + addr &= ~mtd->writesize_mask; @@ -1264,9 +1399,20 @@ Signed-off-by: Weijie Gao + ret = mtk_snand_read_page(msm->snf, addr, datcache, + oobcache, raw); + -+ if (ret < 0) ++ if (ret < 0 && ret != -EBADMSG) + return ret; + ++ if (ret == -EBADMSG) { ++ mtd->ecc_stats.failed++; ++ ecc_failed = true; ++ } else { ++ mtd->ecc_stats.corrected += ret; ++ max_bitflips = max_t(int, ret, max_bitflips); ++ } ++ ++ mtd->ecc_stats.corrected += ret; ++ max_bitflips = max_t(int, ret, max_bitflips); ++ + if (len) { + /* Move data */ + chklen = mtd->writesize - col; @@ -1296,7 +1442,7 @@ Signed-off-by: Weijie Gao + addr += mtd->writesize; + } + -+ return 0; ++ return ecc_failed ? -EBADMSG : max_bitflips; +} + +static int mtk_snand_mtd_read_oob(struct mtd_info *mtd, loff_t from, @@ -1620,7 +1766,7 @@ Signed-off-by: Weijie Gao + + mtd->ooblayout = &mtk_snand_ooblayout; + -+ mtd->ecc_strength = msm->cinfo.ecc_strength * msm->cinfo.num_sectors; ++ mtd->ecc_strength = msm->cinfo.ecc_strength; + mtd->bitflip_threshold = (mtd->ecc_strength * 3) / 4; + mtd->ecc_step_size = msm->cinfo.sector_size; + @@ -1659,6 +1805,7 @@ Signed-off-by: Weijie Gao +static const struct udevice_id mtk_snand_ids[] = { + { .compatible = "mediatek,mt7622-snand", .data = SNAND_SOC_MT7622 }, + { .compatible = "mediatek,mt7629-snand", .data = SNAND_SOC_MT7629 }, ++ { .compatible = "mediatek,mt7981-snand", .data = SNAND_SOC_MT7981 }, + { .compatible = "mediatek,mt7986-snand", .data = SNAND_SOC_MT7986 }, + { /* sentinel */ }, +}; @@ -1837,7 +1984,7 @@ Signed-off-by: Weijie Gao +#endif /* _MTK_SNAND_OS_H_ */ --- /dev/null +++ b/drivers/mtd/mtk-snand/mtk-snand.c -@@ -0,0 +1,1776 @@ +@@ -0,0 +1,1933 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. @@ -1897,8 +2044,16 @@ Signed-off-by: Weijie Gao +#define FIFO_WR_REMAIN_S 8 +#define FIFO_RD_REMAIN_S 0 + ++#define NFI_ADDRCNTR 0x070 ++#define SEC_CNTR GENMASK(16, 12) ++#define SEC_CNTR_S 12 ++#define NFI_SEC_CNTR(val) (((val) & SEC_CNTR) >> SEC_CNTR_S) ++ +#define NFI_STRADDR 0x080 + ++#define NFI_BYTELEN 0x084 ++#define BUS_SEC_CNTR(val) (((val) & SEC_CNTR) >> SEC_CNTR_S) ++ +#define NFI_FDM0L 0x0a0 +#define NFI_FDM0M 0x0a4 +#define NFI_FDML(n) (NFI_FDM0L + (n) * 8) @@ -1915,6 +2070,7 @@ Signed-off-by: Weijie Gao +#define NFI_MASTERSTA_MASK_7622 (MAS_ADDR | MAS_RD | MAS_WR | MAS_RDDLY) +#define AHB_BUS_BUSY BIT(1) +#define BUS_BUSY BIT(0) ++#define NFI_MASTERSTA_MASK_7981 (AHB_BUS_BUSY | BUS_BUSY) +#define NFI_MASTERSTA_MASK_7986 (AHB_BUS_BUSY | BUS_BUSY) + +/* SNFI registers */ @@ -1950,6 +2106,8 @@ Signed-off-by: Weijie Gao +#define DATA_READ_MODE_X4 2 +#define DATA_READ_MODE_DUAL 5 +#define DATA_READ_MODE_QUAD 6 ++#define LATCH_LAT_S 8 ++#define LATCH_LAT GENMASK(9, 8) +#define PG_LOAD_CUSTOM_EN BIT(7) +#define DATARD_CUSTOM_EN BIT(6) +#define CS_DESELECT_CYC_S 0 @@ -1977,6 +2135,11 @@ Signed-off-by: Weijie Gao + +static const uint8_t mt7622_spare_sizes[] = { 16, 26, 27, 28 }; + ++static const uint8_t mt7981_spare_sizes[] = { ++ 16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 61, 63, 64, ++ 67, 74 ++}; ++ +static const uint8_t mt7986_spare_sizes[] = { + 16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 61, 63, 64, + 67, 74 @@ -1993,7 +2156,9 @@ Signed-off-by: Weijie Gao + .empty_page_check = false, + .mastersta_mask = NFI_MASTERSTA_MASK_7622, + .spare_sizes = mt7622_spare_sizes, -+ .num_spare_size = ARRAY_SIZE(mt7622_spare_sizes) ++ .num_spare_size = ARRAY_SIZE(mt7622_spare_sizes), ++ .latch_lat = 0, ++ .sample_delay = 40 + }, + [SNAND_SOC_MT7629] = { + .sector_size = 512, @@ -2005,7 +2170,23 @@ Signed-off-by: Weijie Gao + .empty_page_check = false, + .mastersta_mask = NFI_MASTERSTA_MASK_7622, + .spare_sizes = mt7622_spare_sizes, -+ .num_spare_size = ARRAY_SIZE(mt7622_spare_sizes) ++ .num_spare_size = ARRAY_SIZE(mt7622_spare_sizes), ++ .latch_lat = 0, ++ .sample_delay = 40 ++ }, ++ [SNAND_SOC_MT7981] = { ++ .sector_size = 1024, ++ .max_sectors = 16, ++ .fdm_size = 8, ++ .fdm_ecc_size = 1, ++ .fifo_size = 64, ++ .bbm_swap = true, ++ .empty_page_check = true, ++ .mastersta_mask = NFI_MASTERSTA_MASK_7981, ++ .spare_sizes = mt7981_spare_sizes, ++ .num_spare_size = ARRAY_SIZE(mt7981_spare_sizes), ++ .latch_lat = 0, ++ .sample_delay = 40 + }, + [SNAND_SOC_MT7986] = { + .sector_size = 1024, @@ -2017,7 +2198,9 @@ Signed-off-by: Weijie Gao + .empty_page_check = true, + .mastersta_mask = NFI_MASTERSTA_MASK_7986, + .spare_sizes = mt7986_spare_sizes, -+ .num_spare_size = ARRAY_SIZE(mt7986_spare_sizes) ++ .num_spare_size = ARRAY_SIZE(mt7986_spare_sizes), ++ .latch_lat = 0, ++ .sample_delay = 40 + }, +}; + @@ -2189,7 +2372,7 @@ Signed-off-by: Weijie Gao + snand_log_snfi(snf->pdev, "Failed to reset SNFI MAC\n"); + + nfi_write32(snf, SNF_MISC_CTL, (2 << FIFO_RD_LTC_S) | -+ (10 << CS_DESELECT_CYC_S)); ++ (10 << CS_DESELECT_CYC_S) | (snf->nfi_soc->latch_lat << LATCH_LAT_S)); + + return ret; +} @@ -2485,9 +2668,77 @@ Signed-off-by: Weijie Gao + } +} + ++static int mtk_snand_read_ecc_parity(struct mtk_snand *snf, uint32_t page, ++ uint32_t sect, uint8_t *oob) ++{ ++ uint32_t ecc_bytes = snf->spare_per_sector - snf->nfi_soc->fdm_size; ++ uint32_t coladdr, raw_offs, offs; ++ uint8_t op[4]; ++ ++ if (sizeof(op) + ecc_bytes > SNF_GPRAM_SIZE) { ++ snand_log_snfi(snf->pdev, ++ "ECC parity size does not fit the GPRAM\n"); ++ return -ENOTSUPP; ++ } ++ ++ raw_offs = sect * snf->raw_sector_size + snf->nfi_soc->sector_size + ++ snf->nfi_soc->fdm_size; ++ offs = snf->ecc_steps * snf->nfi_soc->fdm_size + sect * ecc_bytes; ++ ++ /* Column address with plane bit */ ++ coladdr = raw_offs | mtk_snand_get_plane_address(snf, page); ++ ++ op[0] = SNAND_CMD_READ_FROM_CACHE; ++ op[1] = (coladdr >> 8) & 0xff; ++ op[2] = coladdr & 0xff; ++ op[3] = 0; ++ ++ return mtk_snand_mac_io(snf, op, sizeof(op), oob + offs, ecc_bytes); ++} ++ ++static int mtk_snand_check_ecc_result(struct mtk_snand *snf, uint32_t page) ++{ ++ uint8_t *oob = snf->page_cache + snf->writesize; ++ int i, rc, ret = 0, max_bitflips = 0; ++ ++ for (i = 0; i < snf->ecc_steps; i++) { ++ if (snf->sect_bf[i] >= 0) { ++ if (snf->sect_bf[i] > max_bitflips) ++ max_bitflips = snf->sect_bf[i]; ++ continue; ++ } ++ ++ rc = mtk_snand_read_ecc_parity(snf, page, i, oob); ++ if (rc) ++ return rc; ++ ++ rc = mtk_ecc_fixup_empty_sector(snf, i); ++ if (rc < 0) { ++ ret = -EBADMSG; ++ ++ snand_log_ecc(snf->pdev, ++ "Uncorrectable bitflips in page %u sect %u\n", ++ page, i); ++ } else if (rc) { ++ snf->sect_bf[i] = rc; ++ ++ if (snf->sect_bf[i] > max_bitflips) ++ max_bitflips = snf->sect_bf[i]; ++ ++ snand_log_ecc(snf->pdev, ++ "%u bitflip%s corrected in page %u sect %u\n", ++ rc, rc > 1 ? "s" : "", page, i); ++ } else { ++ snf->sect_bf[i] = 0; ++ } ++ } ++ ++ return ret ? ret : max_bitflips; ++} ++ +static int mtk_snand_read_cache(struct mtk_snand *snf, uint32_t page, bool raw) +{ -+ uint32_t coladdr, rwbytes, mode, len; ++ uint32_t coladdr, rwbytes, mode, len, val; + uintptr_t dma_addr; + int ret; + @@ -2507,7 +2758,8 @@ Signed-off-by: Weijie Gao + + /* Set read mode */ + mode = (uint32_t)snf->mode_rfc << DATA_READ_MODE_S; -+ nfi_rmw32(snf, SNF_MISC_CTL, DATA_READ_MODE, mode | DATARD_CUSTOM_EN); ++ nfi_rmw32(snf, SNF_MISC_CTL, DATA_READ_MODE, ++ mode | DATARD_CUSTOM_EN | (snf->nfi_soc->latch_lat << LATCH_LAT_S)); + + /* Set bytes to read */ + rwbytes = snf->ecc_steps * snf->raw_sector_size; @@ -2555,6 +2807,26 @@ Signed-off-by: Weijie Gao + goto cleanup; + } + ++ /* Wait for BUS_SEC_CNTR returning expected value */ ++ ret = read32_poll_timeout(snf->nfi_base + NFI_BYTELEN, val, ++ BUS_SEC_CNTR(val) >= snf->ecc_steps, ++ 0, SNFI_POLL_INTERVAL); ++ if (ret) { ++ snand_log_nfi(snf->pdev, ++ "Timed out waiting for BUS_SEC_CNTR\n"); ++ goto cleanup; ++ } ++ ++ /* Wait for bus becoming idle */ ++ ret = read32_poll_timeout(snf->nfi_base + NFI_MASTERSTA, val, ++ !(val & snf->nfi_soc->mastersta_mask), ++ 0, SNFI_POLL_INTERVAL); ++ if (ret) { ++ snand_log_nfi(snf->pdev, ++ "Timed out waiting for bus becoming idle\n"); ++ goto cleanup; ++ } ++ + if (!raw) { + ret = mtk_ecc_wait_decoder_done(snf); + if (ret) @@ -2562,17 +2834,10 @@ Signed-off-by: Weijie Gao + + mtk_snand_read_fdm(snf, snf->page_cache + snf->writesize); + -+ /* -+ * For new IPs, ecc error may occur on empty pages. -+ * Use an specific indication bit to check empty page. -+ */ -+ if (snf->nfi_soc->empty_page_check && -+ (nfi_read32(snf, NFI_STA) & READ_EMPTY)) -+ ret = 0; -+ else -+ ret = mtk_ecc_check_decode_error(snf, page); -+ ++ mtk_ecc_check_decode_error(snf); + mtk_snand_ecc_decoder_stop(snf); ++ ++ ret = mtk_snand_check_ecc_result(snf, page); + } + +cleanup: @@ -2581,6 +2846,7 @@ Signed-off-by: Weijie Gao + + /* Stop read */ + nfi_write32(snf, NFI_CON, 0); ++ nfi_write16(snf, NFI_CNFG, 0); + + /* Clear SNF done flag */ + nfi_rmw32(snf, SNF_STA_CTL1, 0, CUS_READ_DONE); @@ -2590,7 +2856,7 @@ Signed-off-by: Weijie Gao + nfi_read32(snf, NFI_INTR_STA); + nfi_write32(snf, NFI_INTR_EN, 0); + -+ nfi_rmw32(snf, SNF_MISC_CTL, DATARD_CUSTOM_EN, 0); ++ nfi_rmw32(snf, SNF_MISC_CTL, DATARD_CUSTOM_EN | LATCH_LAT, 0); + + return ret; +} @@ -2626,12 +2892,14 @@ Signed-off-by: Weijie Gao + void *buf, void *oob, bool raw, bool format) +{ + uint64_t die_addr; -+ uint32_t page; -+ int ret; ++ uint32_t page, dly_ctrl3; ++ int ret, retry_cnt = 0; + + die_addr = mtk_snand_select_die_address(snf, addr); + page = die_addr >> snf->writesize_shift; + ++ dly_ctrl3 = nfi_read32(snf, SNF_DLY_CTL3); ++ + ret = mtk_snand_page_op(snf, page, SNAND_CMD_READ_TO_CACHE); + if (ret) + return ret; @@ -2642,10 +2910,30 @@ Signed-off-by: Weijie Gao + return ret; + } + ++retry: + ret = mtk_snand_read_cache(snf, page, raw); + if (ret < 0 && ret != -EBADMSG) + return ret; + ++ if (ret == -EBADMSG && retry_cnt < 16) { ++ nfi_write32(snf, SNF_DLY_CTL3, retry_cnt * 2); ++ retry_cnt++; ++ goto retry; ++ } ++ ++ if (retry_cnt) { ++ if(ret == -EBADMSG) { ++ nfi_write32(snf, SNF_DLY_CTL3, dly_ctrl3); ++ snand_log_chip(snf->pdev, ++ "NFI calibration failed. Original sample delay: 0x%x\n", ++ dly_ctrl3); ++ } else { ++ snand_log_chip(snf->pdev, ++ "NFI calibration passed. New sample delay: 0x%x\n", ++ nfi_read32(snf, SNF_DLY_CTL3)); ++ } ++ } ++ + if (raw) { + if (format) { + mtk_snand_bm_swap_raw(snf); @@ -2719,7 +3007,7 @@ Signed-off-by: Weijie Gao +static int mtk_snand_program_load(struct mtk_snand *snf, uint32_t page, + bool raw) +{ -+ uint32_t coladdr, rwbytes, mode, len; ++ uint32_t coladdr, rwbytes, mode, len, val; + uintptr_t dma_addr; + int ret; + @@ -2789,6 +3077,16 @@ Signed-off-by: Weijie Gao + goto cleanup; + } + ++ /* Wait for NFI_SEC_CNTR returning expected value */ ++ ret = read32_poll_timeout(snf->nfi_base + NFI_ADDRCNTR, val, ++ NFI_SEC_CNTR(val) >= snf->ecc_steps, ++ 0, SNFI_POLL_INTERVAL); ++ if (ret) { ++ snand_log_nfi(snf->pdev, ++ "Timed out waiting for BUS_SEC_CNTR\n"); ++ goto cleanup; ++ } ++ + if (!raw) + mtk_snand_ecc_encoder_stop(snf); + @@ -2797,7 +3095,8 @@ Signed-off-by: Weijie Gao + dma_mem_unmap(snf->pdev, dma_addr, len, true); + + /* Stop write */ -+ nfi_write16(snf, NFI_CON, 0); ++ nfi_write32(snf, NFI_CON, 0); ++ nfi_write16(snf, NFI_CNFG, 0); + + /* Clear SNF done flag */ + nfi_rmw32(snf, SNF_STA_CTL1, 0, CUS_PG_DONE); @@ -3454,7 +3753,7 @@ Signed-off-by: Weijie Gao + + /* Tuning options */ + nfi_write16(snf, NFI_DEBUG_CON1, WBUF_EN); -+ nfi_write32(snf, SNF_DLY_CTL3, (40 << SFCK_SAM_DLY_S)); ++ nfi_write32(snf, SNF_DLY_CTL3, (snf->nfi_soc->sample_delay << SFCK_SAM_DLY_S)); + + /* Interrupts */ + nfi_read32(snf, NFI_INTR_STA); @@ -3523,8 +3822,8 @@ Signed-off-by: Weijie Gao + struct mtk_snand **psnf) +{ + const struct snand_flash_info *snand_info; ++ uint32_t rawpage_size, sect_bf_size; + struct mtk_snand tmpsnf, *snf; -+ uint32_t rawpage_size; + int ret; + + if (!pdata || !psnf) @@ -3565,14 +3864,19 @@ Signed-off-by: Weijie Gao + rawpage_size = snand_info->memorg.pagesize + + snand_info->memorg.sparesize; + ++ sect_bf_size = mtk_snand_socs[pdata->soc].max_sectors * ++ sizeof(*snf->sect_bf); ++ + /* Allocate memory for instance and cache */ -+ snf = generic_mem_alloc(dev, sizeof(*snf) + rawpage_size); ++ snf = generic_mem_alloc(dev, ++ sizeof(*snf) + rawpage_size + sect_bf_size); + if (!snf) { + snand_log_chip(dev, "Failed to allocate memory for instance\n"); + return -ENOMEM; + } + -+ snf->buf_cache = (uint8_t *)((uintptr_t)snf + sizeof(*snf)); ++ snf->sect_bf = (int *)((uintptr_t)snf + sizeof(*snf)); ++ snf->buf_cache = (uint8_t *)((uintptr_t)snf->sect_bf + sect_bf_size); + + /* Allocate memory for DMA buffer */ + snf->page_cache = dma_mem_alloc(dev, rawpage_size); @@ -3636,8 +3940,8 @@ Signed-off-by: Weijie Gao +enum mtk_snand_soc { + SNAND_SOC_MT7622, + SNAND_SOC_MT7629, ++ SNAND_SOC_MT7981, + SNAND_SOC_MT7986, -+ + __SNAND_SOC_MAX +}; + diff --git a/package/boot/uboot-mediatek/patches/000-mtk-15-mtd-mtk-snand-add-support-for-SPL.patch b/package/boot/uboot-mediatek/patches/100-03-mtd-mtk-snand-add-support-for-SPL.patch similarity index 93% rename from package/boot/uboot-mediatek/patches/000-mtk-15-mtd-mtk-snand-add-support-for-SPL.patch rename to package/boot/uboot-mediatek/patches/100-03-mtd-mtk-snand-add-support-for-SPL.patch index 4a06acc2dc..ac56638ff7 100644 --- a/package/boot/uboot-mediatek/patches/000-mtk-15-mtd-mtk-snand-add-support-for-SPL.patch +++ b/package/boot/uboot-mediatek/patches/100-03-mtd-mtk-snand-add-support-for-SPL.patch @@ -1,7 +1,7 @@ -From b7fb0e0674db12bcf53df4b107a17c80758ee5d3 Mon Sep 17 00:00:00 2001 +From a347e374cb338213632c6dde88dd226d64bd8b27 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 3 Mar 2021 08:57:29 +0800 -Subject: [PATCH 05/12] mtd: mtk-snand: add support for SPL +Subject: [PATCH 37/71] mtd: mtk-snand: add support for SPL Add support to initialize SPI-NAND in SPL. Add implementation for SPL NAND loader. @@ -10,8 +10,8 @@ Signed-off-by: Weijie Gao --- drivers/mtd/mtk-snand/Kconfig | 6 ++ drivers/mtd/mtk-snand/Makefile | 4 + - drivers/mtd/mtk-snand/mtk-snand-spl.c | 132 ++++++++++++++++++++++++++ - 3 files changed, 142 insertions(+) + drivers/mtd/mtk-snand/mtk-snand-spl.c | 133 ++++++++++++++++++++++++++ + 3 files changed, 143 insertions(+) create mode 100644 drivers/mtd/mtk-snand/mtk-snand-spl.c --- a/drivers/mtd/mtk-snand/Kconfig @@ -39,7 +39,7 @@ Signed-off-by: Weijie Gao ccflags-y += -DPRIVATE_MTK_SNAND_HEADER --- /dev/null +++ b/drivers/mtd/mtk-snand/mtk-snand-spl.c -@@ -0,0 +1,132 @@ +@@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. @@ -162,6 +162,7 @@ Signed-off-by: Weijie Gao +static const struct udevice_id mtk_snand_ids[] = { + { .compatible = "mediatek,mt7622-snand", .data = SNAND_SOC_MT7622 }, + { .compatible = "mediatek,mt7629-snand", .data = SNAND_SOC_MT7629 }, ++ { .compatible = "mediatek,mt7981-snand", .data = SNAND_SOC_MT7981 }, + { .compatible = "mediatek,mt7986-snand", .data = SNAND_SOC_MT7986 }, + { /* sentinel */ }, +}; diff --git a/package/boot/uboot-mediatek/patches/000-mtk-16-env-add-support-for-generic-MTD-device.patch b/package/boot/uboot-mediatek/patches/100-04-env-add-support-for-generic-MTD-device.patch similarity index 98% rename from package/boot/uboot-mediatek/patches/000-mtk-16-env-add-support-for-generic-MTD-device.patch rename to package/boot/uboot-mediatek/patches/100-04-env-add-support-for-generic-MTD-device.patch index f2e91671fb..9d6beb3ebf 100644 --- a/package/boot/uboot-mediatek/patches/000-mtk-16-env-add-support-for-generic-MTD-device.patch +++ b/package/boot/uboot-mediatek/patches/100-04-env-add-support-for-generic-MTD-device.patch @@ -1,7 +1,7 @@ -From a26620ec83fa3077f0c261046e82091f7455736f Mon Sep 17 00:00:00 2001 +From efc3e6f5d29f87a433b42f15a0b87e04b7cd498d Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 3 Mar 2021 10:11:32 +0800 -Subject: [PATCH 06/12] env: add support for generic MTD device +Subject: [PATCH 38/71] env: add support for generic MTD device Add an env driver for generic MTD device. diff --git a/package/boot/uboot-mediatek/patches/100-05-mtd-add-a-new-mtd-device-type-for-NMBM.patch b/package/boot/uboot-mediatek/patches/100-05-mtd-add-a-new-mtd-device-type-for-NMBM.patch new file mode 100644 index 0000000000..1c62130cf6 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-05-mtd-add-a-new-mtd-device-type-for-NMBM.patch @@ -0,0 +1,44 @@ +From d26a789c451068caf4bbb4d1ac7bc1f592b5493e Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 10:58:06 +0800 +Subject: [PATCH 39/71] mtd: add a new mtd device type for NMBM + +This patch adds a new mtd device type for NMBM so that mtdparts can be +correctly probed. And this also gives us an opportunity to add NMBM support +for filesystems in the future. + +Signed-off-by: Weijie Gao +--- + cmd/mtdparts.c | 3 +++ + include/jffs2/load_kernel.h | 4 +++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/cmd/mtdparts.c ++++ b/cmd/mtdparts.c +@@ -1060,6 +1060,9 @@ int mtd_id_parse(const char *id, const c + } else if (strncmp(p, "spi-nand", 8) == 0) { + *dev_type = MTD_DEV_TYPE_SPINAND; + p += 8; ++ } else if (strncmp(p, "nmbm", 4) == 0) { ++ *dev_type = MTD_DEV_TYPE_NMBM; ++ p += 4; + } else { + printf("incorrect device type in %s\n", id); + return 1; +--- a/include/jffs2/load_kernel.h ++++ b/include/jffs2/load_kernel.h +@@ -16,11 +16,13 @@ + #define MTD_DEV_TYPE_NAND 0x0002 + #define MTD_DEV_TYPE_ONENAND 0x0004 + #define MTD_DEV_TYPE_SPINAND 0x0008 ++#define MTD_DEV_TYPE_NMBM 0x0010 + + #define MTD_DEV_TYPE(type) (type == MTD_DEV_TYPE_NAND ? "nand" : \ + (type == MTD_DEV_TYPE_NOR ? "nor" : \ + (type == MTD_DEV_TYPE_ONENAND ? "onenand" : \ +- "spi-nand"))) \ ++ (type == MTD_DEV_TYPE_SPINAND ? "spi-nand" : \ ++ "nmbm")))) \ + + struct mtd_device { + struct list_head link; diff --git a/package/boot/uboot-mediatek/patches/100-06-mtd-add-core-facility-code-of-NMBM.patch b/package/boot/uboot-mediatek/patches/100-06-mtd-add-core-facility-code-of-NMBM.patch new file mode 100644 index 0000000000..9f80deb137 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-06-mtd-add-core-facility-code-of-NMBM.patch @@ -0,0 +1,3422 @@ +From 690479081fb6a0c0f77f10fb457ad69e71390f15 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 10:26:35 +0800 +Subject: [PATCH 40/71] mtd: add core facility code of NMBM + +This patch adds a NAND bad block management named NMBM (NAND mapping block +management) which supports using a mapping table to deal with bad blocks +before factory shipping and during use. + +Signed-off-by: Weijie Gao +--- + drivers/mtd/Kconfig | 2 + + drivers/mtd/Makefile | 1 + + drivers/mtd/nmbm/Kconfig | 29 + + drivers/mtd/nmbm/Makefile | 5 + + drivers/mtd/nmbm/nmbm-core.c | 2936 +++++++++++++++++++++++++++++++ + drivers/mtd/nmbm/nmbm-debug.h | 37 + + drivers/mtd/nmbm/nmbm-debug.inl | 39 + + drivers/mtd/nmbm/nmbm-private.h | 137 ++ + include/nmbm/nmbm-os.h | 66 + + include/nmbm/nmbm.h | 102 ++ + 10 files changed, 3354 insertions(+) + create mode 100644 drivers/mtd/nmbm/Kconfig + create mode 100644 drivers/mtd/nmbm/Makefile + create mode 100644 drivers/mtd/nmbm/nmbm-core.c + create mode 100644 drivers/mtd/nmbm/nmbm-debug.h + create mode 100644 drivers/mtd/nmbm/nmbm-debug.inl + create mode 100644 drivers/mtd/nmbm/nmbm-private.h + create mode 100644 include/nmbm/nmbm-os.h + create mode 100644 include/nmbm/nmbm.h + +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -174,4 +174,6 @@ source "drivers/mtd/spi/Kconfig" + + source "drivers/mtd/ubi/Kconfig" + ++source "drivers/mtd/nmbm/Kconfig" ++ + endmenu +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -41,3 +41,4 @@ obj-$(CONFIG_SPL_UBI) += ubispl/ + endif + + obj-$(CONFIG_MTK_SPI_NAND) += mtk-snand/ ++obj-$(CONFIG_NMBM) += nmbm/ +--- /dev/null ++++ b/drivers/mtd/nmbm/Kconfig +@@ -0,0 +1,29 @@ ++ ++config NMBM ++ bool "Enable NAND mapping block management" ++ default n ++ ++choice ++ prompt "Default log level" ++ depends on NMBM ++ default NMBM_LOG_LEVEL_INFO ++ ++config NMBM_LOG_LEVEL_DEBUG ++ bool "0 - Debug" ++ ++config NMBM_LOG_LEVEL_INFO ++ bool "1 - Info" ++ ++config NMBM_LOG_LEVEL_WARN ++ bool "2 - Warn" ++ ++config NMBM_LOG_LEVEL_ERR ++ bool "3 - Error" ++ ++config NMBM_LOG_LEVEL_EMERG ++ bool "4 - Emergency" ++ ++config NMBM_LOG_LEVEL_NONE ++ bool "5 - None" ++ ++endchoice +--- /dev/null ++++ b/drivers/mtd/nmbm/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# (C) Copyright 2020 MediaTek Inc. All rights reserved. ++ ++obj-$(CONFIG_NMBM) += nmbm-core.o +--- /dev/null ++++ b/drivers/mtd/nmbm/nmbm-core.c +@@ -0,0 +1,2936 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Weijie Gao ++ */ ++ ++#include "nmbm-private.h" ++ ++#include "nmbm-debug.h" ++ ++#define NMBM_VER_MAJOR 1 ++#define NMBM_VER_MINOR 0 ++#define NMBM_VER NMBM_VERSION_MAKE(NMBM_VER_MAJOR, \ ++ NMBM_VER_MINOR) ++ ++#define NMBM_ALIGN(v, a) (((v) + (a) - 1) & ~((a) - 1)) ++ ++/*****************************************************************************/ ++/* Logging related functions */ ++/*****************************************************************************/ ++ ++/* ++ * nmbm_log_lower - Print log using OS specific routine ++ * @nld: NMBM lower device structure ++ * @level: log level ++ * @fmt: format string ++ */ ++static void nmbm_log_lower(struct nmbm_lower_device *nld, ++ enum nmbm_log_category level, const char *fmt, ...) ++{ ++ va_list ap; ++ ++ if (!nld->logprint) ++ return; ++ ++ va_start(ap, fmt); ++ nld->logprint(nld->arg, level, fmt, ap); ++ va_end(ap); ++} ++ ++/* ++ * nmbm_log - Print log using OS specific routine ++ * @ni: NMBM instance structure ++ * @level: log level ++ * @fmt: format string ++ */ ++static void nmbm_log(struct nmbm_instance *ni, enum nmbm_log_category level, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ ++ if (!ni) ++ return; ++ ++ if (!ni->lower.logprint || level < ni->log_display_level) ++ return; ++ ++ va_start(ap, fmt); ++ ni->lower.logprint(ni->lower.arg, level, fmt, ap); ++ va_end(ap); ++} ++ ++/* ++ * nmbm_set_log_level - Set log display level ++ * @ni: NMBM instance structure ++ * @level: log display level ++ */ ++enum nmbm_log_category nmbm_set_log_level(struct nmbm_instance *ni, ++ enum nmbm_log_category level) ++{ ++ enum nmbm_log_category old; ++ ++ if (!ni) ++ return __NMBM_LOG_MAX; ++ ++ old = ni->log_display_level; ++ ni->log_display_level = level; ++ return old; ++} ++ ++/* ++ * nlog_table_creation - Print log of table creation event ++ * @ni: NMBM instance structure ++ * @main_table: whether the table is main info table ++ * @start_ba: start block address of the table ++ * @end_ba: block address after the end of the table ++ */ ++static void nlog_table_creation(struct nmbm_instance *ni, bool main_table, ++ uint32_t start_ba, uint32_t end_ba) ++{ ++ if (start_ba == end_ba - 1) ++ nlog_info(ni, "%s info table has been written to block %u\n", ++ main_table ? "Main" : "Backup", start_ba); ++ else ++ nlog_info(ni, "%s info table has been written to block %u-%u\n", ++ main_table ? "Main" : "Backup", start_ba, end_ba - 1); ++ ++ nmbm_mark_block_color_info_table(ni, start_ba, end_ba - 1); ++} ++ ++/* ++ * nlog_table_update - Print log of table update event ++ * @ni: NMBM instance structure ++ * @main_table: whether the table is main info table ++ * @start_ba: start block address of the table ++ * @end_ba: block address after the end of the table ++ */ ++static void nlog_table_update(struct nmbm_instance *ni, bool main_table, ++ uint32_t start_ba, uint32_t end_ba) ++{ ++ if (start_ba == end_ba - 1) ++ nlog_debug(ni, "%s info table has been updated in block %u\n", ++ main_table ? "Main" : "Backup", start_ba); ++ else ++ nlog_debug(ni, "%s info table has been updated in block %u-%u\n", ++ main_table ? "Main" : "Backup", start_ba, end_ba - 1); ++ ++ nmbm_mark_block_color_info_table(ni, start_ba, end_ba - 1); ++} ++ ++/* ++ * nlog_table_found - Print log of table found event ++ * @ni: NMBM instance structure ++ * @first_table: whether the table is first found info table ++ * @write_count: write count of the info table ++ * @start_ba: start block address of the table ++ * @end_ba: block address after the end of the table ++ */ ++static void nlog_table_found(struct nmbm_instance *ni, bool first_table, ++ uint32_t write_count, uint32_t start_ba, ++ uint32_t end_ba) ++{ ++ if (start_ba == end_ba - 1) ++ nlog_info(ni, "%s info table with writecount %u found in block %u\n", ++ first_table ? "First" : "Second", write_count, ++ start_ba); ++ else ++ nlog_info(ni, "%s info table with writecount %u found in block %u-%u\n", ++ first_table ? "First" : "Second", write_count, ++ start_ba, end_ba - 1); ++ ++ nmbm_mark_block_color_info_table(ni, start_ba, end_ba - 1); ++} ++ ++/*****************************************************************************/ ++/* Address conversion functions */ ++/*****************************************************************************/ ++ ++/* ++ * addr2ba - Convert a linear address to block address ++ * @ni: NMBM instance structure ++ * @addr: Linear address ++ */ ++static uint32_t addr2ba(struct nmbm_instance *ni, uint64_t addr) ++{ ++ return addr >> ni->erasesize_shift; ++} ++ ++/* ++ * ba2addr - Convert a block address to linear address ++ * @ni: NMBM instance structure ++ * @ba: Block address ++ */ ++static uint64_t ba2addr(struct nmbm_instance *ni, uint32_t ba) ++{ ++ return (uint64_t)ba << ni->erasesize_shift; ++} ++/* ++ * size2blk - Get minimum required blocks for storing specific size of data ++ * @ni: NMBM instance structure ++ * @size: size for storing ++ */ ++static uint32_t size2blk(struct nmbm_instance *ni, uint64_t size) ++{ ++ return (size + ni->lower.erasesize - 1) >> ni->erasesize_shift; ++} ++ ++/*****************************************************************************/ ++/* High level NAND chip APIs */ ++/*****************************************************************************/ ++ ++/* ++ * nmbm_reset_chip - Reset NAND device ++ * @nld: Lower NAND chip structure ++ */ ++static void nmbm_reset_chip(struct nmbm_instance *ni) ++{ ++ if (ni->lower.reset_chip) ++ ni->lower.reset_chip(ni->lower.arg); ++} ++ ++/* ++ * nmbm_read_phys_page - Read page with retry ++ * @ni: NMBM instance structure ++ * @addr: linear address where the data will be read from ++ * @data: the main data to be read ++ * @oob: the oob data to be read ++ * @mode: mode for processing oob data ++ * ++ * Read a page for at most NMBM_TRY_COUNT times. ++ * ++ * Return 0 for success, positive value for corrected bitflip count, ++ * -EBADMSG for ecc error, other negative values for other errors ++ */ ++static int nmbm_read_phys_page(struct nmbm_instance *ni, uint64_t addr, ++ void *data, void *oob, enum nmbm_oob_mode mode) ++{ ++ int tries, ret; ++ ++ for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { ++ ret = ni->lower.read_page(ni->lower.arg, addr, data, oob, mode); ++ if (ret >= 0) ++ return ret; ++ ++ nmbm_reset_chip(ni); ++ } ++ ++ if (ret != -EBADMSG) ++ nlog_err(ni, "Page read failed at address 0x%08llx\n", addr); ++ ++ return ret; ++} ++ ++/* ++ * nmbm_write_phys_page - Write page with retry ++ * @ni: NMBM instance structure ++ * @addr: linear address where the data will be written to ++ * @data: the main data to be written ++ * @oob: the oob data to be written ++ * @mode: mode for processing oob data ++ * ++ * Write a page for at most NMBM_TRY_COUNT times. ++ */ ++static bool nmbm_write_phys_page(struct nmbm_instance *ni, uint64_t addr, ++ const void *data, const void *oob, ++ enum nmbm_oob_mode mode) ++{ ++ int tries, ret; ++ ++ if (ni->lower.flags & NMBM_F_READ_ONLY) { ++ nlog_err(ni, "%s called with NMBM_F_READ_ONLY set\n", addr); ++ return false; ++ } ++ ++ for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { ++ ret = ni->lower.write_page(ni->lower.arg, addr, data, oob, mode); ++ if (!ret) ++ return true; ++ ++ nmbm_reset_chip(ni); ++ } ++ ++ nlog_err(ni, "Page write failed at address 0x%08llx\n", addr); ++ ++ return false; ++} ++ ++/* ++ * nmbm_erase_phys_block - Erase a block with retry ++ * @ni: NMBM instance structure ++ * @addr: Linear address ++ * ++ * Erase a block for at most NMBM_TRY_COUNT times. ++ */ ++static bool nmbm_erase_phys_block(struct nmbm_instance *ni, uint64_t addr) ++{ ++ int tries, ret; ++ ++ if (ni->lower.flags & NMBM_F_READ_ONLY) { ++ nlog_err(ni, "%s called with NMBM_F_READ_ONLY set\n", addr); ++ return false; ++ } ++ ++ for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { ++ ret = ni->lower.erase_block(ni->lower.arg, addr); ++ if (!ret) ++ return true; ++ ++ nmbm_reset_chip(ni); ++ } ++ ++ nlog_err(ni, "Block erasure failed at address 0x%08llx\n", addr); ++ ++ return false; ++} ++ ++/* ++ * nmbm_check_bad_phys_block - Check whether a block is marked bad in OOB ++ * @ni: NMBM instance structure ++ * @ba: block address ++ */ ++static bool nmbm_check_bad_phys_block(struct nmbm_instance *ni, uint32_t ba) ++{ ++ uint64_t addr = ba2addr(ni, ba); ++ int ret; ++ ++ if (ni->lower.is_bad_block) ++ return ni->lower.is_bad_block(ni->lower.arg, addr); ++ ++ /* Treat ECC error as read success */ ++ ret = nmbm_read_phys_page(ni, addr, NULL, ++ ni->page_cache + ni->lower.writesize, ++ NMBM_MODE_RAW); ++ if (ret < 0 && ret != -EBADMSG) ++ return true; ++ ++ return ni->page_cache[ni->lower.writesize] != 0xff; ++} ++ ++/* ++ * nmbm_mark_phys_bad_block - Mark a block bad ++ * @ni: NMBM instance structure ++ * @addr: Linear address ++ */ ++static int nmbm_mark_phys_bad_block(struct nmbm_instance *ni, uint32_t ba) ++{ ++ uint64_t addr = ba2addr(ni, ba); ++ enum nmbm_log_category level; ++ uint32_t off; ++ ++ if (ni->lower.flags & NMBM_F_READ_ONLY) { ++ nlog_err(ni, "%s called with NMBM_F_READ_ONLY set\n", addr); ++ return false; ++ } ++ ++ nlog_info(ni, "Block %u [0x%08llx] will be marked bad\n", ba, addr); ++ ++ if (ni->lower.mark_bad_block) ++ return ni->lower.mark_bad_block(ni->lower.arg, addr); ++ ++ /* Whole page set to 0x00 */ ++ memset(ni->page_cache, 0, ni->rawpage_size); ++ ++ /* Write to all pages within this block, disable all errors */ ++ level = nmbm_set_log_level(ni, __NMBM_LOG_MAX); ++ ++ for (off = 0; off < ni->lower.erasesize; off += ni->lower.writesize) { ++ nmbm_write_phys_page(ni, addr + off, ni->page_cache, ++ ni->page_cache + ni->lower.writesize, ++ NMBM_MODE_RAW); ++ } ++ ++ nmbm_set_log_level(ni, level); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* NMBM related functions */ ++/*****************************************************************************/ ++ ++/* ++ * nmbm_check_header - Check whether a NMBM structure is valid ++ * @data: pointer to a NMBM structure with a NMBM header at beginning ++ * @size: Size of the buffer pointed by @header ++ * ++ * The size of the NMBM structure may be larger than NMBM header, ++ * e.g. block mapping table and block state table. ++ */ ++static bool nmbm_check_header(const void *data, uint32_t size) ++{ ++ const struct nmbm_header *header = data; ++ struct nmbm_header nhdr; ++ uint32_t new_checksum; ++ ++ /* ++ * Make sure expected structure size is equal or smaller than ++ * buffer size. ++ */ ++ if (header->size > size) ++ return false; ++ ++ memcpy(&nhdr, data, sizeof(nhdr)); ++ ++ nhdr.checksum = 0; ++ new_checksum = nmbm_crc32(0, &nhdr, sizeof(nhdr)); ++ if (header->size > sizeof(nhdr)) ++ new_checksum = nmbm_crc32(new_checksum, ++ (const uint8_t *)data + sizeof(nhdr), ++ header->size - sizeof(nhdr)); ++ ++ if (header->checksum != new_checksum) ++ return false; ++ ++ return true; ++} ++ ++/* ++ * nmbm_update_checksum - Update checksum of a NMBM structure ++ * @header: pointer to a NMBM structure with a NMBM header at beginning ++ * ++ * The size of the NMBM structure must be specified by @header->size ++ */ ++static void nmbm_update_checksum(struct nmbm_header *header) ++{ ++ header->checksum = 0; ++ header->checksum = nmbm_crc32(0, header, header->size); ++} ++ ++/* ++ * nmbm_get_spare_block_count - Calculate number of blocks should be reserved ++ * @block_count: number of blocks of data ++ * ++ * Calculate number of blocks should be reserved for data ++ */ ++static uint32_t nmbm_get_spare_block_count(uint32_t block_count) ++{ ++ uint32_t val; ++ ++ val = (block_count + NMBM_SPARE_BLOCK_DIV / 2) / NMBM_SPARE_BLOCK_DIV; ++ val *= NMBM_SPARE_BLOCK_MULTI; ++ ++ if (val < NMBM_SPARE_BLOCK_MIN) ++ val = NMBM_SPARE_BLOCK_MIN; ++ ++ return val; ++} ++ ++/* ++ * nmbm_get_block_state_raw - Get state of a block from raw block state table ++ * @block_state: pointer to raw block state table (bitmap) ++ * @ba: block address ++ */ ++static uint32_t nmbm_get_block_state_raw(nmbm_bitmap_t *block_state, ++ uint32_t ba) ++{ ++ uint32_t unit, shift; ++ ++ unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT; ++ shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK; ++ ++ return (block_state[unit] >> shift) & BLOCK_ST_MASK; ++} ++ ++/* ++ * nmbm_get_block_state - Get state of a block from block state table ++ * @ni: NMBM instance structure ++ * @ba: block address ++ */ ++static uint32_t nmbm_get_block_state(struct nmbm_instance *ni, uint32_t ba) ++{ ++ return nmbm_get_block_state_raw(ni->block_state, ba); ++} ++ ++/* ++ * nmbm_set_block_state - Set state of a block to block state table ++ * @ni: NMBM instance structure ++ * @ba: block address ++ * @state: block state ++ * ++ * Set state of a block. If the block state changed, ni->block_state_changed ++ * will be increased. ++ */ ++static bool nmbm_set_block_state(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t state) ++{ ++ uint32_t unit, shift, orig; ++ nmbm_bitmap_t uv; ++ ++ unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT; ++ shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK; ++ ++ orig = (ni->block_state[unit] >> shift) & BLOCK_ST_MASK; ++ state &= BLOCK_ST_MASK; ++ ++ uv = ni->block_state[unit] & (~(BLOCK_ST_MASK << shift)); ++ uv |= state << shift; ++ ni->block_state[unit] = uv; ++ ++ if (state == BLOCK_ST_BAD) ++ nmbm_mark_block_color_bad(ni, ba); ++ ++ if (orig != state) { ++ ni->block_state_changed++; ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * nmbm_block_walk_asc - Skip specified number of good blocks, ascending addr. ++ * @ni: NMBM instance structure ++ * @ba: start physical block address ++ * @nba: return physical block address after walk ++ * @count: number of good blocks to be skipped ++ * @limit: highest block address allowed for walking ++ * ++ * Start from @ba, skipping any bad blocks, counting @count good blocks, and ++ * return the next good block address. ++ * ++ * If no enough good blocks counted while @limit reached, false will be returned. ++ * ++ * If @count == 0, nearest good block address will be returned. ++ * @limit is not counted in walking. ++ */ ++static bool nmbm_block_walk_asc(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t *nba, uint32_t count, ++ uint32_t limit) ++{ ++ int32_t nblock = count; ++ ++ if (limit >= ni->block_count) ++ limit = ni->block_count - 1; ++ ++ while (ba < limit) { ++ if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD) ++ nblock--; ++ ++ if (nblock < 0) { ++ *nba = ba; ++ return true; ++ } ++ ++ ba++; ++ } ++ ++ return false; ++} ++ ++/* ++ * nmbm_block_walk_desc - Skip specified number of good blocks, descending addr ++ * @ni: NMBM instance structure ++ * @ba: start physical block address ++ * @nba: return physical block address after walk ++ * @count: number of good blocks to be skipped ++ * @limit: lowest block address allowed for walking ++ * ++ * Start from @ba, skipping any bad blocks, counting @count good blocks, and ++ * return the next good block address. ++ * ++ * If no enough good blocks counted while @limit reached, false will be returned. ++ * ++ * If @count == 0, nearest good block address will be returned. ++ * @limit is not counted in walking. ++ */ ++static bool nmbm_block_walk_desc(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t *nba, uint32_t count, uint32_t limit) ++{ ++ int32_t nblock = count; ++ ++ if (limit >= ni->block_count) ++ limit = ni->block_count - 1; ++ ++ while (ba > limit) { ++ if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD) ++ nblock--; ++ ++ if (nblock < 0) { ++ *nba = ba; ++ return true; ++ } ++ ++ ba--; ++ } ++ ++ return false; ++} ++ ++/* ++ * nmbm_block_walk - Skip specified number of good blocks from curr. block addr ++ * @ni: NMBM instance structure ++ * @ascending: whether to walk ascending ++ * @ba: start physical block address ++ * @nba: return physical block address after walk ++ * @count: number of good blocks to be skipped ++ * @limit: highest/lowest block address allowed for walking ++ * ++ * Start from @ba, skipping any bad blocks, counting @count good blocks, and ++ * return the next good block address. ++ * ++ * If no enough good blocks counted while @limit reached, false will be returned. ++ * ++ * If @count == 0, nearest good block address will be returned. ++ * @limit can be set to negative if no limit required. ++ * @limit is not counted in walking. ++ */ ++static bool nmbm_block_walk(struct nmbm_instance *ni, bool ascending, ++ uint32_t ba, uint32_t *nba, int32_t count, ++ int32_t limit) ++{ ++ if (ascending) ++ return nmbm_block_walk_asc(ni, ba, nba, count, limit); ++ ++ return nmbm_block_walk_desc(ni, ba, nba, count, limit); ++} ++ ++/* ++ * nmbm_scan_badblocks - Scan and record all bad blocks ++ * @ni: NMBM instance structure ++ * ++ * Scan the entire lower NAND chip and record all bad blocks in to block state ++ * table. ++ */ ++static void nmbm_scan_badblocks(struct nmbm_instance *ni) ++{ ++ uint32_t ba; ++ ++ for (ba = 0; ba < ni->block_count; ba++) { ++ if (nmbm_check_bad_phys_block(ni, ba)) { ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ nlog_info(ni, "Bad block %u [0x%08llx]\n", ba, ++ ba2addr(ni, ba)); ++ } ++ } ++} ++ ++/* ++ * nmbm_build_mapping_table - Build initial block mapping table ++ * @ni: NMBM instance structure ++ * ++ * The initial mapping table will be compatible with the stratage of ++ * factory production. ++ */ ++static void nmbm_build_mapping_table(struct nmbm_instance *ni) ++{ ++ uint32_t pb, lb; ++ ++ for (pb = 0, lb = 0; pb < ni->mgmt_start_ba; pb++) { ++ if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD) ++ continue; ++ ++ /* Always map to the next good block */ ++ ni->block_mapping[lb++] = pb; ++ } ++ ++ ni->data_block_count = lb; ++ ++ /* Unusable/Management blocks */ ++ for (pb = lb; pb < ni->block_count; pb++) ++ ni->block_mapping[pb] = -1; ++} ++ ++/* ++ * nmbm_erase_block_and_check - Erase a block and check its usability ++ * @ni: NMBM instance structure ++ * @ba: block address to be erased ++ * ++ * Erase a block anc check its usability ++ * ++ * Return true if the block is usable, false if erasure failure or the block ++ * has too many bitflips. ++ */ ++static bool nmbm_erase_block_and_check(struct nmbm_instance *ni, uint32_t ba) ++{ ++ uint64_t addr, off; ++ bool success; ++ int ret; ++ ++ success = nmbm_erase_phys_block(ni, ba2addr(ni, ba)); ++ if (!success) ++ return false; ++ ++ if (!(ni->lower.flags & NMBM_F_EMPTY_PAGE_ECC_OK)) ++ return true; ++ ++ /* Check every page to make sure there aren't too many bitflips */ ++ ++ addr = ba2addr(ni, ba); ++ ++ for (off = 0; off < ni->lower.erasesize; off += ni->lower.writesize) { ++ WATCHDOG_RESET(); ++ ++ ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL, ++ NMBM_MODE_PLACE_OOB); ++ if (ret == -EBADMSG) { ++ /* ++ * NMBM_F_EMPTY_PAGE_ECC_OK means the empty page is ++ * still protected by ECC. So reading pages with ECC ++ * enabled and -EBADMSG means there are too many ++ * bitflips that can't be recovered, and the block ++ * containing the page should be marked bad. ++ */ ++ nlog_err(ni, ++ "Too many bitflips in empty page at 0x%llx\n", ++ addr + off); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++/* ++ * nmbm_erase_range - Erase a range of blocks ++ * @ni: NMBM instance structure ++ * @ba: block address where the erasure will start ++ * @limit: top block address allowed for erasure ++ * ++ * Erase blocks within the specific range. Newly-found bad blocks will be ++ * marked. ++ * ++ * @limit is not counted into the allowed erasure address. ++ */ ++static void nmbm_erase_range(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t limit) ++{ ++ bool success; ++ ++ while (ba < limit) { ++ WATCHDOG_RESET(); ++ ++ if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) ++ goto next_block; ++ ++ /* Insurance to detect unexpected bad block marked by user */ ++ if (nmbm_check_bad_phys_block(ni, ba)) { ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ goto next_block; ++ } ++ ++ success = nmbm_erase_block_and_check(ni, ba); ++ if (success) ++ goto next_block; ++ ++ nmbm_mark_phys_bad_block(ni, ba); ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ ++ next_block: ++ ba++; ++ } ++} ++ ++/* ++ * nmbm_write_repeated_data - Write critical data to a block with retry ++ * @ni: NMBM instance structure ++ * @ba: block address where the data will be written to ++ * @data: the data to be written ++ * @size: size of the data ++ * ++ * Write data to every page of the block. Success only if all pages within ++ * this block have been successfully written. ++ * ++ * Make sure data size is not bigger than one page. ++ * ++ * This function will write and verify every page for at most ++ * NMBM_TRY_COUNT times. ++ */ ++static bool nmbm_write_repeated_data(struct nmbm_instance *ni, uint32_t ba, ++ const void *data, uint32_t size) ++{ ++ uint64_t addr, off; ++ bool success; ++ int ret; ++ ++ if (size > ni->lower.writesize) ++ return false; ++ ++ addr = ba2addr(ni, ba); ++ ++ for (off = 0; off < ni->lower.erasesize; off += ni->lower.writesize) { ++ WATCHDOG_RESET(); ++ ++ /* Prepare page data. fill 0xff to unused region */ ++ memcpy(ni->page_cache, data, size); ++ memset(ni->page_cache + size, 0xff, ni->rawpage_size - size); ++ ++ success = nmbm_write_phys_page(ni, addr + off, ni->page_cache, ++ NULL, NMBM_MODE_PLACE_OOB); ++ if (!success) ++ return false; ++ ++ /* Verify the data just written. ECC error indicates failure */ ++ ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL, ++ NMBM_MODE_PLACE_OOB); ++ if (ret < 0) ++ return false; ++ ++ if (memcmp(ni->page_cache, data, size)) ++ return false; ++ } ++ ++ return true; ++} ++ ++/* ++ * nmbm_write_signature - Write signature to NAND chip ++ * @ni: NMBM instance structure ++ * @limit: top block address allowed for writing ++ * @signature: the signature to be written ++ * @signature_ba: the actual block address where signature is written to ++ * ++ * Write signature within a specific range, from chip bottom to limit. ++ * At most one block will be written. ++ * ++ * @limit is not counted into the allowed write address. ++ */ ++static bool nmbm_write_signature(struct nmbm_instance *ni, uint32_t limit, ++ const struct nmbm_signature *signature, ++ uint32_t *signature_ba) ++{ ++ uint32_t ba = ni->block_count - 1; ++ bool success; ++ ++ while (ba > limit) { ++ WATCHDOG_RESET(); ++ ++ if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) ++ goto next_block; ++ ++ /* Insurance to detect unexpected bad block marked by user */ ++ if (nmbm_check_bad_phys_block(ni, ba)) { ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ goto next_block; ++ } ++ ++ success = nmbm_erase_block_and_check(ni, ba); ++ if (!success) ++ goto skip_bad_block; ++ ++ success = nmbm_write_repeated_data(ni, ba, signature, ++ sizeof(*signature)); ++ if (success) { ++ *signature_ba = ba; ++ return true; ++ } ++ ++ skip_bad_block: ++ nmbm_mark_phys_bad_block(ni, ba); ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ ++ next_block: ++ ba--; ++ }; ++ ++ return false; ++} ++ ++/* ++ * nmbn_read_data - Read data ++ * @ni: NMBM instance structure ++ * @addr: linear address where the data will be read from ++ * @data: the data to be read ++ * @size: the size of data ++ * ++ * Read data range. ++ * Every page will be tried for at most NMBM_TRY_COUNT times. ++ * ++ * Return 0 for success, positive value for corrected bitflip count, ++ * -EBADMSG for ecc error, other negative values for other errors ++ */ ++static int nmbn_read_data(struct nmbm_instance *ni, uint64_t addr, void *data, ++ uint32_t size) ++{ ++ uint64_t off = addr; ++ uint8_t *ptr = data; ++ uint32_t sizeremain = size, chunksize, leading; ++ int ret; ++ ++ while (sizeremain) { ++ WATCHDOG_RESET(); ++ ++ leading = off & ni->writesize_mask; ++ chunksize = ni->lower.writesize - leading; ++ if (chunksize > sizeremain) ++ chunksize = sizeremain; ++ ++ if (chunksize == ni->lower.writesize) { ++ ret = nmbm_read_phys_page(ni, off - leading, ptr, NULL, ++ NMBM_MODE_PLACE_OOB); ++ if (ret < 0) ++ return ret; ++ } else { ++ ret = nmbm_read_phys_page(ni, off - leading, ++ ni->page_cache, NULL, ++ NMBM_MODE_PLACE_OOB); ++ if (ret < 0) ++ return ret; ++ ++ memcpy(ptr, ni->page_cache + leading, chunksize); ++ } ++ ++ off += chunksize; ++ ptr += chunksize; ++ sizeremain -= chunksize; ++ } ++ ++ return 0; ++} ++ ++/* ++ * nmbn_write_verify_data - Write data with validation ++ * @ni: NMBM instance structure ++ * @addr: linear address where the data will be written to ++ * @data: the data to be written ++ * @size: the size of data ++ * ++ * Write data and verify. ++ * Every page will be tried for at most NMBM_TRY_COUNT times. ++ */ ++static bool nmbn_write_verify_data(struct nmbm_instance *ni, uint64_t addr, ++ const void *data, uint32_t size) ++{ ++ uint64_t off = addr; ++ const uint8_t *ptr = data; ++ uint32_t sizeremain = size, chunksize, leading; ++ bool success; ++ int ret; ++ ++ while (sizeremain) { ++ WATCHDOG_RESET(); ++ ++ leading = off & ni->writesize_mask; ++ chunksize = ni->lower.writesize - leading; ++ if (chunksize > sizeremain) ++ chunksize = sizeremain; ++ ++ /* Prepare page data. fill 0xff to unused region */ ++ memset(ni->page_cache, 0xff, ni->rawpage_size); ++ memcpy(ni->page_cache + leading, ptr, chunksize); ++ ++ success = nmbm_write_phys_page(ni, off - leading, ++ ni->page_cache, NULL, ++ NMBM_MODE_PLACE_OOB); ++ if (!success) ++ return false; ++ ++ /* Verify the data just written. ECC error indicates failure */ ++ ret = nmbm_read_phys_page(ni, off - leading, ni->page_cache, ++ NULL, NMBM_MODE_PLACE_OOB); ++ if (ret < 0) ++ return false; ++ ++ if (memcmp(ni->page_cache + leading, ptr, chunksize)) ++ return false; ++ ++ off += chunksize; ++ ptr += chunksize; ++ sizeremain -= chunksize; ++ } ++ ++ return true; ++} ++ ++/* ++ * nmbm_write_mgmt_range - Write management data into NAND within a range ++ * @ni: NMBM instance structure ++ * @addr: preferred start block address for writing ++ * @limit: highest block address allowed for writing ++ * @data: the data to be written ++ * @size: the size of data ++ * @actual_start_ba: actual start block address of data ++ * @actual_end_ba: block address after the end of data ++ * ++ * @limit is not counted into the allowed write address. ++ */ ++static bool nmbm_write_mgmt_range(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t limit, const void *data, ++ uint32_t size, uint32_t *actual_start_ba, ++ uint32_t *actual_end_ba) ++{ ++ const uint8_t *ptr = data; ++ uint32_t sizeremain = size, chunksize; ++ bool success; ++ ++ while (sizeremain && ba < limit) { ++ WATCHDOG_RESET(); ++ ++ chunksize = sizeremain; ++ if (chunksize > ni->lower.erasesize) ++ chunksize = ni->lower.erasesize; ++ ++ if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) ++ goto next_block; ++ ++ /* Insurance to detect unexpected bad block marked by user */ ++ if (nmbm_check_bad_phys_block(ni, ba)) { ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ goto next_block; ++ } ++ ++ success = nmbm_erase_block_and_check(ni, ba); ++ if (!success) ++ goto skip_bad_block; ++ ++ success = nmbn_write_verify_data(ni, ba2addr(ni, ba), ptr, ++ chunksize); ++ if (!success) ++ goto skip_bad_block; ++ ++ if (sizeremain == size) ++ *actual_start_ba = ba; ++ ++ ptr += chunksize; ++ sizeremain -= chunksize; ++ ++ goto next_block; ++ ++ skip_bad_block: ++ nmbm_mark_phys_bad_block(ni, ba); ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ ++ next_block: ++ ba++; ++ } ++ ++ if (sizeremain) ++ return false; ++ ++ *actual_end_ba = ba; ++ ++ return true; ++} ++ ++/* ++ * nmbm_generate_info_table_cache - Generate info table cache data ++ * @ni: NMBM instance structure ++ * ++ * Generate info table cache data to be written into flash. ++ */ ++static bool nmbm_generate_info_table_cache(struct nmbm_instance *ni) ++{ ++ bool changed = false; ++ ++ memset(ni->info_table_cache, 0xff, ni->info_table_size); ++ ++ memcpy(ni->info_table_cache + ni->info_table.state_table_off, ++ ni->block_state, ni->state_table_size); ++ ++ memcpy(ni->info_table_cache + ni->info_table.mapping_table_off, ++ ni->block_mapping, ni->mapping_table_size); ++ ++ ni->info_table.header.magic = NMBM_MAGIC_INFO_TABLE; ++ ni->info_table.header.version = NMBM_VER; ++ ni->info_table.header.size = ni->info_table_size; ++ ++ if (ni->block_state_changed || ni->block_mapping_changed) { ++ ni->info_table.write_count++; ++ changed = true; ++ } ++ ++ memcpy(ni->info_table_cache, &ni->info_table, sizeof(ni->info_table)); ++ ++ nmbm_update_checksum((struct nmbm_header *)ni->info_table_cache); ++ ++ return changed; ++} ++ ++/* ++ * nmbm_write_info_table - Write info table into NAND within a range ++ * @ni: NMBM instance structure ++ * @ba: preferred start block address for writing ++ * @limit: highest block address allowed for writing ++ * @actual_start_ba: actual start block address of info table ++ * @actual_end_ba: block address after the end of info table ++ * ++ * @limit is counted into the allowed write address. ++ */ ++static bool nmbm_write_info_table(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t limit, uint32_t *actual_start_ba, ++ uint32_t *actual_end_ba) ++{ ++ return nmbm_write_mgmt_range(ni, ba, limit, ni->info_table_cache, ++ ni->info_table_size, actual_start_ba, ++ actual_end_ba); ++} ++ ++/* ++ * nmbm_mark_tables_clean - Mark info table `clean' ++ * @ni: NMBM instance structure ++ */ ++static void nmbm_mark_tables_clean(struct nmbm_instance *ni) ++{ ++ ni->block_state_changed = 0; ++ ni->block_mapping_changed = 0; ++} ++ ++/* ++ * nmbm_try_reserve_blocks - Reserve blocks with compromisation ++ * @ni: NMBM instance structure ++ * @ba: start physical block address ++ * @nba: return physical block address after reservation ++ * @count: number of good blocks to be skipped ++ * @min_count: minimum number of good blocks to be skipped ++ * @limit: highest/lowest block address allowed for walking ++ * ++ * Reserve specific blocks. If failed, try to reserve as many as possible. ++ */ ++static bool nmbm_try_reserve_blocks(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t *nba, uint32_t count, ++ int32_t min_count, int32_t limit) ++{ ++ int32_t nblocks = count; ++ bool success; ++ ++ while (nblocks >= min_count) { ++ success = nmbm_block_walk(ni, true, ba, nba, nblocks, limit); ++ if (success) ++ return true; ++ ++ nblocks--; ++ } ++ ++ return false; ++} ++ ++/* ++ * nmbm_rebuild_info_table - Build main & backup info table from scratch ++ * @ni: NMBM instance structure ++ * @allow_no_gap: allow no spare blocks between two tables ++ */ ++static bool nmbm_rebuild_info_table(struct nmbm_instance *ni) ++{ ++ uint32_t table_start_ba, table_end_ba, next_start_ba; ++ uint32_t main_table_end_ba; ++ bool success; ++ ++ /* Set initial value */ ++ ni->main_table_ba = 0; ++ ni->backup_table_ba = 0; ++ ni->mapping_blocks_ba = ni->mapping_blocks_top_ba; ++ ++ /* Write main table */ ++ success = nmbm_write_info_table(ni, ni->mgmt_start_ba, ++ ni->mapping_blocks_top_ba, ++ &table_start_ba, &table_end_ba); ++ if (!success) { ++ /* Failed to write main table, data will be lost */ ++ nlog_emerg(ni, "Unable to write at least one info table!\n"); ++ nlog_emerg(ni, "Please save your data before power off!\n"); ++ ni->protected = 1; ++ return false; ++ } ++ ++ /* Main info table is successfully written, record its offset */ ++ ni->main_table_ba = table_start_ba; ++ main_table_end_ba = table_end_ba; ++ ++ /* Adjust mapping_blocks_ba */ ++ ni->mapping_blocks_ba = table_end_ba; ++ ++ nmbm_mark_tables_clean(ni); ++ ++ nlog_table_creation(ni, true, table_start_ba, table_end_ba); ++ ++ /* Reserve spare blocks for main info table. */ ++ success = nmbm_try_reserve_blocks(ni, table_end_ba, ++ &next_start_ba, ++ ni->info_table_spare_blocks, 0, ++ ni->mapping_blocks_top_ba - ++ size2blk(ni, ni->info_table_size)); ++ if (!success) { ++ /* There is no spare block. */ ++ nlog_debug(ni, "No room for backup info table\n"); ++ return true; ++ } ++ ++ /* Write backup info table. */ ++ success = nmbm_write_info_table(ni, next_start_ba, ++ ni->mapping_blocks_top_ba, ++ &table_start_ba, &table_end_ba); ++ if (!success) { ++ /* There is no enough blocks for backup table. */ ++ nlog_debug(ni, "No room for backup info table\n"); ++ return true; ++ } ++ ++ /* Backup table is successfully written, record its offset */ ++ ni->backup_table_ba = table_start_ba; ++ ++ /* Adjust mapping_blocks_off */ ++ ni->mapping_blocks_ba = table_end_ba; ++ ++ /* Erase spare blocks of main table to clean possible interference data */ ++ nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba); ++ ++ nlog_table_creation(ni, false, table_start_ba, table_end_ba); ++ ++ return true; ++} ++ ++/* ++ * nmbm_rescue_single_info_table - Rescue when there is only one info table ++ * @ni: NMBM instance structure ++ * ++ * This function is called when there is only one info table exists. ++ * This function may fail if we can't write new info table ++ */ ++static bool nmbm_rescue_single_info_table(struct nmbm_instance *ni) ++{ ++ uint32_t table_start_ba, table_end_ba, write_ba; ++ bool success; ++ ++ /* Try to write new info table in front of existing table */ ++ success = nmbm_write_info_table(ni, ni->mgmt_start_ba, ++ ni->main_table_ba, ++ &table_start_ba, ++ &table_end_ba); ++ if (success) { ++ /* ++ * New table becomes the main table, existing table becomes ++ * the backup table. ++ */ ++ ni->backup_table_ba = ni->main_table_ba; ++ ni->main_table_ba = table_start_ba; ++ ++ nmbm_mark_tables_clean(ni); ++ ++ /* Erase spare blocks of main table to clean possible interference data */ ++ nmbm_erase_range(ni, table_end_ba, ni->backup_table_ba); ++ ++ nlog_table_creation(ni, true, table_start_ba, table_end_ba); ++ ++ return true; ++ } ++ ++ /* Try to reserve spare blocks for existing table */ ++ success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba, ++ ni->info_table_spare_blocks, 0, ++ ni->mapping_blocks_top_ba - ++ size2blk(ni, ni->info_table_size)); ++ if (!success) { ++ nlog_warn(ni, "Failed to rescue single info table\n"); ++ return false; ++ } ++ ++ /* Try to write new info table next to the existing table */ ++ while (write_ba >= ni->mapping_blocks_ba) { ++ WATCHDOG_RESET(); ++ ++ success = nmbm_write_info_table(ni, write_ba, ++ ni->mapping_blocks_top_ba, ++ &table_start_ba, ++ &table_end_ba); ++ if (success) ++ break; ++ ++ write_ba--; ++ } ++ ++ if (success) { ++ /* Erase spare blocks of main table to clean possible interference data */ ++ nmbm_erase_range(ni, ni->mapping_blocks_ba, table_start_ba); ++ ++ /* New table becomes the backup table */ ++ ni->backup_table_ba = table_start_ba; ++ ni->mapping_blocks_ba = table_end_ba; ++ ++ nmbm_mark_tables_clean(ni); ++ ++ nlog_table_creation(ni, false, table_start_ba, table_end_ba); ++ ++ return true; ++ } ++ ++ nlog_warn(ni, "Failed to rescue single info table\n"); ++ return false; ++} ++ ++/* ++ * nmbm_update_single_info_table - Update specific one info table ++ * @ni: NMBM instance structure ++ */ ++static bool nmbm_update_single_info_table(struct nmbm_instance *ni, ++ bool update_main_table) ++{ ++ uint32_t write_start_ba, write_limit, table_start_ba, table_end_ba; ++ bool success; ++ ++ /* Determine the write range */ ++ if (update_main_table) { ++ write_start_ba = ni->main_table_ba; ++ write_limit = ni->backup_table_ba; ++ } else { ++ write_start_ba = ni->backup_table_ba; ++ write_limit = ni->mapping_blocks_top_ba; ++ } ++ ++ nmbm_mark_block_color_mgmt(ni, write_start_ba, write_limit - 1); ++ ++ success = nmbm_write_info_table(ni, write_start_ba, write_limit, ++ &table_start_ba, &table_end_ba); ++ if (success) { ++ if (update_main_table) { ++ ni->main_table_ba = table_start_ba; ++ } else { ++ ni->backup_table_ba = table_start_ba; ++ ni->mapping_blocks_ba = table_end_ba; ++ } ++ ++ nmbm_mark_tables_clean(ni); ++ ++ nlog_table_update(ni, update_main_table, table_start_ba, ++ table_end_ba); ++ ++ return true; ++ } ++ ++ if (update_main_table) { ++ /* ++ * If failed to update main table, make backup table the new ++ * main table, and call nmbm_rescue_single_info_table() ++ */ ++ nlog_warn(ni, "Unable to update %s info table\n", ++ update_main_table ? "Main" : "Backup"); ++ ++ ni->main_table_ba = ni->backup_table_ba; ++ ni->backup_table_ba = 0; ++ return nmbm_rescue_single_info_table(ni); ++ } ++ ++ /* Only one table left */ ++ ni->mapping_blocks_ba = ni->backup_table_ba; ++ ni->backup_table_ba = 0; ++ ++ return false; ++} ++ ++/* ++ * nmbm_rescue_main_info_table - Rescue when failed to write main info table ++ * @ni: NMBM instance structure ++ * ++ * This function is called when main info table failed to be written, and ++ * backup info table exists. ++ */ ++static bool nmbm_rescue_main_info_table(struct nmbm_instance *ni) ++{ ++ uint32_t tmp_table_start_ba, tmp_table_end_ba, main_table_start_ba; ++ uint32_t main_table_end_ba, write_ba; ++ uint32_t info_table_erasesize = size2blk(ni, ni->info_table_size); ++ bool success; ++ ++ /* Try to reserve spare blocks for existing backup info table */ ++ success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba, ++ ni->info_table_spare_blocks, 0, ++ ni->mapping_blocks_top_ba - ++ info_table_erasesize); ++ if (!success) { ++ /* There is no spare block. Backup info table becomes the main table. */ ++ nlog_err(ni, "No room for temporary info table\n"); ++ ni->main_table_ba = ni->backup_table_ba; ++ ni->backup_table_ba = 0; ++ return true; ++ } ++ ++ /* Try to write temporary info table into spare unmapped blocks */ ++ while (write_ba >= ni->mapping_blocks_ba) { ++ WATCHDOG_RESET(); ++ ++ success = nmbm_write_info_table(ni, write_ba, ++ ni->mapping_blocks_top_ba, ++ &tmp_table_start_ba, ++ &tmp_table_end_ba); ++ if (success) ++ break; ++ ++ write_ba--; ++ } ++ ++ if (!success) { ++ /* Backup info table becomes the main table */ ++ nlog_err(ni, "Failed to update main info table\n"); ++ ni->main_table_ba = ni->backup_table_ba; ++ ni->backup_table_ba = 0; ++ return true; ++ } ++ ++ /* Adjust mapping_blocks_off */ ++ ni->mapping_blocks_ba = tmp_table_end_ba; ++ ++ nmbm_mark_block_color_mgmt(ni, ni->backup_table_ba, ++ tmp_table_end_ba - 1); ++ ++ /* ++ * Now write main info table at the beginning of management area. ++ * This operation will generally destroy the original backup info ++ * table. ++ */ ++ success = nmbm_write_info_table(ni, ni->mgmt_start_ba, ++ tmp_table_start_ba, ++ &main_table_start_ba, ++ &main_table_end_ba); ++ if (!success) { ++ /* Temporary info table becomes the main table */ ++ ni->main_table_ba = tmp_table_start_ba; ++ ni->backup_table_ba = 0; ++ ++ nmbm_mark_tables_clean(ni); ++ ++ nlog_err(ni, "Failed to update main info table\n"); ++ nmbm_mark_block_color_info_table(ni, tmp_table_start_ba, ++ tmp_table_end_ba - 1); ++ ++ return true; ++ } ++ ++ /* Main info table has been successfully written, record its offset */ ++ ni->main_table_ba = main_table_start_ba; ++ ++ nmbm_mark_tables_clean(ni); ++ ++ nlog_table_creation(ni, true, main_table_start_ba, main_table_end_ba); ++ ++ /* ++ * Temporary info table becomes the new backup info table if it's ++ * not overwritten. ++ */ ++ if (main_table_end_ba <= tmp_table_start_ba) { ++ ni->backup_table_ba = tmp_table_start_ba; ++ ++ nlog_table_creation(ni, false, tmp_table_start_ba, ++ tmp_table_end_ba); ++ ++ return true; ++ } ++ ++ /* Adjust mapping_blocks_off */ ++ ni->mapping_blocks_ba = main_table_end_ba; ++ ++ /* Try to reserve spare blocks for new main info table */ ++ success = nmbm_try_reserve_blocks(ni, main_table_end_ba, &write_ba, ++ ni->info_table_spare_blocks, 0, ++ ni->mapping_blocks_top_ba - ++ info_table_erasesize); ++ if (!success) { ++ /* There is no spare block. Only main table exists. */ ++ nlog_err(ni, "No room for backup info table\n"); ++ ni->backup_table_ba = 0; ++ return true; ++ } ++ ++ /* Write new backup info table. */ ++ while (write_ba >= main_table_end_ba) { ++ WATCHDOG_RESET(); ++ ++ success = nmbm_write_info_table(ni, write_ba, ++ ni->mapping_blocks_top_ba, ++ &tmp_table_start_ba, ++ &tmp_table_end_ba); ++ if (success) ++ break; ++ ++ write_ba--; ++ } ++ ++ if (!success) { ++ nlog_err(ni, "No room for backup info table\n"); ++ ni->backup_table_ba = 0; ++ return true; ++ } ++ ++ /* Backup info table has been successfully written, record its offset */ ++ ni->backup_table_ba = tmp_table_start_ba; ++ ++ /* Adjust mapping_blocks_off */ ++ ni->mapping_blocks_ba = tmp_table_end_ba; ++ ++ /* Erase spare blocks of main table to clean possible interference data */ ++ nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba); ++ ++ nlog_table_creation(ni, false, tmp_table_start_ba, tmp_table_end_ba); ++ ++ return true; ++} ++ ++/* ++ * nmbm_update_info_table_once - Update info table once ++ * @ni: NMBM instance structure ++ * @force: force update ++ * ++ * Update both main and backup info table. Return true if at least one info ++ * table has been successfully written. ++ * This function only try to update info table once regard less of the result. ++ */ ++static bool nmbm_update_info_table_once(struct nmbm_instance *ni, bool force) ++{ ++ uint32_t table_start_ba, table_end_ba; ++ uint32_t main_table_limit; ++ bool success; ++ ++ /* Do nothing if there is no change */ ++ if (!nmbm_generate_info_table_cache(ni) && !force) ++ return true; ++ ++ /* Check whether both two tables exist */ ++ if (!ni->backup_table_ba) { ++ main_table_limit = ni->mapping_blocks_top_ba; ++ goto write_main_table; ++ } ++ ++ nmbm_mark_block_color_mgmt(ni, ni->backup_table_ba, ++ ni->mapping_blocks_ba - 1); ++ ++ /* ++ * Write backup info table in its current range. ++ * Note that limit is set to mapping_blocks_top_off to provide as many ++ * spare blocks as possible for the backup table. If at last ++ * unmapped blocks are used by backup table, mapping_blocks_off will ++ * be adjusted. ++ */ ++ success = nmbm_write_info_table(ni, ni->backup_table_ba, ++ ni->mapping_blocks_top_ba, ++ &table_start_ba, &table_end_ba); ++ if (!success) { ++ /* ++ * There is nothing to do if failed to write backup table. ++ * Write the main table now. ++ */ ++ nlog_err(ni, "No room for backup table\n"); ++ ni->mapping_blocks_ba = ni->backup_table_ba; ++ ni->backup_table_ba = 0; ++ main_table_limit = ni->mapping_blocks_top_ba; ++ goto write_main_table; ++ } ++ ++ /* Backup table is successfully written, record its offset */ ++ ni->backup_table_ba = table_start_ba; ++ ++ /* Adjust mapping_blocks_off */ ++ ni->mapping_blocks_ba = table_end_ba; ++ ++ nmbm_mark_tables_clean(ni); ++ ++ /* The normal limit of main table */ ++ main_table_limit = ni->backup_table_ba; ++ ++ nlog_table_update(ni, false, table_start_ba, table_end_ba); ++ ++write_main_table: ++ if (!ni->main_table_ba) ++ goto rebuild_tables; ++ ++ if (!ni->backup_table_ba) ++ nmbm_mark_block_color_mgmt(ni, ni->mgmt_start_ba, ++ ni->mapping_blocks_ba - 1); ++ else ++ nmbm_mark_block_color_mgmt(ni, ni->mgmt_start_ba, ++ ni->backup_table_ba - 1); ++ ++ /* Write main info table in its current range */ ++ success = nmbm_write_info_table(ni, ni->main_table_ba, ++ main_table_limit, &table_start_ba, ++ &table_end_ba); ++ if (!success) { ++ /* If failed to write main table, go rescue procedure */ ++ if (!ni->backup_table_ba) ++ goto rebuild_tables; ++ ++ return nmbm_rescue_main_info_table(ni); ++ } ++ ++ /* Main info table is successfully written, record its offset */ ++ ni->main_table_ba = table_start_ba; ++ ++ /* Adjust mapping_blocks_off */ ++ if (!ni->backup_table_ba) ++ ni->mapping_blocks_ba = table_end_ba; ++ ++ nmbm_mark_tables_clean(ni); ++ ++ nlog_table_update(ni, true, table_start_ba, table_end_ba); ++ ++ return true; ++ ++rebuild_tables: ++ return nmbm_rebuild_info_table(ni); ++} ++ ++/* ++ * nmbm_update_info_table - Update info table ++ * @ni: NMBM instance structure ++ * ++ * Update both main and backup info table. Return true if at least one table ++ * has been successfully written. ++ * This function will try to update info table repeatedly until no new bad ++ * block found during updating. ++ */ ++static bool nmbm_update_info_table(struct nmbm_instance *ni) ++{ ++ bool success; ++ ++ if (ni->protected) ++ return true; ++ ++ while (ni->block_state_changed || ni->block_mapping_changed) { ++ success = nmbm_update_info_table_once(ni, false); ++ if (!success) { ++ nlog_err(ni, "Failed to update info table\n"); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++/* ++ * nmbm_map_block - Map a bad block to a unused spare block ++ * @ni: NMBM instance structure ++ * @lb: logic block addr to map ++ */ ++static bool nmbm_map_block(struct nmbm_instance *ni, uint32_t lb) ++{ ++ uint32_t pb; ++ bool success; ++ ++ if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) { ++ nlog_warn(ni, "No spare unmapped blocks.\n"); ++ return false; ++ } ++ ++ success = nmbm_block_walk(ni, false, ni->mapping_blocks_top_ba, &pb, 0, ++ ni->mapping_blocks_ba); ++ if (!success) { ++ nlog_warn(ni, "No spare unmapped blocks.\n"); ++ nmbm_update_info_table(ni); ++ ni->mapping_blocks_top_ba = ni->mapping_blocks_ba; ++ return false; ++ } ++ ++ ni->block_mapping[lb] = pb; ++ ni->mapping_blocks_top_ba--; ++ ni->block_mapping_changed++; ++ ++ nlog_info(ni, "Logic block %u mapped to physical blcok %u\n", lb, pb); ++ nmbm_mark_block_color_mapped(ni, pb); ++ ++ return true; ++} ++ ++/* ++ * nmbm_create_info_table - Create info table(s) ++ * @ni: NMBM instance structure ++ * ++ * This function assumes that the chip has no existing info table(s) ++ */ ++static bool nmbm_create_info_table(struct nmbm_instance *ni) ++{ ++ uint32_t lb; ++ bool success; ++ ++ /* Set initial mapping_blocks_top_off */ ++ success = nmbm_block_walk(ni, false, ni->signature_ba, ++ &ni->mapping_blocks_top_ba, 1, ++ ni->mgmt_start_ba); ++ if (!success) { ++ nlog_err(ni, "No room for spare blocks\n"); ++ return false; ++ } ++ ++ /* Generate info table cache */ ++ nmbm_generate_info_table_cache(ni); ++ ++ /* Write info table */ ++ success = nmbm_rebuild_info_table(ni); ++ if (!success) { ++ nlog_err(ni, "Failed to build info tables\n"); ++ return false; ++ } ++ ++ /* Remap bad block(s) at end of data area */ ++ for (lb = ni->data_block_count; lb < ni->mgmt_start_ba; lb++) { ++ success = nmbm_map_block(ni, lb); ++ if (!success) ++ break; ++ ++ ni->data_block_count++; ++ } ++ ++ /* If state table and/or mapping table changed, update info table. */ ++ success = nmbm_update_info_table(ni); ++ if (!success) ++ return false; ++ ++ return true; ++} ++ ++/* ++ * nmbm_create_new - Create NMBM on a new chip ++ * @ni: NMBM instance structure ++ */ ++static bool nmbm_create_new(struct nmbm_instance *ni) ++{ ++ bool success; ++ ++ /* Determine the boundary of management blocks */ ++ ni->mgmt_start_ba = ni->block_count * (NMBM_MGMT_DIV - ni->lower.max_ratio) / NMBM_MGMT_DIV; ++ ++ if (ni->lower.max_reserved_blocks && ni->block_count - ni->mgmt_start_ba > ni->lower.max_reserved_blocks) ++ ni->mgmt_start_ba = ni->block_count - ni->lower.max_reserved_blocks; ++ ++ nlog_info(ni, "NMBM management region starts at block %u [0x%08llx]\n", ++ ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba)); ++ nmbm_mark_block_color_mgmt(ni, ni->mgmt_start_ba, ni->block_count - 1); ++ ++ /* Fill block state table & mapping table */ ++ nmbm_scan_badblocks(ni); ++ nmbm_build_mapping_table(ni); ++ ++ /* Write signature */ ++ ni->signature.header.magic = NMBM_MAGIC_SIGNATURE; ++ ni->signature.header.version = NMBM_VER; ++ ni->signature.header.size = sizeof(ni->signature); ++ ni->signature.nand_size = ni->lower.size; ++ ni->signature.block_size = ni->lower.erasesize; ++ ni->signature.page_size = ni->lower.writesize; ++ ni->signature.spare_size = ni->lower.oobsize; ++ ni->signature.mgmt_start_pb = ni->mgmt_start_ba; ++ ni->signature.max_try_count = NMBM_TRY_COUNT; ++ nmbm_update_checksum(&ni->signature.header); ++ ++ if (ni->lower.flags & NMBM_F_READ_ONLY) { ++ nlog_info(ni, "NMBM has been initialized in read-only mode\n"); ++ return true; ++ } ++ ++ success = nmbm_write_signature(ni, ni->mgmt_start_ba, ++ &ni->signature, &ni->signature_ba); ++ if (!success) { ++ nlog_err(ni, "Failed to write signature to a proper offset\n"); ++ return false; ++ } ++ ++ nlog_info(ni, "Signature has been written to block %u [0x%08llx]\n", ++ ni->signature_ba, ba2addr(ni, ni->signature_ba)); ++ nmbm_mark_block_color_signature(ni, ni->signature_ba); ++ ++ /* Write info table(s) */ ++ success = nmbm_create_info_table(ni); ++ if (success) { ++ nlog_info(ni, "NMBM has been successfully created\n"); ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * nmbm_check_info_table_header - Check if a info table header is valid ++ * @ni: NMBM instance structure ++ * @data: pointer to the info table header ++ */ ++static bool nmbm_check_info_table_header(struct nmbm_instance *ni, void *data) ++{ ++ struct nmbm_info_table_header *ifthdr = data; ++ ++ if (ifthdr->header.magic != NMBM_MAGIC_INFO_TABLE) ++ return false; ++ ++ if (ifthdr->header.size != ni->info_table_size) ++ return false; ++ ++ if (ifthdr->mapping_table_off - ifthdr->state_table_off < ni->state_table_size) ++ return false; ++ ++ if (ni->info_table_size - ifthdr->mapping_table_off < ni->mapping_table_size) ++ return false; ++ ++ return true; ++} ++ ++/* ++ * nmbm_check_info_table - Check if a whole info table is valid ++ * @ni: NMBM instance structure ++ * @start_ba: start block address of this table ++ * @end_ba: end block address of this table ++ * @data: pointer to the info table header ++ * @mapping_blocks_top_ba: return the block address of top remapped block ++ */ ++static bool nmbm_check_info_table(struct nmbm_instance *ni, uint32_t start_ba, ++ uint32_t end_ba, void *data, ++ uint32_t *mapping_blocks_top_ba) ++{ ++ struct nmbm_info_table_header *ifthdr = data; ++ int32_t *block_mapping = (int32_t *)((uintptr_t)data + ifthdr->mapping_table_off); ++ nmbm_bitmap_t *block_state = (nmbm_bitmap_t *)((uintptr_t)data + ifthdr->state_table_off); ++ uint32_t minimum_mapping_pb = ni->signature_ba; ++ uint32_t ba; ++ ++ for (ba = 0; ba < ni->data_block_count; ba++) { ++ if ((block_mapping[ba] >= ni->data_block_count && block_mapping[ba] < end_ba) || ++ block_mapping[ba] == ni->signature_ba) ++ return false; ++ ++ if (block_mapping[ba] >= end_ba && block_mapping[ba] < minimum_mapping_pb) ++ minimum_mapping_pb = block_mapping[ba]; ++ } ++ ++ for (ba = start_ba; ba < end_ba; ba++) { ++ if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) ++ continue; ++ ++ if (nmbm_get_block_state_raw(block_state, ba) != BLOCK_ST_GOOD) ++ return false; ++ } ++ ++ *mapping_blocks_top_ba = minimum_mapping_pb - 1; ++ ++ return true; ++} ++ ++/* ++ * nmbm_try_load_info_table - Try to load info table from a address ++ * @ni: NMBM instance structure ++ * @ba: start block address of the info table ++ * @eba: return the block address after end of the table ++ * @write_count: return the write count of this table ++ * @mapping_blocks_top_ba: return the block address of top remapped block ++ * @table_loaded: used to record whether ni->info_table has valid data ++ */ ++static bool nmbm_try_load_info_table(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t *eba, uint32_t *write_count, ++ uint32_t *mapping_blocks_top_ba, ++ bool table_loaded) ++{ ++ struct nmbm_info_table_header *ifthdr = (void *)ni->info_table_cache; ++ uint8_t *off = ni->info_table_cache; ++ uint32_t limit = ba + size2blk(ni, ni->info_table_size); ++ uint32_t start_ba = 0, chunksize, sizeremain = ni->info_table_size; ++ bool success, checkhdr = true; ++ int ret; ++ ++ while (sizeremain && ba < limit) { ++ WATCHDOG_RESET(); ++ ++ if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) ++ goto next_block; ++ ++ if (nmbm_check_bad_phys_block(ni, ba)) { ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ goto next_block; ++ } ++ ++ chunksize = sizeremain; ++ if (chunksize > ni->lower.erasesize) ++ chunksize = ni->lower.erasesize; ++ ++ /* Assume block with ECC error has no info table data */ ++ ret = nmbn_read_data(ni, ba2addr(ni, ba), off, chunksize); ++ if (ret < 0) ++ goto skip_bad_block; ++ else if (ret > 0) ++ return false; ++ ++ if (checkhdr) { ++ success = nmbm_check_info_table_header(ni, off); ++ if (!success) ++ return false; ++ ++ start_ba = ba; ++ checkhdr = false; ++ } ++ ++ off += chunksize; ++ sizeremain -= chunksize; ++ ++ goto next_block; ++ ++ skip_bad_block: ++ /* Only mark bad in memory */ ++ nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); ++ ++ next_block: ++ ba++; ++ } ++ ++ if (sizeremain) ++ return false; ++ ++ success = nmbm_check_header(ni->info_table_cache, ni->info_table_size); ++ if (!success) ++ return false; ++ ++ *eba = ba; ++ *write_count = ifthdr->write_count; ++ ++ success = nmbm_check_info_table(ni, start_ba, ba, ni->info_table_cache, ++ mapping_blocks_top_ba); ++ if (!success) ++ return false; ++ ++ if (!table_loaded || ifthdr->write_count > ni->info_table.write_count) { ++ memcpy(&ni->info_table, ifthdr, sizeof(ni->info_table)); ++ memcpy(ni->block_state, ++ (uint8_t *)ifthdr + ifthdr->state_table_off, ++ ni->state_table_size); ++ memcpy(ni->block_mapping, ++ (uint8_t *)ifthdr + ifthdr->mapping_table_off, ++ ni->mapping_table_size); ++ ni->info_table.write_count = ifthdr->write_count; ++ } ++ ++ return true; ++} ++ ++/* ++ * nmbm_search_info_table - Search info table from specific address ++ * @ni: NMBM instance structure ++ * @ba: start block address to search ++ * @limit: highest block address allowed for searching ++ * @table_start_ba: return the start block address of this table ++ * @table_end_ba: return the block address after end of this table ++ * @write_count: return the write count of this table ++ * @mapping_blocks_top_ba: return the block address of top remapped block ++ * @table_loaded: used to record whether ni->info_table has valid data ++ */ ++static bool nmbm_search_info_table(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t limit, uint32_t *table_start_ba, ++ uint32_t *table_end_ba, ++ uint32_t *write_count, ++ uint32_t *mapping_blocks_top_ba, ++ bool table_loaded) ++{ ++ bool success; ++ ++ while (ba < limit - size2blk(ni, ni->info_table_size)) { ++ WATCHDOG_RESET(); ++ ++ success = nmbm_try_load_info_table(ni, ba, table_end_ba, ++ write_count, ++ mapping_blocks_top_ba, ++ table_loaded); ++ if (success) { ++ *table_start_ba = ba; ++ return true; ++ } ++ ++ ba++; ++ } ++ ++ return false; ++} ++ ++/* ++ * nmbm_load_info_table - Load info table(s) from a chip ++ * @ni: NMBM instance structure ++ * @ba: start block address to search info table ++ * @limit: highest block address allowed for searching ++ */ ++static bool nmbm_load_info_table(struct nmbm_instance *ni, uint32_t ba, ++ uint32_t limit) ++{ ++ uint32_t main_table_end_ba, backup_table_end_ba, table_end_ba; ++ uint32_t main_mapping_blocks_top_ba, backup_mapping_blocks_top_ba; ++ uint32_t main_table_write_count, backup_table_write_count; ++ uint32_t i; ++ bool success; ++ ++ /* Set initial value */ ++ ni->main_table_ba = 0; ++ ni->backup_table_ba = 0; ++ ni->info_table.write_count = 0; ++ ni->mapping_blocks_top_ba = ni->signature_ba - 1; ++ ni->data_block_count = ni->signature.mgmt_start_pb; ++ ++ /* Find first info table */ ++ success = nmbm_search_info_table(ni, ba, limit, &ni->main_table_ba, ++ &main_table_end_ba, &main_table_write_count, ++ &main_mapping_blocks_top_ba, false); ++ if (!success) { ++ nlog_warn(ni, "No valid info table found\n"); ++ return false; ++ } ++ ++ table_end_ba = main_table_end_ba; ++ ++ nlog_table_found(ni, true, main_table_write_count, ni->main_table_ba, ++ main_table_end_ba); ++ ++ /* Find second info table */ ++ success = nmbm_search_info_table(ni, main_table_end_ba, limit, ++ &ni->backup_table_ba, &backup_table_end_ba, ++ &backup_table_write_count, &backup_mapping_blocks_top_ba, true); ++ if (!success) { ++ nlog_warn(ni, "Second info table not found\n"); ++ } else { ++ table_end_ba = backup_table_end_ba; ++ ++ nlog_table_found(ni, false, backup_table_write_count, ++ ni->backup_table_ba, backup_table_end_ba); ++ } ++ ++ /* Pick mapping_blocks_top_ba */ ++ if (!ni->backup_table_ba) { ++ ni->mapping_blocks_top_ba= main_mapping_blocks_top_ba; ++ } else { ++ if (main_table_write_count >= backup_table_write_count) ++ ni->mapping_blocks_top_ba = main_mapping_blocks_top_ba; ++ else ++ ni->mapping_blocks_top_ba = backup_mapping_blocks_top_ba; ++ } ++ ++ /* Set final mapping_blocks_ba */ ++ ni->mapping_blocks_ba = table_end_ba; ++ ++ /* Set final data_block_count */ ++ for (i = ni->signature.mgmt_start_pb; i > 0; i--) { ++ if (ni->block_mapping[i - 1] >= 0) { ++ ni->data_block_count = i; ++ break; ++ } ++ } ++ ++ /* Debug purpose: mark mapped blocks and bad blocks */ ++ for (i = 0; i < ni->data_block_count; i++) { ++ if (ni->block_mapping[i] > ni->mapping_blocks_top_ba) ++ nmbm_mark_block_color_mapped(ni, ni->block_mapping[i]); ++ } ++ ++ for (i = 0; i < ni->block_count; i++) { ++ if (nmbm_get_block_state(ni, i) == BLOCK_ST_BAD) ++ nmbm_mark_block_color_bad(ni, i); ++ } ++ ++ /* Regenerate the info table cache from the final selected info table */ ++ nmbm_generate_info_table_cache(ni); ++ ++ if (ni->lower.flags & NMBM_F_READ_ONLY) ++ return true; ++ ++ /* ++ * If only one table exists, try to write another table. ++ * If two tables have different write count, try to update info table ++ */ ++ if (!ni->backup_table_ba) { ++ success = nmbm_rescue_single_info_table(ni); ++ } else if (main_table_write_count != backup_table_write_count) { ++ /* Mark state & mapping tables changed */ ++ ni->block_state_changed = 1; ++ ni->block_mapping_changed = 1; ++ ++ success = nmbm_update_single_info_table(ni, ++ main_table_write_count < backup_table_write_count); ++ } else { ++ success = true; ++ } ++ ++ /* ++ * If there is no spare unmapped blocks, or still only one table ++ * exists, set the chip to read-only ++ */ ++ if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) { ++ nlog_warn(ni, "No spare unmapped blocks. Device is now read-only\n"); ++ ni->protected = 1; ++ } else if (!success) { ++ nlog_warn(ni, "Only one info table found. Device is now read-only\n"); ++ ni->protected = 1; ++ } ++ ++ return true; ++} ++ ++/* ++ * nmbm_load_existing - Load NMBM from a new chip ++ * @ni: NMBM instance structure ++ */ ++static bool nmbm_load_existing(struct nmbm_instance *ni) ++{ ++ bool success; ++ ++ /* Calculate the boundary of management blocks */ ++ ni->mgmt_start_ba = ni->signature.mgmt_start_pb; ++ ++ nlog_debug(ni, "NMBM management region starts at block %u [0x%08llx]\n", ++ ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba)); ++ nmbm_mark_block_color_mgmt(ni, ni->mgmt_start_ba, ++ ni->signature_ba - 1); ++ ++ /* Look for info table(s) */ ++ success = nmbm_load_info_table(ni, ni->mgmt_start_ba, ++ ni->signature_ba); ++ if (success) { ++ nlog_info(ni, "NMBM has been successfully attached %s\n", ++ (ni->lower.flags & NMBM_F_READ_ONLY) ? "in read-only mode" : ""); ++ return true; ++ } ++ ++ if (!(ni->lower.flags & NMBM_F_CREATE)) ++ return false; ++ ++ /* Fill block state table & mapping table */ ++ nmbm_scan_badblocks(ni); ++ nmbm_build_mapping_table(ni); ++ ++ if (ni->lower.flags & NMBM_F_READ_ONLY) { ++ nlog_info(ni, "NMBM has been initialized in read-only mode\n"); ++ return true; ++ } ++ ++ /* Write info table(s) */ ++ success = nmbm_create_info_table(ni); ++ if (success) { ++ nlog_info(ni, "NMBM has been successfully created\n"); ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * nmbm_find_signature - Find signature in the lower NAND chip ++ * @ni: NMBM instance structure ++ * @signature_ba: used for storing block address of the signature ++ * @signature_ba: return the actual block address of signature block ++ * ++ * Find a valid signature from a specific range in the lower NAND chip, ++ * from bottom (highest address) to top (lowest address) ++ * ++ * Return true if found. ++ */ ++static bool nmbm_find_signature(struct nmbm_instance *ni, ++ struct nmbm_signature *signature, ++ uint32_t *signature_ba) ++{ ++ struct nmbm_signature sig; ++ uint64_t off, addr; ++ uint32_t block_count, ba, limit; ++ bool success; ++ int ret; ++ ++ /* Calculate top and bottom block address */ ++ block_count = ni->lower.size >> ni->erasesize_shift; ++ ba = block_count; ++ limit = (block_count / NMBM_MGMT_DIV) * (NMBM_MGMT_DIV - ni->lower.max_ratio); ++ if (ni->lower.max_reserved_blocks && block_count - limit > ni->lower.max_reserved_blocks) ++ limit = block_count - ni->lower.max_reserved_blocks; ++ ++ while (ba >= limit) { ++ WATCHDOG_RESET(); ++ ++ ba--; ++ addr = ba2addr(ni, ba); ++ ++ if (nmbm_check_bad_phys_block(ni, ba)) ++ continue; ++ ++ /* Check every page. ++ * As long as at leaset one page contains valid signature, ++ * the block is treated as a valid signature block. ++ */ ++ for (off = 0; off < ni->lower.erasesize; ++ off += ni->lower.writesize) { ++ WATCHDOG_RESET(); ++ ++ ret = nmbn_read_data(ni, addr + off, &sig, ++ sizeof(sig)); ++ if (ret) ++ continue; ++ ++ /* Check for header size and checksum */ ++ success = nmbm_check_header(&sig, sizeof(sig)); ++ if (!success) ++ continue; ++ ++ /* Check for header magic */ ++ if (sig.header.magic == NMBM_MAGIC_SIGNATURE) { ++ /* Found it */ ++ memcpy(signature, &sig, sizeof(sig)); ++ *signature_ba = ba; ++ return true; ++ } ++ } ++ }; ++ ++ return false; ++} ++ ++/* ++ * is_power_of_2_u64 - Check whether a 64-bit integer is power of 2 ++ * @n: number to check ++ */ ++static bool is_power_of_2_u64(uint64_t n) ++{ ++ return (n != 0 && ((n & (n - 1)) == 0)); ++} ++ ++/* ++ * nmbm_check_lower_members - Validate the members of lower NAND device ++ * @nld: Lower NAND chip structure ++ */ ++static bool nmbm_check_lower_members(struct nmbm_lower_device *nld) ++{ ++ ++ if (!nld->size || !is_power_of_2_u64(nld->size)) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, ++ "Chip size %llu is not valid\n", nld->size); ++ return false; ++ } ++ ++ if (!nld->erasesize || !is_power_of_2(nld->erasesize)) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, ++ "Block size %u is not valid\n", nld->erasesize); ++ return false; ++ } ++ ++ if (!nld->writesize || !is_power_of_2(nld->writesize)) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, ++ "Page size %u is not valid\n", nld->writesize); ++ return false; ++ } ++ ++ if (!nld->oobsize || !is_power_of_2(nld->oobsize)) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, ++ "Page spare size %u is not valid\n", nld->oobsize); ++ return false; ++ } ++ ++ if (!nld->read_page) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, "read_page() is required\n"); ++ return false; ++ } ++ ++ if (!(nld->flags & NMBM_F_READ_ONLY) && (!nld->write_page || !nld->erase_block)) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, ++ "write_page() and erase_block() are required\n"); ++ return false; ++ } ++ ++ /* Data sanity check */ ++ if (!nld->max_ratio) ++ nld->max_ratio = 1; ++ ++ if (nld->max_ratio >= NMBM_MGMT_DIV - 1) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, ++ "max ratio %u is invalid\n", nld->max_ratio); ++ return false; ++ } ++ ++ if (nld->max_reserved_blocks && nld->max_reserved_blocks < NMBM_MGMT_BLOCKS_MIN) { ++ nmbm_log_lower(nld, NMBM_LOG_ERR, ++ "max reserved blocks %u is too small\n", nld->max_reserved_blocks); ++ return false; ++ } ++ ++ return true; ++} ++ ++/* ++ * nmbm_calc_structure_size - Calculate the instance structure size ++ * @nld: NMBM lower device structure ++ */ ++size_t nmbm_calc_structure_size(struct nmbm_lower_device *nld) ++{ ++ uint32_t state_table_size, mapping_table_size, info_table_size; ++ uint32_t block_count; ++ ++ block_count = nmbm_lldiv(nld->size, nld->erasesize); ++ ++ /* Calculate info table size */ ++ state_table_size = ((block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) / ++ NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE; ++ mapping_table_size = block_count * sizeof(int32_t); ++ ++ info_table_size = NMBM_ALIGN(sizeof(struct nmbm_info_table_header), ++ nld->writesize); ++ info_table_size += NMBM_ALIGN(state_table_size, nld->writesize); ++ info_table_size += NMBM_ALIGN(mapping_table_size, nld->writesize); ++ ++ return info_table_size + state_table_size + mapping_table_size + ++ nld->writesize + nld->oobsize + sizeof(struct nmbm_instance); ++} ++ ++/* ++ * nmbm_init_structure - Initialize members of instance structure ++ * @ni: NMBM instance structure ++ */ ++static void nmbm_init_structure(struct nmbm_instance *ni) ++{ ++ uint32_t pages_per_block, blocks_per_chip; ++ uintptr_t ptr; ++ ++ pages_per_block = ni->lower.erasesize / ni->lower.writesize; ++ blocks_per_chip = nmbm_lldiv(ni->lower.size, ni->lower.erasesize); ++ ++ ni->rawpage_size = ni->lower.writesize + ni->lower.oobsize; ++ ni->rawblock_size = pages_per_block * ni->rawpage_size; ++ ni->rawchip_size = blocks_per_chip * ni->rawblock_size; ++ ++ ni->writesize_mask = ni->lower.writesize - 1; ++ ni->erasesize_mask = ni->lower.erasesize - 1; ++ ++ ni->writesize_shift = ffs(ni->lower.writesize) - 1; ++ ni->erasesize_shift = ffs(ni->lower.erasesize) - 1; ++ ++ /* Calculate number of block this chip */ ++ ni->block_count = ni->lower.size >> ni->erasesize_shift; ++ ++ /* Calculate info table size */ ++ ni->state_table_size = ((ni->block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) / ++ NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE; ++ ni->mapping_table_size = ni->block_count * sizeof(*ni->block_mapping); ++ ++ ni->info_table_size = NMBM_ALIGN(sizeof(ni->info_table), ++ ni->lower.writesize); ++ ni->info_table.state_table_off = ni->info_table_size; ++ ++ ni->info_table_size += NMBM_ALIGN(ni->state_table_size, ++ ni->lower.writesize); ++ ni->info_table.mapping_table_off = ni->info_table_size; ++ ++ ni->info_table_size += NMBM_ALIGN(ni->mapping_table_size, ++ ni->lower.writesize); ++ ++ ni->info_table_spare_blocks = nmbm_get_spare_block_count( ++ size2blk(ni, ni->info_table_size)); ++ ++ /* Assign memory to members */ ++ ptr = (uintptr_t)ni + sizeof(*ni); ++ ++ ni->info_table_cache = (void *)ptr; ++ ptr += ni->info_table_size; ++ ++ ni->block_state = (void *)ptr; ++ ptr += ni->state_table_size; ++ ++ ni->block_mapping = (void *)ptr; ++ ptr += ni->mapping_table_size; ++ ++ ni->page_cache = (uint8_t *)ptr; ++ ++ /* Initialize block state table */ ++ ni->block_state_changed = 0; ++ memset(ni->block_state, 0xff, ni->state_table_size); ++ ++ /* Initialize block mapping table */ ++ ni->block_mapping_changed = 0; ++} ++ ++/* ++ * nmbm_attach - Attach to a lower device ++ * @nld: NMBM lower device structure ++ * @ni: NMBM instance structure ++ */ ++int nmbm_attach(struct nmbm_lower_device *nld, struct nmbm_instance *ni) ++{ ++ bool success; ++ ++ if (!nld || !ni) ++ return -EINVAL; ++ ++ /* Set default log level */ ++ ni->log_display_level = NMBM_DEFAULT_LOG_LEVEL; ++ ++ /* Check lower members */ ++ success = nmbm_check_lower_members(nld); ++ if (!success) ++ return -EINVAL; ++ ++ /* Initialize NMBM instance */ ++ memcpy(&ni->lower, nld, sizeof(struct nmbm_lower_device)); ++ nmbm_init_structure(ni); ++ ++ success = nmbm_find_signature(ni, &ni->signature, &ni->signature_ba); ++ if (!success) { ++ if (!(nld->flags & NMBM_F_CREATE)) { ++ nlog_err(ni, "Signature not found\n"); ++ return -ENODEV; ++ } ++ ++ success = nmbm_create_new(ni); ++ if (!success) ++ return -ENODEV; ++ ++ return 0; ++ } ++ ++ nlog_info(ni, "Signature found at block %u [0x%08llx]\n", ++ ni->signature_ba, ba2addr(ni, ni->signature_ba)); ++ nmbm_mark_block_color_signature(ni, ni->signature_ba); ++ ++ if (ni->signature.header.version != NMBM_VER) { ++ nlog_err(ni, "NMBM version %u.%u is not supported\n", ++ NMBM_VERSION_MAJOR_GET(ni->signature.header.version), ++ NMBM_VERSION_MINOR_GET(ni->signature.header.version)); ++ return -EINVAL; ++ } ++ ++ if (ni->signature.nand_size != nld->size || ++ ni->signature.block_size != nld->erasesize || ++ ni->signature.page_size != nld->writesize || ++ ni->signature.spare_size != nld->oobsize) { ++ nlog_err(ni, "NMBM configuration mismatch\n"); ++ return -EINVAL; ++ } ++ ++ success = nmbm_load_existing(ni); ++ if (!success) ++ return -ENODEV; ++ ++ return 0; ++} ++ ++/* ++ * nmbm_detach - Detach from a lower device, and save all tables ++ * @ni: NMBM instance structure ++ */ ++int nmbm_detach(struct nmbm_instance *ni) ++{ ++ if (!ni) ++ return -EINVAL; ++ ++ if (!(ni->lower.flags & NMBM_F_READ_ONLY)) ++ nmbm_update_info_table(ni); ++ ++ nmbm_mark_block_color_normal(ni, 0, ni->block_count - 1); ++ ++ return 0; ++} ++ ++/* ++ * nmbm_erase_logic_block - Erase a logic block ++ * @ni: NMBM instance structure ++ * @nmbm_erase_logic_block: logic block address ++ * ++ * Logic block will be mapped to physical block before erasing. ++ * Bad block found during erasinh will be remapped to a good block if there is ++ * still at least one good spare block available. ++ */ ++static int nmbm_erase_logic_block(struct nmbm_instance *ni, uint32_t block_addr) ++{ ++ uint32_t pb; ++ bool success; ++ ++retry: ++ /* Map logic block to physical block */ ++ pb = ni->block_mapping[block_addr]; ++ ++ /* Whether the logic block is good (has valid mapping) */ ++ if ((int32_t)pb < 0) { ++ nlog_debug(ni, "Logic block %u is a bad block\n", block_addr); ++ return -EIO; ++ } ++ ++ /* Remap logic block if current physical block is a bad block */ ++ if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD || ++ nmbm_get_block_state(ni, pb) == BLOCK_ST_NEED_REMAP) ++ goto remap_logic_block; ++ ++ /* Insurance to detect unexpected bad block marked by user */ ++ if (nmbm_check_bad_phys_block(ni, pb)) { ++ nlog_warn(ni, "Found unexpected bad block possibly marked by user\n"); ++ nmbm_set_block_state(ni, pb, BLOCK_ST_BAD); ++ goto remap_logic_block; ++ } ++ ++ success = nmbm_erase_block_and_check(ni, pb); ++ if (success) ++ return 0; ++ ++ /* Mark bad block */ ++ nmbm_mark_phys_bad_block(ni, pb); ++ nmbm_set_block_state(ni, pb, BLOCK_ST_BAD); ++ ++remap_logic_block: ++ /* Try to assign a new block */ ++ success = nmbm_map_block(ni, block_addr); ++ if (!success) { ++ /* Mark logic block unusable, and update info table */ ++ ni->block_mapping[block_addr] = -1; ++ if (nmbm_get_block_state(ni, pb) != BLOCK_ST_NEED_REMAP) ++ nmbm_set_block_state(ni, pb, BLOCK_ST_BAD); ++ nmbm_update_info_table(ni); ++ return -EIO; ++ } ++ ++ /* Update info table before erasing */ ++ if (nmbm_get_block_state(ni, pb) != BLOCK_ST_NEED_REMAP) ++ nmbm_set_block_state(ni, pb, BLOCK_ST_BAD); ++ nmbm_update_info_table(ni); ++ ++ goto retry; ++} ++ ++/* ++ * nmbm_erase_block_range - Erase logic blocks ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ * @size: erase range ++ * @failed_addr: return failed block address if error occurs ++ */ ++int nmbm_erase_block_range(struct nmbm_instance *ni, uint64_t addr, ++ uint64_t size, uint64_t *failed_addr) ++{ ++ uint32_t start_ba, end_ba; ++ int ret; ++ ++ if (!ni) ++ return -EINVAL; ++ ++ /* Sanity check */ ++ if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) { ++ nlog_debug(ni, "Device is forced read-only\n"); ++ return -EROFS; ++ } ++ ++ if (addr >= ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Address 0x%llx is invalid\n", addr); ++ return -EINVAL; ++ } ++ ++ if (addr + size > ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Erase range 0xllxu is too large\n", size); ++ return -EINVAL; ++ } ++ ++ if (!size) { ++ nlog_warn(ni, "No blocks to be erased\n"); ++ return 0; ++ } ++ ++ start_ba = addr2ba(ni, addr); ++ end_ba = addr2ba(ni, addr + size - 1); ++ ++ while (start_ba <= end_ba) { ++ WATCHDOG_RESET(); ++ ++ ret = nmbm_erase_logic_block(ni, start_ba); ++ if (ret) { ++ if (failed_addr) ++ *failed_addr = ba2addr(ni, start_ba); ++ return ret; ++ } ++ ++ start_ba++; ++ } ++ ++ return 0; ++} ++ ++/* ++ * nmbm_read_logic_page - Read page based on logic address ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ * @data: buffer to store main data. optional. ++ * @oob: buffer to store oob data. optional. ++ * @mode: read mode ++ * ++ * Return 0 for success, positive value for corrected bitflip count, ++ * -EBADMSG for ecc error, other negative values for other errors ++ */ ++static int nmbm_read_logic_page(struct nmbm_instance *ni, uint64_t addr, ++ void *data, void *oob, enum nmbm_oob_mode mode) ++{ ++ uint32_t lb, pb, offset; ++ uint64_t paddr; ++ ++ /* Extract block address and in-block offset */ ++ lb = addr2ba(ni, addr); ++ offset = addr & ni->erasesize_mask; ++ ++ /* Map logic block to physical block */ ++ pb = ni->block_mapping[lb]; ++ ++ /* Whether the logic block is good (has valid mapping) */ ++ if ((int32_t)pb < 0) { ++ nlog_debug(ni, "Logic block %u is a bad block\n", lb); ++ return -EIO; ++ } ++ ++ /* Fail if physical block is marked bad */ ++ if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD) ++ return -EIO; ++ ++ /* Assemble new address */ ++ paddr = ba2addr(ni, pb) + offset; ++ ++ return nmbm_read_phys_page(ni, paddr, data, oob, mode); ++} ++ ++/* ++ * nmbm_read_single_page - Read one page based on logic address ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ * @data: buffer to store main data. optional. ++ * @oob: buffer to store oob data. optional. ++ * @mode: read mode ++ * ++ * Return 0 for success, positive value for corrected bitflip count, ++ * -EBADMSG for ecc error, other negative values for other errors ++ */ ++int nmbm_read_single_page(struct nmbm_instance *ni, uint64_t addr, void *data, ++ void *oob, enum nmbm_oob_mode mode) ++{ ++ if (!ni) ++ return -EINVAL; ++ ++ /* Sanity check */ ++ if (ni->protected) { ++ nlog_debug(ni, "Device is forced read-only\n"); ++ return -EROFS; ++ } ++ ++ if (addr >= ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Address 0x%llx is invalid\n", addr); ++ return -EINVAL; ++ } ++ ++ return nmbm_read_logic_page(ni, addr, data, oob, mode); ++} ++ ++/* ++ * nmbm_read_range - Read data without oob ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ * @size: data size to read ++ * @data: buffer to store main data to be read ++ * @mode: read mode ++ * @retlen: return actual data size read ++ * ++ * Return 0 for success, positive value for corrected bitflip count, ++ * -EBADMSG for ecc error, other negative values for other errors ++ */ ++int nmbm_read_range(struct nmbm_instance *ni, uint64_t addr, size_t size, ++ void *data, enum nmbm_oob_mode mode, size_t *retlen) ++{ ++ uint64_t off = addr; ++ uint8_t *ptr = data; ++ size_t sizeremain = size, chunksize, leading; ++ bool has_ecc_err = false; ++ int ret, max_bitflips = 0; ++ ++ if (!ni) ++ return -EINVAL; ++ ++ /* Sanity check */ ++ if (ni->protected) { ++ nlog_debug(ni, "Device is forced read-only\n"); ++ return -EROFS; ++ } ++ ++ if (addr >= ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Address 0x%llx is invalid\n", addr); ++ return -EINVAL; ++ } ++ ++ if (addr + size > ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Read range 0x%llx is too large\n", size); ++ return -EINVAL; ++ } ++ ++ if (!size) { ++ nlog_warn(ni, "No data to be read\n"); ++ return 0; ++ } ++ ++ while (sizeremain) { ++ WATCHDOG_RESET(); ++ ++ leading = off & ni->writesize_mask; ++ chunksize = ni->lower.writesize - leading; ++ if (chunksize > sizeremain) ++ chunksize = sizeremain; ++ ++ if (chunksize == ni->lower.writesize) { ++ ret = nmbm_read_logic_page(ni, off - leading, ptr, ++ NULL, mode); ++ if (ret < 0 && ret != -EBADMSG) ++ break; ++ } else { ++ ret = nmbm_read_logic_page(ni, off - leading, ++ ni->page_cache, NULL, ++ mode); ++ if (ret < 0 && ret != -EBADMSG) ++ break; ++ ++ memcpy(ptr, ni->page_cache + leading, chunksize); ++ } ++ ++ if (ret == -EBADMSG) ++ has_ecc_err = true; ++ ++ if (ret > max_bitflips) ++ max_bitflips = ret; ++ ++ off += chunksize; ++ ptr += chunksize; ++ sizeremain -= chunksize; ++ } ++ ++ if (retlen) ++ *retlen = size - sizeremain; ++ ++ if (ret < 0 && ret != -EBADMSG) ++ return ret; ++ ++ if (has_ecc_err) ++ return -EBADMSG; ++ ++ return max_bitflips; ++} ++ ++/* ++ * nmbm_write_logic_page - Read page based on logic address ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ * @data: buffer contains main data. optional. ++ * @oob: buffer contains oob data. optional. ++ * @mode: write mode ++ */ ++static int nmbm_write_logic_page(struct nmbm_instance *ni, uint64_t addr, ++ const void *data, const void *oob, ++ enum nmbm_oob_mode mode) ++{ ++ uint32_t lb, pb, offset; ++ uint64_t paddr; ++ bool success; ++ ++ /* Extract block address and in-block offset */ ++ lb = addr2ba(ni, addr); ++ offset = addr & ni->erasesize_mask; ++ ++ /* Map logic block to physical block */ ++ pb = ni->block_mapping[lb]; ++ ++ /* Whether the logic block is good (has valid mapping) */ ++ if ((int32_t)pb < 0) { ++ nlog_debug(ni, "Logic block %u is a bad block\n", lb); ++ return -EIO; ++ } ++ ++ /* Fail if physical block is marked bad */ ++ if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD) ++ return -EIO; ++ ++ /* Assemble new address */ ++ paddr = ba2addr(ni, pb) + offset; ++ ++ success = nmbm_write_phys_page(ni, paddr, data, oob, mode); ++ if (success) ++ return 0; ++ ++ /* ++ * Do not remap bad block here. Just mark this block in state table. ++ * Remap this block on erasing. ++ */ ++ nmbm_set_block_state(ni, pb, BLOCK_ST_NEED_REMAP); ++ nmbm_update_info_table(ni); ++ ++ return -EIO; ++} ++ ++/* ++ * nmbm_write_single_page - Write one page based on logic address ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ * @data: buffer contains main data. optional. ++ * @oob: buffer contains oob data. optional. ++ * @mode: write mode ++ */ ++int nmbm_write_single_page(struct nmbm_instance *ni, uint64_t addr, ++ const void *data, const void *oob, ++ enum nmbm_oob_mode mode) ++{ ++ if (!ni) ++ return -EINVAL; ++ ++ /* Sanity check */ ++ if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) { ++ nlog_debug(ni, "Device is forced read-only\n"); ++ return -EROFS; ++ } ++ ++ if (addr >= ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Address 0x%llx is invalid\n", addr); ++ return -EINVAL; ++ } ++ ++ return nmbm_write_logic_page(ni, addr, data, oob, mode); ++} ++ ++/* ++ * nmbm_write_range - Write data without oob ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ * @size: data size to write ++ * @data: buffer contains data to be written ++ * @mode: write mode ++ * @retlen: return actual data size written ++ */ ++int nmbm_write_range(struct nmbm_instance *ni, uint64_t addr, size_t size, ++ const void *data, enum nmbm_oob_mode mode, ++ size_t *retlen) ++{ ++ uint64_t off = addr; ++ const uint8_t *ptr = data; ++ size_t sizeremain = size, chunksize, leading; ++ int ret; ++ ++ if (!ni) ++ return -EINVAL; ++ ++ /* Sanity check */ ++ if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) { ++ nlog_debug(ni, "Device is forced read-only\n"); ++ return -EROFS; ++ } ++ ++ if (addr >= ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Address 0x%llx is invalid\n", addr); ++ return -EINVAL; ++ } ++ ++ if (addr + size > ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Write size 0x%zx is too large\n", size); ++ return -EINVAL; ++ } ++ ++ if (!size) { ++ nlog_warn(ni, "No data to be written\n"); ++ return 0; ++ } ++ ++ while (sizeremain) { ++ WATCHDOG_RESET(); ++ ++ leading = off & ni->writesize_mask; ++ chunksize = ni->lower.writesize - leading; ++ if (chunksize > sizeremain) ++ chunksize = sizeremain; ++ ++ if (chunksize == ni->lower.writesize) { ++ ret = nmbm_write_logic_page(ni, off - leading, ptr, ++ NULL, mode); ++ if (ret) ++ break; ++ } else { ++ memset(ni->page_cache, 0xff, leading); ++ memcpy(ni->page_cache + leading, ptr, chunksize); ++ ++ ret = nmbm_write_logic_page(ni, off - leading, ++ ni->page_cache, NULL, ++ mode); ++ if (ret) ++ break; ++ } ++ ++ off += chunksize; ++ ptr += chunksize; ++ sizeremain -= chunksize; ++ } ++ ++ if (retlen) ++ *retlen = size - sizeremain; ++ ++ return ret; ++} ++ ++/* ++ * nmbm_check_bad_block - Check whether a logic block is usable ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ */ ++int nmbm_check_bad_block(struct nmbm_instance *ni, uint64_t addr) ++{ ++ uint32_t lb, pb; ++ ++ if (!ni) ++ return -EINVAL; ++ ++ if (addr >= ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Address 0x%llx is invalid\n", addr); ++ return -EINVAL; ++ } ++ ++ lb = addr2ba(ni, addr); ++ ++ /* Map logic block to physical block */ ++ pb = ni->block_mapping[lb]; ++ ++ if ((int32_t)pb < 0) ++ return 1; ++ ++ if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * nmbm_mark_bad_block - Mark a logic block unusable ++ * @ni: NMBM instance structure ++ * @addr: logic linear address ++ */ ++int nmbm_mark_bad_block(struct nmbm_instance *ni, uint64_t addr) ++{ ++ uint32_t lb, pb; ++ ++ if (!ni) ++ return -EINVAL; ++ ++ /* Sanity check */ ++ if (ni->protected || (ni->lower.flags & NMBM_F_READ_ONLY)) { ++ nlog_debug(ni, "Device is forced read-only\n"); ++ return -EROFS; ++ } ++ ++ if (addr >= ba2addr(ni, ni->data_block_count)) { ++ nlog_err(ni, "Address 0x%llx is invalid\n", addr); ++ return -EINVAL; ++ } ++ ++ lb = addr2ba(ni, addr); ++ ++ /* Map logic block to physical block */ ++ pb = ni->block_mapping[lb]; ++ ++ if ((int32_t)pb < 0) ++ return 0; ++ ++ ni->block_mapping[lb] = -1; ++ nmbm_mark_phys_bad_block(ni, pb); ++ nmbm_set_block_state(ni, pb, BLOCK_ST_BAD); ++ nmbm_update_info_table(ni); ++ ++ return 0; ++} ++ ++/* ++ * nmbm_get_avail_size - Get available user data size ++ * @ni: NMBM instance structure ++ */ ++uint64_t nmbm_get_avail_size(struct nmbm_instance *ni) ++{ ++ if (!ni) ++ return 0; ++ ++ return (uint64_t)ni->data_block_count << ni->erasesize_shift; ++} ++ ++/* ++ * nmbm_get_lower_device - Get lower device structure ++ * @ni: NMBM instance structure ++ * @nld: pointer to hold the data of lower device structure ++ */ ++int nmbm_get_lower_device(struct nmbm_instance *ni, struct nmbm_lower_device *nld) ++{ ++ if (!ni) ++ return -EINVAL; ++ ++ if (nld) ++ memcpy(nld, &ni->lower, sizeof(*nld)); ++ ++ return 0; ++} ++ ++#include "nmbm-debug.inl" +--- /dev/null ++++ b/drivers/mtd/nmbm/nmbm-debug.h +@@ -0,0 +1,37 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Debug addons for NAND Mapped-block Management (NMBM) ++ * ++ * Author: Weijie Gao ++ */ ++ ++#ifndef _NMBM_DEBUG_H_ ++#define _NMBM_DEBUG_H_ ++ ++#include "nmbm-private.h" ++ ++#define nmbm_mark_block_color_normal(ni, start_ba, end_ba) ++#define nmbm_mark_block_color_bad(ni, ba) ++#define nmbm_mark_block_color_mgmt(ni, start_ba, end_ba) ++#define nmbm_mark_block_color_signature(ni, ba) ++#define nmbm_mark_block_color_info_table(ni, start_ba, end_ba) ++#define nmbm_mark_block_color_mapped(ni, ba) ++ ++uint32_t nmbm_debug_get_block_state(struct nmbm_instance *ni, uint32_t ba); ++char nmbm_debug_get_phys_block_type(struct nmbm_instance *ni, uint32_t ba); ++ ++enum nmmb_block_type { ++ NMBM_BLOCK_GOOD_DATA, ++ NMBM_BLOCK_GOOD_MGMT, ++ NMBM_BLOCK_BAD, ++ NMBM_BLOCK_MAIN_INFO_TABLE, ++ NMBM_BLOCK_BACKUP_INFO_TABLE, ++ NMBM_BLOCK_REMAPPED, ++ NMBM_BLOCK_SIGNATURE, ++ ++ __NMBM_BLOCK_TYPE_MAX ++}; ++ ++#endif /* _NMBM_DEBUG_H_ */ +--- /dev/null ++++ b/drivers/mtd/nmbm/nmbm-debug.inl +@@ -0,0 +1,39 @@ ++ ++uint32_t nmbm_debug_get_block_state(struct nmbm_instance *ni, uint32_t ba) ++{ ++ return nmbm_get_block_state(ni, ba); ++} ++ ++char nmbm_debug_get_phys_block_type(struct nmbm_instance *ni, uint32_t ba) ++{ ++ uint32_t eba, limit; ++ bool success; ++ ++ if (nmbm_get_block_state(ni, ba) == BLOCK_ST_BAD) ++ return NMBM_BLOCK_BAD; ++ ++ if (ba < ni->data_block_count) ++ return NMBM_BLOCK_GOOD_DATA; ++ ++ if (ba == ni->signature_ba) ++ return NMBM_BLOCK_SIGNATURE; ++ ++ if (ni->main_table_ba) { ++ limit = ni->backup_table_ba ? ni->backup_table_ba : ++ ni->mapping_blocks_ba; ++ ++ success = nmbm_block_walk_asc(ni, ni->main_table_ba, &eba, ++ size2blk(ni, ni->info_table_size), limit); ++ ++ if (success && ba >= ni->main_table_ba && ba < eba) ++ return NMBM_BLOCK_MAIN_INFO_TABLE; ++ } ++ ++ if (ba >= ni->backup_table_ba && ba < ni->mapping_blocks_ba) ++ return NMBM_BLOCK_BACKUP_INFO_TABLE; ++ ++ if (ba > ni->mapping_blocks_top_ba && ba < ni->signature_ba) ++ return NMBM_BLOCK_REMAPPED; ++ ++ return NMBM_BLOCK_GOOD_MGMT; ++} +--- /dev/null ++++ b/drivers/mtd/nmbm/nmbm-private.h +@@ -0,0 +1,137 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Definitions for NAND Mapped-block Management (NMBM) ++ * ++ * Author: Weijie Gao ++ */ ++ ++#ifndef _NMBM_PRIVATE_H_ ++#define _NMBM_PRIVATE_H_ ++ ++#include ++ ++#define NMBM_MAGIC_SIGNATURE 0x304d4d4e /* NMM0 */ ++#define NMBM_MAGIC_INFO_TABLE 0x314d4d4e /* NMM1 */ ++ ++#define NMBM_VERSION_MAJOR_S 0 ++#define NMBM_VERSION_MAJOR_M 0xffff ++#define NMBM_VERSION_MINOR_S 16 ++#define NMBM_VERSION_MINOR_M 0xffff ++#define NMBM_VERSION_MAKE(major, minor) (((major) & NMBM_VERSION_MAJOR_M) | \ ++ (((minor) & NMBM_VERSION_MINOR_M) << \ ++ NMBM_VERSION_MINOR_S)) ++#define NMBM_VERSION_MAJOR_GET(ver) (((ver) >> NMBM_VERSION_MAJOR_S) & \ ++ NMBM_VERSION_MAJOR_M) ++#define NMBM_VERSION_MINOR_GET(ver) (((ver) >> NMBM_VERSION_MINOR_S) & \ ++ NMBM_VERSION_MINOR_M) ++ ++typedef uint32_t nmbm_bitmap_t; ++#define NMBM_BITMAP_UNIT_SIZE (sizeof(nmbm_bitmap_t)) ++#define NMBM_BITMAP_BITS_PER_BLOCK 2 ++#define NMBM_BITMAP_BITS_PER_UNIT (8 * sizeof(nmbm_bitmap_t)) ++#define NMBM_BITMAP_BLOCKS_PER_UNIT (NMBM_BITMAP_BITS_PER_UNIT / \ ++ NMBM_BITMAP_BITS_PER_BLOCK) ++ ++#define NMBM_SPARE_BLOCK_MULTI 1 ++#define NMBM_SPARE_BLOCK_DIV 2 ++#define NMBM_SPARE_BLOCK_MIN 2 ++ ++#define NMBM_MGMT_DIV 16 ++#define NMBM_MGMT_BLOCKS_MIN 32 ++ ++#define NMBM_TRY_COUNT 3 ++ ++#define BLOCK_ST_BAD 0 ++#define BLOCK_ST_NEED_REMAP 2 ++#define BLOCK_ST_GOOD 3 ++#define BLOCK_ST_MASK 3 ++ ++struct nmbm_header { ++ uint32_t magic; ++ uint32_t version; ++ uint32_t size; ++ uint32_t checksum; ++}; ++ ++struct nmbm_signature { ++ struct nmbm_header header; ++ uint64_t nand_size; ++ uint32_t block_size; ++ uint32_t page_size; ++ uint32_t spare_size; ++ uint32_t mgmt_start_pb; ++ uint8_t max_try_count; ++ uint8_t padding[3]; ++}; ++ ++struct nmbm_info_table_header { ++ struct nmbm_header header; ++ uint32_t write_count; ++ uint32_t state_table_off; ++ uint32_t mapping_table_off; ++ uint32_t padding; ++}; ++ ++struct nmbm_instance { ++ struct nmbm_lower_device lower; ++ ++ uint32_t rawpage_size; ++ uint32_t rawblock_size; ++ uint32_t rawchip_size; ++ ++ uint32_t writesize_mask; ++ uint32_t erasesize_mask; ++ uint16_t writesize_shift; ++ uint16_t erasesize_shift; ++ ++ struct nmbm_signature signature; ++ ++ uint8_t *info_table_cache; ++ uint32_t info_table_size; ++ uint32_t info_table_spare_blocks; ++ struct nmbm_info_table_header info_table; ++ ++ nmbm_bitmap_t *block_state; ++ uint32_t block_state_changed; ++ uint32_t state_table_size; ++ ++ int32_t *block_mapping; ++ uint32_t block_mapping_changed; ++ uint32_t mapping_table_size; ++ ++ uint8_t *page_cache; ++ ++ int protected; ++ ++ uint32_t block_count; ++ uint32_t data_block_count; ++ ++ uint32_t mgmt_start_ba; ++ uint32_t main_table_ba; ++ uint32_t backup_table_ba; ++ uint32_t mapping_blocks_ba; ++ uint32_t mapping_blocks_top_ba; ++ uint32_t signature_ba; ++ ++ enum nmbm_log_category log_display_level; ++}; ++ ++/* Log utilities */ ++#define nlog_debug(ni, fmt, ...) \ ++ nmbm_log(ni, NMBM_LOG_DEBUG, fmt, ##__VA_ARGS__) ++ ++#define nlog_info(ni, fmt, ...) \ ++ nmbm_log(ni, NMBM_LOG_INFO, fmt, ##__VA_ARGS__) ++ ++#define nlog_warn(ni, fmt, ...) \ ++ nmbm_log(ni, NMBM_LOG_WARN, fmt, ##__VA_ARGS__) ++ ++#define nlog_err(ni, fmt, ...) \ ++ nmbm_log(ni, NMBM_LOG_ERR, fmt, ##__VA_ARGS__) ++ ++#define nlog_emerg(ni, fmt, ...) \ ++ nmbm_log(ni, NMBM_LOG_EMERG, fmt, ##__VA_ARGS__) ++ ++#endif /* _NMBM_PRIVATE_H_ */ +--- /dev/null ++++ b/include/nmbm/nmbm-os.h +@@ -0,0 +1,66 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * OS-dependent definitions for NAND Mapped-block Management (NMBM) ++ * ++ * Author: Weijie Gao ++ */ ++ ++#ifndef _NMBM_OS_H_ ++#define _NMBM_OS_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static inline uint32_t nmbm_crc32(uint32_t crcval, const void *buf, size_t size) ++{ ++ uint chksz; ++ const unsigned char *p = buf; ++ ++ while (size) { ++ if (size > UINT_MAX) ++ chksz = UINT_MAX; ++ else ++ chksz = (uint)size; ++ ++ crcval = crc32_no_comp(crcval, p, chksz); ++ size -= chksz; ++ p += chksz; ++ } ++ ++ return crcval; ++} ++ ++static inline uint32_t nmbm_lldiv(uint64_t dividend, uint32_t divisor) ++{ ++#if BITS_PER_LONG == 64 ++ return dividend / divisor; ++#else ++ __div64_32(÷nd, divisor); ++ return dividend; ++#endif ++} ++ ++#ifdef CONFIG_NMBM_LOG_LEVEL_DEBUG ++#define NMBM_DEFAULT_LOG_LEVEL 0 ++#elif defined(NMBM_LOG_LEVEL_INFO) ++#define NMBM_DEFAULT_LOG_LEVEL 1 ++#elif defined(NMBM_LOG_LEVEL_WARN) ++#define NMBM_DEFAULT_LOG_LEVEL 2 ++#elif defined(NMBM_LOG_LEVEL_ERR) ++#define NMBM_DEFAULT_LOG_LEVEL 3 ++#elif defined(NMBM_LOG_LEVEL_EMERG) ++#define NMBM_DEFAULT_LOG_LEVEL 4 ++#elif defined(NMBM_LOG_LEVEL_NONE) ++#define NMBM_DEFAULT_LOG_LEVEL 5 ++#else ++#define NMBM_DEFAULT_LOG_LEVEL 1 ++#endif ++ ++#endif /* _NMBM_OS_H_ */ +--- /dev/null ++++ b/include/nmbm/nmbm.h +@@ -0,0 +1,102 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Definitions for NAND Mapped-block Management (NMBM) ++ * ++ * Author: Weijie Gao ++ */ ++ ++#ifndef _NMBM_H_ ++#define _NMBM_H_ ++ ++#include ++ ++enum nmbm_log_category { ++ NMBM_LOG_DEBUG, ++ NMBM_LOG_INFO, ++ NMBM_LOG_WARN, ++ NMBM_LOG_ERR, ++ NMBM_LOG_EMERG, ++ ++ __NMBM_LOG_MAX ++}; ++ ++enum nmbm_oob_mode { ++ NMBM_MODE_PLACE_OOB, ++ NMBM_MODE_AUTO_OOB, ++ NMBM_MODE_RAW, ++ ++ __NMBM_MODE_MAX ++}; ++ ++struct nmbm_lower_device { ++ uint32_t max_ratio; ++ uint32_t max_reserved_blocks; ++ int flags; ++ ++ uint64_t size; ++ uint32_t erasesize; ++ uint32_t writesize; ++ uint32_t oobsize; ++ uint32_t oobavail; ++ ++ void *arg; ++ int (*reset_chip)(void *arg); ++ ++ /* ++ * read_page: ++ * return 0 if succeeds ++ * return positive number for ecc error ++ * return negative number for other errors ++ */ ++ int (*read_page)(void *arg, uint64_t addr, void *buf, void *oob, enum nmbm_oob_mode mode); ++ int (*write_page)(void *arg, uint64_t addr, const void *buf, const void *oob, enum nmbm_oob_mode mode); ++ int (*erase_block)(void *arg, uint64_t addr); ++ ++ int (*is_bad_block)(void *arg, uint64_t addr); ++ int (*mark_bad_block)(void *arg, uint64_t addr); ++ ++ /* OS-dependent logging function */ ++ void (*logprint)(void *arg, enum nmbm_log_category level, const char *fmt, va_list ap); ++}; ++ ++struct nmbm_instance; ++ ++/* Create NMBM if management area not found, or not complete */ ++#define NMBM_F_CREATE 0x01 ++ ++/* Empty page is also protected by ECC, and bitflip(s) can be corrected */ ++#define NMBM_F_EMPTY_PAGE_ECC_OK 0x02 ++ ++/* Do not write anything back to flash */ ++#define NMBM_F_READ_ONLY 0x04 ++ ++size_t nmbm_calc_structure_size(struct nmbm_lower_device *nld); ++int nmbm_attach(struct nmbm_lower_device *nld, struct nmbm_instance *ni); ++int nmbm_detach(struct nmbm_instance *ni); ++ ++enum nmbm_log_category nmbm_set_log_level(struct nmbm_instance *ni, ++ enum nmbm_log_category level); ++ ++int nmbm_erase_block_range(struct nmbm_instance *ni, uint64_t addr, ++ uint64_t size, uint64_t *failed_addr); ++int nmbm_read_single_page(struct nmbm_instance *ni, uint64_t addr, void *data, ++ void *oob, enum nmbm_oob_mode mode); ++int nmbm_read_range(struct nmbm_instance *ni, uint64_t addr, size_t size, ++ void *data, enum nmbm_oob_mode mode, size_t *retlen); ++int nmbm_write_single_page(struct nmbm_instance *ni, uint64_t addr, ++ const void *data, const void *oob, ++ enum nmbm_oob_mode mode); ++int nmbm_write_range(struct nmbm_instance *ni, uint64_t addr, size_t size, ++ const void *data, enum nmbm_oob_mode mode, ++ size_t *retlen); ++ ++int nmbm_check_bad_block(struct nmbm_instance *ni, uint64_t addr); ++int nmbm_mark_bad_block(struct nmbm_instance *ni, uint64_t addr); ++ ++uint64_t nmbm_get_avail_size(struct nmbm_instance *ni); ++ ++int nmbm_get_lower_device(struct nmbm_instance *ni, struct nmbm_lower_device *nld); ++ ++#endif /* _NMBM_H_ */ diff --git a/package/boot/uboot-mediatek/patches/100-07-mtd-nmbm-add-support-for-mtd.patch b/package/boot/uboot-mediatek/patches/100-07-mtd-nmbm-add-support-for-mtd.patch new file mode 100644 index 0000000000..644ac8f105 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-07-mtd-nmbm-add-support-for-mtd.patch @@ -0,0 +1,958 @@ +From 0524995f07fcd216a1a7e267fdb5cf2b0ede8489 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 10:42:12 +0800 +Subject: [PATCH 41/71] mtd: nmbm: add support for mtd + +Add support to create NMBM based on MTD devices + +Signed-off-by: Weijie Gao +--- + drivers/mtd/nmbm/Kconfig | 5 + + drivers/mtd/nmbm/Makefile | 1 + + drivers/mtd/nmbm/nmbm-mtd.c | 890 ++++++++++++++++++++++++++++++++++++ + include/nmbm/nmbm-mtd.h | 27 ++ + 4 files changed, 923 insertions(+) + create mode 100644 drivers/mtd/nmbm/nmbm-mtd.c + create mode 100644 include/nmbm/nmbm-mtd.h + +--- a/drivers/mtd/nmbm/Kconfig ++++ b/drivers/mtd/nmbm/Kconfig +@@ -27,3 +27,8 @@ config NMBM_LOG_LEVEL_NONE + bool "5 - None" + + endchoice ++ ++config NMBM_MTD ++ bool "Enable MTD based NAND mapping block management" ++ default n ++ depends on NMBM +--- a/drivers/mtd/nmbm/Makefile ++++ b/drivers/mtd/nmbm/Makefile +@@ -3,3 +3,4 @@ + # (C) Copyright 2020 MediaTek Inc. All rights reserved. + + obj-$(CONFIG_NMBM) += nmbm-core.o ++obj-$(CONFIG_NMBM_MTD) += nmbm-mtd.o +--- /dev/null ++++ b/drivers/mtd/nmbm/nmbm-mtd.c +@@ -0,0 +1,890 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Weijie Gao ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "nmbm-debug.h" ++ ++#define NMBM_UPPER_MTD_NAME "nmbm" ++ ++static uint32_t nmbm_id_cnt; ++static LIST_HEAD(nmbm_devs); ++ ++struct nmbm_mtd { ++ struct mtd_info upper; ++ char *name; ++ uint32_t id; ++ ++ struct mtd_info *lower; ++ ++ struct nmbm_instance *ni; ++ uint8_t *page_cache; ++ ++ struct list_head node; ++}; ++ ++static int nmbm_lower_read_page(void *arg, uint64_t addr, void *buf, void *oob, ++ enum nmbm_oob_mode mode) ++{ ++ struct nmbm_mtd *nm = arg; ++ struct mtd_oob_ops ops; ++ int ret; ++ ++ memset(&ops, 0, sizeof(ops)); ++ ++ switch (mode) { ++ case NMBM_MODE_PLACE_OOB: ++ ops.mode = MTD_OPS_PLACE_OOB; ++ break; ++ case NMBM_MODE_AUTO_OOB: ++ ops.mode = MTD_OPS_AUTO_OOB; ++ break; ++ case NMBM_MODE_RAW: ++ ops.mode = MTD_OPS_RAW; ++ break; ++ default: ++ pr_debug("%s: unsupported NMBM mode: %u\n", __func__, mode); ++ return -ENOTSUPP; ++ } ++ ++ if (buf) { ++ ops.datbuf = buf; ++ ops.len = nm->lower->writesize; ++ } ++ ++ if (oob) { ++ ops.oobbuf = oob; ++ ops.ooblen = mtd_oobavail(nm->lower, &ops); ++ } ++ ++ ret = mtd_read_oob(nm->lower, addr, &ops); ++ nm->upper.ecc_stats.corrected = nm->lower->ecc_stats.corrected; ++ nm->upper.ecc_stats.failed = nm->lower->ecc_stats.failed; ++ ++ /* Report error on failure (including ecc error) */ ++ if (ret < 0 && ret != -EUCLEAN) ++ return ret; ++ ++ /* ++ * Since mtd_read_oob() won't report exact bitflips, what we can know ++ * is whether bitflips exceeds the threshold. ++ * We want the -EUCLEAN to be passed to the upper layer, but not the ++ * error value itself. To achieve this, report bitflips above the ++ * threshold. ++ */ ++ ++ if (ret == -EUCLEAN) { ++ return min_t(u32, nm->lower->bitflip_threshold + 1, ++ nm->lower->ecc_strength); ++ } ++ ++ /* For bitflips less than the threshold, return 0 */ ++ ++ return 0; ++} ++ ++static int nmbm_lower_write_page(void *arg, uint64_t addr, const void *buf, ++ const void *oob, enum nmbm_oob_mode mode) ++{ ++ struct nmbm_mtd *nm = arg; ++ struct mtd_oob_ops ops; ++ ++ memset(&ops, 0, sizeof(ops)); ++ ++ switch (mode) { ++ case NMBM_MODE_PLACE_OOB: ++ ops.mode = MTD_OPS_PLACE_OOB; ++ break; ++ case NMBM_MODE_AUTO_OOB: ++ ops.mode = MTD_OPS_AUTO_OOB; ++ break; ++ case NMBM_MODE_RAW: ++ ops.mode = MTD_OPS_RAW; ++ break; ++ default: ++ pr_debug("%s: unsupported NMBM mode: %u\n", __func__, mode); ++ return -ENOTSUPP; ++ } ++ ++ if (buf) { ++ ops.datbuf = (uint8_t *)buf; ++ ops.len = nm->lower->writesize; ++ } ++ ++ if (oob) { ++ ops.oobbuf = (uint8_t *)oob; ++ ops.ooblen = mtd_oobavail(nm->lower, &ops); ++ } ++ ++ return mtd_write_oob(nm->lower, addr, &ops); ++} ++ ++static int nmbm_lower_erase_block(void *arg, uint64_t addr) ++{ ++ struct nmbm_mtd *nm = arg; ++ struct erase_info ei; ++ ++ memset(&ei, 0, sizeof(ei)); ++ ++ ei.mtd = nm->lower; ++ ei.addr = addr; ++ ei.len = nm->lower->erasesize; ++ ++ return mtd_erase(nm->lower, &ei); ++} ++ ++static int nmbm_lower_is_bad_block(void *arg, uint64_t addr) ++{ ++ struct nmbm_mtd *nm = arg; ++ ++ return mtd_block_isbad(nm->lower, addr); ++} ++ ++static int nmbm_lower_mark_bad_block(void *arg, uint64_t addr) ++{ ++ struct nmbm_mtd *nm = arg; ++ ++ return mtd_block_markbad(nm->lower, addr); ++} ++ ++static void nmbm_lower_log(void *arg, enum nmbm_log_category level, ++ const char *fmt, va_list ap) ++{ ++ vprintf(fmt, ap); ++} ++ ++static int nmbm_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper); ++ ++ /* Do not allow read past end of device */ ++ if ((from + len) > mtd->size) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ return nmbm_read_range(nm->ni, from, len, buf, MTD_OPS_PLACE_OOB, ++ retlen); ++} ++ ++static int nmbm_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const u_char *buf) ++{ ++ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper); ++ ++ /* Do not allow write past end of device */ ++ if ((to + len) > mtd->size) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ return nmbm_write_range(nm->ni, to, len, buf, MTD_OPS_PLACE_OOB, ++ retlen); ++} ++ ++static int nmbm_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper); ++ int ret; ++ ++ instr->state = MTD_ERASING; ++ ++ ret = nmbm_erase_block_range(nm->ni, instr->addr, instr->len, ++ &instr->fail_addr); ++ if (ret) ++ instr->state = MTD_ERASE_FAILED; ++ else ++ instr->state = MTD_ERASE_DONE; ++ ++ if (!ret) ++ /* FIXME */ ++ /* mtd_erase_callback(instr); */ ++ return ret; ++ else ++ ret = -EIO; ++ ++ return ret; ++} ++ ++static int nmbm_mtd_read_data(struct nmbm_mtd *nm, uint64_t addr, ++ struct mtd_oob_ops *ops, enum nmbm_oob_mode mode) ++{ ++ size_t len, ooblen, maxooblen, chklen; ++ uint32_t col, ooboffs; ++ uint8_t *datcache, *oobcache; ++ bool has_ecc_err = false; ++ int ret, max_bitflips = 0; ++ ++ col = addr & nm->lower->writesize_mask; ++ addr &= ~nm->lower->writesize_mask; ++ maxooblen = mtd_oobavail(nm->lower, ops); ++ ooboffs = ops->ooboffs; ++ ooblen = ops->ooblen; ++ len = ops->len; ++ ++ datcache = len ? nm->page_cache : NULL; ++ oobcache = ooblen ? nm->page_cache + nm->lower->writesize : NULL; ++ ++ ops->oobretlen = 0; ++ ops->retlen = 0; ++ ++ while (len || ooblen) { ++ WATCHDOG_RESET(); ++ ++ ret = nmbm_read_single_page(nm->ni, addr, datcache, oobcache, ++ mode); ++ if (ret < 0 && ret != -EBADMSG) ++ return ret; ++ ++ /* Continue reading on ecc error */ ++ if (ret == -EBADMSG) ++ has_ecc_err = true; ++ ++ /* Record the maximum bitflips between pages */ ++ if (ret > max_bitflips) ++ max_bitflips = ret; ++ ++ if (len) { ++ /* Move data */ ++ chklen = nm->lower->writesize - col; ++ if (chklen > len) ++ chklen = len; ++ ++ memcpy(ops->datbuf + ops->retlen, datcache + col, ++ chklen); ++ len -= chklen; ++ col = 0; /* (col + chklen) % */ ++ ops->retlen += chklen; ++ } ++ ++ if (ooblen) { ++ /* Move oob */ ++ chklen = maxooblen - ooboffs; ++ if (chklen > ooblen) ++ chklen = ooblen; ++ ++ memcpy(ops->oobbuf + ops->oobretlen, oobcache + ooboffs, ++ chklen); ++ ooblen -= chklen; ++ ooboffs = 0; /* (ooboffs + chklen) % maxooblen; */ ++ ops->oobretlen += chklen; ++ } ++ ++ addr += nm->lower->writesize; ++ } ++ ++ if (has_ecc_err) ++ return -EBADMSG; ++ ++ return max_bitflips; ++} ++ ++static int nmbm_mtd_read_oob(struct mtd_info *mtd, loff_t from, ++ struct mtd_oob_ops *ops) ++{ ++ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper); ++ uint32_t maxooblen; ++ enum nmbm_oob_mode mode; ++ ++ if (!ops->oobbuf && !ops->datbuf) { ++ if (ops->ooblen || ops->len) ++ return -EINVAL; ++ ++ return 0; ++ } ++ ++ switch (ops->mode) { ++ case MTD_OPS_PLACE_OOB: ++ mode = NMBM_MODE_PLACE_OOB; ++ break; ++ case MTD_OPS_AUTO_OOB: ++ mode = NMBM_MODE_AUTO_OOB; ++ break; ++ case MTD_OPS_RAW: ++ mode = NMBM_MODE_RAW; ++ break; ++ default: ++ pr_debug("%s: unsupported oob mode: %u\n", __func__, ops->mode); ++ return -ENOTSUPP; ++ } ++ ++ maxooblen = mtd_oobavail(mtd, ops); ++ ++ /* Do not allow read past end of device */ ++ if (ops->datbuf && (from + ops->len) > mtd->size) { ++ pr_debug("%s: attempt to read beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (!ops->oobbuf) { ++ /* Optimized for reading data only */ ++ return nmbm_read_range(nm->ni, from, ops->len, ops->datbuf, ++ mode, &ops->retlen); ++ } ++ ++ if (unlikely(ops->ooboffs >= maxooblen)) { ++ pr_debug("%s: attempt to start read outside oob\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (unlikely(from >= mtd->size || ++ ops->ooboffs + ops->ooblen > ((mtd->size >> mtd->writesize_shift) - ++ (from >> mtd->writesize_shift)) * maxooblen)) { ++ pr_debug("%s: attempt to read beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ return nmbm_mtd_read_data(nm, from, ops, mode); ++} ++ ++static int nmbm_mtd_write_data(struct nmbm_mtd *nm, uint64_t addr, ++ struct mtd_oob_ops *ops, enum nmbm_oob_mode mode) ++{ ++ size_t len, ooblen, maxooblen, chklen; ++ uint32_t col, ooboffs; ++ uint8_t *datcache, *oobcache; ++ int ret; ++ ++ col = addr & nm->lower->writesize_mask; ++ addr &= ~nm->lower->writesize_mask; ++ maxooblen = mtd_oobavail(nm->lower, ops); ++ ooboffs = ops->ooboffs; ++ ooblen = ops->ooblen; ++ len = ops->len; ++ ++ datcache = len ? nm->page_cache : NULL; ++ oobcache = ooblen ? nm->page_cache + nm->lower->writesize : NULL; ++ ++ ops->oobretlen = 0; ++ ops->retlen = 0; ++ ++ while (len || ooblen) { ++ WATCHDOG_RESET(); ++ ++ if (len) { ++ /* Move data */ ++ chklen = nm->lower->writesize - col; ++ if (chklen > len) ++ chklen = len; ++ ++ memset(datcache, 0xff, col); ++ memcpy(datcache + col, ops->datbuf + ops->retlen, ++ chklen); ++ memset(datcache + col + chklen, 0xff, ++ nm->lower->writesize - col - chklen); ++ len -= chklen; ++ col = 0; /* (col + chklen) % */ ++ ops->retlen += chklen; ++ } ++ ++ if (ooblen) { ++ /* Move oob */ ++ chklen = maxooblen - ooboffs; ++ if (chklen > ooblen) ++ chklen = ooblen; ++ ++ memset(oobcache, 0xff, ooboffs); ++ memcpy(oobcache + ooboffs, ++ ops->oobbuf + ops->oobretlen, chklen); ++ memset(oobcache + ooboffs + chklen, 0xff, ++ nm->lower->oobsize - ooboffs - chklen); ++ ooblen -= chklen; ++ ooboffs = 0; /* (ooboffs + chklen) % maxooblen; */ ++ ops->oobretlen += chklen; ++ } ++ ++ ret = nmbm_write_single_page(nm->ni, addr, datcache, oobcache, ++ mode); ++ if (ret) ++ return ret; ++ ++ addr += nm->lower->writesize; ++ } ++ ++ return 0; ++} ++ ++static int nmbm_mtd_write_oob(struct mtd_info *mtd, loff_t to, ++ struct mtd_oob_ops *ops) ++{ ++ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper); ++ enum nmbm_oob_mode mode; ++ uint32_t maxooblen; ++ ++ if (!ops->oobbuf && !ops->datbuf) { ++ if (ops->ooblen || ops->len) ++ return -EINVAL; ++ ++ return 0; ++ } ++ ++ switch (ops->mode) { ++ case MTD_OPS_PLACE_OOB: ++ mode = NMBM_MODE_PLACE_OOB; ++ break; ++ case MTD_OPS_AUTO_OOB: ++ mode = NMBM_MODE_AUTO_OOB; ++ break; ++ case MTD_OPS_RAW: ++ mode = NMBM_MODE_RAW; ++ break; ++ default: ++ pr_debug("%s: unsupported oob mode: %u\n", __func__, ++ ops->mode); ++ return -ENOTSUPP; ++ } ++ ++ maxooblen = mtd_oobavail(mtd, ops); ++ ++ /* Do not allow write past end of device */ ++ if (ops->datbuf && (to + ops->len) > mtd->size) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (!ops->oobbuf) { ++ /* Optimized for writing data only */ ++ return nmbm_write_range(nm->ni, to, ops->len, ops->datbuf, ++ mode, &ops->retlen); ++ } ++ ++ if (unlikely(ops->ooboffs >= maxooblen)) { ++ pr_debug("%s: attempt to start write outside oob\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (unlikely(to >= mtd->size || ++ ops->ooboffs + ops->ooblen > ((mtd->size >> mtd->writesize_shift) - ++ (to >> mtd->writesize_shift)) * maxooblen)) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ return nmbm_mtd_write_data(nm, to, ops, mode); ++} ++ ++static int nmbm_mtd_block_isbad(struct mtd_info *mtd, loff_t offs) ++{ ++ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper); ++ ++ return nmbm_check_bad_block(nm->ni, offs); ++} ++ ++static int nmbm_mtd_block_markbad(struct mtd_info *mtd, loff_t offs) ++{ ++ struct nmbm_mtd *nm = container_of(mtd, struct nmbm_mtd, upper); ++ ++ return nmbm_mark_bad_block(nm->ni, offs); ++} ++ ++int nmbm_attach_mtd(struct mtd_info *lower, int flags, uint32_t max_ratio, ++ uint32_t max_reserved_blocks, struct mtd_info **upper) ++{ ++ struct nmbm_lower_device nld; ++ struct nmbm_instance *ni; ++ struct mtd_info *mtd; ++ struct nmbm_mtd *nm; ++ size_t namelen, alloc_size; ++ int ret; ++ ++ if (!lower) ++ return -EINVAL; ++ ++ if (lower->type != MTD_NANDFLASH || lower->flags != MTD_CAP_NANDFLASH) ++ return -ENOTSUPP; ++ ++ namelen = strlen(NMBM_UPPER_MTD_NAME) + 16; ++ ++ nm = calloc(sizeof(*nm) + lower->writesize + lower->oobsize + namelen + 1, 1); ++ if (!nm) ++ return -ENOMEM; ++ ++ nm->lower = lower; ++ nm->name = (char *)nm + sizeof(*nm); ++ nm->page_cache = (uint8_t *)nm->name + namelen + 1; ++ ++ nm->id = nmbm_id_cnt++; ++ snprintf(nm->name, namelen + 1, "%s%u", NMBM_UPPER_MTD_NAME, nm->id); ++ ++ memset(&nld, 0, sizeof(nld)); ++ ++ nld.flags = flags; ++ nld.max_ratio = max_ratio; ++ nld.max_reserved_blocks = max_reserved_blocks; ++ ++ nld.size = lower->size; ++ nld.erasesize = lower->erasesize; ++ nld.writesize = lower->writesize; ++ nld.oobsize = lower->oobsize; ++ nld.oobavail = lower->oobavail; ++ ++ nld.arg = nm; ++ nld.read_page = nmbm_lower_read_page; ++ nld.write_page = nmbm_lower_write_page; ++ nld.erase_block = nmbm_lower_erase_block; ++ nld.is_bad_block = nmbm_lower_is_bad_block; ++ nld.mark_bad_block = nmbm_lower_mark_bad_block; ++ ++ nld.logprint = nmbm_lower_log; ++ ++ alloc_size = nmbm_calc_structure_size(&nld); ++ ni = calloc(alloc_size, 1); ++ if (!ni) { ++ free(nm); ++ return -ENOMEM; ++ } ++ ++ ret = nmbm_attach(&nld, ni); ++ if (ret) { ++ free(ni); ++ free(nm); ++ return ret; ++ } ++ ++ nm->ni = ni; ++ ++ /* Initialize upper mtd */ ++ mtd = &nm->upper; ++ ++ mtd->name = nm->name; ++ mtd->type = MTD_DEV_TYPE_NMBM; ++ mtd->flags = lower->flags; ++ ++ mtd->size = (uint64_t)ni->data_block_count * ni->lower.erasesize; ++ mtd->erasesize = lower->erasesize; ++ mtd->writesize = lower->writesize; ++ mtd->writebufsize = lower->writesize; ++ mtd->oobsize = lower->oobsize; ++ mtd->oobavail = lower->oobavail; ++ ++ mtd->erasesize_shift = lower->erasesize_shift; ++ mtd->writesize_shift = lower->writesize_shift; ++ mtd->erasesize_mask = lower->erasesize_mask; ++ mtd->writesize_mask = lower->writesize_mask; ++ ++ mtd->bitflip_threshold = lower->bitflip_threshold; ++ ++ /* XXX: should this be duplicated? */ ++ mtd->ooblayout = lower->ooblayout; ++ mtd->ecclayout = lower->ecclayout; ++ ++ mtd->ecc_step_size = lower->ecc_step_size; ++ mtd->ecc_strength = lower->ecc_strength; ++ ++ mtd->numeraseregions = lower->numeraseregions; ++ mtd->eraseregions = lower->eraseregions; ++ ++ mtd->_read = nmbm_mtd_read; ++ mtd->_write = nmbm_mtd_write; ++ mtd->_erase = nmbm_mtd_erase; ++ mtd->_read_oob = nmbm_mtd_read_oob; ++ mtd->_write_oob = nmbm_mtd_write_oob; ++ mtd->_block_isbad = nmbm_mtd_block_isbad; ++ mtd->_block_markbad = nmbm_mtd_block_markbad; ++ ++ *upper = mtd; ++ ++ list_add_tail(&nm->node, &nmbm_devs); ++ ++ return 0; ++} ++ ++int nmbm_free_mtd(struct mtd_info *upper) ++{ ++ struct nmbm_mtd *pos; ++ ++ if (!upper) ++ return -EINVAL; ++ ++ list_for_each_entry(pos, &nmbm_devs, node) { ++ if (&pos->upper == upper) { ++ list_del(&pos->node); ++ ++ nmbm_detach(pos->ni); ++ free(pos->ni); ++ free(pos); ++ ++ return 0; ++ } ++ } ++ ++ return -ENODEV; ++} ++ ++struct mtd_info *nmbm_mtd_get_upper_by_index(uint32_t index) ++{ ++ struct nmbm_mtd *nm; ++ ++ list_for_each_entry(nm, &nmbm_devs, node) { ++ if (nm->id == index) ++ return &nm->upper; ++ } ++ ++ return NULL; ++} ++ ++struct mtd_info *nmbm_mtd_get_upper(struct mtd_info *lower) ++{ ++ struct nmbm_mtd *nm; ++ ++ list_for_each_entry(nm, &nmbm_devs, node) { ++ if (nm->lower == lower) ++ return &nm->upper; ++ } ++ ++ return NULL; ++} ++ ++void nmbm_mtd_list_devices(void) ++{ ++ struct nmbm_mtd *nm; ++ ++ printf("Index NMBM device Lower device\n"); ++ printf("========================================\n"); ++ ++ list_for_each_entry(nm, &nmbm_devs, node) { ++ printf("%-8u%-20s%s\n", nm->id, nm->name, nm->lower->name); ++ } ++} ++ ++int nmbm_mtd_print_info(const char *name) ++{ ++ struct nmbm_mtd *nm; ++ bool found = false; ++ ++ list_for_each_entry(nm, &nmbm_devs, node) { ++ if (!strcmp(nm->name, name)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ printf("Error: NMBM device '%s' not found\n", name); ++ return -ENODEV; ++ } ++ ++ printf("%s:\n", name); ++ printf("Total blocks: %u\n", nm->ni->block_count); ++ printf("Data blocks: %u\n", nm->ni->data_block_count); ++ printf("Management start block: %u\n", nm->ni->mgmt_start_ba); ++ printf("Info table size: 0x%x\n", nm->ni->info_table_size); ++ ++ if (nm->ni->main_table_ba) ++ printf("Main info table start block: %u\n", nm->ni->main_table_ba); ++ else ++ printf("Main info table start block: Not exist\n"); ++ ++ if (nm->ni->backup_table_ba) ++ printf("Backup info table start block: %u\n", nm->ni->backup_table_ba); ++ else ++ printf("Backup info table start block: Not exist\n"); ++ ++ printf("Signature block: %u\n", nm->ni->signature_ba); ++ printf("Mapping blocks top address: %u\n", nm->ni->mapping_blocks_top_ba); ++ printf("Mapping blocks limit address: %u\n", nm->ni->mapping_blocks_ba); ++ ++ return 0; ++} ++ ++static const char nmbm_block_legends[] = { ++ [NMBM_BLOCK_GOOD_DATA] = '-', ++ [NMBM_BLOCK_GOOD_MGMT] = '+', ++ [NMBM_BLOCK_BAD] = 'B', ++ [NMBM_BLOCK_MAIN_INFO_TABLE] = 'I', ++ [NMBM_BLOCK_BACKUP_INFO_TABLE] = 'i', ++ [NMBM_BLOCK_REMAPPED] = 'M', ++ [NMBM_BLOCK_SIGNATURE] = 'S', ++}; ++ ++int nmbm_mtd_print_states(const char *name) ++{ ++ struct nmbm_mtd *nm; ++ enum nmmb_block_type bt; ++ bool found = false; ++ uint32_t i; ++ ++ list_for_each_entry(nm, &nmbm_devs, node) { ++ if (!strcmp(nm->name, name)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ printf("Error: NMBM device '%s' not found\n", name); ++ return -ENODEV; ++ } ++ ++ printf("Physical blocks:\n"); ++ printf("\n"); ++ ++ printf("Legends:\n"); ++ printf(" - Good data block\n"); ++ printf(" + Good management block\n"); ++ printf(" B Bad block\n"); ++ printf(" I Main info table\n"); ++ printf(" i Backup info table\n"); ++ printf(" M Remapped spare block\n"); ++ printf(" S Signature block\n"); ++ printf("\n"); ++ ++ for (i = 0; i < nm->ni->block_count; i++) { ++ if (i % 64 == 0) ++ printf(" "); ++ ++ bt = nmbm_debug_get_phys_block_type(nm->ni, i); ++ if (bt < __NMBM_BLOCK_TYPE_MAX) ++ putc(nmbm_block_legends[bt]); ++ else ++ putc('?'); ++ ++ if (i % 64 == 63) ++ printf("\n"); ++ } ++ ++ printf("\n"); ++ printf("Logical blocks:\n"); ++ printf("\n"); ++ ++ printf("Legends:\n"); ++ printf(" - Good block\n"); ++ printf(" + Initially remapped block\n"); ++ printf(" M Remapped block\n"); ++ printf(" B Bad/Unmapped block\n"); ++ printf("\n"); ++ ++ for (i = 0; i < nm->ni->data_block_count; i++) { ++ if (i % 64 == 0) ++ printf(" "); ++ ++ if (nm->ni->block_mapping[i] < 0) ++ putc('B'); ++ else if (nm->ni->block_mapping[i] == i) ++ putc('-'); ++ else if (nm->ni->block_mapping[i] < nm->ni->data_block_count) ++ putc('+'); ++ else if (nm->ni->block_mapping[i] > nm->ni->mapping_blocks_top_ba && ++ nm->ni->block_mapping[i] < nm->ni->signature_ba) ++ putc('M'); ++ else ++ putc('?'); ++ ++ if (i % 64 == 63) ++ printf("\n"); ++ } ++ ++ return 0; ++} ++ ++int nmbm_mtd_print_bad_blocks(const char *name) ++{ ++ struct nmbm_mtd *nm; ++ bool found = false; ++ uint32_t i; ++ ++ list_for_each_entry(nm, &nmbm_devs, node) { ++ if (!strcmp(nm->name, name)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ printf("Error: NMBM device '%s' not found\n", name); ++ return -ENODEV; ++ } ++ ++ printf("Physical blocks:\n"); ++ ++ for (i = 0; i < nm->ni->block_count; i++) { ++ switch (nmbm_debug_get_block_state(nm->ni, i)) { ++ case BLOCK_ST_BAD: ++ printf("%-12u [0x%08llx] - Bad\n", i, ++ (uint64_t)i << nm->ni->erasesize_shift); ++ break; ++ case BLOCK_ST_NEED_REMAP: ++ printf("%-12u [0x%08llx] - Awaiting remapping\n", i, ++ (uint64_t)i << nm->ni->erasesize_shift); ++ break; ++ } ++ } ++ ++ printf("\n"); ++ printf("Logical blocks:\n"); ++ ++ for (i = 0; i < nm->ni->data_block_count; i++) { ++ if (nm->ni->block_mapping[i] < 0) { ++ printf("%-12u [0x%08llx] - Bad\n", i, ++ (uint64_t)i << nm->ni->erasesize_shift); ++ } ++ } ++ ++ return 0; ++} ++ ++int nmbm_mtd_print_mappings(const char *name, int printall) ++{ ++ struct nmbm_mtd *nm; ++ bool found = false; ++ int32_t pb; ++ uint32_t i; ++ ++ list_for_each_entry(nm, &nmbm_devs, node) { ++ if (!strcmp(nm->name, name)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ printf("Error: NMBM device '%s' not found\n", name); ++ return -ENODEV; ++ } ++ ++ printf("Logical Block Physical Block\n"); ++ printf("==================================\n"); ++ ++ if (!printall) { ++ for (i = 0; i < nm->ni->data_block_count; i++) { ++ pb = nm->ni->block_mapping[i]; ++ if (pb < 0) ++ printf("%-20uUnmapped\n", i); ++ else if ((uint32_t)pb > nm->ni->mapping_blocks_top_ba && ++ (uint32_t)pb < nm->ni->signature_ba) ++ printf("%-20u%u\n", i, pb); ++ } ++ ++ return 0; ++ } ++ ++ for (i = 0; i < nm->ni->data_block_count; i++) { ++ pb = nm->ni->block_mapping[i]; ++ ++ if (pb >= 0) ++ printf("%-20u%u\n", i, pb); ++ else ++ printf("%-20uUnmapped\n", i); ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/include/nmbm/nmbm-mtd.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Weijie Gao ++ */ ++ ++#ifndef _NMBM_MTD_H_ ++#define _NMBM_MTD_H_ ++ ++#include ++ ++int nmbm_attach_mtd(struct mtd_info *lower, int flags, uint32_t max_ratio, ++ uint32_t max_reserved_blocks, struct mtd_info **upper); ++ ++int nmbm_free_mtd(struct mtd_info *upper); ++ ++struct mtd_info *nmbm_mtd_get_upper_by_index(uint32_t index); ++struct mtd_info *nmbm_mtd_get_upper(struct mtd_info *lower); ++ ++void nmbm_mtd_list_devices(void); ++int nmbm_mtd_print_info(const char *name); ++int nmbm_mtd_print_states(const char *name); ++int nmbm_mtd_print_bad_blocks(const char *name); ++int nmbm_mtd_print_mappings(const char *name, int printall); ++ ++#endif /* _NMBM_MTD_H_ */ diff --git a/package/boot/uboot-mediatek/patches/100-08-common-board_r-add-support-to-initialize-NMBM-after-.patch b/package/boot/uboot-mediatek/patches/100-08-common-board_r-add-support-to-initialize-NMBM-after-.patch new file mode 100644 index 0000000000..3dab053677 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-08-common-board_r-add-support-to-initialize-NMBM-after-.patch @@ -0,0 +1,46 @@ +From dcf24c8deeb43a4406ae18136c8700dc2f867415 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 11:18:03 +0800 +Subject: [PATCH 42/71] common: board_r: add support to initialize NMBM after + nand initialization + +This patch add support to initialize NMBM after nand initialized. + +Signed-off-by: Weijie Gao +--- + common/board_r.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/common/board_r.c ++++ b/common/board_r.c +@@ -382,6 +382,20 @@ static int initr_nand(void) + } + #endif + ++#ifdef CONFIG_NMBM_MTD ++ ++__weak int board_nmbm_init(void) ++{ ++ return 0; ++} ++ ++/* go init the NMBM */ ++static int initr_nmbm(void) ++{ ++ return board_nmbm_init(); ++} ++#endif ++ + #if defined(CONFIG_CMD_ONENAND) + /* go init the NAND */ + static int initr_onenand(void) +@@ -703,6 +717,9 @@ static init_fnc_t init_sequence_r[] = { + #ifdef CONFIG_CMD_ONENAND + initr_onenand, + #endif ++#ifdef CONFIG_NMBM_MTD ++ initr_nmbm, ++#endif + #ifdef CONFIG_MMC + initr_mmc, + #endif diff --git a/package/boot/uboot-mediatek/patches/100-09-cmd-add-nmbm-command.patch b/package/boot/uboot-mediatek/patches/100-09-cmd-add-nmbm-command.patch new file mode 100644 index 0000000000..e6e155bc14 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-09-cmd-add-nmbm-command.patch @@ -0,0 +1,370 @@ +From 0af8d0aac77f4df4bc7dadbcdea5d9a16f5f3e45 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 10:44:57 +0800 +Subject: [PATCH 43/71] cmd: add nmbm command + +Add nmbm command for debugging, data operations and image-booting support + +Signed-off-by: Weijie Gao +--- + cmd/Kconfig | 6 + + cmd/Makefile | 1 + + cmd/nmbm.c | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 334 insertions(+) + create mode 100644 cmd/nmbm.c + +--- a/cmd/Kconfig ++++ b/cmd/Kconfig +@@ -1260,6 +1260,12 @@ config CMD_NAND_TORTURE + + endif # CMD_NAND + ++config CMD_NMBM ++ depends on NMBM_MTD ++ bool "nmbm" ++ help ++ NAND mapping block management (NMBM) utility ++ + config CMD_NVME + bool "nvme" + depends on NVME +--- a/cmd/Makefile ++++ b/cmd/Makefile +@@ -114,6 +114,7 @@ obj-y += legacy-mtd-utils.o + endif + obj-$(CONFIG_CMD_MUX) += mux.o + obj-$(CONFIG_CMD_NAND) += nand.o ++obj-$(CONFIG_CMD_NMBM) += nmbm.o + obj-$(CONFIG_CMD_NET) += net.o + obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o + obj-$(CONFIG_CMD_ONENAND) += onenand.o +--- /dev/null ++++ b/cmd/nmbm.c +@@ -0,0 +1,327 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Weijie Gao ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static int nmbm_parse_offset_size(struct mtd_info *mtd, char *off_str, ++ char *size_str, uint64_t *off, ++ uint64_t *size) ++{ ++ char *end; ++ ++ *off = simple_strtoull(off_str, &end, 16); ++ if (end == off_str) { ++ printf("Error: offset '%s' is invalid\n", off_str); ++ return -EINVAL; ++ } ++ ++ if (*off >= mtd->size) { ++ printf("Error: offset '0x%llx' is beyond the end of device\n", ++ *off); ++ return -EINVAL; ++ } ++ ++ *size = simple_strtoull(size_str, &end, 16); ++ if (end == off_str) { ++ printf("Error: size '%s' is invalid\n", off_str); ++ return -EINVAL; ++ } ++ ++ if (*off + *size > mtd->size) { ++ printf("Error: size '0x%llx' is too large\n", *size); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int do_nmbm_erase(struct mtd_info *mtd, uint64_t offset, uint64_t size) ++{ ++ struct erase_info ei; ++ int ret; ++ ++ memset(&ei, 0, sizeof(ei)); ++ ++ ei.mtd = mtd; ++ ei.addr = offset; ++ ei.len = size; ++ ++ printf("Erasing from 0x%llx, size 0x%llx ...\n", offset, size); ++ ++ ret = mtd_erase(mtd, &ei); ++ ++ if (!ret) { ++ printf("Succeeded\n"); ++ return CMD_RET_SUCCESS; ++ } ++ ++ printf("Failed at 0x%llx\n", ei.fail_addr); ++ ++ return CMD_RET_FAILURE; ++} ++ ++static int do_nmbm_rw(int read, struct mtd_info *mtd, uintptr_t addr, ++ uint64_t offset, size_t size) ++{ ++ size_t retlen; ++ int ret; ++ ++ printf("%s 0x%llx, size 0x%zx\n", read ? "Reading from" : "Writing to", ++ offset, size); ++ ++ if (read) ++ ret = mtd_read(mtd, offset, size, &retlen, (void *)addr); ++ else ++ ret = mtd_write(mtd, offset, size, &retlen, (void *)addr); ++ ++ if (!ret) { ++ printf("Succeeded\n"); ++ return CMD_RET_SUCCESS; ++ } ++ ++ printf("Failed at 0x%llx\n", offset + retlen); ++ ++ return CMD_RET_FAILURE; ++} ++ ++static int do_nmbm_mtd_boot(struct cmd_tbl *cmdtp, struct mtd_info *mtd, ++ int argc, char *const argv[]) ++{ ++ bool print_image_contents = true; ++ uintptr_t loadaddr = image_load_addr; ++ char *end, *image_name; ++ const char *ep; ++ size_t retlen; ++ uint32_t size; ++ uint64_t off; ++ int ret; ++ ++#if defined(CONFIG_CMD_MTDPARTS) ++ struct mtd_device *partdev; ++ struct mtd_info *partmtd; ++ struct part_info *part; ++ u8 pnum; ++#endif ++ ++ ep = env_get("autostart"); ++ ++ if (ep && !strcmp(ep, "yes")) ++ print_image_contents = false; ++ ++ if (argc == 2) { ++ loadaddr = simple_strtoul(argv[0], &end, 0); ++ if (*end || end == argv[0]) { ++ printf("'%s' is not a valid address\n", argv[0]); ++ return CMD_RET_FAILURE; ++ } ++ ++ argc--; ++ argv++; ++ } ++ ++ off = simple_strtoull(argv[0], &end, 0); ++ if (*end || end == argv[0]) { ++#if defined(CONFIG_CMD_MTDPARTS) ++ ret = mtdparts_init(); ++ if (ret) ++ return CMD_RET_FAILURE; ++ ++ ret = find_dev_and_part(argv[0], &partdev, &pnum, &part); ++ if (ret) ++ return CMD_RET_FAILURE; ++ ++ if (partdev->id->type != MTD_DEV_TYPE_NMBM) { ++ printf("'%s' is not a NMBM device partition\n", ++ argv[0]); ++ return CMD_RET_FAILURE; ++ } ++ ++ partmtd = nmbm_mtd_get_upper_by_index(partdev->id->num); ++ ++ if (partmtd != mtd) { ++ printf("'%s' does not belong to this device\n", ++ argv[0]); ++ return CMD_RET_FAILURE; ++ } ++ ++ off = part->offset; ++#else ++ printf("'%s' is not a valid offset\n", argv[0]); ++ return CMD_RET_FAILURE; ++#endif ++ } ++ ++ ret = mtd_read(mtd, off, sizeof(image_header_t), &retlen, ++ (void *)loadaddr); ++ if (ret || retlen != sizeof(image_header_t)) { ++ printf("Failed to read NMBM at offset 0x%08llx\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ switch (genimg_get_format((void *)loadaddr)) { ++#if defined(CONFIG_LEGACY_IMAGE_FORMAT) ++ case IMAGE_FORMAT_LEGACY: ++ size = image_get_image_size((image_header_t *)loadaddr); ++ image_name = "legacy"; ++ break; ++#endif ++#if defined(CONFIG_FIT) ++ case IMAGE_FORMAT_FIT: ++ size = fit_get_size((const void *)loadaddr); ++ image_name = "FIT"; ++ break; ++#endif ++ default: ++ printf("Error: no Image found at offset 0x%08llx\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ printf("Loading %s image at offset 0x%llx to memory 0x%08lx, size 0x%x ...\n", ++ image_name, off, loadaddr, size); ++ ++ ret = mtd_read(mtd, off, size, &retlen, (void *)loadaddr); ++ if (ret || retlen != size) { ++ printf("Error: Failed to load image at offset 0x%08llx\n", ++ off + retlen); ++ return CMD_RET_FAILURE; ++ } ++ ++ switch (genimg_get_format((void *)loadaddr)) { ++#if defined(CONFIG_LEGACY_IMAGE_FORMAT) ++ case IMAGE_FORMAT_LEGACY: ++ if (print_image_contents) ++ image_print_contents((void *)loadaddr); ++ break; ++#endif ++#if defined(CONFIG_FIT) ++ case IMAGE_FORMAT_FIT: ++ if (print_image_contents) ++ fit_print_contents((void *)loadaddr); ++ break; ++#endif ++ } ++ ++ image_load_addr = loadaddr; ++ ++ return bootm_maybe_autostart(cmdtp, "nmbm"); ++} ++ ++static int do_nmbm(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd; ++ uint64_t offset, size; ++ char *end; ++ uintptr_t addr; ++ int ret, all = 0; ++ ++ if (argc == 1) ++ return CMD_RET_USAGE; ++ ++ if (!strcmp(argv[1], "list")) { ++ nmbm_mtd_list_devices(); ++ return CMD_RET_SUCCESS; ++ } ++ ++ if (argc < 3) ++ return CMD_RET_USAGE; ++ ++ if (!strcmp(argv[2], "info")) ++ return !!nmbm_mtd_print_info(argv[1]); ++ ++ if (!strcmp(argv[2], "state")) ++ return !!nmbm_mtd_print_states(argv[1]); ++ ++ if (!strcmp(argv[2], "bad")) ++ return !!nmbm_mtd_print_bad_blocks(argv[1]); ++ ++ if (!strcmp(argv[2], "mapping")) { ++ if (argc >= 4) { ++ if (!strcmp(argv[3], "all")) ++ all = 1; ++ } ++ ++ return nmbm_mtd_print_mappings(argv[1], all); ++ } ++ ++ if (argc < 4) ++ return CMD_RET_USAGE; ++ ++ mtd = get_mtd_device_nm(argv[1]); ++ if (IS_ERR(mtd)) { ++ printf("Error: NMBM device '%s' not found\n", argv[1]); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (mtd->type != MTD_DEV_TYPE_NMBM) { ++ printf("Error: '%s' is not a NMBM device\n", argv[1]); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (!strcmp(argv[2], "boot")) ++ return do_nmbm_mtd_boot(cmdtp, mtd, argc - 3, argv + 3); ++ ++ if (argc < 5) ++ return CMD_RET_USAGE; ++ ++ if (!strcmp(argv[2], "erase")) { ++ ret = nmbm_parse_offset_size(mtd, argv[3], argv[4], &offset, ++ &size); ++ if (ret) ++ return CMD_RET_FAILURE; ++ ++ return do_nmbm_erase(mtd, offset, size); ++ } ++ ++ if (argc < 6) ++ return CMD_RET_USAGE; ++ ++ ret = nmbm_parse_offset_size(mtd, argv[4], argv[5], &offset, &size); ++ if (ret) ++ return CMD_RET_FAILURE; ++ ++ if (size > SIZE_MAX) { ++ printf("Error: size 0x%llx is too large\n", size); ++ return -EINVAL; ++ } ++ ++ addr = simple_strtoul(argv[3], &end, 16); ++ if (end == argv[3]) { ++ printf("Error: addr '%s' is invalid\n", argv[3]); ++ return -EINVAL; ++ } ++ ++ if (!strcmp(argv[2], "read")) ++ return do_nmbm_rw(1, mtd, addr, offset, (size_t)size); ++ ++ if (!strcmp(argv[2], "write")) ++ return do_nmbm_rw(0, mtd, addr, offset, (size_t)size); ++ ++ return CMD_RET_USAGE; ++} ++ ++U_BOOT_CMD( ++ nmbm, CONFIG_SYS_MAXARGS, 0, do_nmbm, ++ "NMBM utility commands", ++ "\n" ++ "nmbm list - List NMBM devices\n" ++ "nmbm info - Display NMBM information\n" ++ "nmbm state - Display block states\n" ++ "nmbm bad - Display bad blocks\n" ++ "nmbm boot - Boot from NMBM\n" ++ "nmbm mapping [all] - Display block mapping\n" ++ "nmbm erase - Erase blocks\n" ++ "nmbm read - Read data\n" ++ "nmbm write - Write data\n" ++); diff --git a/package/boot/uboot-mediatek/patches/100-10-cmd-mtd-add-markbad-subcommand-for-NMBM-testing.patch b/package/boot/uboot-mediatek/patches/100-10-cmd-mtd-add-markbad-subcommand-for-NMBM-testing.patch new file mode 100644 index 0000000000..6e38ec4ac9 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-10-cmd-mtd-add-markbad-subcommand-for-NMBM-testing.patch @@ -0,0 +1,80 @@ +From 6dbbc8affb6ab22f940d13d0e928d5e881127ca4 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 11:22:57 +0800 +Subject: [PATCH 44/71] cmd: mtd: add markbad subcommand for NMBM testing + +This patch adds: +* Mark bad block on lower mtd device and erase on upper mtd +device, which will trigger remapping: +$ mtd markbad spi-nand0 0x20000 (mark block1 as bad) +$ mtd erase nmbm0 0x20000 0x20000 (let nmbm detect the bad block and remap it) + +* Clear bad block mark through: +$ mtd erase.dontskipbad spi-nand0 0x20000 0x20000 +(After cleaning bad block mark, we need to rebuild nmbm manage table.) + +Signed-off-by: SkyLake.Huang +--- + cmd/mtd.c | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +--- a/cmd/mtd.c ++++ b/cmd/mtd.c +@@ -492,6 +492,42 @@ out_put_mtd: + return CMD_RET_SUCCESS; + } + ++static int do_mtd_markbad(struct cmd_tbl *cmdtp, int flag, int argc, ++ char * const argv[]) ++{ ++ struct mtd_info *mtd; ++ loff_t off; ++ int ret; ++ ++ if (argc < 3) ++ return CMD_RET_USAGE; ++ ++ mtd = get_mtd_by_name(argv[1]); ++ if (IS_ERR(mtd) || !mtd) ++ return CMD_RET_FAILURE; ++ ++ if (!mtd_can_have_bb(mtd)) { ++ printf("Only NAND-based devices can have mark blocks\n"); ++ goto out_put_mtd; ++ } ++ ++ off = simple_strtoull(argv[2], NULL, 0); ++ ++ ret = mtd_block_markbad(mtd, off); ++ if (!ret) { ++ printf("MTD device %s block at 0x%08llx marked bad\n", ++ mtd->name, off); ++ } else { ++ printf("MTD device %s block at 0x%08llx mark bad failed\n", ++ mtd->name, off); ++ } ++ ++out_put_mtd: ++ put_mtd_device(mtd); ++ ++ return CMD_RET_SUCCESS; ++} ++ + #ifdef CONFIG_AUTO_COMPLETE + static int mtd_name_complete(int argc, char *const argv[], char last_char, + int maxv, char *cmdv[]) +@@ -540,6 +576,7 @@ static char mtd_help_text[] = + "\n" + "Specific functions:\n" + "mtd bad \n" ++ "mtd markbad \n" + "\n" + "With:\n" + "\t: NAND partition/chip name (or corresponding DM device name or OF path)\n" +@@ -565,4 +602,6 @@ U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils" + U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase, + mtd_name_complete), + U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad, ++ mtd_name_complete), ++ U_BOOT_SUBCMD_MKENT_COMPLETE(markbad, 3, 1, do_mtd_markbad, + mtd_name_complete)); diff --git a/package/boot/uboot-mediatek/patches/100-11-env-add-support-for-NMBM-upper-MTD-layer.patch b/package/boot/uboot-mediatek/patches/100-11-env-add-support-for-NMBM-upper-MTD-layer.patch new file mode 100644 index 0000000000..2791332b04 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-11-env-add-support-for-NMBM-upper-MTD-layer.patch @@ -0,0 +1,280 @@ +From 240d98e6ad0aed3c11236aa40a60bbd6fe01fae5 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 10:50:46 +0800 +Subject: [PATCH 45/71] env: add support for NMBM upper MTD layer + +Add an env driver for NMBM upper MTD layer + +Signed-off-by: Weijie Gao +--- + cmd/nvedit.c | 3 +- + env/Kconfig | 19 ++++- + env/Makefile | 1 + + env/env.c | 3 + + env/nmbm.c | 155 +++++++++++++++++++++++++++++++++++++++++ + include/env_internal.h | 1 + + tools/Makefile | 1 + + 7 files changed, 180 insertions(+), 3 deletions(-) + create mode 100644 env/nmbm.c + +--- a/cmd/nvedit.c ++++ b/cmd/nvedit.c +@@ -50,6 +50,7 @@ DECLARE_GLOBAL_DATA_PTR; + defined(CONFIG_ENV_IS_IN_EXT4) || \ + defined(CONFIG_ENV_IS_IN_MTD) || \ + defined(CONFIG_ENV_IS_IN_NAND) || \ ++ defined(CONFIG_ENV_IS_IN_NMBM) || \ + defined(CONFIG_ENV_IS_IN_NVRAM) || \ + defined(CONFIG_ENV_IS_IN_ONENAND) || \ + defined(CONFIG_ENV_IS_IN_SATA) || \ +@@ -64,7 +65,7 @@ DECLARE_GLOBAL_DATA_PTR; + #if !defined(ENV_IS_IN_DEVICE) && \ + !defined(CONFIG_ENV_IS_NOWHERE) + # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|MTD|\ +-NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE ++NAND|NMBM|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE + #endif + + /* +--- a/env/Kconfig ++++ b/env/Kconfig +@@ -37,7 +37,7 @@ config ENV_IS_NOWHERE + !ENV_IS_IN_MMC && !ENV_IS_IN_NAND && \ + !ENV_IS_IN_NVRAM && !ENV_IS_IN_ONENAND && \ + !ENV_IS_IN_REMOTE && !ENV_IS_IN_SPI_FLASH && \ +- !ENV_IS_IN_UBI && !ENV_IS_IN_MTD ++ !ENV_IS_IN_UBI && !ENV_IS_IN_NMBM && !ENV_IS_IN_MTD + help + Define this if you don't want to or can't have an environment stored + on a storage medium. In this case the environment will still exist +@@ -285,6 +285,21 @@ config ENV_IS_IN_NAND + Currently, CONFIG_ENV_OFFSET_REDUND is not supported when + using CONFIG_ENV_OFFSET_OOB. + ++config ENV_IS_IN_NMBM ++ bool "Environment in a NMBM upper MTD layer" ++ depends on !CHAIN_OF_TRUST ++ depends on NMBM_MTD ++ help ++ Define this if you have a NMBM upper MTD which you want to use for ++ the environment. ++ ++ - CONFIG_ENV_OFFSET: ++ - CONFIG_ENV_SIZE: ++ ++ These two #defines specify the offset and size of the environment ++ area within the first NAND device. CONFIG_ENV_OFFSET must be ++ aligned to an erase block boundary. ++ + config ENV_IS_IN_NVRAM + bool "Environment in a non-volatile RAM" + depends on !CHAIN_OF_TRUST +@@ -561,7 +576,7 @@ config ENV_MTD_NAME + config ENV_OFFSET + hex "Environment offset" + depends on ENV_IS_IN_EEPROM || ENV_IS_IN_MMC || ENV_IS_IN_NAND || \ +- ENV_IS_IN_SPI_FLASH || ENV_IS_IN_MTD ++ ENV_IS_IN_SPI_FLASH || ENV_IS_IN_NMBM || ENV_IS_IN_MTD + default 0x3f8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC + default 0x140000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH + default 0xF0000 if ARCH_SUNXI +--- a/env/Makefile ++++ b/env/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_FAT) + + obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_EXT4) += ext4.o + obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_MTD) += mtd.o + obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_NAND) += nand.o ++obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_NMBM) += nmbm.o + obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_SPI_FLASH) += sf.o + obj-$(CONFIG_$(SPL_TPL_)ENV_IS_IN_FLASH) += flash.o + +--- a/env/env.c ++++ b/env/env.c +@@ -75,6 +75,9 @@ static enum env_location env_locations[] + #ifdef CONFIG_ENV_IS_IN_NAND + ENVL_NAND, + #endif ++#ifdef CONFIG_ENV_IS_IN_NMBM ++ ENVL_NMBM, ++#endif + #ifdef CONFIG_ENV_IS_IN_NVRAM + ENVL_NVRAM, + #endif +--- /dev/null ++++ b/env/nmbm.c +@@ -0,0 +1,155 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Weijie Gao ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if defined(CONFIG_CMD_SAVEENV) && defined(CONFIG_NMBM_MTD) ++#define CMD_SAVEENV ++#endif ++ ++#if defined(ENV_IS_EMBEDDED) ++env_t *env_ptr = &environment; ++#else /* ! ENV_IS_EMBEDDED */ ++env_t *env_ptr; ++#endif /* ENV_IS_EMBEDDED */ ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++static int env_nmbm_init(void) ++{ ++#if defined(ENV_IS_EMBEDDED) ++ int crc1_ok = 0, crc2_ok = 0; ++ env_t *tmp_env1; ++ ++ tmp_env1 = env_ptr; ++ crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc; ++ ++ if (!crc1_ok && !crc2_ok) { ++ gd->env_addr = 0; ++ gd->env_valid = ENV_INVALID; ++ ++ return 0; ++ } else if (crc1_ok && !crc2_ok) { ++ gd->env_valid = ENV_VALID; ++ } ++ ++ if (gd->env_valid == ENV_VALID) ++ env_ptr = tmp_env1; ++ ++ gd->env_addr = (ulong)env_ptr->data; ++ ++#else /* ENV_IS_EMBEDDED */ ++ gd->env_addr = (ulong)&default_environment[0]; ++ gd->env_valid = ENV_VALID; ++#endif /* ENV_IS_EMBEDDED */ ++ ++ return 0; ++} ++ ++#ifdef CMD_SAVEENV ++static int env_nmbm_save(void) ++{ ++ ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); ++ struct mtd_info *mtd; ++ struct erase_info ei; ++ int ret = 0; ++ ++ ret = env_export(env_new); ++ if (ret) ++ return ret; ++ ++ mtd = nmbm_mtd_get_upper_by_index(0); ++ if (!mtd) ++ return 1; ++ ++ printf("Erasing on NMBM...\n"); ++ memset(&ei, 0, sizeof(ei)); ++ ++ ei.mtd = mtd; ++ ei.addr = CONFIG_ENV_OFFSET; ++ ei.len = CONFIG_ENV_SIZE; ++ ++ if (mtd_erase(mtd, &ei)) ++ return 1; ++ ++ printf("Writing on NMBM... "); ++ ret = mtd_write(mtd, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, NULL, ++ (u_char *)env_new); ++ puts(ret ? "FAILED!\n" : "OK\n"); ++ ++ return !!ret; ++} ++#endif /* CMD_SAVEENV */ ++ ++static int readenv(size_t offset, u_char *buf) ++{ ++ struct mtd_info *mtd; ++ struct mtd_oob_ops ops; ++ int ret; ++ size_t len = CONFIG_ENV_SIZE; ++ ++ mtd = nmbm_mtd_get_upper_by_index(0); ++ if (!mtd) ++ return 1; ++ ++ ops.mode = MTD_OPS_AUTO_OOB; ++ ops.ooblen = 0; ++ while(len > 0) { ++ ops.datbuf = buf; ++ ops.len = min(len, (size_t)mtd->writesize); ++ ops.oobbuf = NULL; ++ ++ ret = mtd_read_oob(mtd, offset, &ops); ++ if (ret) ++ return 1; ++ ++ buf += mtd->writesize; ++ len -= mtd->writesize; ++ offset += mtd->writesize; ++ } ++ ++ return 0; ++} ++ ++static int env_nmbm_load(void) ++{ ++#if !defined(ENV_IS_EMBEDDED) ++ ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); ++ int ret; ++ ++ ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf); ++ if (ret) { ++ env_set_default("readenv() failed", 0); ++ return -EIO; ++ } ++ ++ return env_import(buf, 1, H_EXTERNAL); ++#endif /* ! ENV_IS_EMBEDDED */ ++ ++ return 0; ++} ++ ++U_BOOT_ENV_LOCATION(nmbm) = { ++ .location = ENVL_NMBM, ++ ENV_NAME("NMBM") ++ .load = env_nmbm_load, ++#if defined(CMD_SAVEENV) ++ .save = env_save_ptr(env_nmbm_save), ++#endif ++ .init = env_nmbm_init, ++}; +--- a/include/env_internal.h ++++ b/include/env_internal.h +@@ -132,6 +132,7 @@ enum env_location { + ENVL_MMC, + ENVL_MTD, + ENVL_NAND, ++ ENVL_NMBM, + ENVL_NVRAM, + ENVL_ONENAND, + ENVL_REMOTE, +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -43,6 +43,7 @@ ENVCRC-$(CONFIG_ENV_IS_IN_FLASH) = y + ENVCRC-$(CONFIG_ENV_IS_IN_ONENAND) = y + ENVCRC-$(CONFIG_ENV_IS_IN_MTD) = y + ENVCRC-$(CONFIG_ENV_IS_IN_NAND) = y ++ENVCRC-$(CONFIG_ENV_IS_IN_NMBM) = y + ENVCRC-$(CONFIG_ENV_IS_IN_NVRAM) = y + ENVCRC-$(CONFIG_ENV_IS_IN_SPI_FLASH) = y + CONFIG_BUILD_ENVCRC ?= $(ENVCRC-y) diff --git a/package/boot/uboot-mediatek/patches/100-12-mtd-mtk-snand-add-NMBM-support-for-SPL.patch b/package/boot/uboot-mediatek/patches/100-12-mtd-mtk-snand-add-NMBM-support-for-SPL.patch new file mode 100644 index 0000000000..32b21be255 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-12-mtd-mtk-snand-add-NMBM-support-for-SPL.patch @@ -0,0 +1,173 @@ +From 9e8ac4fc7125795ac5e8834aaf454fd45b99c580 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 10:53:03 +0800 +Subject: [PATCH 46/71] mtd: mtk-snand: add NMBM support for SPL + +Add NMBM support for mtk-snand SPL loader + +Signed-off-by: Weijie Gao +--- + drivers/mtd/mtk-snand/mtk-snand-spl.c | 127 ++++++++++++++++++++++++++ + 1 file changed, 127 insertions(+) + +--- a/drivers/mtd/mtk-snand/mtk-snand-spl.c ++++ b/drivers/mtd/mtk-snand/mtk-snand-spl.c +@@ -13,12 +13,134 @@ + #include + #include + ++#include ++ + #include "mtk-snand.h" + + static struct mtk_snand *snf; + static struct mtk_snand_chip_info cinfo; + static u32 oobavail; + ++#ifdef CONFIG_ENABLE_NAND_NMBM ++static struct nmbm_instance *ni; ++ ++static int nmbm_lower_read_page(void *arg, uint64_t addr, void *buf, void *oob, ++ enum nmbm_oob_mode mode) ++{ ++ int ret; ++ bool raw = mode == NMBM_MODE_RAW ? true : false; ++ ++ if (mode == NMBM_MODE_AUTO_OOB) { ++ ret = mtk_snand_read_page_auto_oob(snf, addr, buf, oob, ++ oobavail, NULL, false); ++ } else { ++ ret = mtk_snand_read_page(snf, addr, buf, oob, raw); ++ } ++ ++ if (ret == -EBADMSG) ++ return 1; ++ else if (ret >= 0) ++ return 0; ++ ++ return ret; ++} ++ ++static int nmbm_lower_write_page(void *arg, uint64_t addr, const void *buf, ++ const void *oob, enum nmbm_oob_mode mode) ++{ ++ bool raw = mode == NMBM_MODE_RAW ? true : false; ++ ++ if (mode == NMBM_MODE_AUTO_OOB) { ++ return mtk_snand_write_page_auto_oob(snf, addr, buf, oob, ++ oobavail, NULL, false); ++ } ++ ++ return mtk_snand_write_page(snf, addr, buf, oob, raw); ++} ++ ++static int nmbm_lower_erase_block(void *arg, uint64_t addr) ++{ ++ return mtk_snand_erase_block(snf, addr); ++} ++ ++static int nmbm_lower_is_bad_block(void *arg, uint64_t addr) ++{ ++ return mtk_snand_block_isbad(snf, addr); ++} ++ ++static int nmbm_lower_mark_bad_block(void *arg, uint64_t addr) ++{ ++ return mtk_snand_block_markbad(snf, addr); ++} ++ ++static void nmbm_lower_log(void *arg, enum nmbm_log_category level, ++ const char *fmt, va_list ap) ++{ ++ vprintf(fmt, ap); ++} ++ ++static int nmbm_init(void) ++{ ++ struct nmbm_lower_device nld; ++ size_t ni_size; ++ int ret; ++ ++ memset(&nld, 0, sizeof(nld)); ++ ++ nld.flags = NMBM_F_CREATE; ++ nld.max_ratio = CONFIG_NMBM_MAX_RATIO; ++ nld.max_reserved_blocks = CONFIG_NMBM_MAX_BLOCKS; ++ ++ nld.size = cinfo.chipsize; ++ nld.erasesize = cinfo.blocksize; ++ nld.writesize = cinfo.pagesize; ++ nld.oobsize = cinfo.sparesize; ++ nld.oobavail = oobavail; ++ ++ nld.read_page = nmbm_lower_read_page; ++ nld.write_page = nmbm_lower_write_page; ++ nld.erase_block = nmbm_lower_erase_block; ++ nld.is_bad_block = nmbm_lower_is_bad_block; ++ nld.mark_bad_block = nmbm_lower_mark_bad_block; ++ ++ nld.logprint = nmbm_lower_log; ++ ++ ni_size = nmbm_calc_structure_size(&nld); ++ ni = malloc(ni_size); ++ if (!ni) { ++ printf("Failed to allocate memory (0x%u) for NMBM instance\n", ++ ni_size); ++ return -ENOMEM; ++ } ++ ++ memset(ni, 0, ni_size); ++ ++ printf("Initializing NMBM ...\n"); ++ ++ ret = nmbm_attach(&nld, ni); ++ if (ret) { ++ ni = NULL; ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) ++{ ++ size_t retlen; ++ ++ if (!ni) ++ return -ENODEV; ++ ++ nmbm_read_range(ni, offs, size, dst, NMBM_MODE_PLACE_OOB, &retlen); ++ if (retlen != size) ++ return -EIO; ++ ++ return 0; ++} ++ ++#else + static u8 *page_cache; + + int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) +@@ -60,6 +182,7 @@ int nand_spl_load_image(uint32_t offs, u + + return ret; + } ++#endif + + void nand_init(void) + { +@@ -105,11 +228,15 @@ void nand_init(void) + printf("SPI-NAND: %s (%uMB)\n", cinfo.model, + (u32)(cinfo.chipsize >> 20)); + ++#ifdef CONFIG_ENABLE_NAND_NMBM ++ nmbm_init(); ++#else + page_cache = malloc(cinfo.pagesize + cinfo.sparesize); + if (!page_cache) { + mtk_snand_cleanup(snf); + printf("mtk-snand-spl: failed to allocate page cache\n"); + } ++#endif + } + + void nand_deselect(void) diff --git a/package/boot/uboot-mediatek/patches/100-13-cmd-add-a-new-command-for-NAND-flash-debugging.patch b/package/boot/uboot-mediatek/patches/100-13-cmd-add-a-new-command-for-NAND-flash-debugging.patch new file mode 100644 index 0000000000..bf4ed97f13 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-13-cmd-add-a-new-command-for-NAND-flash-debugging.patch @@ -0,0 +1,1118 @@ +From 88271cb3ae9c68dc200d627653df96fc557c2a64 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 10:55:35 +0800 +Subject: [PATCH 47/71] cmd: add a new command for NAND flash debugging + +Add a command 'nand-ext' for NAND flash debugging: +- Dump a page with oob, with optional raw read support +- Display all bad blocks +- Mark a block as bad block +- Set a bitflip on a page +- Erase +- Read / write data from/to any offset with any size +- Read / write pages with oob +- Erase, read and write support skip bad block or forced mode, support + raw mode, supporot auto-oob mode +- Supports operating on a specific partition +- No need to specify NAND device name + +Signed-off-by: Weijie Gao +--- + cmd/Kconfig | 8 + + cmd/Makefile | 1 + + cmd/nand-ext.c | 1062 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 1071 insertions(+) + create mode 100644 cmd/nand-ext.c + +--- a/cmd/Kconfig ++++ b/cmd/Kconfig +@@ -1260,6 +1260,14 @@ config CMD_NAND_TORTURE + + endif # CMD_NAND + ++config CMD_NAND_EXT ++ bool "nand - extended nand utility for debugging" ++ depends on !CMD_NAND ++ default y if MTD_RAW_NAND || MTD_SPI_NAND || MTK_SPI_NAND ++ select MTD_PARTITIONS ++ help ++ NAND flash R/W and debugging support. ++ + config CMD_NMBM + depends on NMBM_MTD + bool "nmbm" +--- a/cmd/Makefile ++++ b/cmd/Makefile +@@ -114,6 +114,7 @@ obj-y += legacy-mtd-utils.o + endif + obj-$(CONFIG_CMD_MUX) += mux.o + obj-$(CONFIG_CMD_NAND) += nand.o ++obj-$(CONFIG_CMD_NAND_EXT) += nand-ext.o + obj-$(CONFIG_CMD_NMBM) += nmbm.o + obj-$(CONFIG_CMD_NET) += net.o + obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o +--- /dev/null ++++ b/cmd/nand-ext.c +@@ -0,0 +1,1062 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2021 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Weijie Gao ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct mtd_info *curr_dev; ++ ++static void mtd_show_parts(struct mtd_info *mtd, int level) ++{ ++ struct mtd_info *part; ++ int i; ++ ++ list_for_each_entry(part, &mtd->partitions, node) { ++ for (i = 0; i < level; i++) ++ printf("\t"); ++ printf(" - 0x%012llx-0x%012llx : \"%s\"\n", ++ part->offset, part->offset + part->size, part->name); ++ ++ mtd_show_parts(part, level + 1); ++ } ++} ++ ++static void mtd_show_device(struct mtd_info *mtd) ++{ ++ /* Device */ ++ printf("* %s\n", mtd->name); ++#if defined(CONFIG_DM) ++ if (mtd->dev) { ++ printf(" - device: %s\n", mtd->dev->name); ++ printf(" - parent: %s\n", mtd->dev->parent->name); ++ printf(" - driver: %s\n", mtd->dev->driver->name); ++ } ++#endif ++ ++ /* MTD device information */ ++ printf(" - type: "); ++ switch (mtd->type) { ++ case MTD_NANDFLASH: ++ printf("NAND flash\n"); ++ break; ++ case MTD_MLCNANDFLASH: ++ printf("MLC NAND flash\n"); ++ break; ++ case MTD_ABSENT: ++ default: ++ printf("Not supported\n"); ++ break; ++ } ++ ++ printf(" - block size: 0x%x bytes\n", mtd->erasesize); ++ printf(" - page size: 0x%x bytes\n", mtd->writesize); ++ printf(" - OOB size: %u bytes\n", mtd->oobsize); ++ printf(" - OOB available: %u bytes\n", mtd->oobavail); ++ ++ if (mtd->ecc_strength) { ++ printf(" - ECC strength: %u bits\n", mtd->ecc_strength); ++ printf(" - ECC step size: %u bytes\n", mtd->ecc_step_size); ++ printf(" - bitflip threshold: %u bits\n", ++ mtd->bitflip_threshold); ++ } ++ ++ printf(" - 0x%012llx-0x%012llx : \"%s\"\n", ++ mtd->offset, mtd->offset + mtd->size, mtd->name); ++ ++ /* MTD partitions, if any */ ++ mtd_show_parts(mtd, 1); ++} ++ ++static int do_nand_list(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd; ++ int dev_nb = 0; ++ ++ /* Ensure all devices (and their partitions) are probed */ ++ mtd_probe_devices(); ++ ++ printf("List of NAND devices:\n"); ++ mtd_for_each_device(mtd) { ++ if (mtd->type != MTD_NANDFLASH && mtd->type != MTD_MLCNANDFLASH) ++ continue; ++ ++ if (!mtd_is_partition(mtd)) ++ mtd_show_device(mtd); ++ ++ dev_nb++; ++ } ++ ++ if (!dev_nb) ++ printf("No NAND MTD device found\n"); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static struct mtd_info *nand_get_curr_dev(void) ++{ ++ struct mtd_info *mtd, *first_dev = NULL; ++ int err, dev_nb = 0; ++ ++ if (curr_dev) { ++ mtd = get_mtd_device(curr_dev, -1); ++ if (!IS_ERR_OR_NULL(mtd)) { ++ __put_mtd_device(mtd); ++ return mtd; ++ } ++ ++ curr_dev = NULL; ++ } ++ ++ /* Ensure all devices (and their partitions) are probed */ ++ mtd_probe_devices(); ++ ++ mtd_for_each_device(mtd) { ++ if (mtd->type != MTD_NANDFLASH && mtd->type != MTD_MLCNANDFLASH) ++ continue; ++ ++ if (!mtd_is_partition(mtd)) { ++ if (!first_dev) ++ first_dev = mtd; ++ dev_nb++; ++ } ++ } ++ ++ if (!dev_nb) { ++ printf("No NAND MTD device found\n"); ++ return NULL; ++ } ++ ++ if (dev_nb > 1) { ++ printf("No active NAND MTD device specified\n"); ++ return NULL; ++ } ++ ++ err = __get_mtd_device(first_dev); ++ if (err) { ++ printf("Failed to get MTD device '%s': err %d\n", ++ first_dev->name, err); ++ return NULL; ++ } ++ ++ curr_dev = first_dev; ++ ++ printf("'%s' is now active device\n", first_dev->name); ++ ++ return curr_dev; ++} ++ ++static struct mtd_info *nand_get_part(struct mtd_info *master, ++ const char *name) ++{ ++ struct mtd_info *slave; ++ ++ list_for_each_entry(slave, &master->partitions, node) { ++ if (!strcmp(slave->name, name)) ++ return slave; ++ } ++ ++ return NULL; ++} ++ ++static int do_nand_info(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(); ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ mtd_show_device(mtd); ++ ++ return 0; ++} ++ ++static int do_nand_select(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd, *old; ++ ++ if (argc < 2) { ++ printf("MTD device name must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ mtd = get_mtd_device_nm(argv[1]); ++ if (!mtd) { ++ printf("MTD device '%s' not found\n", argv[1]); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (mtd_is_partition(mtd)) { ++ printf("Error: '%s' is a MTD partition\n", argv[1]); ++ __put_mtd_device(mtd); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (mtd->type != MTD_NANDFLASH && mtd->type != MTD_MLCNANDFLASH) { ++ printf("Error: '%s' is not a NAND device\n", argv[1]); ++ __put_mtd_device(mtd); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (mtd == curr_dev) { ++ __put_mtd_device(mtd); ++ return CMD_RET_SUCCESS; ++ } ++ ++ if (curr_dev) { ++ old = get_mtd_device(curr_dev, -1); ++ if (!IS_ERR_OR_NULL(old)) { ++ __put_mtd_device(old); ++ __put_mtd_device(curr_dev); ++ } ++ ++ curr_dev = NULL; ++ } ++ ++ curr_dev = mtd; ++ ++ printf("'%s' is now active device\n", curr_dev->name); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static void dump_buf(const u8 *data, size_t size, u64 addr) ++{ ++ const u8 *p = data; ++ u32 i, chklen; ++ ++ while (size) { ++ chklen = 16; ++ if (chklen > size) ++ chklen = (u32)size; ++ ++ printf("%08llx: ", addr); ++ ++ for (i = 0; i < chklen; i++) { ++ if (i && (i % 4 == 0)) ++ printf(" "); ++ ++ printf("%02x ", p[i]); ++ } ++ ++ for (i = chklen; i < 16; i++) { ++ if (i && (i % 4 == 0)) ++ printf(" "); ++ ++ printf(" "); ++ } ++ printf(" "); ++ ++ for (i = 0; i < chklen; i++) { ++ if (p[i] < 32 || p[i] >= 0x7f) ++ printf("."); ++ else ++ printf("%c", p[i]); ++ } ++ printf("\n"); ++ ++ p += chklen; ++ size -= chklen; ++ addr += chklen; ++ } ++} ++ ++static int do_nand_dump(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(); ++ struct mtd_oob_ops io_op = {}; ++ bool raw = false; ++ int ret; ++ u64 off; ++ u8 *buf; ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ if (strstr(argv[0], ".raw")) ++ raw = true; ++ ++ if (argc < 2) { ++ printf("Dump offset must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ off = simple_strtoull(argv[1], NULL, 0); ++ if (off >= mtd->size) { ++ printf("Offset 0x%llx is larger than flash size\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ off &= ~(u64)mtd->writesize_mask; ++ ++ buf = malloc(mtd->writesize + mtd->oobsize); ++ if (!buf) { ++ printf("Failed to allocate buffer\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB; ++ io_op.len = mtd->writesize; ++ io_op.datbuf = buf; ++ io_op.ooblen = mtd->oobsize; ++ io_op.oobbuf = buf + mtd->writesize; ++ ++ ret = mtd_read_oob(mtd, off, &io_op); ++ if (ret < 0 && ret != -EUCLEAN && ret != -EBADMSG) { ++ printf("Failed to read page at 0x%llx, err %d\n", off, ret); ++ free(buf); ++ return CMD_RET_FAILURE; ++ } ++ ++ printf("Dump of %spage at 0x%llx:\n", raw ? "raw " : "", off); ++ dump_buf(buf, mtd->writesize, off); ++ ++ printf("\n"); ++ printf("OOB:\n"); ++ dump_buf(buf + mtd->writesize, mtd->oobsize, 0); ++ ++ free(buf); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static int do_nand_bad(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(); ++ u64 off = 0; ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ while (off < mtd->size) { ++ if (mtd_block_isbad(mtd, off)) ++ printf("\t%08llx\n", off); ++ ++ off += mtd->erasesize; ++ } ++ ++ return 0; ++} ++ ++static int do_nand_markbad(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(); ++ u64 off; ++ int ret; ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ if (argc < 2) { ++ printf("Missing address within a block to be marked bad\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ off = simple_strtoull(argv[1], NULL, 0); ++ if (off >= mtd->size) { ++ printf("Offset 0x%llx is larger than flash size\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ off &= ~(u64)mtd->erasesize_mask; ++ ++ ret = mtd_block_markbad(mtd, off); ++ ++ if (!ret) ++ printf("Block at 0x%08llx has been marked bad\n", off); ++ else ++ printf("Failed to mark bad block at 0x%08llx\n", off); ++ ++ return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS; ++} ++ ++static int do_nand_bitflip(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(); ++ struct mtd_oob_ops io_op = {}; ++ u32 col, bit; ++ bool res; ++ u64 off; ++ u8 *buf; ++ int ret; ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ if (argc < 2) { ++ printf("Missing address to generate bitflip\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ off = simple_strtoull(argv[1], NULL, 0); ++ if (off >= mtd->size) { ++ printf("Offset 0x%llx is larger than flash size\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (argc < 3) { ++ printf("Missing column address\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ col = simple_strtoul(argv[2], NULL, 0); ++ if (col >= mtd->writesize + mtd->oobsize) { ++ printf("Column address must be less than %u\n", ++ mtd->writesize + mtd->oobsize); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (argc < 4) { ++ printf("Missing bit position\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ bit = simple_strtoul(argv[3], NULL, 0); ++ if (bit > 7) { ++ printf("Bit position must be less than 8\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ off &= ~(u64)mtd->writesize_mask; ++ ++ buf = malloc(mtd->writesize + mtd->oobsize); ++ if (!buf) { ++ printf("Failed to allocate buffer\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ io_op.mode = MTD_OPS_RAW; ++ io_op.len = mtd->writesize; ++ io_op.datbuf = buf; ++ io_op.ooblen = mtd->oobsize; ++ io_op.oobbuf = buf + mtd->writesize; ++ ++ ret = mtd_read_oob(mtd, off, &io_op); ++ if (ret < 0) { ++ printf("Failed to read page at 0x%llx, err %d\n", off, ret); ++ free(buf); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (!(buf[col] & (1 << bit))) { ++ printf("Bit %u at byte %u is already zero\n", bit, col); ++ free(buf); ++ return CMD_RET_FAILURE; ++ } ++ ++ buf[col] &= ~(1 << bit); ++ ++ memset(&io_op, 0, sizeof(io_op)); ++ io_op.mode = MTD_OPS_RAW; ++ io_op.len = mtd->writesize; ++ io_op.datbuf = buf; ++ io_op.ooblen = mtd->oobsize; ++ io_op.oobbuf = buf + mtd->writesize; ++ ++ ret = mtd_write_oob(mtd, off, &io_op); ++ ++ if (ret < 0) { ++ printf("Failed to write page at 0x%llx, err %d\n", off, ret); ++ return CMD_RET_FAILURE; ++ } ++ ++ memset(&io_op, 0, sizeof(io_op)); ++ io_op.mode = MTD_OPS_RAW; ++ io_op.len = mtd->writesize; ++ io_op.datbuf = buf; ++ io_op.ooblen = mtd->oobsize; ++ io_op.oobbuf = buf + mtd->writesize; ++ ++ ret = mtd_read_oob(mtd, off, &io_op); ++ if (ret < 0) { ++ printf("Failed to read page at 0x%llx, err %d\n", off, ret); ++ free(buf); ++ return CMD_RET_FAILURE; ++ } ++ ++ res = (buf[col] & (1 << bit)) == 0; ++ free(buf); ++ ++ if (res) { ++ printf("Bit %u at byte %u has been changed to 0\n", bit, col); ++ return CMD_RET_SUCCESS; ++ } ++ ++ printf("Failed to change bit %u at byte %u to 0\n", bit, col); ++ return CMD_RET_FAILURE; ++} ++ ++static int do_nand_erase(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(), *part; ++ bool spread = false, force = false; ++ u64 off, size, end, limit; ++ struct erase_info ei; ++ char *ends; ++ int ret; ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ if (strstr(argv[0], ".spread")) ++ spread = true; ++ ++ if (strstr(argv[0], ".force")) ++ force = true; ++ ++ if (spread && force) { ++ printf("spread and force must not be set at the same time\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (argc < 2) { ++ printf("Erase start offset/partition must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ part = nand_get_part(mtd, argv[1]); ++ if (part) { ++ off = part->offset; ++ ++ if (argc < 3) ++ size = part->size; ++ else ++ size = simple_strtoull(argv[2], NULL, 0); ++ ++ if (size > part->size) { ++ printf("Erase end offset is larger than partition size\n"); ++ printf("Erase size reduced to 0x%llx\n", part->size); ++ ++ size = part->size; ++ } ++ ++ limit = off + part->size; ++ } else { ++ off = simple_strtoull(argv[1], &ends, 0); ++ ++ if (ends == argv[1] || *ends) { ++ printf("Partition '%s' not found\n", argv[1]); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (off >= mtd->size) { ++ printf("Offset 0x%llx is larger than flash size\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (argc < 3) { ++ printf("Erase size offset must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ size = simple_strtoull(argv[2], NULL, 0); ++ ++ if (off + size > mtd->size) { ++ printf("Erase end offset is larger than flash size\n"); ++ ++ size = mtd->size - off; ++ printf("Erase size reduced to 0x%llx\n", size); ++ } ++ ++ limit = mtd->size; ++ } ++ ++ end = off + size; ++ off &= ~(u64)mtd->erasesize_mask; ++ end = (end + mtd->erasesize_mask) & (~(u64)mtd->erasesize_mask); ++ size = end - off; ++ ++ printf("Erasing from 0x%llx to 0x%llx, size 0x%llx ...\n", ++ off, end - 1, end - off); ++ ++ while (size && off < limit) { ++ if (mtd_block_isbad(mtd, off)) { ++ printf("Bad block at 0x%llx", off); ++ ++ if (spread) { ++ printf(" ... skipped\n"); ++ off += mtd->erasesize; ++ continue; ++ } ++ ++ if (!force) { ++ printf(" ... aborted\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ printf(" ... will be force erased\n"); ++ } ++ ++ memset(&ei, 0, sizeof(ei)); ++ ++ ei.mtd = mtd; ++ ei.addr = off; ++ ei.len = mtd->erasesize; ++ ei.scrub = force; ++ ++ ret = mtd_erase(mtd, &ei); ++ if (ret) { ++ printf("Erase failed at 0x%llx\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ off += mtd->erasesize; ++ size -= mtd->erasesize; ++ } ++ ++ printf("Succeeded\n"); ++ ++ return CMD_RET_SUCCESS; ++} ++ ++static bool is_empty_page(const u8 *buf, size_t size) ++{ ++ size_t i; ++ ++ for (i = 0; i < size; i++) { ++ if (buf[i] != 0xff) ++ return false; ++ } ++ ++ return true; ++} ++ ++static int do_nand_io_normal(int argc, char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(), *part; ++ bool spread = false, force = false, raw = false, writeff = false; ++ bool read = false, checkbad = true; ++ struct mtd_oob_ops io_op = {}; ++ size_t size, padding, chksz; ++ uintptr_t addr; ++ u64 off, offp; ++ char *ends; ++ u8 *buf; ++ int ret; ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ if (!strncmp(argv[0], "read", 4)) ++ read = true; ++ ++ if (strstr(argv[0], ".spread")) ++ spread = true; ++ ++ if (strstr(argv[0], ".force")) ++ force = true; ++ ++ if (strstr(argv[0], ".raw")) ++ raw = true; ++ ++ if (strstr(argv[0], ".ff")) ++ writeff = true; ++ ++ if (spread && force) { ++ printf("spread and force must not be set at the same time\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (argc < 2) { ++ printf("Data address must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ addr = simple_strtoul(argv[1], NULL, 0); ++ ++ if (argc < 3) { ++ printf("Flash address/partition must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ part = nand_get_part(mtd, argv[2]); ++ if (part) { ++ if (argc < 4) { ++ off = 0; ++ } else { ++ off = simple_strtoull(argv[3], NULL, 0); ++ if (off + part->offset >= part->size) { ++ printf("Offset is larger than partition size\n"); ++ return CMD_RET_FAILURE; ++ } ++ } ++ ++ if (argc < 5) { ++ size = part->size - off; ++ } else { ++ size = simple_strtoul(argv[4], NULL, 0); ++ if (off + size > part->size) { ++ printf("Data size is too large\n"); ++ return CMD_RET_FAILURE; ++ } ++ } ++ ++ off += part->offset; ++ } else { ++ off = simple_strtoull(argv[2], &ends, 0); ++ ++ if (ends == argv[1] || *ends) { ++ printf("Partition '%s' not found\n", argv[2]); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (off >= mtd->size) { ++ printf("Offset 0x%llx is larger than flash size\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (argc < 4) { ++ printf("Data size must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ size = simple_strtoul(argv[3], NULL, 0); ++ if (off + size > mtd->size) { ++ printf("Data size is too large\n"); ++ return CMD_RET_FAILURE; ++ } ++ } ++ ++ buf = malloc(mtd->writesize); ++ if (!buf) { ++ printf("Failed to allocate buffer\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ printf("%s from 0x%llx to 0x%llx, size 0x%zx ...\n", ++ read ? "Reading" : "Writing", off, off + size - 1, size); ++ ++ while (size && off < mtd->size) { ++ if (checkbad || !(off & mtd->erasesize_mask)) { ++ offp = off & ~(u64)mtd->erasesize_mask; ++ ++ if (mtd_block_isbad(mtd, offp)) { ++ printf("Bad block at 0x%llx", offp); ++ ++ if (spread) { ++ printf(" ... skipped\n"); ++ off += mtd->erasesize; ++ checkbad = true; ++ continue; ++ } ++ ++ if (!force) { ++ printf(" ... aborted\n"); ++ goto err_out; ++ } ++ ++ printf(" ... continue\n"); ++ } ++ ++ checkbad = false; ++ } ++ ++ padding = off & mtd->writesize_mask; ++ chksz = mtd->writesize - padding; ++ chksz = min_t(size_t, chksz, size); ++ ++ offp = off & ~(u64)mtd->writesize_mask; ++ ++ memset(&io_op, 0, sizeof(io_op)); ++ io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_PLACE_OOB; ++ io_op.len = mtd->writesize; ++ ++ if (chksz < mtd->writesize) ++ io_op.datbuf = buf; ++ else ++ io_op.datbuf = (void *)addr; ++ ++ if (read) { ++ ret = mtd_read_oob(mtd, offp, &io_op); ++ if (ret && ret != -EUCLEAN && ret != -EBADMSG) ++ goto io_err; ++ ++ if (chksz < mtd->writesize) ++ memcpy((void *)addr, buf + padding, chksz); ++ } else { ++ if (chksz < mtd->writesize) { ++ memset(buf, 0xff, mtd->writesize); ++ memcpy(buf + padding, (void *)addr, chksz); ++ } ++ ++ if (is_empty_page(io_op.datbuf, io_op.len) && !writeff) ++ ret = 0; ++ else ++ ret = mtd_write_oob(mtd, offp, &io_op); ++ ++ if (ret) ++ goto io_err; ++ } ++ ++ size -= chksz; ++ addr += chksz; ++ off += chksz; ++ } ++ ++ if (!size) { ++ printf("Succeeded\n"); ++ ret = CMD_RET_SUCCESS; ++ goto out; ++ } ++ ++ printf("0x%zx byte%s remained for %s\n", size, size > 1 ? "s" : "", ++ read ? "read" : "write"); ++ goto err_out; ++ ++io_err: ++ printf("%s error %d at 0x%llx\n", read ? "Read" : "Write", ret, offp); ++ ++err_out: ++ ret = CMD_RET_FAILURE; ++ ++out: ++ free(buf); ++ return ret; ++} ++ ++static int do_nand_io_page(int argc, char *const argv[]) ++{ ++ struct mtd_info *mtd = nand_get_curr_dev(), *part; ++ bool spread = false, force = false, raw = false, autooob = false; ++ bool read = false, checkbad = true, writeff = false; ++ struct mtd_oob_ops io_op = {}; ++ uintptr_t addr; ++ u64 off, offp; ++ char *ends; ++ u32 count; ++ int ret; ++ ++ if (!mtd) ++ return CMD_RET_FAILURE; ++ ++ if (!strncmp(argv[0], "read", 4)) ++ read = true; ++ ++ if (strstr(argv[0], ".spread")) ++ spread = true; ++ ++ if (strstr(argv[0], ".force")) ++ force = true; ++ ++ if (strstr(argv[0], ".raw")) ++ raw = true; ++ ++ if (strstr(argv[0], ".auto")) ++ autooob = true; ++ ++ if (spread && force) { ++ printf("spread and force must not be set at the same time\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (raw && autooob) { ++ printf("raw and auto must not be set at the same time\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (argc < 2) { ++ printf("Data address must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ addr = simple_strtoul(argv[1], NULL, 0); ++ ++ if (argc < 3) { ++ printf("Flash address/partition must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ part = nand_get_part(mtd, argv[2]); ++ if (part) { ++ if (argc < 4) { ++ printf("Partition offset / page count must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ if (argc < 5) { ++ off = 0; ++ ++ count = simple_strtoul(argv[3], NULL, 0); ++ if (part->offset + count * mtd->writesize > part->size) { ++ printf("Page count exceeds partition size\n"); ++ return CMD_RET_FAILURE; ++ } ++ } else { ++ off = simple_strtoull(argv[3], NULL, 0); ++ if (off >= part->size) { ++ printf("Offset 0x%llx is larger than partition size\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ off &= ~(u64)mtd->writesize_mask; ++ ++ count = simple_strtoul(argv[4], NULL, 0); ++ if (part->offset + off + count * mtd->writesize > part->size) { ++ printf("Page count exceeds partition size\n"); ++ return CMD_RET_FAILURE; ++ } ++ } ++ ++ off += part->offset; ++ } else { ++ off = simple_strtoull(argv[2], &ends, 0); ++ ++ if (ends == argv[1] || *ends) { ++ printf("Partition '%s' not found\n", argv[2]); ++ return CMD_RET_FAILURE; ++ } ++ ++ if (off >= mtd->size) { ++ printf("Offset 0x%llx is larger than flash size\n", off); ++ return CMD_RET_FAILURE; ++ } ++ ++ off &= ~(u64)mtd->writesize_mask; ++ ++ if (argc < 4) { ++ printf("Page count must be specified\n"); ++ return CMD_RET_USAGE; ++ } ++ ++ count = simple_strtoul(argv[3], NULL, 0); ++ if (off + count * mtd->writesize > mtd->size) { ++ printf("Page count exceeds flash size\n"); ++ return CMD_RET_FAILURE; ++ } ++ } ++ ++ printf("%s from 0x%llx to 0x%llx (+%u), count %u ...\n", ++ read ? "Reading" : "Writing", off, ++ off + count * mtd->writesize - 1, mtd->oobsize, count); ++ ++ while (count && off < mtd->size) { ++ if (checkbad || !(off & mtd->erasesize_mask)) { ++ offp = off & ~(u64)mtd->erasesize_mask; ++ ++ if (mtd_block_isbad(mtd, offp)) { ++ printf("Bad block at 0x%llx", offp); ++ ++ if (spread) { ++ printf(" ... skipped\n"); ++ off += mtd->erasesize; ++ checkbad = true; ++ continue; ++ } ++ ++ if (!force) { ++ printf(" ... aborted\n"); ++ return CMD_RET_FAILURE; ++ } ++ ++ printf(" ... continue\n"); ++ } ++ ++ checkbad = false; ++ } ++ ++ memset(&io_op, 0, sizeof(io_op)); ++ ++ if (raw) ++ io_op.mode = MTD_OPS_RAW; ++ else if (autooob) ++ io_op.mode = MTD_OPS_AUTO_OOB; ++ else ++ io_op.mode = MTD_OPS_PLACE_OOB; ++ ++ io_op.len = mtd->writesize; ++ io_op.ooblen = mtd->oobsize; ++ io_op.datbuf = (void *)addr; ++ io_op.oobbuf = io_op.datbuf + mtd->writesize; ++ ++ if (read) { ++ ret = mtd_read_oob(mtd, off, &io_op); ++ if (ret && ret != -EUCLEAN && ret != -EBADMSG) ++ goto io_err; ++ } else { ++ if (is_empty_page((void *)addr, mtd->writesize + mtd->oobsize) && !writeff) ++ ret = 0; ++ else ++ ret = mtd_write_oob(mtd, off, &io_op); ++ ++ if (ret) ++ goto io_err; ++ } ++ ++ count--; ++ addr += mtd->writesize + mtd->oobsize; ++ off += mtd->writesize; ++ } ++ ++ if (!count) { ++ printf("Succeeded\n"); ++ return CMD_RET_SUCCESS; ++ } ++ ++ printf("%u page%s remained for %s\n", count, count > 1 ? "s" : "", ++ read ? "read" : "write"); ++ return CMD_RET_FAILURE; ++ ++io_err: ++ printf("%s error %d at 0x%llx\n", read ? "Read" : "Write", ret, off); ++ return CMD_RET_FAILURE; ++} ++ ++static int do_nand_io(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ if (strstr(argv[0], ".oob")) ++ return do_nand_io_page(argc, argv); ++ ++ return do_nand_io_normal(argc, argv); ++} ++ ++#ifdef CONFIG_SYS_LONGHELP ++static char nand_help_text[] = ++ "- NAND flash R/W and debugging utility\n" ++ "nand list\n" ++ "nand info - Show active NAND devices\n" ++ "nand select - Select active NAND devices\n" ++ "nand dump[.raw] \n" ++ "nand bad\n" ++ "nand markbad \n" ++ "nand bitflip \n" ++ "nand erase[.spread|.force] [ | []]\n" ++ "nand read[.spread|.force][.raw] \n" ++ " [ []]\n" ++ "nand write[.spread|.force][.raw][.ff] \n" ++ " [ []]\n" ++ "nand read.oob[.spread|.force][.raw|.auto] \n" ++ " [] \n" ++ "nand write.oob[.spread|.force][.raw|.auto][.ff] \n" ++ " [] \n"; ++#endif ++ ++U_BOOT_CMD_WITH_SUBCMDS(nand, "NAND utility", ++ nand_help_text, ++ U_BOOT_SUBCMD_MKENT(list, 1, 0, do_nand_list), ++ U_BOOT_SUBCMD_MKENT(info, 1, 0, do_nand_info), ++ U_BOOT_SUBCMD_MKENT(select, 2, 0, do_nand_select), ++ U_BOOT_SUBCMD_MKENT(dump, 2, 0, do_nand_dump), ++ U_BOOT_SUBCMD_MKENT(bad, 1, 0, do_nand_bad), ++ U_BOOT_SUBCMD_MKENT(markbad, 2, 0, do_nand_markbad), ++ U_BOOT_SUBCMD_MKENT(bitflip, 4, 0, do_nand_bitflip), ++ U_BOOT_SUBCMD_MKENT(erase, 3, 0, do_nand_erase), ++ U_BOOT_SUBCMD_MKENT(read, 5, 0, do_nand_io), ++ U_BOOT_SUBCMD_MKENT(write, 5, 0, do_nand_io) ++); diff --git a/package/boot/uboot-mediatek/patches/100-14-mtd-spi-nor-add-support-to-read-flash-unique-ID.patch b/package/boot/uboot-mediatek/patches/100-14-mtd-spi-nor-add-support-to-read-flash-unique-ID.patch new file mode 100644 index 0000000000..6a61045955 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-14-mtd-spi-nor-add-support-to-read-flash-unique-ID.patch @@ -0,0 +1,142 @@ +From c4172a95df8a57a66c70a8b9948b9600a01c4cb7 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 11:32:08 +0800 +Subject: [PATCH 49/71] mtd: spi-nor: add support to read flash unique ID + +This patch adds support to read unique ID from spi-nor flashes. + +Signed-off-by: Weijie Gao +--- + drivers/mtd/spi/spi-nor-core.c | 95 ++++++++++++++++++++++++++++++++++ + include/linux/mtd/spi-nor.h | 2 + + 2 files changed, 97 insertions(+) + +--- a/drivers/mtd/spi/spi-nor-core.c ++++ b/drivers/mtd/spi/spi-nor-core.c +@@ -2742,6 +2742,100 @@ static int spi_nor_init_params(struct sp + return 0; + } + ++static int spi_nor_read_uuid(struct spi_nor *nor) ++{ ++ u8 read_opcode, addr_width, read_dummy; ++ loff_t addr; ++ u8 *uuid; ++ u8 uuid_len; ++ int shift = 0; ++ int ret; ++ int i; ++ struct spi_mem_op op; ++ ++ read_opcode = nor->read_opcode; ++ addr_width = nor->addr_width; ++ read_dummy = nor->read_dummy; ++ ++ switch (JEDEC_MFR(nor->info)) { ++ case SNOR_MFR_WINBOND: ++ uuid_len = 8; ++ nor->read_opcode = 0x4b; ++ nor->addr_width = 0; ++ addr = 0x0; ++ nor->read_dummy = 4; ++ break; ++ case SNOR_MFR_GIGADEVICE: ++ uuid_len = 16; ++ nor->read_opcode = 0x4b; ++ nor->addr_width = 3; ++ addr = 0x0; ++ nor->read_dummy = 1; ++ break; ++ case CFI_MFR_ST: ++ case SNOR_MFR_MICRON: ++ uuid_len = 17; ++ shift = 3; ++ nor->read_opcode = 0x9f; ++ nor->addr_width = 0; ++ addr = 0x0; ++ nor->read_dummy = 0; ++ break; ++ case SNOR_MFR_EON: ++ uuid_len = 12; ++ nor->read_opcode = 0x5a; ++ nor->addr_width = 3; ++ addr = 0x80; ++ nor->read_dummy = 1; ++ break; ++ /* Automotive only in SPANSION's NOR devices */ ++ case SNOR_MFR_SPANSION: ++ uuid_len = 11; ++ shift = 386; ++ nor->read_opcode = 0x9f; ++ nor->addr_width = 0; ++ addr = 0x0; ++ nor->read_dummy = 0; ++ break; ++ default: ++ printf("UUID not supported on this device.\n"); ++ return -ENOTSUPP; ++ } ++ ++ uuid = kmalloc((uuid_len + shift) * sizeof(*uuid), GFP_KERNEL); ++ if (!uuid) { ++ ret = -ENOMEM; ++ goto read_err; ++ } ++ memset(uuid, 0x0, (uuid_len + shift) * sizeof(*uuid)); ++ ++ op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0), ++ SPI_MEM_OP_ADDR(nor->addr_width, addr, 0), ++ SPI_MEM_OP_DUMMY(nor->read_dummy, 0), ++ SPI_MEM_OP_DATA_IN(uuid_len+shift, NULL, 0)); ++ ++ spi_nor_setup_op(nor, &op, nor->reg_proto); ++ ++ ret = spi_nor_read_write_reg(nor, &op, uuid); ++ if (ret < 0) { ++ dev_dbg(nor->dev, "error %d reading %x\n", ret, nor->read_opcode); ++ goto read_err; ++ } ++ ++ printf("UUID: 0x"); ++ for(i = 0; iread_opcode = read_opcode; ++ nor->addr_width = addr_width; ++ nor->read_dummy = read_dummy; ++ kfree(uuid); ++ ++ return ret; ++} ++ + static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size) + { + size_t i; +@@ -3719,6 +3813,7 @@ int spi_nor_scan(struct spi_nor *nor) + nor->write = spi_nor_write_data; + nor->read_reg = spi_nor_read_reg; + nor->write_reg = spi_nor_write_reg; ++ nor->read_uuid = spi_nor_read_uuid; + + nor->setup = spi_nor_default_setup; + +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -28,6 +28,7 @@ + #define SNOR_MFR_SPANSION CFI_MFR_AMD + #define SNOR_MFR_SST CFI_MFR_SST + #define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */ ++#define SNOR_MFR_EON CFI_MFR_EON + #define SNOR_MFR_CYPRESS 0x34 + + /* +@@ -547,6 +548,7 @@ struct spi_nor { + void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); + int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); + int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); ++ int (*read_uuid)(struct spi_nor *nor); + + ssize_t (*read)(struct spi_nor *nor, loff_t from, + size_t len, u_char *read_buf); diff --git a/package/boot/uboot-mediatek/patches/100-15-cmd-sf-add-support-to-read-flash-unique-ID.patch b/package/boot/uboot-mediatek/patches/100-15-cmd-sf-add-support-to-read-flash-unique-ID.patch new file mode 100644 index 0000000000..972a022d4b --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-15-cmd-sf-add-support-to-read-flash-unique-ID.patch @@ -0,0 +1,48 @@ +From e60939acbebd07161f3978d1c6f13123fdd2ebf2 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 11:27:02 +0800 +Subject: [PATCH 50/71] cmd: sf: add support to read flash unique ID + +This patch adds support to display unique ID from spi-nor flashes + +Signed-off-by: Weijie Gao +--- + cmd/sf.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/cmd/sf.c ++++ b/cmd/sf.c +@@ -391,6 +391,14 @@ static int do_spi_protect(int argc, char + return ret == 0 ? 0 : 1; + } + ++static int do_spi_flash_read_uuid(void) ++{ ++ int ret = 0; ++ ret = flash->read_uuid(flash); ++ ++ return ret == 0 ? 0 : 1; ++} ++ + enum { + STAGE_ERASE, + STAGE_CHECK, +@@ -587,6 +595,8 @@ static int do_spi_flash(struct cmd_tbl * + ret = do_spi_flash_erase(argc, argv); + else if (strcmp(cmd, "protect") == 0) + ret = do_spi_protect(argc, argv); ++ else if (strcmp(cmd, "uuid") == 0) ++ ret = do_spi_flash_read_uuid(); + else if (IS_ENABLED(CONFIG_CMD_SF_TEST) && !strcmp(cmd, "test")) + ret = do_spi_flash_test(argc, argv); + else +@@ -617,7 +627,8 @@ static const char long_help[] = + " at `addr' to flash at `offset'\n" + " or to start of mtd `partition'\n" + "sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n" +- " at address 'sector'" ++ " at address 'sector'\n" ++ "sf uuid - read uuid from flash" + #ifdef CONFIG_CMD_SF_TEST + "\nsf test offset len - run a very basic destructive test" + #endif diff --git a/package/boot/uboot-mediatek/patches/210-cmd-bootmenu-add-ability-to-select-item-by-shortkey.patch b/package/boot/uboot-mediatek/patches/100-16-cmd-bootmenu-add-ability-to-select-item-by-shortkey.patch similarity index 62% rename from package/boot/uboot-mediatek/patches/210-cmd-bootmenu-add-ability-to-select-item-by-shortkey.patch rename to package/boot/uboot-mediatek/patches/100-16-cmd-bootmenu-add-ability-to-select-item-by-shortkey.patch index dc9c9ae5e4..ee45ff0de6 100644 --- a/package/boot/uboot-mediatek/patches/210-cmd-bootmenu-add-ability-to-select-item-by-shortkey.patch +++ b/package/boot/uboot-mediatek/patches/100-16-cmd-bootmenu-add-ability-to-select-item-by-shortkey.patch @@ -1,26 +1,20 @@ -From afea25576fc92d562b248b783cf03564eb4521da Mon Sep 17 00:00:00 2001 +From 5a15437610e8e8c68dc347845a83d0cbad80ca08 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Tue, 19 Jan 2021 10:58:48 +0800 -Subject: [PATCH 12/12] cmd: bootmenu: add ability to select item by shortkey +Subject: [PATCH 51/71] cmd: bootmenu: add ability to select item by shortkey Add ability to use shortkey to select item for bootmenu command Signed-off-by: Weijie Gao --- - cmd/bootmenu.c | 77 +++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 70 insertions(+), 7 deletions(-) + cmd/bootmenu.c | 34 ++++++++++++++++++++++++----- + common/menu.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++-- + include/menu.h | 12 +++++++---- + 3 files changed, 93 insertions(+), 11 deletions(-) --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -87,16 +88,17 @@ static char *bootmenu_choice_entry(void +@@ -87,16 +87,17 @@ static char *bootmenu_choice_entry(void struct bootmenu_data *menu = data; struct bootmenu_entry *iter; enum bootmenu_key key = KEY_NONE; @@ -40,7 +34,7 @@ Signed-off-by: Weijie Gao } switch (key) { -@@ -110,6 +112,12 @@ static char *bootmenu_choice_entry(void +@@ -110,6 +111,12 @@ static char *bootmenu_choice_entry(void ++menu->active; /* no menu key selected, regenerate menu */ return NULL; @@ -53,28 +47,43 @@ Signed-off-by: Weijie Gao case KEY_SELECT: iter = menu->first; for (i = 0; i < menu->active; ++i) -@@ -181,12 +189,19 @@ static int prepare_bootmenu_entry(struct +@@ -167,6 +174,9 @@ static int prepare_bootmenu_entry(struct + unsigned short int i = *index; + struct bootmenu_entry *entry = NULL; + struct bootmenu_entry *iter = *current; ++ char *choice_option; ++ char choice_char; ++ int len; + + while ((option = bootmenu_getoption(i))) { + +@@ -181,11 +191,24 @@ static int prepare_bootmenu_entry(struct if (!entry) return -ENOMEM; - entry->title = strndup(option, sep - option); -+ entry->title = malloc((sep - option) + 4); ++ /* Add KEY_CHOICE support: '%d. %s\0' : len --> len + 4 */ ++ len = sep - option + 4; ++ choice_option = malloc(len); ++ if (!choice_option) { ++ free(entry->title); ++ free(entry); ++ return -ENOMEM; ++ } ++ if (!get_choice_char(i, &choice_char)) ++ len = snprintf(choice_option, len, "%c. %s", choice_char, option); ++ else ++ len = snprintf(choice_option, len, " %s", option); ++ entry->title = strndup(choice_option, len); if (!entry->title) { free(entry); return -ENOMEM; } ++ free(choice_option); -+ if (i < ARRAY_SIZE(choice_chars)) { -+ sprintf(entry->title, "%c. %.*s", choice_chars[i], -+ (int)(sep - option), option); -+ } else { -+ sprintf(entry->title, " %.*s", (int)(sep - option), option); -+ } -+ entry->command = strdup(sep + 1); if (!entry->command) { - free(entry->title); -@@ -331,6 +346,7 @@ static struct bootmenu_data *bootmenu_cr +@@ -331,6 +354,7 @@ static struct bootmenu_data *bootmenu_cr menu->delay = delay; menu->active = 0; menu->first = NULL; @@ -82,7 +91,7 @@ Signed-off-by: Weijie Gao default_str = env_get("bootmenu_default"); if (default_str) -@@ -356,9 +372,9 @@ static struct bootmenu_data *bootmenu_cr +@@ -356,9 +380,9 @@ static struct bootmenu_data *bootmenu_cr /* Add Quit entry if entering U-Boot console is disabled */ if (!IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE)) @@ -96,18 +105,17 @@ Signed-off-by: Weijie Gao free(entry); --- a/common/menu.c +++ b/common/menu.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -47,6 +48,17 @@ struct menu { +@@ -47,6 +47,33 @@ struct menu { int item_cnt; }; ++const char choice_chars[] = { ++ '1', '2', '3', '4', '5', '6', '7', '8', '9', ++ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', ++ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', ++ 'u', 'v', 'w', 'x', 'y', 'z' ++}; ++ +static int find_choice(char choice) +{ + int i; @@ -118,11 +126,20 @@ Signed-off-by: Weijie Gao + + return -1; +} ++ ++int get_choice_char(int index, char *result) ++{ ++ if (index < ARRAY_SIZE(choice_chars)) ++ *result = choice_chars[index]; ++ else ++ return -1; ++ return 0; ++} + /* * An iterator function for menu items. callback will be called for each item * in m, with m, a pointer to the item, and extra being passed to callback. If -@@ -426,7 +438,7 @@ int menu_destroy(struct menu *m) +@@ -426,7 +453,7 @@ int menu_destroy(struct menu *m) } void bootmenu_autoboot_loop(struct bootmenu_data *menu, @@ -131,7 +148,7 @@ Signed-off-by: Weijie Gao { int i, c; -@@ -456,6 +468,19 @@ void bootmenu_autoboot_loop(struct bootm +@@ -456,6 +483,19 @@ void bootmenu_autoboot_loop(struct bootm break; default: *key = KEY_NONE; @@ -151,7 +168,7 @@ Signed-off-by: Weijie Gao break; } -@@ -475,10 +500,16 @@ void bootmenu_autoboot_loop(struct bootm +@@ -475,10 +515,16 @@ void bootmenu_autoboot_loop(struct bootm } void bootmenu_loop(struct bootmenu_data *menu, @@ -169,7 +186,7 @@ Signed-off-by: Weijie Gao if (*esc == 1) { if (tstc()) { c = getchar(); -@@ -504,6 +535,14 @@ void bootmenu_loop(struct bootmenu_data +@@ -504,6 +550,14 @@ void bootmenu_loop(struct bootmenu_data if (c == '\e') { *esc = 1; *key = KEY_NONE; @@ -186,7 +203,29 @@ Signed-off-by: Weijie Gao case 1: --- a/include/menu.h +++ b/include/menu.h -@@ -40,6 +40,7 @@ struct bootmenu_data { +@@ -2,10 +2,11 @@ + /* + * Copyright 2010-2011 Calxeda, Inc. + */ +- + #ifndef __MENU_H__ + #define __MENU_H__ + ++#include ++ + struct menu; + + struct menu *menu_create(char *title, int timeout, int prompt, +@@ -18,6 +19,8 @@ int menu_get_choice(struct menu *m, void + int menu_item_add(struct menu *m, char *item_key, void *item_data); + int menu_destroy(struct menu *m); + int menu_default_choice(struct menu *m, void **choice); ++/* Add KEY_CHOICE support */ ++int get_choice_char(int index, char *result); + + /** + * menu_show() Show a boot menu +@@ -40,6 +43,7 @@ struct bootmenu_data { int active; /* active menu entry */ int count; /* total count of menu entries */ struct bootmenu_entry *first; /* first menu entry */ @@ -194,7 +233,7 @@ Signed-off-by: Weijie Gao }; enum bootmenu_key { -@@ -48,11 +49,19 @@ enum bootmenu_key { +@@ -48,11 +52,11 @@ enum bootmenu_key { KEY_DOWN, KEY_SELECT, KEY_QUIT, @@ -206,13 +245,6 @@ Signed-off-by: Weijie Gao + enum bootmenu_key *key, int *esc, int *choice); void bootmenu_loop(struct bootmenu_data *menu, - enum bootmenu_key *key, int *esc); +- + enum bootmenu_key *key, int *esc, int *choice); -+ -+static const char choice_chars[] = { -+ '1', '2', '3', '4', '5', '6', '7', '8', '9', -+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', -+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', -+ 'u', 'v', 'w', 'x', 'y', 'z' -+}; - #endif /* __MENU_H__ */ diff --git a/package/boot/uboot-mediatek/patches/100-17-common-spl-spl_nand-enable-CONFIG_SYS_NAND_U_BOOT_OF.patch b/package/boot/uboot-mediatek/patches/100-17-common-spl-spl_nand-enable-CONFIG_SYS_NAND_U_BOOT_OF.patch new file mode 100644 index 0000000000..149a156ba2 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-17-common-spl-spl_nand-enable-CONFIG_SYS_NAND_U_BOOT_OF.patch @@ -0,0 +1,28 @@ +From 7ab891faaaf2b6126694352d4503dc40605a6aec Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 15:10:02 +0800 +Subject: [PATCH 52/71] common: spl: spl_nand: enable + CONFIG_SYS_NAND_U_BOOT_OFFS undefined + +Enable using spl_nand with CONFIG_SYS_NAND_U_BOOT_OFFS undefined since +mtk-snand does not require raw nand framework. + +Signed-off-by: Weijie Gao +--- + common/spl/spl_nand.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/common/spl/spl_nand.c ++++ b/common/spl/spl_nand.c +@@ -16,7 +16,11 @@ + + uint32_t __weak spl_nand_get_uboot_raw_page(void) + { ++#ifdef CONFIG_SYS_NAND_U_BOOT_OFFS + return CONFIG_SYS_NAND_U_BOOT_OFFS; ++#else ++ return 0; ++#endif + } + + #if defined(CONFIG_SPL_NAND_RAW_ONLY) diff --git a/package/boot/uboot-mediatek/patches/000-mtk-17-board-mt7629-add-support-for-booting-from-SPI-NAND.patch b/package/boot/uboot-mediatek/patches/100-18-board-mt7629-add-support-for-booting-from-SPI-NAND.patch similarity index 61% rename from package/boot/uboot-mediatek/patches/000-mtk-17-board-mt7629-add-support-for-booting-from-SPI-NAND.patch rename to package/boot/uboot-mediatek/patches/100-18-board-mt7629-add-support-for-booting-from-SPI-NAND.patch index 4ee3d6f320..b6243db9c2 100644 --- a/package/boot/uboot-mediatek/patches/000-mtk-17-board-mt7629-add-support-for-booting-from-SPI-NAND.patch +++ b/package/boot/uboot-mediatek/patches/100-18-board-mt7629-add-support-for-booting-from-SPI-NAND.patch @@ -1,7 +1,7 @@ -From 3757223c3354b9feeffcbe916eb18eb8873bd133 Mon Sep 17 00:00:00 2001 +From 452dc98572f8353f77551bcce5a2ca8cd050f498 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 3 Mar 2021 10:48:53 +0800 -Subject: [PATCH 07/12] board: mt7629: add support for booting from SPI-NAND +Subject: [PATCH 53/71] board: mt7629: add support for booting from SPI-NAND Add support for mt7629 to boot from SPI-NAND. Add a new defconfig for mt7629+spi-nand configuration. @@ -11,10 +11,12 @@ Signed-off-by: Weijie Gao arch/arm/dts/mt7629-rfb-u-boot.dtsi | 8 ++ arch/arm/dts/mt7629-rfb.dts | 10 +++ arch/arm/dts/mt7629.dtsi | 16 ++++ - board/mediatek/mt7629/Kconfig | 35 ++++++++- - configs/mt7629_nand_rfb_defconfig | 111 ++++++++++++++++++++++++++++ - include/configs/mt7629.h | 7 ++ - 6 files changed, 186 insertions(+), 1 deletion(-) + arch/arm/mach-mediatek/Kconfig | 4 +- + board/mediatek/mt7629/Kconfig | 40 ++++++++++ + board/mediatek/mt7629/mt7629_rfb.c | 5 ++ + configs/mt7629_nand_rfb_defconfig | 113 ++++++++++++++++++++++++++++ + 7 files changed, 195 insertions(+), 1 deletion(-) + create mode 100644 board/mediatek/mt7629/Kconfig create mode 100644 configs/mt7629_nand_rfb_defconfig --- a/arch/arm/dts/mt7629-rfb-u-boot.dtsi @@ -85,9 +87,78 @@ Signed-off-by: Weijie Gao snor: snor@11014000 { compatible = "mediatek,mtk-snor"; reg = <0x11014000 0x1000>; +--- a/arch/arm/mach-mediatek/Kconfig ++++ b/arch/arm/mach-mediatek/Kconfig +@@ -131,9 +131,11 @@ config SYS_CONFIG_NAME + + config MTK_BROM_HEADER_INFO + string +- default "media=nor" if TARGET_MT8518 || TARGET_MT8512 || TARGET_MT7629 || TARGET_MT7622 ++ default "media=nor" if TARGET_MT8518 || TARGET_MT8512 || TARGET_MT7622 + default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8183 + default "media=snand;nandinfo=2k+64" if TARGET_MT7981 || TARGET_MT7986 + default "lk=1" if TARGET_MT7623 + ++source "board/mediatek/mt7629/Kconfig" ++ + endif +--- /dev/null ++++ b/board/mediatek/mt7629/Kconfig +@@ -0,0 +1,40 @@ ++if TARGET_MT7629 ++ ++config MTK_BROM_HEADER_INFO ++ string ++ default "media=nor" if BOOT_FROM_SNOR ++ default "media=snand;nandinfo=2k+64" if BOOT_FROM_SNAND_2K_64 ++ default "media=snand;nandinfo=2k+128" if BOOT_FROM_SNAND_2K_128 ++ default "media=snand;nandinfo=4k+128" if BOOT_FROM_SNAND_4K_128 ++ default "media=snand;nandinfo=4k+256" if BOOT_FROM_SNAND_4K_256 ++ ++choice ++ prompt "Boot device" ++ default BOOT_FROM_SNOR ++ ++config BOOT_FROM_SNOR ++ bool "SPI-NOR" ++ ++config BOOT_FROM_SNAND_2K_64 ++ bool "SPI-NAND (2K+64)" ++ select MT7629_BOOT_FROM_SNAND ++ ++config BOOT_FROM_SNAND_2K_128 ++ bool "SPI-NAND (2K+128)" ++ select MT7629_BOOT_FROM_SNAND ++ ++config BOOT_FROM_SNAND_4K_128 ++ bool "SPI-NAND (4K+128)" ++ select MT7629_BOOT_FROM_SNAND ++ ++config BOOT_FROM_SNAND_4K_256 ++ bool "SPI-NAND (4K+256)" ++ select MT7629_BOOT_FROM_SNAND ++ ++endchoice ++ ++config MT7629_BOOT_FROM_SNAND ++ bool ++ default n ++ ++endif +--- a/board/mediatek/mt7629/mt7629_rfb.c ++++ b/board/mediatek/mt7629/mt7629_rfb.c +@@ -15,3 +15,8 @@ int board_init(void) + + return 0; + } ++ ++uint32_t spl_nand_get_uboot_raw_page(void) ++{ ++ return CONFIG_SPL_PAD_TO; ++} --- /dev/null +++ b/configs/mt7629_nand_rfb_defconfig -@@ -0,0 +1,111 @@ +@@ -0,0 +1,113 @@ +CONFIG_ARM=y +CONFIG_SYS_ARCH_TIMER=y +CONFIG_SYS_THUMB_BUILD=y @@ -96,36 +167,42 @@ Signed-off-by: Weijie Gao +CONFIG_SYS_MALLOC_F_LEN=0x4000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_ENV_SIZE=0x20000 -+CONFIG_ENV_OFFSET=0x100000 ++CONFIG_ENV_OFFSET=0x0 ++CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb" +CONFIG_SPL_TEXT_BASE=0x201000 +CONFIG_TARGET_MT7629=y +CONFIG_BOOT_FROM_SNAND_2K_64=y -+CONFIG_SPL_SERIAL_SUPPORT=y -+CONFIG_SPL_DRIVERS_MISC_SUPPORT=y ++CONFIG_SPL_SERIAL=y +CONFIG_SPL_STACK_R_ADDR=0x40800000 ++CONFIG_SYS_LOAD_ADDR=0x42007f1c +CONFIG_SPL_PAYLOAD="u-boot.img" +CONFIG_BUILD_TARGET="u-boot-mtk.bin" -+CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb" ++CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y ++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x41fffef0 +CONFIG_SPL_IMAGE="spl/u-boot-spl-mtk.bin" +CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_BOOTDELAY=3 ++# CONFIG_AUTOBOOT is not set +CONFIG_DEFAULT_FDT_FILE="mt7629-rfb" +CONFIG_SYS_CONSOLE_IS_IN_ENV=y -+CONFIG_SYS_STDIO_DEREGISTER=y +# CONFIG_DISPLAY_BOARDINFO is not set ++CONFIG_SPL_MAX_SIZE=0x20000 ++CONFIG_SPL_FOOTPRINT_LIMIT=y ++CONFIG_SPL_MAX_FOOTPRINT=0x20000 +CONFIG_SPL_SYS_MALLOC_SIMPLE=y ++# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set ++CONFIG_SPL_STACK=0x106000 +CONFIG_SPL_STACK_R=y +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_NAND_SUPPORT=y -+CONFIG_SPL_WATCHDOG_SUPPORT=y ++CONFIG_SPL_WATCHDOG=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="U-Boot> " -+CONFIG_CMD_BOOTMENU=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_SYS_BOOTM_LEN=0x4000000 ++CONFIG_CMD_BOOTMENU=y +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_XIMG is not set +CONFIG_CMD_BIND=y @@ -140,13 +217,10 @@ Signed-off-by: Weijie Gao +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_LOG=y -+CONFIG_EFI_PARTITION=y -+# CONFIG_SPL_PARTITION_UUIDS is not set -+CONFIG_PARTITION_TYPE_GUID=y +CONFIG_OF_SPL_REMOVE_PROPS="interrupt-parent assigned-clocks assigned-clock-parents" +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_MTD=y -+CONFIG_ENV_MTD_NAME="spi-nand0" ++CONFIG_ENV_MTD_NAME="u-boot-env" +CONFIG_ENV_SIZE_REDUND=0x40000 +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_NET_RANDOM_ETHADDR=y @@ -155,7 +229,6 @@ Signed-off-by: Weijie Gao +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y -+CONFIG_BLK=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +# CONFIG_MMC is not set @@ -189,35 +262,13 @@ Signed-off-by: Weijie Gao +CONFIG_SPL_SYSRESET=y +CONFIG_SYSRESET_WATCHDOG=y +CONFIG_USB=y -+CONFIG_DM_USB=y +# CONFIG_SPL_DM_USB is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MTK=y +CONFIG_USB_STORAGE=y +CONFIG_WDT_MTK=y -+CONFIG_FAT_WRITE=y ++# CONFIG_SHA256 is not set ++# CONFIG_SPL_SHA1 is not set +CONFIG_LZMA=y +CONFIG_SPL_LZMA=y +# CONFIG_EFI_LOADER is not set ---- a/include/configs/mt7629.h -+++ b/include/configs/mt7629.h -@@ -25,12 +25,19 @@ - - /* Defines for SPL */ - #define CONFIG_SPL_STACK 0x106000 -+#ifdef CONFIG_MT7629_BOOT_FROM_SNAND -+#define CONFIG_SPL_MAX_SIZE SZ_128K -+#define CONFIG_SPL_MAX_FOOTPRINT SZ_128K -+#define CONFIG_SPL_PAD_TO 0x20000 -+#define CONFIG_SYS_NAND_U_BOOT_OFFS CONFIG_SPL_PAD_TO -+#else - #define CONFIG_SPL_MAX_SIZE SZ_64K - #define CONFIG_SPL_MAX_FOOTPRINT SZ_64K - #define CONFIG_SPL_PAD_TO 0x10000 - - #define CONFIG_SPI_ADDR 0x30000000 - #define CONFIG_SYS_UBOOT_BASE (CONFIG_SPI_ADDR + CONFIG_SPL_PAD_TO) -+#endif - - /* SPL -> Uboot */ - #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_2M - \ diff --git a/package/boot/uboot-mediatek/patches/000-mtk-18-board-mt7622-use-new-spi-nand-driver.patch b/package/boot/uboot-mediatek/patches/100-19-board-mt7622-use-new-spi-nand-driver.patch similarity index 85% rename from package/boot/uboot-mediatek/patches/000-mtk-18-board-mt7622-use-new-spi-nand-driver.patch rename to package/boot/uboot-mediatek/patches/100-19-board-mt7622-use-new-spi-nand-driver.patch index 84101d0ef9..6e90f47f35 100644 --- a/package/boot/uboot-mediatek/patches/000-mtk-18-board-mt7622-use-new-spi-nand-driver.patch +++ b/package/boot/uboot-mediatek/patches/100-19-board-mt7622-use-new-spi-nand-driver.patch @@ -1,7 +1,7 @@ -From 6bcd65ed47844e747ff6db066b092632f1760256 Mon Sep 17 00:00:00 2001 +From 4c1803cc08b1618d935c1386f43f43a4e9c97697 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 3 Mar 2021 10:51:43 +0800 -Subject: [PATCH 08/12] board: mt7622: use new spi-nand driver +Subject: [PATCH 54/71] board: mt7622: use new spi-nand driver Enable new spi-nand driver support for mt7622_rfb_defconfig @@ -14,7 +14,7 @@ Signed-off-by: Weijie Gao --- a/arch/arm/dts/mt7622-rfb.dts +++ b/arch/arm/dts/mt7622-rfb.dts -@@ -188,6 +188,13 @@ +@@ -196,6 +196,13 @@ }; }; @@ -26,11 +26,11 @@ Signed-off-by: Weijie Gao +}; + &uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; + status = "okay"; + }; --- a/arch/arm/dts/mt7622.dtsi +++ b/arch/arm/dts/mt7622.dtsi -@@ -53,6 +53,22 @@ +@@ -77,6 +77,22 @@ #size-cells = <0>; }; @@ -55,7 +55,7 @@ Signed-off-by: Weijie Gao reg = <0x11014000 0x1000>; --- a/configs/mt7622_rfb_defconfig +++ b/configs/mt7622_rfb_defconfig -@@ -16,6 +16,7 @@ CONFIG_LOG=y +@@ -18,6 +18,7 @@ CONFIG_LOG=y CONFIG_SYS_PROMPT="MT7622> " CONFIG_CMD_BOOTMENU=y CONFIG_CMD_MMC=y @@ -63,7 +63,7 @@ Signed-off-by: Weijie Gao CONFIG_CMD_PCI=y CONFIG_CMD_SF_TEST=y CONFIG_CMD_PING=y -@@ -28,6 +29,10 @@ CONFIG_SYSCON=y +@@ -33,6 +34,10 @@ CONFIG_SYSCON=y CONFIG_CLK=y CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_MTK=y diff --git a/package/boot/uboot-mediatek/patches/100-20-board-mt7981-add-reference-board-using-new-spi-nand-.patch b/package/boot/uboot-mediatek/patches/100-20-board-mt7981-add-reference-board-using-new-spi-nand-.patch new file mode 100644 index 0000000000..2cd62a2c19 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-20-board-mt7981-add-reference-board-using-new-spi-nand-.patch @@ -0,0 +1,223 @@ +From d5841f8707dcb7a1f73607de67ab45dba93a56a4 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Fri, 29 Jul 2022 17:04:12 +0800 +Subject: [PATCH 55/71] board: mt7981: add reference board using new spi-nand + driver + +Add a new reference board using new spi-nand driver for SPI-NAND flash on +SNFI interface + +Signed-off-by: Weijie Gao +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/mt7981-snfi-nand-rfb.dts | 132 +++++++++++++++++++++++++ + configs/mt7981_snfi_nand_rfb_defconfig | 57 +++++++++++ + 3 files changed, 190 insertions(+) + create mode 100644 arch/arm/dts/mt7981-snfi-nand-rfb.dts + create mode 100644 configs/mt7981_snfi_nand_rfb_defconfig + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -1206,6 +1206,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt7623n-bananapi-bpi-r2.dtb \ + mt7629-rfb.dtb \ + mt7981-rfb.dtb \ ++ mt7981-snfi-nand-rfb.dtb \ + mt7981-emmc-rfb.dtb \ + mt7981-sd-rfb.dtb \ + mt7986a-rfb.dtb \ +--- /dev/null ++++ b/arch/arm/dts/mt7981-snfi-nand-rfb.dts +@@ -0,0 +1,132 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "mt7981-rfb"; ++ compatible = "mediatek,mt7981", "mediatek,mt7981-rfb"; ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ snfi_pins: snfi-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "snfi"; ++ }; ++ ++ clk { ++ pins = "SPI0_CLK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-pu { ++ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI0_MOSI", "SPI0_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_1"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 */ ++ one_pwm_pins: one-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1"; ++ }; ++ }; ++ ++ /* pin15 as pwm0 and pin14 as pwm1 */ ++ two_pwm_pins: two-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0"; ++ }; ++ }; ++ ++ /* pin15 as pwm0, pin14 as pwm1, pin7 as pwm2 */ ++ three_pwm_pins: three-pwm-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm0_1", "pwm1_0", "pwm2"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_45"; ++ }; ++ }; ++}; ++ ++&snand { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&snfi_pins>; ++ status = "okay"; ++ quad-spi; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&two_pwm_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; +--- /dev/null ++++ b/configs/mt7981_snfi_nand_rfb_defconfig +@@ -0,0 +1,57 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x20000 ++CONFIG_DEFAULT_DEVICE_TREE="mt7981-snfi-nand-rfb" ++CONFIG_TARGET_MT7981=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++# CONFIG_AUTOBOOT is not set ++CONFIG_DEFAULT_FDT_FILE="mt7981-snfi-nand-rfb" ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7981> " ++CONFIG_SYS_CBSIZE=512 ++CONFIG_SYS_PBSIZE=1049 ++# 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_UNLZ4 is not set ++# CONFIG_CMD_UNZIP is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_SMC=y ++CONFIG_MTDIDS_DEFAULT="spi-nand0=spi-nand0" ++CONFIG_MTDPARTS_DEFAULT="spi-nand0:1024k(bl2),512k(u-boot-env),2048k(factory),2048k(fip),65536k(ubi)" ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++# CONFIG_MMC is not set ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTK_SPI_NAND=y ++CONFIG_MTK_SPI_NAND_MTD=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_HEXDUMP=y diff --git a/package/boot/uboot-mediatek/patches/100-21-mtd-spi-nor-add-more-flash-ids.patch b/package/boot/uboot-mediatek/patches/100-21-mtd-spi-nor-add-more-flash-ids.patch new file mode 100644 index 0000000000..228bde1567 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-21-mtd-spi-nor-add-more-flash-ids.patch @@ -0,0 +1,76 @@ +From a2df2df6fd1aec32572c7b30ccf5a184ec1763fd Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 16:32:17 +0800 +Subject: [PATCH 56/71] mtd: spi-nor: add more flash ids + +Add more spi-nor flash ids + +Signed-off-by: Weijie Gao +--- + drivers/mtd/spi/spi-nor-core.c | 1 + + drivers/mtd/spi/spi-nor-ids.c | 23 ++++++++++++++++++++++- + 2 files changed, 23 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi/spi-nor-core.c ++++ b/drivers/mtd/spi/spi-nor-core.c +@@ -641,6 +641,7 @@ static int set_4byte(struct spi_nor *nor + case SNOR_MFR_ISSI: + case SNOR_MFR_MACRONIX: + case SNOR_MFR_WINBOND: ++ case SNOR_MFR_EON: + if (need_wren) + write_enable(nor); + +--- a/drivers/mtd/spi/spi-nor-ids.c ++++ b/drivers/mtd/spi/spi-nor-ids.c +@@ -83,7 +83,8 @@ const struct flash_info spi_nor_ids[] = + { INFO("en25q32b", 0x1c3016, 0, 64 * 1024, 64, 0) }, + { INFO("en25q64", 0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("en25q128b", 0x1c3018, 0, 64 * 1024, 256, 0) }, +- { INFO("en25qh128", 0x1c7018, 0, 64 * 1024, 256, 0) }, ++ { INFO("en25qh128", 0x1c7018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { INFO("en25qh256", 0x1c7019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("en25s64", 0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, + #endif + #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ +@@ -119,6 +120,11 @@ const struct flash_info spi_nor_ids[] = + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { ++ INFO("gd25q256", 0xc84019, 0, 64 * 1024, 512, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, ++ { + INFO("gd25lq128", 0xc86018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +@@ -395,6 +401,16 @@ const struct flash_info spi_nor_ids[] = + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { ++ INFO("w25q256jv", 0xef7019, 0, 64 * 1024, 512, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, ++ { ++ INFO("w25q512jv", 0xef7020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, ++ { + INFO("w25q128jw", 0xef8018, 0, 64 * 1024, 256, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +@@ -439,6 +455,11 @@ const struct flash_info spi_nor_ids[] = + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { INFO("w25q256", 0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { ++ INFO("w25q512", 0xef4020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) ++ }, + { INFO("w25m512jw", 0xef6119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25m512jv", 0xef7119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25h02jv", 0xef9022, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, diff --git a/package/boot/uboot-mediatek/patches/100-22-mtd-spi-nand-backport-from-upstream-kernel.patch b/package/boot/uboot-mediatek/patches/100-22-mtd-spi-nand-backport-from-upstream-kernel.patch new file mode 100644 index 0000000000..1c83479d0d --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-22-mtd-spi-nand-backport-from-upstream-kernel.patch @@ -0,0 +1,1550 @@ +From a3c5878599d530330027412eb8be12f816ac215c Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 27 Jul 2022 16:36:13 +0800 +Subject: [PATCH 57/71] mtd: spi-nand: backport from upstream kernel + +Backport new features from upstream kernel + +Signed-off-by: Weijie Gao +--- + drivers/mtd/nand/spi/Kconfig | 8 + + drivers/mtd/nand/spi/core.c | 101 ++++++---- + drivers/mtd/nand/spi/gigadevice.c | 322 ++++++++++++++++++++++++++---- + drivers/mtd/nand/spi/macronix.c | 173 +++++++++++++--- + drivers/mtd/nand/spi/micron.c | 50 ++--- + drivers/mtd/nand/spi/toshiba.c | 66 +++--- + drivers/mtd/nand/spi/winbond.c | 171 +++++++++++++--- + include/linux/mtd/spinand.h | 86 +++++--- + 8 files changed, 753 insertions(+), 224 deletions(-) + +--- a/drivers/mtd/nand/spi/Kconfig ++++ b/drivers/mtd/nand/spi/Kconfig +@@ -5,3 +5,11 @@ menuconfig MTD_SPI_NAND + select SPI_MEM + help + This is the framework for the SPI NAND device drivers. ++ ++config MTD_SPI_NAND_W25N01KV ++ tristate "Winbond W25N01KV Support" ++ select MTD_SPI_NAND ++ default n ++ help ++ Winbond W25N01KV share the same ID with W25N01GV. However, they have ++ different attributes. +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #else +@@ -451,10 +452,11 @@ out: + return status & STATUS_BUSY ? -ETIMEDOUT : 0; + } + +-static int spinand_read_id_op(struct spinand_device *spinand, u8 *buf) ++static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr, ++ u8 ndummy, u8 *buf) + { +- struct spi_mem_op op = SPINAND_READID_OP(0, spinand->scratchbuf, +- SPINAND_MAX_ID_LEN); ++ struct spi_mem_op op = SPINAND_READID_OP( ++ naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN); + int ret; + + ret = spi_mem_exec_op(spinand->slave, &op); +@@ -464,18 +466,6 @@ static int spinand_read_id_op(struct spi + return ret; + } + +-static int spinand_reset_op(struct spinand_device *spinand) +-{ +- struct spi_mem_op op = SPINAND_RESET_OP; +- int ret; +- +- ret = spi_mem_exec_op(spinand->slave, &op); +- if (ret) +- return ret; +- +- return spinand_wait(spinand, NULL); +-} +- + static int spinand_lock_block(struct spinand_device *spinand, u8 lock) + { + return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock); +@@ -836,24 +826,63 @@ static const struct spinand_manufacturer + &winbond_spinand_manufacturer, + }; + +-static int spinand_manufacturer_detect(struct spinand_device *spinand) ++static int spinand_manufacturer_match(struct spinand_device *spinand, ++ enum spinand_readid_method rdid_method) + { ++ u8 *id = spinand->id.data; + unsigned int i; + int ret; + + for (i = 0; i < ARRAY_SIZE(spinand_manufacturers); i++) { +- ret = spinand_manufacturers[i]->ops->detect(spinand); +- if (ret > 0) { +- spinand->manufacturer = spinand_manufacturers[i]; +- return 0; +- } else if (ret < 0) { +- return ret; +- } ++ const struct spinand_manufacturer *manufacturer = ++ spinand_manufacturers[i]; ++ ++ if (id[0] != manufacturer->id) ++ continue; ++ ++ ret = spinand_match_and_init(spinand, ++ manufacturer->chips, ++ manufacturer->nchips, ++ rdid_method); ++ if (ret < 0) ++ continue; ++ ++ spinand->manufacturer = manufacturer; ++ return 0; + } + + return -ENOTSUPP; + } + ++static int spinand_id_detect(struct spinand_device *spinand) ++{ ++ u8 *id = spinand->id.data; ++ int ret; ++ ++ ret = spinand_read_id_op(spinand, 0, 0, id); ++ if (ret) ++ return ret; ++ ret = spinand_manufacturer_match(spinand, SPINAND_READID_METHOD_OPCODE); ++ if (!ret) ++ return 0; ++ ++ ret = spinand_read_id_op(spinand, 1, 0, id); ++ if (ret) ++ return ret; ++ ret = spinand_manufacturer_match(spinand, ++ SPINAND_READID_METHOD_OPCODE_ADDR); ++ if (!ret) ++ return 0; ++ ++ ret = spinand_read_id_op(spinand, 0, 1, id); ++ if (ret) ++ return ret; ++ ret = spinand_manufacturer_match(spinand, ++ SPINAND_READID_METHOD_OPCODE_DUMMY); ++ ++ return ret; ++} ++ + static int spinand_manufacturer_init(struct spinand_device *spinand) + { + if (spinand->manufacturer->ops->init) +@@ -909,9 +938,9 @@ spinand_select_op_variant(struct spinand + * @spinand: SPI NAND object + * @table: SPI NAND device description table + * @table_size: size of the device description table ++ * @rdid_method: read id method to match + * +- * Should be used by SPI NAND manufacturer drivers when they want to find a +- * match between a device ID retrieved through the READ_ID command and an ++ * Match between a device ID retrieved through the READ_ID command and an + * entry in the SPI NAND description table. If a match is found, the spinand + * object will be initialized with information provided by the matching + * spinand_info entry. +@@ -920,8 +949,10 @@ spinand_select_op_variant(struct spinand + */ + int spinand_match_and_init(struct spinand_device *spinand, + const struct spinand_info *table, +- unsigned int table_size, u8 devid) ++ unsigned int table_size, ++ enum spinand_readid_method rdid_method) + { ++ u8 *id = spinand->id.data; + struct nand_device *nand = spinand_to_nand(spinand); + unsigned int i; + +@@ -929,13 +960,17 @@ int spinand_match_and_init(struct spinan + const struct spinand_info *info = &table[i]; + const struct spi_mem_op *op; + +- if (devid != info->devid) ++ if (rdid_method != info->devid.method) ++ continue; ++ ++ if (memcmp(id + 1, info->devid.id, info->devid.len)) + continue; + + nand->memorg = table[i].memorg; + nand->eccreq = table[i].eccreq; + spinand->eccinfo = table[i].eccinfo; + spinand->flags = table[i].flags; ++ spinand->id.len = 1 + table[i].devid.len; + spinand->select_target = table[i].select_target; + + op = spinand_select_op_variant(spinand, +@@ -967,17 +1002,7 @@ static int spinand_detect(struct spinand + struct nand_device *nand = spinand_to_nand(spinand); + int ret; + +- ret = spinand_reset_op(spinand); +- if (ret) +- return ret; +- +- ret = spinand_read_id_op(spinand, spinand->id.data); +- if (ret) +- return ret; +- +- spinand->id.len = SPINAND_MAX_ID_LEN; +- +- ret = spinand_manufacturer_detect(spinand); ++ ret = spinand_id_detect(spinand); + if (ret) { + dev_err(spinand->slave->dev, "unknown raw ID %*phN\n", + SPINAND_MAX_ID_LEN, spinand->id.data); +--- a/drivers/mtd/nand/spi/gigadevice.c ++++ b/drivers/mtd/nand/spi/gigadevice.c +@@ -22,8 +22,13 @@ + + #define GD5FXGQXXEXXG_REG_STATUS2 0xf0 + ++#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4) ++#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4) ++#define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS (1 << 4) ++#define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR (7 << 4) ++ + /* Q4 devices, QUADIO: Dummy bytes valid for 1 and 2 GBit variants */ +-static SPINAND_OP_VARIANTS(gd5fxgq4_read_cache_variants, ++static SPINAND_OP_VARIANTS(read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), +@@ -31,8 +36,17 @@ static SPINAND_OP_VARIANTS(gd5fxgq4_read + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + +-/* Q5 devices, QUADIO: Dummy bytes only valid for 1 GBit variants */ +-static SPINAND_OP_VARIANTS(gd5f1gq5_read_cache_variants, ++static SPINAND_OP_VARIANTS(read_cache_variants_f, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0)); ++ ++/* For Q5 devices, QUADIO use different dummy byte settings */ ++/* Q5 1Gb */ ++static SPINAND_OP_VARIANTS(dummy2_read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), +@@ -40,6 +54,15 @@ static SPINAND_OP_VARIANTS(gd5f1gq5_read + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + ++/* Q5 2Gb & 4Gb */ ++static SPINAND_OP_VARIANTS(dummy4_read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ + static SPINAND_OP_VARIANTS(write_cache_variants, + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), + SPINAND_PROG_LOAD(true, 0, NULL, 0)); +@@ -48,7 +71,65 @@ static SPINAND_OP_VARIANTS(update_cache_ + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), + SPINAND_PROG_LOAD(false, 0, NULL, 0)); + +-static int gd5fxgqxxexxg_ooblayout_ecc(struct mtd_info *mtd, int section, ++static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 8; ++ region->length = 8; ++ ++ return 0; ++} ++ ++static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ if (section) { ++ region->offset = 16 * section; ++ region->length = 8; ++ } else { ++ /* section 0 has one byte reserved for bad block mark */ ++ region->offset = 1; ++ region->length = 7; ++ } ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = { ++ .ecc = gd5fxgq4xa_ooblayout_ecc, ++ .rfree = gd5fxgq4xa_ooblayout_free, ++}; ++ ++static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & STATUS_ECC_MASK) { ++ case STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS: ++ /* 1-7 bits are flipped. return the maximum. */ ++ return 7; ++ ++ case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS: ++ return 8; ++ ++ case STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) + { + if (section) +@@ -60,7 +141,7 @@ static int gd5fxgqxxexxg_ooblayout_ecc(s + return 0; + } + +-static int gd5fxgqxxexxg_ooblayout_free(struct mtd_info *mtd, int section, ++static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) + { + if (section) +@@ -73,7 +154,13 @@ static int gd5fxgqxxexxg_ooblayout_free( + return 0; + } + +-static int gd5fxgq4xexxg_ecc_get_status(struct spinand_device *spinand, ++/* Valid for Q4/Q5 and Q6 (untested) devices */ ++static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = { ++ .ecc = gd5fxgqx_variant2_ooblayout_ecc, ++ .rfree = gd5fxgqx_variant2_ooblayout_free, ++}; ++ ++static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand, + u8 status) + { + u8 status2; +@@ -152,59 +239,214 @@ static int gd5fxgq5xexxg_ecc_get_status( + return -EINVAL; + } + +-static const struct mtd_ooblayout_ops gd5fxgqxxexxg_ooblayout = { +- .ecc = gd5fxgqxxexxg_ooblayout_ecc, +- .rfree = gd5fxgqxxexxg_ooblayout_free, ++static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) { ++ case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS: ++ return 3; ++ ++ case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */ ++ return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2; ++ } ++ ++ return -EINVAL; ++} ++ ++static int esmt_1_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 8; ++ region->length = 8; ++ ++ return 0; ++} ++ ++static int esmt_1_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 2; ++ region->length = 6; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops esmt_1_ooblayout = { ++ .ecc = esmt_1_ooblayout_ecc, ++ .rfree = esmt_1_ooblayout_free, + }; + + static const struct spinand_info gigadevice_spinand_table[] = { +- SPINAND_INFO("GD5F1GQ4UExxG", 0xd1, +- NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), ++ SPINAND_INFO("F50L1G41LB", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), +- SPINAND_INFO_OP_VARIANTS(&gd5fxgq4_read_cache_variants, ++ SPINAND_INFO_OP_VARIANTS(&dummy2_read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, +- SPINAND_ECCINFO(&gd5fxgqxxexxg_ooblayout, +- gd5fxgq4xexxg_ecc_get_status)), +- SPINAND_INFO("GD5F1GQ5UExxG", 0x51, ++ SPINAND_ECCINFO(&esmt_1_ooblayout, NULL)), ++ SPINAND_INFO("GD5F1GQ4xA", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, ++ gd5fxgq4xa_ecc_get_status)), ++ SPINAND_INFO("GD5F2GQ4xA", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2), ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, ++ gd5fxgq4xa_ecc_get_status)), ++ SPINAND_INFO("GD5F4GQ4xA", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4), ++ NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, ++ gd5fxgq4xa_ecc_get_status)), ++ SPINAND_INFO("GD5F1GQ4UExxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq4uexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F1GQ4UFxxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq4ufxxg_ecc_get_status)), ++ SPINAND_INFO("GD5F1GQ5UExxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(4, 512), +- SPINAND_INFO_OP_VARIANTS(&gd5f1gq5_read_cache_variants, ++ SPINAND_INFO_OP_VARIANTS(&dummy2_read_cache_variants, + &write_cache_variants, + &update_cache_variants), +- 0, +- SPINAND_ECCINFO(&gd5fxgqxxexxg_ooblayout, ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq5xexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F2GQ5UExxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq5xexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F4GQ6UExxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x55), ++ NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq5xexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F1GM7UExxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x91), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq4uexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F2GM7UExxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x92), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq4uexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F4GM8UExxG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x95), ++ NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq4uexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F1GQ5UExxH", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x31), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&dummy2_read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq5xexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F2GQ5UExxH", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x32), ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, ++ gd5fxgq5xexxg_ecc_get_status)), ++ SPINAND_INFO("GD5F4GQ6UExxH", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), ++ NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&dummy4_read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq5xexxg_ecc_get_status)), + }; + +-static int gigadevice_spinand_detect(struct spinand_device *spinand) +-{ +- u8 *id = spinand->id.data; +- int ret; +- +- /* +- * For GD NANDs, There is an address byte needed to shift in before IDs +- * are read out, so the first byte in raw_id is dummy. +- */ +- if (id[1] != SPINAND_MFR_GIGADEVICE) +- return 0; +- +- ret = spinand_match_and_init(spinand, gigadevice_spinand_table, +- ARRAY_SIZE(gigadevice_spinand_table), +- id[2]); +- if (ret) +- return ret; +- +- return 1; +-} +- + static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = { +- .detect = gigadevice_spinand_detect, + }; + + const struct spinand_manufacturer gigadevice_spinand_manufacturer = { + .id = SPINAND_MFR_GIGADEVICE, + .name = "GigaDevice", ++ .chips = gigadevice_spinand_table, ++ .nchips = ARRAY_SIZE(gigadevice_spinand_table), + .ops = &gigadevice_spinand_manuf_ops, + }; +--- a/drivers/mtd/nand/spi/macronix.c ++++ b/drivers/mtd/nand/spi/macronix.c +@@ -105,7 +105,8 @@ static int mx35lf1ge4ab_ecc_get_status(s + } + + static const struct spinand_info macronix_spinand_table[] = { +- SPINAND_INFO("MX35LF1GE4AB", 0x12, ++ SPINAND_INFO("MX35LF1GE4AB", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -114,7 +115,8 @@ static const struct spinand_info macroni + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), +- SPINAND_INFO("MX35LF2GE4AB", 0x22, ++ SPINAND_INFO("MX35LF2GE4AB", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22), + NAND_MEMORG(1, 2048, 64, 64, 2048, 2, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -122,7 +124,96 @@ static const struct spinand_info macroni + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), +- SPINAND_INFO("MX35UF4GE4AD", 0xb7, ++ SPINAND_INFO("MX35LF2GE4AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26), ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35LF4GE4AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37), ++ NAND_MEMORG(1, 4096, 128, 64, 2048, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35LF1G24AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), ++ SPINAND_INFO("MX35LF2G24AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), ++ SPINAND_INFO("MX35LF4G24AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), ++ NAND_MEMORG(1, 4096, 256, 64, 2048, 2, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), ++ SPINAND_INFO("MX31LF1GE4BC", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX31UF1GE4BC", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ ++ SPINAND_INFO("MX35LF2G14AC", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20), ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 2, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35UF4G24AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5), ++ NAND_MEMORG(1, 4096, 256, 64, 2048, 2, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35UF4GE4AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -131,7 +222,28 @@ static const struct spinand_info macroni + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), +- SPINAND_INFO("MX35UF2GE4AD", 0xa6, ++ SPINAND_INFO("MX35UF2G14AC", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0), ++ NAND_MEMORG(1, 2048, 64, 64, 2048, 2, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35UF2G24AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35UF2GE4AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6), + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -140,16 +252,28 @@ static const struct spinand_info macroni + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), +- SPINAND_INFO("MX35UF2GE4AC", 0xa2, ++ SPINAND_INFO("MX35UF2GE4AC", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2), + NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), + NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35UF1G14AC", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), +- SPINAND_INFO("MX35UF1GE4AD", 0x96, ++ SPINAND_INFO("MX35UF1G24AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -158,7 +282,18 @@ static const struct spinand_info macroni + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), +- SPINAND_INFO("MX35UF1GE4AC", 0x92, ++ SPINAND_INFO("MX35UF1GE4AD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, ++ mx35lf1ge4ab_ecc_get_status)), ++ SPINAND_INFO("MX35UF1GE4AC", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -170,33 +305,13 @@ static const struct spinand_info macroni + + }; + +-static int macronix_spinand_detect(struct spinand_device *spinand) +-{ +- u8 *id = spinand->id.data; +- int ret; +- +- /* +- * Macronix SPI NAND read ID needs a dummy byte, so the first byte in +- * raw_id is garbage. +- */ +- if (id[1] != SPINAND_MFR_MACRONIX) +- return 0; +- +- ret = spinand_match_and_init(spinand, macronix_spinand_table, +- ARRAY_SIZE(macronix_spinand_table), +- id[2]); +- if (ret) +- return ret; +- +- return 1; +-} +- + static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = { +- .detect = macronix_spinand_detect, + }; + + const struct spinand_manufacturer macronix_spinand_manufacturer = { + .id = SPINAND_MFR_MACRONIX, + .name = "Macronix", ++ .chips = macronix_spinand_table, ++ .nchips = ARRAY_SIZE(macronix_spinand_table), + .ops = ¯onix_spinand_manuf_ops, + }; +--- a/drivers/mtd/nand/spi/micron.c ++++ b/drivers/mtd/nand/spi/micron.c +@@ -120,7 +120,8 @@ static int micron_8_ecc_get_status(struc + + static const struct spinand_info micron_spinand_table[] = { + /* M79A 2Gb 3.3V */ +- SPINAND_INFO("MT29F2G01ABAGD", 0x24, ++ SPINAND_INFO("MT29F2G01ABAGD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), + NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -130,7 +131,8 @@ static const struct spinand_info micron_ + SPINAND_ECCINFO(µn_8_ooblayout, + micron_8_ecc_get_status)), + /* M79A 2Gb 1.8V */ +- SPINAND_INFO("MT29F2G01ABBGD", 0x25, ++ SPINAND_INFO("MT29F2G01ABBGD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), + NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -140,7 +142,8 @@ static const struct spinand_info micron_ + SPINAND_ECCINFO(µn_8_ooblayout, + micron_8_ecc_get_status)), + /* M78A 1Gb 3.3V */ +- SPINAND_INFO("MT29F1G01ABAFD", 0x14, ++ SPINAND_INFO("MT29F1G01ABAFD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -150,7 +153,8 @@ static const struct spinand_info micron_ + SPINAND_ECCINFO(µn_8_ooblayout, + micron_8_ecc_get_status)), + /* M78A 1Gb 1.8V */ +- SPINAND_INFO("MT29F1G01ABAFD", 0x15, ++ SPINAND_INFO("MT29F1G01ABAFD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -160,7 +164,8 @@ static const struct spinand_info micron_ + SPINAND_ECCINFO(µn_8_ooblayout, + micron_8_ecc_get_status)), + /* M79A 4Gb 3.3V */ +- SPINAND_INFO("MT29F4G01ADAGD", 0x36, ++ SPINAND_INFO("MT29F4G01ADAGD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x36), + NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 2), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -171,7 +176,8 @@ static const struct spinand_info micron_ + micron_8_ecc_get_status), + SPINAND_SELECT_TARGET(micron_select_target)), + /* M70A 4Gb 3.3V */ +- SPINAND_INFO("MT29F4G01ABAFD", 0x34, ++ SPINAND_INFO("MT29F4G01ABAFD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -181,7 +187,8 @@ static const struct spinand_info micron_ + SPINAND_ECCINFO(µn_8_ooblayout, + micron_8_ecc_get_status)), + /* M70A 4Gb 1.8V */ +- SPINAND_INFO("MT29F4G01ABBFD", 0x35, ++ SPINAND_INFO("MT29F4G01ABBFD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -191,7 +198,8 @@ static const struct spinand_info micron_ + SPINAND_ECCINFO(µn_8_ooblayout, + micron_8_ecc_get_status)), + /* M70A 8Gb 3.3V */ +- SPINAND_INFO("MT29F8G01ADAFD", 0x46, ++ SPINAND_INFO("MT29F8G01ADAFD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x46), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 2), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -202,7 +210,8 @@ static const struct spinand_info micron_ + micron_8_ecc_get_status), + SPINAND_SELECT_TARGET(micron_select_target)), + /* M70A 8Gb 1.8V */ +- SPINAND_INFO("MT29F8G01ADBFD", 0x47, ++ SPINAND_INFO("MT29F8G01ADBFD", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x47), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 2), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -214,26 +223,6 @@ static const struct spinand_info micron_ + SPINAND_SELECT_TARGET(micron_select_target)), + }; + +-static int micron_spinand_detect(struct spinand_device *spinand) +-{ +- u8 *id = spinand->id.data; +- int ret; +- +- /* +- * Micron SPI NAND read ID need a dummy byte, +- * so the first byte in raw_id is dummy. +- */ +- if (id[1] != SPINAND_MFR_MICRON) +- return 0; +- +- ret = spinand_match_and_init(spinand, micron_spinand_table, +- ARRAY_SIZE(micron_spinand_table), id[2]); +- if (ret) +- return ret; +- +- return 1; +-} +- + static int micron_spinand_init(struct spinand_device *spinand) + { + /* +@@ -248,12 +237,13 @@ static int micron_spinand_init(struct sp + } + + static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = { +- .detect = micron_spinand_detect, + .init = micron_spinand_init, + }; + + const struct spinand_manufacturer micron_spinand_manufacturer = { + .id = SPINAND_MFR_MICRON, + .name = "Micron", ++ .chips = micron_spinand_table, ++ .nchips = ARRAY_SIZE(micron_spinand_table), + .ops = µn_spinand_manuf_ops, + }; +--- a/drivers/mtd/nand/spi/toshiba.c ++++ b/drivers/mtd/nand/spi/toshiba.c +@@ -111,7 +111,8 @@ static int tx58cxgxsxraix_ecc_get_status + + static const struct spinand_info toshiba_spinand_table[] = { + /* 3.3V 1Gb (1st generation) */ +- SPINAND_INFO("TC58CVG0S3HRAIG", 0xC2, ++ SPINAND_INFO("TC58CVG0S3HRAIG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -121,7 +122,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 3.3V 2Gb (1st generation) */ +- SPINAND_INFO("TC58CVG1S3HRAIG", 0xCB, ++ SPINAND_INFO("TC58CVG1S3HRAIG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB), + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -131,7 +133,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 3.3V 4Gb (1st generation) */ +- SPINAND_INFO("TC58CVG2S0HRAIG", 0xCD, ++ SPINAND_INFO("TC58CVG2S0HRAIG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -141,7 +144,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 1Gb (1st generation) */ +- SPINAND_INFO("TC58CYG0S3HRAIG", 0xB2, ++ SPINAND_INFO("TC58CYG0S3HRAIG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -151,7 +155,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 2Gb (1st generation) */ +- SPINAND_INFO("TC58CYG1S3HRAIG", 0xBB, ++ SPINAND_INFO("TC58CYG1S3HRAIG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB), + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -161,7 +166,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 4Gb (1st generation) */ +- SPINAND_INFO("TC58CYG2S0HRAIG", 0xBD, ++ SPINAND_INFO("TC58CYG2S0HRAIG", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -176,7 +182,8 @@ static const struct spinand_info toshiba + * QE_BIT. + */ + /* 3.3V 1Gb (2nd generation) */ +- SPINAND_INFO("TC58CVG0S3HRAIJ", 0xE2, ++ SPINAND_INFO("TC58CVG0S3HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -186,7 +193,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 3.3V 2Gb (2nd generation) */ +- SPINAND_INFO("TC58CVG1S3HRAIJ", 0xEB, ++ SPINAND_INFO("TC58CVG1S3HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB), + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -196,7 +204,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 3.3V 4Gb (2nd generation) */ +- SPINAND_INFO("TC58CVG2S0HRAIJ", 0xED, ++ SPINAND_INFO("TC58CVG2S0HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -206,7 +215,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 3.3V 8Gb (2nd generation) */ +- SPINAND_INFO("TH58CVG3S0HRAIJ", 0xE4, ++ SPINAND_INFO("TH58CVG3S0HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), + NAND_MEMORG(1, 4096, 256, 64, 4096, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -216,7 +226,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 1Gb (2nd generation) */ +- SPINAND_INFO("TC58CYG0S3HRAIJ", 0xD2, ++ SPINAND_INFO("TC58CYG0S3HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -226,7 +237,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 2Gb (2nd generation) */ +- SPINAND_INFO("TC58CYG1S3HRAIJ", 0xDB, ++ SPINAND_INFO("TC58CYG1S3HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB), + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -236,7 +248,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 4Gb (2nd generation) */ +- SPINAND_INFO("TC58CYG2S0HRAIJ", 0xDD, ++ SPINAND_INFO("TC58CYG2S0HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -246,7 +259,8 @@ static const struct spinand_info toshiba + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 8Gb (2nd generation) */ +- SPINAND_INFO("TH58CYG3S0HRAIJ", 0xD4, ++ SPINAND_INFO("TH58CYG3S0HRAIJ", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4), + NAND_MEMORG(1, 4096, 256, 64, 4096, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -257,33 +271,13 @@ static const struct spinand_info toshiba + tx58cxgxsxraix_ecc_get_status)), + }; + +-static int toshiba_spinand_detect(struct spinand_device *spinand) +-{ +- u8 *id = spinand->id.data; +- int ret; +- +- /* +- * Toshiba SPI NAND read ID needs a dummy byte, +- * so the first byte in id is garbage. +- */ +- if (id[1] != SPINAND_MFR_TOSHIBA) +- return 0; +- +- ret = spinand_match_and_init(spinand, toshiba_spinand_table, +- ARRAY_SIZE(toshiba_spinand_table), +- id[2]); +- if (ret) +- return ret; +- +- return 1; +-} +- + static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = { +- .detect = toshiba_spinand_detect, + }; + + const struct spinand_manufacturer toshiba_spinand_manufacturer = { + .id = SPINAND_MFR_TOSHIBA, + .name = "Toshiba", ++ .chips = toshiba_spinand_table, ++ .nchips = ARRAY_SIZE(toshiba_spinand_table), + .ops = &toshiba_spinand_manuf_ops, + }; +--- a/drivers/mtd/nand/spi/winbond.c ++++ b/drivers/mtd/nand/spi/winbond.c +@@ -19,6 +19,25 @@ + + #define WINBOND_CFG_BUF_READ BIT(3) + ++#define W25N02_N04KV_STATUS_ECC_MASK (3 << 4) ++#define W25N02_N04KV_STATUS_ECC_NO_BITFLIPS (0 << 4) ++#define W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS (1 << 4) ++#define W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4) ++#define W25N02_N04KV_STATUS_ECC_UNCOR_ERROR (2 << 4) ++ ++#define W25N01_M02GV_STATUS_ECC_MASK (3 << 4) ++#define W25N01_M02GV_STATUS_ECC_NO_BITFLIPS (0 << 4) ++#define W25N01_M02GV_STATUS_ECC_1_BITFLIPS (1 << 4) ++#define W25N01_M02GV_STATUS_ECC_UNCOR_ERROR (2 << 4) ++ ++#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV) ++#define W25N01KV_STATUS_ECC_MASK (3 << 4) ++#define W25N01KV_STATUS_ECC_NO_BITFLIPS (0 << 4) ++#define W25N01KV_STATUS_ECC_1_3_BITFLIPS (1 << 4) ++#define W25N01KV_STATUS_ECC_4_BITFLIPS (3 << 4) ++#define W25N01KV_STATUS_ECC_UNCOR_ERROR (2 << 4) ++#endif ++ + static SPINAND_OP_VARIANTS(read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), +@@ -35,6 +54,35 @@ static SPINAND_OP_VARIANTS(update_cache_ + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), + SPINAND_PROG_LOAD(false, 0, NULL, 0)); + ++static int w25n02kv_n04kv_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 64; ++ region->length = 16; ++ ++ return 0; ++} ++ ++static int w25n02kv_n04kv_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 2; ++ region->length = 14; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops w25n02kv_n04kv_ooblayout = { ++ .ecc = w25n02kv_n04kv_ooblayout_ecc, ++ .rfree = w25n02kv_n04kv_ooblayout_free, ++}; ++ + static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) + { +@@ -78,8 +126,63 @@ static int w25m02gv_select_target(struct + return spi_mem_exec_op(spinand->slave, &op); + } + ++#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV) ++static int w25n01kv_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & W25N01KV_STATUS_ECC_MASK) { ++ case W25N01KV_STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case W25N01KV_STATUS_ECC_1_3_BITFLIPS: ++ return 3; ++ ++ case W25N01KV_STATUS_ECC_4_BITFLIPS: ++ return 4; ++ ++ case W25N01KV_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++#endif ++ ++static int w25n02kv_n04kv_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & W25N02_N04KV_STATUS_ECC_MASK) { ++ case W25N02_N04KV_STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS: ++ return 3; ++ ++ case W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS: ++ return 4; ++ ++ /* W25N02_N04KV_use internal 8bit ECC algorithm. ++ * But the ECC strength is 4 bit requried. ++ * Return 3 if the bit bit flip count less than 5. ++ * Return 4 if the bit bit flip count more than 5 to 8. ++ */ ++ ++ case W25N02_N04KV_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ + static const struct spinand_info winbond_spinand_table[] = { +- SPINAND_INFO("W25M02GV", 0xAB, ++ SPINAND_INFO("W25M02GV", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 2), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -88,7 +191,19 @@ static const struct spinand_info winbond + 0, + SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), + SPINAND_SELECT_TARGET(w25m02gv_select_target)), +- SPINAND_INFO("W25N01GV", 0xAA, ++#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV) ++ SPINAND_INFO("W25N01KV", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21), ++ NAND_MEMORG(1, 2048, 96, 64, 1024, 1, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout, w25n01kv_ecc_get_status)), ++#else ++ SPINAND_INFO("W25N01GV", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, +@@ -96,32 +211,31 @@ static const struct spinand_info winbond + &update_cache_variants), + 0, + SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), +-}; +- +-/** +- * winbond_spinand_detect - initialize device related part in spinand_device +- * struct if it is a Winbond device. +- * @spinand: SPI NAND device structure +- */ +-static int winbond_spinand_detect(struct spinand_device *spinand) +-{ +- u8 *id = spinand->id.data; +- int ret; +- +- /* +- * Winbond SPI NAND read ID need a dummy byte, +- * so the first byte in raw_id is dummy. ++#endif ++ SPINAND_INFO("W25N02KV", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout, ++ w25n02kv_n04kv_ecc_get_status)), ++ /* W25N04KV has 2-die(lun), however, it can select die automatically. ++ * Treat it as single die here and double block size. + */ +- if (id[1] != SPINAND_MFR_WINBOND) +- return 0; +- +- ret = spinand_match_and_init(spinand, winbond_spinand_table, +- ARRAY_SIZE(winbond_spinand_table), id[2]); +- if (ret) +- return ret; +- +- return 1; +-} ++ SPINAND_INFO("W25N04KV", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), ++ NAND_MEMORG(1, 2048, 128, 64, 4096, 2, 1, 1), ++ NAND_ECCREQ(4, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ 0, ++ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout, ++ w25n02kv_n04kv_ecc_get_status)), ++}; + + static int winbond_spinand_init(struct spinand_device *spinand) + { +@@ -142,12 +256,13 @@ static int winbond_spinand_init(struct s + } + + static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = { +- .detect = winbond_spinand_detect, + .init = winbond_spinand_init, + }; + + const struct spinand_manufacturer winbond_spinand_manufacturer = { + .id = SPINAND_MFR_WINBOND, + .name = "Winbond", ++ .chips = winbond_spinand_table, ++ .nchips = ARRAY_SIZE(winbond_spinand_table), + .ops = &winbond_spinand_manuf_ops, + }; +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -39,15 +39,15 @@ + SPI_MEM_OP_NO_DUMMY, \ + SPI_MEM_OP_NO_DATA) + +-#define SPINAND_READID_OP(ndummy, buf, len) \ ++#define SPINAND_READID_OP(naddr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1), \ +- SPI_MEM_OP_NO_ADDR, \ ++ SPI_MEM_OP_ADDR(naddr, 0, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 1)) + + #define SPINAND_SET_FEATURE_OP(reg, valptr) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x1f, 1), \ +- SPI_MEM_OP_ADDR(1, reg, 1), \ ++ SPI_MEM_OP_ADDR(1, reg, 1), \ + SPI_MEM_OP_NO_DUMMY, \ + SPI_MEM_OP_DATA_OUT(1, valptr, 1)) + +@@ -75,18 +75,36 @@ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 1)) + ++#define SPINAND_PAGE_READ_FROM_CACHE_OP_3A(fast, addr, ndummy, buf, len)\ ++ SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \ ++ SPI_MEM_OP_ADDR(3, addr, 1), \ ++ SPI_MEM_OP_DUMMY(ndummy, 1), \ ++ SPI_MEM_OP_DATA_IN(len, buf, 1)) ++ + #define SPINAND_PAGE_READ_FROM_CACHE_X2_OP(addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ + SPI_MEM_OP_ADDR(2, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 2)) + ++#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(addr, ndummy, buf, len) \ ++ SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ ++ SPI_MEM_OP_ADDR(3, addr, 1), \ ++ SPI_MEM_OP_DUMMY(ndummy, 1), \ ++ SPI_MEM_OP_DATA_IN(len, buf, 2)) ++ + #define SPINAND_PAGE_READ_FROM_CACHE_X4_OP(addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ + SPI_MEM_OP_ADDR(2, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 4)) + ++#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(addr, ndummy, buf, len) \ ++ SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ ++ SPI_MEM_OP_ADDR(3, addr, 1), \ ++ SPI_MEM_OP_DUMMY(ndummy, 1), \ ++ SPI_MEM_OP_DATA_IN(len, buf, 4)) ++ + #define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ + SPI_MEM_OP_ADDR(2, addr, 2), \ +@@ -153,37 +171,46 @@ struct spinand_device; + * @data: buffer containing the id bytes. Currently 4 bytes large, but can + * be extended if required + * @len: ID length +- * +- * struct_spinand_id->data contains all bytes returned after a READ_ID command, +- * including dummy bytes if the chip does not emit ID bytes right after the +- * READ_ID command. The responsibility to extract real ID bytes is left to +- * struct_manufacurer_ops->detect(). + */ + struct spinand_id { + u8 data[SPINAND_MAX_ID_LEN]; + int len; + }; + ++enum spinand_readid_method { ++ SPINAND_READID_METHOD_OPCODE, ++ SPINAND_READID_METHOD_OPCODE_ADDR, ++ SPINAND_READID_METHOD_OPCODE_DUMMY, ++}; ++ ++/** ++ * struct spinand_devid - SPI NAND device id structure ++ * @id: device id of current chip ++ * @len: number of bytes in device id ++ * @method: method to read chip id ++ * There are 3 possible variants: ++ * SPINAND_READID_METHOD_OPCODE: chip id is returned immediately ++ * after read_id opcode. ++ * SPINAND_READID_METHOD_OPCODE_ADDR: chip id is returned after ++ * read_id opcode + 1-byte address. ++ * SPINAND_READID_METHOD_OPCODE_DUMMY: chip id is returned after ++ * read_id opcode + 1 dummy byte. ++ */ ++struct spinand_devid { ++ const u8 *id; ++ const u8 len; ++ const enum spinand_readid_method method; ++}; ++ + /** + * struct manufacurer_ops - SPI NAND manufacturer specific operations +- * @detect: detect a SPI NAND device. Every time a SPI NAND device is probed +- * the core calls the struct_manufacurer_ops->detect() hook of each +- * registered manufacturer until one of them return 1. Note that +- * the first thing to check in this hook is that the manufacturer ID +- * in struct_spinand_device->id matches the manufacturer whose +- * ->detect() hook has been called. Should return 1 if there's a +- * match, 0 if the manufacturer ID does not match and a negative +- * error code otherwise. When true is returned, the core assumes +- * that properties of the NAND chip (spinand->base.memorg and +- * spinand->base.eccreq) have been filled + * @init: initialize a SPI NAND device + * @cleanup: cleanup a SPI NAND device + * + * Each SPI NAND manufacturer driver should implement this interface so that +- * NAND chips coming from this vendor can be detected and initialized properly. ++ * NAND chips coming from this vendor can be initialized properly. + */ + struct spinand_manufacturer_ops { +- int (*detect)(struct spinand_device *spinand); + int (*init)(struct spinand_device *spinand); + void (*cleanup)(struct spinand_device *spinand); + }; +@@ -192,11 +219,16 @@ struct spinand_manufacturer_ops { + * struct spinand_manufacturer - SPI NAND manufacturer instance + * @id: manufacturer ID + * @name: manufacturer name ++ * @devid_len: number of bytes in device ID ++ * @chips: supported SPI NANDs under current manufacturer ++ * @nchips: number of SPI NANDs available in chips array + * @ops: manufacturer operations + */ + struct spinand_manufacturer { + u8 id; + char *name; ++ const struct spinand_info *chips; ++ const size_t nchips; + const struct spinand_manufacturer_ops *ops; + }; + +@@ -268,7 +300,7 @@ struct spinand_ecc_info { + */ + struct spinand_info { + const char *model; +- u8 devid; ++ struct spinand_devid devid; + u32 flags; + struct nand_memory_organization memorg; + struct nand_ecc_req eccreq; +@@ -282,6 +314,13 @@ struct spinand_info { + unsigned int target); + }; + ++#define SPINAND_ID(__method, ...) \ ++ { \ ++ .id = (const u8[]){ __VA_ARGS__ }, \ ++ .len = sizeof((u8[]){ __VA_ARGS__ }), \ ++ .method = __method, \ ++ } ++ + #define SPINAND_INFO_OP_VARIANTS(__read, __write, __update) \ + { \ + .read_cache = __read, \ +@@ -440,9 +479,10 @@ static inline void spinand_set_ofnode(st + } + #endif /* __UBOOT__ */ + +-int spinand_match_and_init(struct spinand_device *dev, ++int spinand_match_and_init(struct spinand_device *spinand, + const struct spinand_info *table, +- unsigned int table_size, u8 devid); ++ unsigned int table_size, ++ enum spinand_readid_method rdid_method); + + int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); + int spinand_select_target(struct spinand_device *spinand, unsigned int target); diff --git a/package/boot/uboot-mediatek/patches/100-23-mmc-mtk-sd-add-support-to-display-verbose-error-log.patch b/package/boot/uboot-mediatek/patches/100-23-mmc-mtk-sd-add-support-to-display-verbose-error-log.patch new file mode 100644 index 0000000000..b6a2229170 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-23-mmc-mtk-sd-add-support-to-display-verbose-error-log.patch @@ -0,0 +1,78 @@ +From 793bed29e78cc54d989333d756fef51efaca4e56 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Tue, 26 Jul 2022 09:29:18 +0800 +Subject: [PATCH 58/71] mmc: mtk-sd: add support to display verbose error log + +Add an option to enable debug log, and also display verbose error log for +both command and data. + +Signed-off-by: Weijie Gao +--- + drivers/mmc/Kconfig | 8 ++++++++ + drivers/mmc/Makefile | 4 ++++ + drivers/mmc/mtk-sd.c | 24 +++++++++++++++--------- + 3 files changed, 27 insertions(+), 9 deletions(-) + +--- a/drivers/mmc/Kconfig ++++ b/drivers/mmc/Kconfig +@@ -789,6 +789,14 @@ config MMC_MTK + This is needed if support for any SD/SDIO/MMC devices is required. + If unsure, say N. + ++config MMC_MTK_DEBUG ++ bool "Display verbose error log" ++ default n ++ depends on MMC_MTK ++ help ++ Enable this option to allow verbose error log being displayed for ++ debugging. ++ + endif + + config FSL_ESDHC +--- a/drivers/mmc/Makefile ++++ b/drivers/mmc/Makefile +@@ -84,3 +84,7 @@ obj-$(CONFIG_RENESAS_SDHI) += tmio-comm + obj-$(CONFIG_MMC_BCM2835) += bcm2835_sdhost.o + obj-$(CONFIG_MMC_MTK) += mtk-sd.o + obj-$(CONFIG_MMC_SDHCI_F_SDH30) += f_sdh30.o ++ ++ifdef CONFIG_MMC_MTK_DEBUG ++CFLAGS_mtk-sd.o += -DDEBUG ++endif +--- a/drivers/mmc/mtk-sd.c ++++ b/drivers/mmc/mtk-sd.c +@@ -778,18 +778,24 @@ static int msdc_ops_send_cmd(struct udev + if (cmd_ret && + !(cmd_ret == -EIO && + (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK || +- cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200))) ++ cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200))) { ++ dev_dbg(dev, "MSDC start command failure with %d, cmd=%d, arg=0x%x\n", ++ cmd_ret, cmd->cmdidx, cmd->cmdarg); + return cmd_ret; +- +- if (data) { +- data_ret = msdc_start_data(host, data); +- if (cmd_ret) +- return cmd_ret; +- else +- return data_ret; + } + +- return 0; ++ if (!data) ++ return cmd_ret; ++ ++ data_ret = msdc_start_data(host, data); ++ if (cmd_ret) ++ return cmd_ret; ++ ++ if (data_ret) ++ dev_dbg(dev, "MSDC start data failure with %d, cmd=%d, arg=0x%x\n", ++ data_ret, cmd->cmdidx, cmd->cmdarg); ++ ++ return data_ret; + } + + static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) diff --git a/package/boot/uboot-mediatek/patches/100-24-cmd-ubi-make-volume-find-create-remove-APIs-public.patch b/package/boot/uboot-mediatek/patches/100-24-cmd-ubi-make-volume-find-create-remove-APIs-public.patch new file mode 100644 index 0000000000..ba32fa869d --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-24-cmd-ubi-make-volume-find-create-remove-APIs-public.patch @@ -0,0 +1,58 @@ +From dd66fc817f7ab7a4fcab9836a9251a8f64f329df Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 16:58:36 +0800 +Subject: [PATCH 59/71] cmd: ubi: make volume find/create/remove APIs public + +Export ubi_create_vol/ubi_find_volume/ubi_remove_vol to public so that they +can be used by other programs. + +Signed-off-by: Weijie Gao +--- + cmd/ubi.c | 8 ++++---- + include/ubi_uboot.h | 4 ++++ + 2 files changed, 8 insertions(+), 4 deletions(-) + +--- a/cmd/ubi.c ++++ b/cmd/ubi.c +@@ -148,8 +148,8 @@ bad: + return err; + } + +-static int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id, +- bool skipcheck) ++int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id, ++ bool skipcheck) + { + struct ubi_mkvol_req req; + int err; +@@ -182,7 +182,7 @@ static int ubi_create_vol(char *volume, + return ubi_create_volume(ubi, &req); + } + +-static struct ubi_volume *ubi_find_volume(char *volume) ++struct ubi_volume *ubi_find_volume(char *volume) + { + struct ubi_volume *vol = NULL; + int i; +@@ -197,7 +197,7 @@ static struct ubi_volume *ubi_find_volum + return NULL; + } + +-static int ubi_remove_vol(char *volume) ++int ubi_remove_vol(char *volume) + { + int err, reserved_pebs, i; + struct ubi_volume *vol; +--- a/include/ubi_uboot.h ++++ b/include/ubi_uboot.h +@@ -73,6 +73,10 @@ extern void ubi_exit(void); + extern int ubi_part(char *part_name, const char *vid_header_offset); + extern int ubi_volume_write(char *volume, void *buf, size_t size); + extern int ubi_volume_read(char *volume, char *buf, size_t size); ++extern int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id, ++ bool skipcheck); ++extern struct ubi_volume *ubi_find_volume(char *volume); ++extern int ubi_remove_vol(char *volume); + + extern struct ubi_device *ubi_devices[]; + int cmd_ubifs_mount(char *vol_name); diff --git a/package/boot/uboot-mediatek/patches/100-25-cmd-ubi-allow-creating-volume-with-all-free-spaces.patch b/package/boot/uboot-mediatek/patches/100-25-cmd-ubi-allow-creating-volume-with-all-free-spaces.patch new file mode 100644 index 0000000000..1d62c05e40 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-25-cmd-ubi-allow-creating-volume-with-all-free-spaces.patch @@ -0,0 +1,27 @@ +From f6a4130959af1e6d13d616203e42ed3c894666ad Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 17:00:00 +0800 +Subject: [PATCH 60/71] cmd: ubi: allow creating volume with all free spaces + +Allow creating volume with all free spaces by giving a negative size value. + +Signed-off-by: Weijie Gao +--- + cmd/ubi.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/cmd/ubi.c ++++ b/cmd/ubi.c +@@ -161,7 +161,11 @@ int ubi_create_vol(char *volume, int64_t + + req.vol_id = vol_id; + req.alignment = 1; +- req.bytes = size; ++ ++ if (size < 0) ++ req.bytes = ubi->avail_pebs * ubi->leb_size; ++ else ++ req.bytes = size; + + strcpy(req.name, volume); + req.name_len = strlen(volume); diff --git a/package/boot/uboot-mediatek/patches/100-26-env-ubi-add-support-to-create-environment-volume-if-.patch b/package/boot/uboot-mediatek/patches/100-26-env-ubi-add-support-to-create-environment-volume-if-.patch new file mode 100644 index 0000000000..08b14a6b29 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-26-env-ubi-add-support-to-create-environment-volume-if-.patch @@ -0,0 +1,72 @@ +From fc0c70a7c6a088072d0c77e5a59d5e9b7754c6db Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 17:01:20 +0800 +Subject: [PATCH 61/71] env: ubi: add support to create environment volume if + it does not exist + +Add an option to allow environment volume being auto created if not exist. + +Signed-off-by: Weijie Gao +--- + env/Kconfig | 6 ++++++ + env/ubi.c | 20 ++++++++++++++++++++ + 2 files changed, 26 insertions(+) + +--- a/env/Kconfig ++++ b/env/Kconfig +@@ -647,6 +647,12 @@ config ENV_UBI_VOLUME_REDUND + help + Name of the redundant volume that you want to store the environment in. + ++config ENV_UBI_VOLUME_CREATE ++ bool "Create UBI volume if not exist" ++ depends on ENV_IS_IN_UBI ++ help ++ Create the UBI volume if it does not exist. ++ + config ENV_UBI_VID_OFFSET + int "ubi environment VID offset" + depends on ENV_IS_IN_UBI +--- a/env/ubi.c ++++ b/env/ubi.c +@@ -100,6 +100,18 @@ static int env_ubi_save(void) + #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ + #endif /* CONFIG_CMD_SAVEENV */ + ++int __weak env_ubi_volume_create(const char *volume) ++{ ++ struct ubi_volume *vol; ++ ++ vol = ubi_find_volume((char *)volume); ++ if (vol) ++ return 0; ++ ++ return ubi_create_vol((char *)volume, CONFIG_ENV_SIZE, true, ++ UBI_VOL_NUM_AUTO, false); ++} ++ + #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT + static int env_ubi_load(void) + { +@@ -129,6 +141,11 @@ static int env_ubi_load(void) + return -EIO; + } + ++ if (IS_ENABLED(CONFIG_ENV_UBI_VOLUME_CREATE)) { ++ env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME); ++ env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME_REDUND); ++ } ++ + read1_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1, + CONFIG_ENV_SIZE); + if (read1_fail) +@@ -166,6 +183,9 @@ static int env_ubi_load(void) + return -EIO; + } + ++ if (IS_ENABLED(CONFIG_ENV_UBI_VOLUME_CREATE)) ++ env_ubi_volume_create(CONFIG_ENV_UBI_VOLUME); ++ + if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, buf, CONFIG_ENV_SIZE)) { + printf("\n** Unable to read env from %s:%s **\n", + CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); diff --git a/package/boot/uboot-mediatek/patches/600-ubi-detect-eof-marker.patch b/package/boot/uboot-mediatek/patches/100-27-mtd-ubi-add-support-for-UBI-end-of-filesystem-marker.patch similarity index 65% rename from package/boot/uboot-mediatek/patches/600-ubi-detect-eof-marker.patch rename to package/boot/uboot-mediatek/patches/100-27-mtd-ubi-add-support-for-UBI-end-of-filesystem-marker.patch index 5d312eca8f..cd1794f0d1 100644 --- a/package/boot/uboot-mediatek/patches/600-ubi-detect-eof-marker.patch +++ b/package/boot/uboot-mediatek/patches/100-27-mtd-ubi-add-support-for-UBI-end-of-filesystem-marker.patch @@ -1,3 +1,18 @@ +From 189a2fe96931ef3ea0e187c8e9bfa589c2a0ae10 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Mon, 25 Jul 2022 17:24:56 +0800 +Subject: [PATCH 62/71] mtd: ubi: add support for UBI end-of-filesystem marker + used by OpenWrt + +Add support for UBI end-of-filesystem marker used by OpenWrt to allow +attaching a new UBI mtd partition just upgraded. + +Signed-off-by: Weijie Gao +--- + drivers/mtd/ubi/attach.c | 25 ++++++++++++++++++++++--- + drivers/mtd/ubi/ubi.h | 1 + + 2 files changed, 23 insertions(+), 3 deletions(-) + --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c @@ -802,6 +802,13 @@ out_unlock: diff --git a/package/boot/uboot-mediatek/patches/100-28-include-configs-mt7986-h-from-SDK.patch b/package/boot/uboot-mediatek/patches/100-28-include-configs-mt7986-h-from-SDK.patch new file mode 100644 index 0000000000..110b1bb237 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-28-include-configs-mt7986-h-from-SDK.patch @@ -0,0 +1,26 @@ +--- a/include/configs/mt7986.h ++++ b/include/configs/mt7986.h +@@ -11,6 +11,11 @@ + + #include + ++#define CONFIG_SYS_MAXARGS 32 ++#define CONFIG_SYS_BOOTM_LEN SZ_128M ++#define CONFIG_SYS_CBSIZE SZ_1K ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ ++ sizeof(CONFIG_SYS_PROMPT) + 16) + #define CONFIG_SYS_NONCACHED_MEMORY SZ_1M + #define CONFIG_SYS_MMC_ENV_DEV 0 + +@@ -19,6 +24,11 @@ + + /* SPL -> Uboot */ + #define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE ++#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_2M - \ ++ GENERATED_GBL_DATA_SIZE) ++ ++/* Flash */ ++#define CONFIG_SYS_NAND_MAX_CHIPS 1 + + /* DRAM */ + #define CONFIG_SYS_SDRAM_BASE 0x40000000 diff --git a/package/boot/uboot-mediatek/patches/100-29-board-mediatek-wire-up-NMBM-support.patch b/package/boot/uboot-mediatek/patches/100-29-board-mediatek-wire-up-NMBM-support.patch new file mode 100644 index 0000000000..9808e2c860 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/100-29-board-mediatek-wire-up-NMBM-support.patch @@ -0,0 +1,240 @@ +From 6792b57b3ba61ca6d69ea4a13a58bed65fc5da87 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 7 Aug 2022 04:04:46 +0200 +Subject: [PATCH] board: mediatek: wire-up NMBM support + +--- + board/mediatek/mt7622/mt7622_rfb.c | 38 +++++++++++++++++++++ + board/mediatek/mt7629/mt7629_rfb.c | 38 +++++++++++++++++++++ + board/mediatek/mt7981/mt7981_rfb.c | 52 ++++++++++++++++++++++++++++ + board/mediatek/mt7986/mt7986_rfb.c | 54 ++++++++++++++++++++++++++++++ + 4 files changed, 182 insertions(+) + +--- a/board/mediatek/mt7622/mt7622_rfb.c ++++ b/board/mediatek/mt7622/mt7622_rfb.c +@@ -10,6 +10,11 @@ + #include + #include + ++#include ++#include ++#include ++#include ++ + DECLARE_GLOBAL_DATA_PTR; + + int board_init(void) +@@ -24,3 +29,36 @@ int board_late_init(void) + env_relocate(); + return 0; + } ++ ++int board_nmbm_init(void) ++{ ++#ifdef CONFIG_ENABLE_NAND_NMBM ++ struct mtd_info *lower, *upper; ++ int ret; ++ ++ printf("\n"); ++ printf("Initializing NMBM ...\n"); ++ ++ mtd_probe_devices(); ++ ++ lower = get_mtd_device_nm("spi-nand0"); ++ if (IS_ERR(lower) || !lower) { ++ printf("Lower MTD device 'spi-nand0' not found\n"); ++ return 0; ++ } ++ ++ ret = nmbm_attach_mtd(lower, ++ NMBM_F_CREATE | NMBM_F_EMPTY_PAGE_ECC_OK, ++ CONFIG_NMBM_MAX_RATIO, ++ CONFIG_NMBM_MAX_BLOCKS, &upper); ++ ++ printf("\n"); ++ ++ if (ret) ++ return 0; ++ ++ add_mtd_device(upper); ++#endif ++ ++ return 0; ++} +--- a/board/mediatek/mt7629/mt7629_rfb.c ++++ b/board/mediatek/mt7629/mt7629_rfb.c +@@ -6,6 +6,11 @@ + #include + #include + ++#include ++#include ++#include ++#include ++ + DECLARE_GLOBAL_DATA_PTR; + + int board_init(void) +@@ -20,3 +25,36 @@ uint32_t spl_nand_get_uboot_raw_page(voi + { + return CONFIG_SPL_PAD_TO; + } ++ ++int board_nmbm_init(void) ++{ ++#ifdef CONFIG_ENABLE_NAND_NMBM ++ struct mtd_info *lower, *upper; ++ int ret; ++ ++ printf("\n"); ++ printf("Initializing NMBM ...\n"); ++ ++ mtd_probe_devices(); ++ ++ lower = get_mtd_device_nm("spi-nand0"); ++ if (IS_ERR(lower) || !lower) { ++ printf("Lower MTD device 'spi-nand0' not found\n"); ++ return 0; ++ } ++ ++ ret = nmbm_attach_mtd(lower, ++ NMBM_F_CREATE | NMBM_F_EMPTY_PAGE_ECC_OK, ++ CONFIG_NMBM_MAX_RATIO, ++ CONFIG_NMBM_MAX_BLOCKS, &upper); ++ ++ printf("\n"); ++ ++ if (ret) ++ return 0; ++ ++ add_mtd_device(upper); ++#endif ++ ++ return 0; ++} +--- a/board/mediatek/mt7981/mt7981_rfb.c ++++ b/board/mediatek/mt7981/mt7981_rfb.c +@@ -4,7 +4,59 @@ + * Author: Sam Shih + */ + ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ + int board_init(void) + { ++ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; ++ return 0; ++} ++ ++int board_late_init(void) ++{ ++ gd->env_valid = 1; //to load environment variable from persistent store ++ env_relocate(); ++ return 0; ++} ++ ++int board_nmbm_init(void) ++{ ++#ifdef CONFIG_ENABLE_NAND_NMBM ++ struct mtd_info *lower, *upper; ++ int ret; ++ ++ printf("\n"); ++ printf("Initializing NMBM ...\n"); ++ ++ mtd_probe_devices(); ++ ++ lower = get_mtd_device_nm("spi-nand0"); ++ if (IS_ERR(lower) || !lower) { ++ printf("Lower MTD device 'spi-nand0' not found\n"); ++ return 0; ++ } ++ ++ ret = nmbm_attach_mtd(lower, NMBM_F_CREATE, CONFIG_NMBM_MAX_RATIO, ++ CONFIG_NMBM_MAX_BLOCKS, &upper); ++ ++ printf("\n"); ++ ++ if (ret) ++ return 0; ++ ++ add_mtd_device(upper); ++#endif ++ + return 0; + } +--- a/board/mediatek/mt7986/mt7986_rfb.c ++++ b/board/mediatek/mt7986/mt7986_rfb.c +@@ -4,7 +4,61 @@ + * Author: Sam Shih + */ + ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ + int board_init(void) + { ++ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; ++ return 0; ++} ++ ++int board_late_init(void) ++{ ++ gd->env_valid = 1; //to load environment variable from persistent store ++ env_relocate(); ++ return 0; ++} ++ ++int board_nmbm_init(void) ++{ ++#ifdef CONFIG_ENABLE_NAND_NMBM ++ struct mtd_info *lower, *upper; ++ int ret; ++ ++ printf("\n"); ++ printf("Initializing NMBM ...\n"); ++ ++ mtd_probe_devices(); ++ ++ lower = get_mtd_device_nm("spi-nand0"); ++ if (IS_ERR(lower) || !lower) { ++ printf("Lower MTD device 'spi-nand0' not found\n"); ++ return 0; ++ } ++ ++ ret = nmbm_attach_mtd(lower, ++ NMBM_F_CREATE | NMBM_F_EMPTY_PAGE_ECC_OK, ++ CONFIG_NMBM_MAX_RATIO, ++ CONFIG_NMBM_MAX_BLOCKS, &upper); ++ ++ printf("\n"); ++ ++ if (ret) ++ return 0; ++ ++ add_mtd_device(upper); ++#endif ++ + return 0; + } diff --git a/package/boot/uboot-mediatek/patches/110-no-kwbimage.patch b/package/boot/uboot-mediatek/patches/110-no-kwbimage.patch index 6d4af1f174..5fb896d92d 100644 --- a/package/boot/uboot-mediatek/patches/110-no-kwbimage.patch +++ b/package/boot/uboot-mediatek/patches/110-no-kwbimage.patch @@ -1,6 +1,6 @@ --- a/tools/Makefile +++ b/tools/Makefile -@@ -120,7 +120,6 @@ dumpimage-mkimage-objs := aisimage.o \ +@@ -121,7 +121,6 @@ dumpimage-mkimage-objs := aisimage.o \ imximage.o \ imx8image.o \ imx8mimage.o \ diff --git a/package/boot/uboot-mediatek/patches/200-cmd-add-imsz-and-imszb.patch b/package/boot/uboot-mediatek/patches/200-cmd-add-imsz-and-imszb.patch index 1759b04899..cc6aa64cbc 100644 --- a/package/boot/uboot-mediatek/patches/200-cmd-add-imsz-and-imszb.patch +++ b/package/boot/uboot-mediatek/patches/200-cmd-add-imsz-and-imszb.patch @@ -1,9 +1,10 @@ --- a/cmd/bootm.c +++ b/cmd/bootm.c -@@ -257,6 +257,65 @@ U_BOOT_CMD( +@@ -257,6 +257,67 @@ U_BOOT_CMD( /* iminfo - print header info for a requested image */ /*******************************************************************/ #if defined(CONFIG_CMD_IMI) ++#if defined(CONFIG_FIT) +#define SECTOR_SHIFT 9 +static int image_totalsize(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[], short int in_blocks) @@ -63,12 +64,13 @@ + "addr [maxhdrlen] [varname]\n" +); + ++#endif static int do_iminfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { --- a/boot/image-fit.c +++ b/boot/image-fit.c -@@ -1995,6 +1995,51 @@ static const char *fit_get_image_type_pr +@@ -1994,6 +1994,51 @@ static const char *fit_get_image_type_pr return "unknown"; } diff --git a/package/boot/uboot-mediatek/patches/211-cmd-bootmenu-custom-title.patch b/package/boot/uboot-mediatek/patches/211-cmd-bootmenu-custom-title.patch index f1e60c6407..72926ea2e7 100644 --- a/package/boot/uboot-mediatek/patches/211-cmd-bootmenu-custom-title.patch +++ b/package/boot/uboot-mediatek/patches/211-cmd-bootmenu-custom-title.patch @@ -1,6 +1,6 @@ --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c -@@ -431,7 +431,11 @@ static void menu_display_statusline(stru +@@ -439,7 +439,11 @@ static void menu_display_statusline(stru printf(ANSI_CURSOR_POSITION, 1, 1); puts(ANSI_CLEAR_LINE); printf(ANSI_CURSOR_POSITION, 2, 3); @@ -13,7 +13,7 @@ puts(ANSI_CLEAR_LINE_TO_END); printf(ANSI_CURSOR_POSITION, 3, 1); puts(ANSI_CLEAR_LINE); -@@ -516,6 +520,7 @@ static enum bootmenu_ret bootmenu_show(i +@@ -524,6 +528,7 @@ static enum bootmenu_ret bootmenu_show(i return BOOTMENU_RET_FAIL; } @@ -23,7 +23,7 @@ goto cleanup; --- a/include/menu.h +++ b/include/menu.h -@@ -40,6 +40,7 @@ struct bootmenu_data { +@@ -43,6 +43,7 @@ struct bootmenu_data { int active; /* active menu entry */ int count; /* total count of menu entries */ struct bootmenu_entry *first; /* first menu entry */ diff --git a/package/boot/uboot-mediatek/patches/220-cmd-env-readmem.patch b/package/boot/uboot-mediatek/patches/220-cmd-env-readmem.patch index 544767e2fa..4ffbc17208 100644 --- a/package/boot/uboot-mediatek/patches/220-cmd-env-readmem.patch +++ b/package/boot/uboot-mediatek/patches/220-cmd-env-readmem.patch @@ -15,7 +15,7 @@ help --- a/cmd/nvedit.c +++ b/cmd/nvedit.c -@@ -408,6 +408,60 @@ int do_env_ask(struct cmd_tbl *cmdtp, in +@@ -409,6 +409,60 @@ int do_env_ask(struct cmd_tbl *cmdtp, in } #endif @@ -76,7 +76,7 @@ #if defined(CONFIG_CMD_ENV_CALLBACK) static int print_static_binding(const char *var_name, const char *callback_name, void *priv) -@@ -1231,6 +1285,9 @@ static struct cmd_tbl cmd_env_sub[] = { +@@ -1232,6 +1286,9 @@ static struct cmd_tbl cmd_env_sub[] = { U_BOOT_CMD_MKENT(load, 1, 0, do_env_load, "", ""), #endif U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""), @@ -86,7 +86,7 @@ #if defined(CONFIG_CMD_RUN) U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""), #endif -@@ -1322,6 +1379,9 @@ static char env_help_text[] = +@@ -1323,6 +1380,9 @@ static char env_help_text[] = #if defined(CONFIG_CMD_NVEDIT_EFI) "env print -e [-guid guid] [-n] [name ...] - print UEFI environment\n" #endif @@ -96,7 +96,7 @@ #if defined(CONFIG_CMD_RUN) "env run var [...] - run commands in an environment variable\n" #endif -@@ -1431,6 +1491,17 @@ U_BOOT_CMD( +@@ -1432,6 +1492,17 @@ U_BOOT_CMD( ); #endif diff --git a/package/boot/uboot-mediatek/patches/301-mt7622-generic-reset-button-ignore-env.patch b/package/boot/uboot-mediatek/patches/301-mt7622-generic-reset-button-ignore-env.patch index 43270a7a72..9fae6d056f 100644 --- a/package/boot/uboot-mediatek/patches/301-mt7622-generic-reset-button-ignore-env.patch +++ b/package/boot/uboot-mediatek/patches/301-mt7622-generic-reset-button-ignore-env.patch @@ -15,9 +15,9 @@ +#define CONFIG_RESET_BUTTON_LABEL "reset" +#endif - DECLARE_GLOBAL_DATA_PTR; - -@@ -20,7 +27,19 @@ int board_init(void) + #include + #include +@@ -25,7 +32,19 @@ int board_init(void) int board_late_init(void) { @@ -40,9 +40,9 @@ } --- a/arch/arm/mach-mediatek/Kconfig +++ b/arch/arm/mach-mediatek/Kconfig -@@ -115,4 +115,8 @@ config MTK_BROM_HEADER_INFO - default "media=emmc" if TARGET_MT8516 || TARGET_MT8365 || TARGET_MT8183 - default "lk=1" if TARGET_MT7623 +@@ -138,4 +138,8 @@ config MTK_BROM_HEADER_INFO + + source "board/mediatek/mt7629/Kconfig" +config RESET_BUTTON_LABEL + string "Button to trigger factory reset" diff --git a/package/boot/uboot-mediatek/patches/303-mt7986-generic-reset-button-ignore-env.patch b/package/boot/uboot-mediatek/patches/303-mt7986-generic-reset-button-ignore-env.patch new file mode 100644 index 0000000000..5011e74257 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/303-mt7986-generic-reset-button-ignore-env.patch @@ -0,0 +1,40 @@ +--- a/board/mediatek/mt7986/mt7986_rfb.c ++++ b/board/mediatek/mt7986/mt7986_rfb.c +@@ -6,9 +6,16 @@ + + #include + #include ++#include ++#include + #include + #include + #include ++#include ++ ++#ifndef CONFIG_RESET_BUTTON_LABEL ++#define CONFIG_RESET_BUTTON_LABEL "reset" ++#endif + + #include + #include +@@ -25,7 +32,19 @@ int board_init(void) + + int board_late_init(void) + { +- gd->env_valid = 1; //to load environment variable from persistent store ++ struct udevice *dev; ++ ++ gd->env_valid = ENV_VALID; ++ if (!button_get_by_label(CONFIG_RESET_BUTTON_LABEL, &dev)) { ++ puts("reset button found\n"); ++#ifdef CONFIG_RESET_BUTTON_SETTLE_DELAY ++ mdelay(CONFIG_RESET_BUTTON_SETTLE_DELAY); ++#endif ++ if (button_get_state(dev) == BUTTON_ON) { ++ puts("button pushed, resetting environment\n"); ++ gd->env_valid = ENV_INVALID; ++ } ++ } + env_relocate(); + return 0; + } diff --git a/package/boot/uboot-mediatek/patches/350-add-support-for-Winbond-W25Q512JV.patch b/package/boot/uboot-mediatek/patches/350-add-support-for-Winbond-W25Q512JV.patch deleted file mode 100644 index da746bb124..0000000000 --- a/package/boot/uboot-mediatek/patches/350-add-support-for-Winbond-W25Q512JV.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/mtd/spi/spi-nor-ids.c -+++ b/drivers/mtd/spi/spi-nor-ids.c -@@ -376,6 +376,8 @@ const struct flash_info spi_nor_ids[] = - SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) - }, - { INFO("w25q256", 0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { INFO("w25q512jv", 0xef4020, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ | -+ SPI_NOR_HAS_TB | SPI_NOR_HAS_LOCK) }, - { INFO("w25m512jw", 0xef6119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { INFO("w25m512jv", 0xef7119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - #endif diff --git a/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch b/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch index 5ce3a7cd2a..de37764b68 100644 --- a/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch +++ b/package/boot/uboot-mediatek/patches/404-add-bananapi_bpi-r64_defconfigs.patch @@ -643,7 +643,7 @@ +boot_write_bl2=mtd erase bl2 && mtd write spi-nand0 $loadaddr 0x0 0x20000 && mtd write spi-nand0 $loadaddr 0x20000 0x20000 && mtd write spi-nand0 $loadaddr 0x40000 0x20000 && mtd write spi-nand0 $loadaddr 0x60000 0x20000 +boot_write_fip=mtd erase fip && mtd write fip $loadaddr +check_ubi=ubi part ubi || run ubi_format -+reset_factory=ubi part ubi ; ubi write 0x0 ubootenv 0x0 ; ubi write 0x0 ubootenv2 0x0 ; ubi remove rootfs_data ++reset_factory=mw $loadaddr 0x0 0x100000 ; ubi part ubi ; ubi write $loadaddr ubootenv 0x100000 ; ubi write $loadaddr ubootenv2 0x100000 ; ubi remove rootfs_data +ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset +ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi +ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs diff --git a/package/boot/uboot-mediatek/patches/410-add-linksys-e8450.patch b/package/boot/uboot-mediatek/patches/410-add-linksys-e8450.patch index decb485042..cbcd098c3b 100644 --- a/package/boot/uboot-mediatek/patches/410-add-linksys-e8450.patch +++ b/package/boot/uboot-mediatek/patches/410-add-linksys-e8450.patch @@ -342,7 +342,7 @@ + mt7622-linksys-e8450-ubi.dtb \ mt7623n-bananapi-bpi-r2.dtb \ mt7629-rfb.dtb \ - mt8183-pumpkin.dtb \ + mt7981-rfb.dtb \ --- /dev/null +++ b/linksys_e8450_env @@ -0,0 +1,57 @@ @@ -390,7 +390,7 @@ +boot_write_bl2=mtd erase bl2 && mtd write spi-nand0 $loadaddr 0x0 0x20000 && mtd write spi-nand0 $loadaddr 0x20000 0x20000 && mtd write spi-nand0 $loadaddr 0x40000 0x20000 && mtd write spi-nand0 $loadaddr 0x60000 0x20000 +boot_write_fip=mtd erase fip && mtd write fip $loadaddr +check_ubi=ubi part ubi || run ubi_format -+reset_factory=ubi part ubi ; ubi write 0x0 ubootenv 0x0 ; ubi write 0x0 ubootenv2 0x0 ; ubi remove rootfs_data ++reset_factory=mw $loadaddr 0x0 0x100000 ; ubi part ubi ; ubi write $loadaddr ubootenv 0x100000 ; ubi write $loadaddr ubootenv2 0x100000 ; ubi remove rootfs_data +ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset +ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi +ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs 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 1e5c4e8a16..8279d250f3 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 @@ -1,6 +1,6 @@ --- /dev/null +++ b/configs/mt7622_ubnt_unifi-6-lr_defconfig -@@ -0,0 +1,141 @@ +@@ -0,0 +1,142 @@ +CONFIG_ARM=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -142,9 +142,10 @@ +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_XMC=y ++CONFIG_SPI_FLASH_USE_4K_SECTORS=y --- /dev/null +++ b/arch/arm/dts/mt7622-ubnt-unifi-6-lr.dts -@@ -0,0 +1,200 @@ +@@ -0,0 +1,187 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. @@ -283,19 +284,6 @@ + }; +}; + -+&snfi { -+ pinctrl-names = "default", "snfi"; -+ pinctrl-0 = <&snor_pins>; -+ pinctrl-1 = <&snfi_pins>; -+ status = "okay"; -+ -+ spi-flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ u-boot,dm-pre-reloc; -+ }; -+}; -+ +&snor { + pinctrl-names = "default"; + pinctrl-0 = <&snor_pins>; @@ -354,7 +342,7 @@ + mt7622-ubnt-unifi-6-lr.dtb \ mt7623n-bananapi-bpi-r2.dtb \ mt7629-rfb.dtb \ - mt8183-pumpkin.dtb \ + mt7981-rfb.dtb \ --- /dev/null +++ b/ubnt_unifi-6-lr_env @@ -0,0 +1,50 @@ @@ -364,10 +352,10 @@ +loadaddr=0x48000000 +bootcmd=if pstore check ; then run boot_recovery ; else run boot_nor ; fi +bootdelay=0 -+bootfile=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-ubootmod-initramfs-recovery.itb -+bootfile_bl2=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-ubootmod-preloader.bin -+bootfile_fip=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-ubootmod-bl31-uboot.fip -+bootfile_upg=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-ubootmod-squashfs-sysupgrade.itb ++bootfile=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-v1-ubootmod-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-v1-ubootmod-preloader.bin ++bootfile_fip=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-v1-ubootmod-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-mt7622-ubnt_unifi-6-lr-v1-ubootmod-squashfs-sysupgrade.itb +bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 +bootmenu_default=0 +bootmenu_delay=0 @@ -401,7 +389,7 @@ +reset_factory=mtd erase nor0 0xc0000 0x10000 && reset +nor_read_production=mtd read nor0 $loadaddr 0x1000000 0x1000 && imsz $loadaddr image_size && mtd read nor0 $loadaddr 0x1000000 $image_size +nor_read_recovery=mtd read nor0 $loadaddr 0x120000 0x1000 && imsz $loadaddr image_size && mtd read nor0 $loadaddr 0x120000 $image_size -+nor_pad_size=imsz $loadaddr image_size ; setexpr image_eb $image_size / 0x1000 ; setexpr tmp1 image_size % 0x1000 ; test 0x$tmp1 -gt 0 && setexpr image_eb $image_eb + 1 ; setexpr image_eb $image_eb * 0x1000 ++nor_pad_size=imsz $loadaddr image_size ; setexpr image_eb 0x$image_size / 0x1000 ; setexpr tmp1 0x$image_size % 0x1000 ; test 0x$tmp1 -gt 0 && setexpr image_eb 0x$image_eb + 1 ; setexpr image_eb 0x$image_eb * 0x1000 +nor_write_production=run nor_pad_size ; test 0x$image_eb -le 0x3000000 && mtd erase nor0 0x1000000 0x$image_eb && mtd write nor0 $loadaddr 0x1000000 $filesize +nor_write_recovery=run nor_pad_size ; test 0x$image_eb -le 0xee0000 && mtd erase nor0 0x120000 0x$image_eb && mtd write nor0 $loadaddr 0x120000 $filesize +_init_env=setenv _init_env ; saveenv @@ -418,7 +406,7 @@ DECLARE_GLOBAL_DATA_PTR; -@@ -392,6 +393,20 @@ static int initr_onenand(void) +@@ -406,6 +407,20 @@ static int initr_onenand(void) } #endif @@ -439,9 +427,9 @@ #ifdef CONFIG_MMC static int initr_mmc(void) { -@@ -703,6 +718,9 @@ static init_fnc_t init_sequence_r[] = { - #ifdef CONFIG_CMD_ONENAND - initr_onenand, +@@ -720,6 +735,9 @@ static init_fnc_t init_sequence_r[] = { + #ifdef CONFIG_NMBM_MTD + initr_nmbm, #endif +#ifdef CONFIG_SPI_FLASH + initr_spiflash, diff --git a/package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch b/package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch new file mode 100644 index 0000000000..48835e43af --- /dev/null +++ b/package/boot/uboot-mediatek/patches/430-add-bpi-r3.patch @@ -0,0 +1,1368 @@ +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -1211,6 +1211,8 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt7981-snfi-nand-rfb.dtb \ + mt7981-emmc-rfb.dtb \ + mt7981-sd-rfb.dtb \ ++ mt7986a-bpi-r3-sd.dtb \ ++ mt7986a-bpi-r3-emmc.dtb \ + mt7986a-rfb.dtb \ + mt7986b-rfb.dtb \ + mt7986a-sd-rfb.dtb \ +--- /dev/null ++++ b/configs/mt7986a_bpi-r3-emmc_defconfig +@@ -0,0 +1,192 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TARGET_MT7986=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-bpi-r3-emmc" ++CONFIG_DEFAULT_ENV_FILE="bananapi_bpi-r3_emmc_env" ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7986a-bpi-r3-emmc.dtb" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SMBIOS_PRODUCT_NAME="" ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_CFB_CONSOLE_ANSI=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_GPIO_HOG=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_FIT=y ++CONFIG_FIT_ENABLE_SHA256_SUPPORT=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_BOOTP=y ++CONFIG_CMD_BUTTON=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_ECHO=y ++CONFIG_CMD_ENV_READMEM=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_EXT4=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FDT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_CMD_FS_UUID=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_ITEST=y ++CONFIG_CMD_LED=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_LINK_LOCAL=y ++# CONFIG_CMD_MBR is not set ++CONFIG_CMD_MMC=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PCI=y ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_PWM=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_TFTPBOOT=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_CMD_UBIFS=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_SETEXPR=y ++CONFIG_CMD_SLEEP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_SOURCE=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_USB=y ++CONFIG_CMD_UUID=y ++CONFIG_DISPLAY_CPUINFO=y ++CONFIG_DM_MMC=y ++CONFIG_DM_MTD=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_DM_USB=y ++CONFIG_DM_PWM=y ++CONFIG_PWM_MTK=y ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_PARTITION_UUIDS=y ++CONFIG_NETCONSOLE=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DM_GPIO=y ++CONFIG_DM_SCSI=y ++CONFIG_AHCI=y ++CONFIG_AHCI_PCI=y ++CONFIG_SCSI_AHCI=y ++CONFIG_SCSI=y ++CONFIG_CMD_SCSI=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PHY_FIXED=y ++CONFIG_MTK_AHCI=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PCI=y ++CONFIG_MTD=y ++CONFIG_MTD_UBI_FASTMAP=y ++CONFIG_DM_PCI=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_MMC=y ++CONFIG_MMC_DEFAULT_DEV=1 ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_MMC_SUPPORTS_TUNING=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPI_NAND=y ++CONFIG_MTK_SPI_NAND_MTD=y ++CONFIG_SYSRESET_WATCHDOG=y ++CONFIG_WDT_MTK=y ++CONFIG_LZO=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_RANDOM_UUID=y ++CONFIG_REGEX=y ++CONFIG_USB=y ++CONFIG_USB_HOST=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_ENV_OFFSET=0x400000 ++CONFIG_ENV_OFFSET_REDUND=0x440000 ++CONFIG_ENV_SIZE=0x40000 ++CONFIG_ENV_SIZE_REDUND=0x40000 ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_HEXDUMP=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTK_SPIM=y ++#CONFIG_MTK_SNOR=y ++CONFIG_DM_SPI_FLASH=y ++CONFIG_SPI_FLASH_MTD=y ++CONFIG_SPI_FLASH_WINBOND=y ++# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set ++CONFIG_CMD_MTD=y ++CONFIG_CMD_SF=y ++CONFIG_CMD_NAND=y ++CONFIG_CMD_NAND_TRIMFFS=y ++# CONFIG_ENABLE_NAND_NMBM is not set +--- /dev/null ++++ b/configs/mt7986a_bpi-r3-nor_defconfig +@@ -0,0 +1,193 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TARGET_MT7986=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-bpi-r3-emmc" ++CONFIG_DEFAULT_ENV_FILE="bananapi_bpi-r3_nor_env" ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7986a-bpi-r3-emmc.dtb" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SMBIOS_PRODUCT_NAME="" ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_CFB_CONSOLE_ANSI=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_GPIO_HOG=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_FIT=y ++CONFIG_FIT_ENABLE_SHA256_SUPPORT=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_BOOTP=y ++CONFIG_CMD_BUTTON=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_ECHO=y ++CONFIG_CMD_ENV_READMEM=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_EXT4=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FDT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_CMD_FS_UUID=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_ITEST=y ++CONFIG_CMD_LED=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_LINK_LOCAL=y ++# CONFIG_CMD_MBR is not set ++CONFIG_CMD_MMC=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PCI=y ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_PWM=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_TFTPBOOT=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_CMD_UBIFS=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_SETEXPR=y ++CONFIG_CMD_SLEEP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_SOURCE=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_USB=y ++CONFIG_CMD_UUID=y ++CONFIG_DISPLAY_CPUINFO=y ++CONFIG_DM_MMC=y ++CONFIG_DM_MTD=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_DM_USB=y ++CONFIG_DM_PWM=y ++CONFIG_PWM_MTK=y ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_PARTITION_UUIDS=y ++CONFIG_NETCONSOLE=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DM_GPIO=y ++CONFIG_DM_SCSI=y ++CONFIG_AHCI=y ++CONFIG_AHCI_PCI=y ++CONFIG_SCSI_AHCI=y ++CONFIG_SCSI=y ++CONFIG_CMD_SCSI=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PHY_FIXED=y ++CONFIG_MTK_AHCI=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PCI=y ++CONFIG_MTD=y ++CONFIG_MTD_UBI_FASTMAP=y ++CONFIG_DM_PCI=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_MMC=y ++CONFIG_MMC_DEFAULT_DEV=1 ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_MMC_SUPPORTS_TUNING=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPI_NAND=y ++CONFIG_MTK_SPI_NAND_MTD=y ++CONFIG_SYSRESET_WATCHDOG=y ++CONFIG_WDT_MTK=y ++CONFIG_LZO=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_RANDOM_UUID=y ++CONFIG_REGEX=y ++CONFIG_USB=y ++CONFIG_USB_HOST=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MTD=y ++CONFIG_ENV_MTD_NAME="u-boot-env" ++CONFIG_ENV_OFFSET=0x0 ++CONFIG_ENV_OFFSET_REDUND=0x20000 ++CONFIG_ENV_SIZE=0x20000 ++CONFIG_ENV_SIZE_REDUND=0x20000 ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_HEXDUMP=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++#CONFIG_MTD_SPI_NAND=y ++CONFIG_MTK_SPIM=y ++#CONFIG_MTK_SNOR=y ++CONFIG_DM_SPI_FLASH=y ++CONFIG_SPI_FLASH_MTD=y ++CONFIG_SPI_FLASH_WINBOND=y ++# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set ++CONFIG_CMD_MTD=y ++CONFIG_CMD_SF=y ++#CONFIG_CMD_NAND=y ++#CONFIG_CMD_NAND_TRIMFFS=y ++# CONFIG_ENABLE_NAND_NMBM is not set +--- /dev/null ++++ b/configs/mt7986a_bpi-r3-sd_defconfig +@@ -0,0 +1,192 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TARGET_MT7986=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-bpi-r3-sd" ++CONFIG_DEFAULT_ENV_FILE="bananapi_bpi-r3_sdmmc_env" ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7986a-bpi-r3-sd.dtb" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SMBIOS_PRODUCT_NAME="" ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_CFB_CONSOLE_ANSI=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_GPIO_HOG=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_FIT=y ++CONFIG_FIT_ENABLE_SHA256_SUPPORT=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_BOOTP=y ++CONFIG_CMD_BUTTON=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_ECHO=y ++CONFIG_CMD_ENV_READMEM=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_EXT4=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FDT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_CMD_FS_UUID=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_ITEST=y ++CONFIG_CMD_LED=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_LINK_LOCAL=y ++# CONFIG_CMD_MBR is not set ++CONFIG_CMD_MMC=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PCI=y ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_PWM=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_TFTPBOOT=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_CMD_UBIFS=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_SETEXPR=y ++CONFIG_CMD_SLEEP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_SOURCE=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_USB=y ++CONFIG_CMD_UUID=y ++CONFIG_DISPLAY_CPUINFO=y ++CONFIG_DM_MMC=y ++CONFIG_DM_MTD=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_DM_USB=y ++CONFIG_DM_PWM=y ++CONFIG_PWM_MTK=y ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_PARTITION_UUIDS=y ++CONFIG_NETCONSOLE=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DM_GPIO=y ++CONFIG_DM_SCSI=y ++CONFIG_AHCI=y ++CONFIG_AHCI_PCI=y ++CONFIG_SCSI_AHCI=y ++CONFIG_SCSI=y ++CONFIG_CMD_SCSI=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PHY_FIXED=y ++CONFIG_MTK_AHCI=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PCI=y ++CONFIG_MTD=y ++CONFIG_MTD_UBI_FASTMAP=y ++CONFIG_DM_PCI=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_MMC=y ++CONFIG_MMC_DEFAULT_DEV=1 ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_MMC_SUPPORTS_TUNING=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPI_NAND=y ++CONFIG_MTK_SPI_NAND_MTD=y ++CONFIG_SYSRESET_WATCHDOG=y ++CONFIG_WDT_MTK=y ++CONFIG_LZO=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_RANDOM_UUID=y ++CONFIG_REGEX=y ++CONFIG_USB=y ++CONFIG_USB_HOST=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_ENV_OFFSET=0x400000 ++CONFIG_ENV_OFFSET_REDUND=0x440000 ++CONFIG_ENV_SIZE=0x40000 ++CONFIG_ENV_SIZE_REDUND=0x40000 ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_HEXDUMP=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTK_SPIM=y ++#CONFIG_MTK_SNOR=y ++CONFIG_DM_SPI_FLASH=y ++CONFIG_SPI_FLASH_MTD=y ++CONFIG_SPI_FLASH_WINBOND=y ++# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set ++CONFIG_CMD_MTD=y ++CONFIG_CMD_SF=y ++CONFIG_CMD_NAND=y ++CONFIG_CMD_NAND_TRIMFFS=y ++# CONFIG_ENABLE_NAND_NMBM is not set +--- /dev/null ++++ b/configs/mt7986a_bpi-r3-snand_defconfig +@@ -0,0 +1,193 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TARGET_MT7986=y ++CONFIG_SYS_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-bpi-r3-emmc" ++CONFIG_DEFAULT_ENV_FILE="bananapi_bpi-r3_snand_env" ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7986a-bpi-r3-emmc.dtb" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SMBIOS_PRODUCT_NAME="" ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_CFB_CONSOLE_ANSI=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_GPIO_HOG=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_FIT=y ++CONFIG_FIT_ENABLE_SHA256_SUPPORT=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_BOOTP=y ++CONFIG_CMD_BUTTON=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_ECHO=y ++CONFIG_CMD_ENV_READMEM=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_EXT4=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FDT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_CMD_FS_UUID=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_ITEST=y ++CONFIG_CMD_LED=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_LINK_LOCAL=y ++# CONFIG_CMD_MBR is not set ++CONFIG_CMD_MMC=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PCI=y ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_PWM=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_TFTPBOOT=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_CMD_UBIFS=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_SETEXPR=y ++CONFIG_CMD_SLEEP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_SOURCE=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_USB=y ++CONFIG_CMD_UUID=y ++CONFIG_DISPLAY_CPUINFO=y ++CONFIG_DM_MMC=y ++CONFIG_DM_MTD=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_DM_USB=y ++CONFIG_DM_PWM=y ++CONFIG_PWM_MTK=y ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_PARTITION_UUIDS=y ++CONFIG_NETCONSOLE=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DM_GPIO=y ++CONFIG_DM_SCSI=y ++CONFIG_AHCI=y ++CONFIG_AHCI_PCI=y ++CONFIG_SCSI_AHCI=y ++CONFIG_SCSI=y ++CONFIG_CMD_SCSI=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PHY_FIXED=y ++CONFIG_MTK_AHCI=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PCI=y ++CONFIG_MTD=y ++CONFIG_MTD_UBI_FASTMAP=y ++CONFIG_DM_PCI=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_MMC=y ++CONFIG_MMC_DEFAULT_DEV=1 ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_MMC_SUPPORTS_TUNING=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPI_NAND=y ++CONFIG_MTK_SPI_NAND_MTD=y ++CONFIG_SYSRESET_WATCHDOG=y ++CONFIG_WDT_MTK=y ++CONFIG_LZO=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_RANDOM_UUID=y ++CONFIG_REGEX=y ++CONFIG_USB=y ++CONFIG_USB_HOST=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_UBI=y ++CONFIG_ENV_UBI_PART="ubi" ++CONFIG_ENV_SIZE=0x1f000 ++CONFIG_ENV_SIZE_REDUND=0x1f000 ++CONFIG_ENV_UBI_VOLUME="ubootenv" ++CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_HEXDUMP=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTK_SPIM=y ++#CONFIG_MTK_SNOR=y ++#CONFIG_DM_SPI_FLASH=y ++#CONFIG_SPI_FLASH_MTD=y ++#CONFIG_SPI_FLASH_WINBOND=y ++# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set ++CONFIG_CMD_MTD=y ++#CONFIG_CMD_SF=y ++CONFIG_CMD_NAND=y ++CONFIG_CMD_NAND_TRIMFFS=y ++# CONFIG_ENABLE_NAND_NMBM is not set +--- /dev/null ++++ b/arch/arm/dts/mt7986a-bpi-r3-emmc.dts +@@ -0,0 +1,33 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986a-bpi-r3-sd.dts" ++#include ++/ { ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <8>; ++ max-frequency = <200000000>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++ non-removable; ++ status = "okay"; ++}; ++ +--- /dev/null ++++ b/arch/arm/dts/mt7986a-bpi-r3-sd.dts +@@ -0,0 +1,269 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2021 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7986.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "BananaPi BPi-R3"; ++ compatible = "mediatek,mt7986", "mediatek,mt7986-sd-rfb"; ++ ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ ++ factory { ++ label = "reset"; ++ gpios = <&gpio 9 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wps { ++ label = "wps"; ++ gpios = <&gpio 10 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_status_green: green { ++ label = "green:status"; ++ gpios = <&gpio 69 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ led_status_blue: blue { ++ label = "blue:status"; ++ gpios = <&gpio 86 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "disabled"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "sgmii"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_2"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ pwm_pins: pwm0-pins-func-1 { ++ mux { ++ function = "pwm"; ++ groups = "pwm0"; ++ }; ++ }; ++ ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_51"; ++ }; ++ ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-dsl { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; ++ }; ++ ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++ ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pins>; ++ status = "okay"; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <1>; ++ sample_sel = <0>; ++ ++ spi_nor@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x40000>; ++ }; ++ ++ partition@40000 { ++ label = "u-boot-env"; ++ reg = <0x40000 0x40000>; ++ }; ++ ++ partition@80000 { ++ label = "reserved"; ++ reg = <0x80000 0x80000>; ++ }; ++ ++ partition@100000 { ++ label = "fip"; ++ reg = <0x100000 0x80000>; ++ }; ++ ++ partition@180000 { ++ label = "recovery"; ++ reg = <0x180000 0xa80000>; ++ }; ++ ++ partition@c00000 { ++ label = "fit"; ++ reg = <0xc00000 0x1400000>; ++ }; ++ }; ++ }; ++ ++ spi_nand@1 { ++ compatible = "spi-nand"; ++ reg = <1>; ++ spi-max-frequency = <52000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x80000>; ++ }; ++ ++ partition@80000 { ++ label = "factory"; ++ reg = <0x80000 0x300000>; ++ }; ++ ++ partition@380000 { ++ label = "fip"; ++ reg = <0x380000 0x200000>; ++ }; ++ ++ partition@580000 { ++ label = "ubi"; ++ reg = <0x580000 0x7a80000>; ++ }; ++ }; ++ }; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ bus-width = <4>; ++ max-frequency = <52000000>; ++ cap-sd-highspeed; ++ r_smpl = <1>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_3p3v>; ++ status = "okay"; ++}; ++ +--- /dev/null ++++ b/bananapi_bpi-r3_sdmmc_env +@@ -0,0 +1,75 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=root=/dev/mmcblk0p65 ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_sdmmc ; fi ++bootconf=config-mt7986a-bananapi-bpi-r3 ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb ++bootfile_upg=openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb ++bootled_pwr=green:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) [SD card] ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from SD card.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from SD card.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to SD card.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to SD card.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Install bootloader, recovery and production to NOR.=if sf probe ; then run nor_init ; else echo "NOR not detected" ; fi ; run bootmenu_confirm_return ++bootmenu_7=Install bootloader, recovery and production to NAND.=if nand info ; then run ubi_init ; else echo "NAND not detected" ; fi ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_update_conf=if nand info ; then setenv bootconf config-mt7986a-bananapi-bpi-r3-snand ; else if sf probe ; then setenv bootconf config-mt7986a-bananapi-bpi-r3-nor ; else setenv bootconf config-mt7986a-bananapi-bpi-r3 ; fi ; fi ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=led $bootled_pwr on ; run boot_update_conf ; run sdmmc_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=led $bootled_rec on ; run boot_update_conf ; run sdmmc_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_sdmmc=run boot_production ; run boot_recovery ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_production=run boot_update_conf ; tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run sdmmc_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=run boot_update_conf ; tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run sdmmc_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp=run boot_update_conf ; tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++mmc_write_vol=imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc erase 0x$part_addr 0x$part_size && mmc write $loadaddr 0x$part_addr 0x$image_size ++mmc_read_vol=mmc read $loadaddr $part_addr 0x8 && imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc read $loadaddr 0x$part_addr 0x$image_size && setexpr filesize $image_size * 0x200 ++part_default=production ++part_recovery=recovery ++reset_factory=eraseenv && reset ++sdmmc_read_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_read_vol ++sdmmc_read_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_read_vol ++sdmmc_read_snand_bl2=part start mmc 0 install part_addr && mmc read $loadaddr $part_addr 0x400 ++sdmmc_read_snand_fip=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x800 && mmc read $loadaddr $offset 0x1000 ++sdmmc_read_nor_bl2=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x2800 && mmc read $loadaddr $offset 0x400 ++sdmmc_read_nor_fip=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x3000 && mmc read $loadaddr $offset 0x1000 ++sdmmc_read_emmc_install=part start mmc 0 install part_addr && setexpr offset $part_addr + 0x3800 && mmc read $loadaddr $offset 0x4000 ++sdmmc_write_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_write_vol ++sdmmc_write_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_write_vol ++mtd_write_fip=mtd erase fip && mtd write fip $loadaddr ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++nor_pad_size=imsz $loadaddr image_size ; setexpr image_eb 0x$image_size / 0x10000 ; setexpr tmp1 0x$image_size % 0x10000 ; test 0x$tmp1 -gt 0 && setexpr image_eb 0x$image_eb + 1 ; setexpr image_eb $image_eb * 0x10000 ++nor_erase_env=mtd erase u-boot-env ++nor_write_production=run nor_pad_size ; test 0x$image_eb -le 0x3000000 && mtd erase fit && mtd write fit $loadaddr 0x0 $image_eb ++nor_write_recovery=run nor_pad_size ; test 0x$image_eb -le 0x900000 && mtd erase recovery 0x0 0x$image_eb && mtd write recovery $loadaddr 0x0 $image_eb ++nor_init=run nor_init_bl && run nor_init_openwrt ++nor_init_bl=run sdmmc_read_nor_bl2 && run mtd_write_bl2 && run sdmmc_read_nor_fip && run mtd_write_fip && run nor_erase_env ++nor_init_openwrt=run sdmmc_read_recovery && iminfo $loadaddr && run nor_write_recovery ; run sdmmc_read_production && iminfo $loadaddr && run nor_write_production ++ubi_create_env=ubi create ubootenv 0x100000 dynamic 0 ; ubi create ubootenv2 0x100000 dynamic 1 ++ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ++ubi_init=run ubi_init_bl && run ubi_format && run ubi_create_env && run ubi_init_openwrt && run ubi_init_emmc_install ++ubi_init_openwrt=run sdmmc_read_recovery && iminfo $loadaddr && run ubi_write_recovery ; run sdmmc_read_production && iminfo $loadaddr && run ubi_write_production ++ubi_init_bl=run sdmmc_read_snand_bl2 && run mtd_write_bl2 && run sdmmc_read_snand_fip && run mtd_write_fip ++ubi_init_emmc_install=run sdmmc_read_emmc_install && run ubi_write_emmc_install ++ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi ++ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data ++ubi_write_emmc_install=ubi check emmc_install && ubi remote emmc_install ; ubi create emmc_install 0x800000 dynamic ; ubi write $loadaddr emmc_install 0x800000 ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic 2 && ubi write $loadaddr fit $filesize ++ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic 3 && ubi write $loadaddr recovery $filesize ++_init_env=setenv _init_env ; setenv _create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" +--- /dev/null ++++ b/bananapi_bpi-r3_nor_env +@@ -0,0 +1,55 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=root=/dev/mtdblock0p1 ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_nor ; fi ++bootconf=config-mt7986a-bananapi-bpi-r3-emmc-nor ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-bananapi_bpi-r3-nor-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-bananapi_bpi-r3-nor-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb ++bootled_pwr=green:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) [SPI-NOR] ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from flash.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from flash.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to flash.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to flash.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to flash.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to flash.=run boot_tftp_write_preloader ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=run boot_update_conf ; led $bootled_pwr on ; run nor_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=run boot_update_conf ; led $bootled_rec on ; run nor_read_recovery ; bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_serial_write_fip=loadx $loadaddr 115200 && run boot_write_fip ++boot_serial_write_preloader=loadx $loadaddr 115200 && run boot_write_preloader ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_production=run boot_update_conf ; tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run nor_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=run boot_update_conf ; tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run nor_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp=run boot_update_conf ; tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run boot_write_fip ++boot_tftp_write_preloader=tftpboot $loadaddr $bootfile_bl2 && run boot_write_preloader ++boot_update_conf=if mmc partconf 0 ; then setenv bootconf config-mt7986a-bananapi-bpi-r3-emmc-nor ; else setenv bootconf config-mt7986a-bananapi-bpi-r3-nor ; fi ++boot_nor=run boot_production ; run boot_recovery ++boot_write_fip=mtd erase fip && mtd write fip $loadaddr ++boot_write_preloader=mtd erase bl2 && mtd write bl2 $loadaddr ++reset_factory=mtd erase u-boot-env ++nor_read_production=mtd read fit $loadaddr 0x0 0x1000 && imsz $loadaddr image_size && mtd read fit $loadaddr 0x0 $image_size ++nor_read_recovery=mtd read recovery $loadaddr 0x0 0x1000 && imsz $loadaddr image_size && mtd read recovery $loadaddr 0x0 $image_size ++nor_pad_size=imsz $loadaddr image_size ; setexpr image_eb 0x$image_size / 0x10000 ; setexpr tmp1 0x$image_size % 0x10000 ; test 0x$tmp1 -gt 0 && setexpr image_eb 0x$image_eb + 1 ; setexpr image_eb $image_eb * 0x10000 ++nor_write_production=run nor_pad_size ; test 0x$image_eb -le 0x3000000 && mtd erase fit && mtd write fit $loadaddr 0x0 $image_eb ++nor_write_recovery=run nor_pad_size ; test 0x$image_eb -le 0x900000 && mtd erase recovery 0x0 0x$image_eb && mtd write recovery $loadaddr 0x0 $image_eb ++_init_env=setenv _init_env ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" +--- /dev/null ++++ b/bananapi_bpi-r3_snand_env +@@ -0,0 +1,69 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=root=/dev/ubiblock0_2p1 ++bootconf=config-mt7986a-bananapi-bpi-r3-snand ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-bananapi_bpi-r3-snand-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-bananapi_bpi-r3-snand-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb ++bootled_pwr=green:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) [SPI-NAND] ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from NAND.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from NAND.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to NAND.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to NAND.=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_8=Install bootloader, recovery and production to eMMC.=if mmc partconf 0 ; then run emmc_init ; else echo "eMMC not detected" ; fi ; run bootmenu_confirm_return ++bootmenu_9=Reboot.=reset ++bootmenu_10=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=run boot_update_conf ; led $bootled_pwr on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=run boot_update_conf ; led $bootled_rec on ; run ubi_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_ubi=run boot_update_conf ; run boot_production ; run boot_recovery ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_production=run boot_update_conf ; tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run ubi_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=run boot_update_conf ; tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run ubi_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp=run boot_update_conf ; tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run mtd_write_fip && run reset_factory ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run mtd_write_bl2 ++boot_update_conf=if mmc partconf 0 ; then setenv bootconf config-mt7986a-bananapi-bpi-r3-emmc-snand ; else setenv bootconf config-mt7986a-bananapi-bpi-r3-snand ; fi ++part_default=production ++part_recovery=recovery ++reset_factory=ubi part ubi ; mw $loadaddr 0x0 0x800 ; ubi write $loadaddr ubootenv 0x800 ; ubi write $loadaddr ubootenv2 0x800 ++mtd_write_fip=mtd erase fip && mtd write fip $loadaddr ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x100000 dynamic 0 ; ubi check ubootenv2 || ubi create ubootenv2 0x100000 dynamic 1 ++ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset ++ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi ++ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs ++ubi_read_recovery=ubi check recovery && ubi read $loadaddr recovery ++ubi_read_emmc_install=ubi check emmc_install && ubi read $loadaddr emmc_install ++ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic 2 && ubi write $loadaddr fit $filesize ++ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic 3 && ubi write $loadaddr recovery $filesize ++mmc_write_vol=imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc erase 0x$part_addr 0x$part_size && mmc write $loadaddr 0x$part_addr 0x$image_size ++emmc_init=mmc dev 0 && mmc bootbus 0 0 0 0 && run emmc_init_bl && run emmc_init_openwrt ; env default bootcmd ; saveenv ; saveenv ++emmc_init_bl=run ubi_read_emmc_install && setenv fileaddr $loadaddr && run emmc_write_bl2 && setexpr fileaddr $loadaddr + 0x100000 && run emmc_write_fip && setexpr fileaddr $loadaddr + 0x500000 && run emmc_write_hdr ++emmc_init_openwrt=run ubi_read_recovery && iminfo $loadaddr && run emmc_write_recovery ; run ubi_read_production && iminfo $loadaddr && run emmc_write_production ++emmc_write_bl2=mmc partconf 0 1 1 1 && mmc erase 0x0 0x400 && mmc write $fileaddr 0x0 0x400 ; mmc partconf 0 1 1 0 ++emmc_write_fip=mmc erase 0x3400 0x2000 && mmc write $fileaddr 0x3400 0x2000 && mmc erase 0x2000 0x800 ++emmc_write_hdr=mmc erase 0x0 0x40 && mmc write $fileaddr 0x0 0x40 ++emmc_write_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_write_vol ++emmc_write_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_write_vol ++_init_env=setenv _init_env ; run ubi_create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" +--- /dev/null ++++ b/bananapi_bpi-r3_emmc_env +@@ -0,0 +1,56 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=root=/dev/mmcblk0p65 ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_emmc ; fi ++bootconf=config-mt7986a-bananapi-bpi-r3-emmc ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-bananapi_bpi-r3-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-bananapi_bpi-r3-emmc-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-bananapi_bpi-r3-emmc-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-bananapi_bpi-r3-squashfs-sysupgrade.itb ++bootled_pwr=green:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) [eMMC] ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from eMMC.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from eMMC.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to eMMC.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to eMMC.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to eMMC.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to eMMC.=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=run boot_update_conf ; led $bootled_pwr on ; run emmc_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=run boot_update_conf ; led $bootled_rec on ; run emmc_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_emmc=run boot_update_conf ; run boot_production ; run boot_recovery ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_production=run boot_update_conf ; tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run emmc_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=run boot_update_conf ; tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run emmc_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run emmc_write_fip ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run emmc_write_bl2 ++boot_tftp=run boot_update_conf ; tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_update_conf=if nand info ; then setenv bootconf config-mt7986a-bananapi-bpi-r3-emmc-snand ; else setenv bootconf config-mt7986a-bananapi-bpi-r3-emmc-nor ; fi ++mmc_write_vol=imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc erase 0x$part_addr 0x$part_size && mmc write $loadaddr 0x$part_addr 0x$image_size ++mmc_read_vol=mmc read $loadaddr $part_addr 0x8 && imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc read $loadaddr 0x$part_addr 0x$image_size && setexpr filesize $image_size * 0x200 ++part_default=production ++part_recovery=recovery ++reset_factory=eraseenv && reset ++emmc_read_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_read_vol ++emmc_read_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_read_vol ++emmc_write_bl2=mmc partconf 0 1 1 1 && mmc erase 0x0 0x400 && mmc write $fileaddr 0x0 0x400 ; mmc partconf 0 1 1 0 ++emmc_write_fip=mmc erase 0x3400 0x2000 && mmc write $fileaddr 0x3400 0x2000 && mmc erase 0x2000 0x800 ++emmc_write_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_write_vol ++emmc_write_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_write_vol ++_init_env=setenv _init_env ; setenv _create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" diff --git a/package/devel/strace/Makefile b/package/devel/strace/Makefile index bfa79490f8..9d9db65c17 100644 --- a/package/devel/strace/Makefile +++ b/package/devel/strace/Makefile @@ -9,12 +9,12 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=strace -PKG_VERSION:=5.18 -PKG_RELEASE:=2 +PKG_VERSION:=5.19 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://strace.io/files/$(PKG_VERSION) -PKG_HASH:=60293ea79ac9253d600cdc9be077ad2988ca22284a439c9e66be5150db3d1187 +PKG_HASH:=aa3dc1c8e60e4f6ff3d396514aa247f3c7bf719d8a8dc4dd4fa793be786beca3 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=LGPL-2.1-or-later diff --git a/package/kernel/lantiq/ltq-vdsl-fw/src/vdsl_fw_install.sh b/package/kernel/lantiq/ltq-vdsl-fw/src/vdsl_fw_install.sh index baf230ac75..c5574ffca2 100755 --- a/package/kernel/lantiq/ltq-vdsl-fw/src/vdsl_fw_install.sh +++ b/package/kernel/lantiq/ltq-vdsl-fw/src/vdsl_fw_install.sh @@ -1,5 +1,5 @@ #!/bin/sh -FW="/tmp/firmware-speedport-w921v-1.46.000.bin" +FW="/tmp/firmware-speedport-w921v-1.48.000.bin" URL="https://www.telekom.de/hilfe/downloads/firmware-speedport-w-921v-1.48.000.bin" FW_TAPI="vr9_tapi_fw.bin" FW_DSL="vr9_dsl_fw_annex_b.bin" diff --git a/package/kernel/lantiq/ltq-vdsl-fw/src/w921v_fw_cutter.c b/package/kernel/lantiq/ltq-vdsl-fw/src/w921v_fw_cutter.c index 5f47daabed..92c4be165d 100644 --- a/package/kernel/lantiq/ltq-vdsl-fw/src/w921v_fw_cutter.c +++ b/package/kernel/lantiq/ltq-vdsl-fw/src/w921v_fw_cutter.c @@ -26,7 +26,7 @@ #include "LzmaWrapper.h" -#define FW_NAME "/tmp/firmware-speedport-w-921v-1.48.000.bin" +#define FW_NAME "/tmp/firmware-speedport-w921v-1.48.000.bin" #define MAGIC 0x50 #define MAGIC_SZ 0x3FFC00 diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index 72ed6ca2fd..a5b018aa1e 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -407,8 +407,9 @@ $(eval $(call KernelPackage,crypto-hw-padlock)) define KernelPackage/crypto-hw-safexcel TITLE:= MVEBU SafeXcel Crypto Engine module - DEPENDS:=@(TARGET_mvebu_cortexa53||TARGET_mvebu_cortexa72) +eip197-mini-firmware \ - +kmod-crypto-authenc +kmod-crypto-md5 +kmod-crypto-hmac +kmod-crypto-sha256 +kmod-crypto-sha512 + DEPENDS:=@(TARGET_mvebu_cortexa53||TARGET_mvebu_cortexa72||TARGET_mediatek_filogic||TARGET_mediatek_mt7623) \ + +eip197-mini-firmware +kmod-crypto-authenc +kmod-crypto-des +kmod-crypto-md5 +kmod-crypto-hmac \ + +kmod-crypto-sha1 +kmod-crypto-sha256 +kmod-crypto-sha512 KCONFIG:= \ CONFIG_CRYPTO_HW=y \ CONFIG_CRYPTO_DEV_SAFEXCEL diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 354449b810..ff58d27bc2 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2022-07-03 -PKG_SOURCE_VERSION:=93e3fce916c62d06892d41bf00d0f4c2926c9a0b -PKG_MIRROR_HASH:=ad966e7aa81301f0601ceb7aae2ecb471c452f5d8366f701add807152fd08971 +PKG_SOURCE_DATE:=2022-08-26 +PKG_SOURCE_VERSION:=5ec78e1ec43d1e39edfea1efb9fd4541fa004af0 +PKG_MIRROR_HASH:=b96ec5199d423dc27e4fe7f0e94c8d5970f6db812237816235f3b735a5cb216a PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 @@ -226,6 +226,12 @@ define KernelPackage/mt7915e AUTOLOAD:=$(call AutoProbe,mt7915e) endef +define KernelPackage/mt7986-firmware + $(KernelPackage/mt76-default) + DEPENDS:=@TARGET_mediatek_filogic + TITLE:=MediaTek MT7986 firmware +endef + define KernelPackage/mt7921-common $(KernelPackage/mt76-default) TITLE:=MediaTek MT7615 wireless driver common code @@ -343,6 +349,10 @@ ifdef CONFIG_PACKAGE_kmod-mt7663u endif ifdef CONFIG_PACKAGE_kmod-mt7915e PKG_MAKE_FLAGS += CONFIG_MT7915E=m + ifdef CONFIG_TARGET_mediatek_filogic + PKG_MAKE_FLAGS += CONFIG_MT7986_WMAC=y + NOSTDINC_FLAGS += -DCONFIG_MT7986_WMAC + endif endif ifdef CONFIG_PACKAGE_kmod-mt7921-common PKG_MAKE_FLAGS += CONFIG_MT7921_COMMON=m @@ -450,6 +460,19 @@ define KernelPackage/mt7915e/install $(1)/lib/firmware/mediatek endef +define KernelPackage/mt7986-firmware/install + $(INSTALL_DIR) $(1)/lib/firmware/mediatek + cp \ + $(PKG_BUILD_DIR)/firmware/mt7986_wa.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_wm_mt7975.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_wm.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_rom_patch_mt7975.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_rom_patch.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7975_dual.bin \ + $(PKG_BUILD_DIR)/firmware/mt7986_eeprom_mt7976_dual.bin \ + $(1)/lib/firmware/mediatek +endef + define KernelPackage/mt7921e/install $(INSTALL_DIR) $(1)/lib/firmware/mediatek cp \ @@ -485,6 +508,7 @@ $(eval $(call KernelPackage,mt7663-usb-sdio)) $(eval $(call KernelPackage,mt7663u)) $(eval $(call KernelPackage,mt7663s)) $(eval $(call KernelPackage,mt7915e)) +$(eval $(call KernelPackage,mt7986-firmware)) $(eval $(call KernelPackage,mt7921-common)) $(eval $(call KernelPackage,mt7921u)) $(eval $(call KernelPackage,mt7921s)) diff --git a/package/libs/libnftnl/Makefile b/package/libs/libnftnl/Makefile index 657ebd098d..93aae692d4 100644 --- a/package/libs/libnftnl/Makefile +++ b/package/libs/libnftnl/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libnftnl -PKG_VERSION:=1.2.2 +PKG_VERSION:=1.2.3 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files -PKG_HASH:=9efc004f9d15918d68f9e98e194d55e030168f33bb67c3e7a545b740c9ed6d0a +PKG_HASH:=e916ea9b79f9518560b9a187251a7c042442a9ecbce7f36be7908888605d0255 PKG_MAINTAINER:=Steven Barth PKG_LICENSE:=GPL-2.0-or-later diff --git a/package/libs/mbedtls/Makefile b/package/libs/mbedtls/Makefile index 7897142a99..e1900fcb58 100644 --- a/package/libs/mbedtls/Makefile +++ b/package/libs/mbedtls/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mbedtls -PKG_VERSION:=2.28.0 +PKG_VERSION:=2.28.1 PKG_RELEASE:=$(AUTORELEASE) PKG_USE_MIPS16:=0 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/ARMmbed/mbedtls/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=6519579b836ed78cc549375c7c18b111df5717e86ca0eeff4cb64b2674f424cc +PKG_HASH:=6797a7b6483ef589deeab8d33d401ed235d7be25eeecda1be8ddfed406d40ff4 PKG_LICENSE:=GPL-2.0-or-later PKG_LICENSE_FILES:=gpl-2.0.txt diff --git a/package/libs/mbedtls/patches/100-fix-compile.patch b/package/libs/mbedtls/patches/100-fix-compile.patch new file mode 100644 index 0000000000..c3b26ac9c9 --- /dev/null +++ b/package/libs/mbedtls/patches/100-fix-compile.patch @@ -0,0 +1,22 @@ +Fix a compile problem introduced in commit 331c3421d1f0 ("Address review comments") + +Bug report: https://github.com/Mbed-TLS/mbedtls/issues/6243 + +--- a/programs/ssl/ssl_server2.c ++++ b/programs/ssl/ssl_server2.c +@@ -2511,7 +2511,6 @@ int main( int argc, char *argv[] ) + } + key_cert_init2 = 2; + #endif /* MBEDTLS_ECDSA_C */ +- } + + #if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.key_opaque != 0 ) +@@ -2540,6 +2539,7 @@ int main( int argc, char *argv[] ) + } + #endif /* MBEDTLS_USE_PSA_CRYPTO */ + #endif /* MBEDTLS_CERTS_C */ ++ } + + mbedtls_printf( " ok (key types: %s - %s)\n", mbedtls_pk_get_name( &pkey ), mbedtls_pk_get_name( &pkey2 ) ); + #endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/package/libs/mbedtls/patches/200-config.patch b/package/libs/mbedtls/patches/200-config.patch index faf5bb5db9..54d4cf431d 100644 --- a/package/libs/mbedtls/patches/200-config.patch +++ b/package/libs/mbedtls/patches/200-config.patch @@ -1,6 +1,6 @@ --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h -@@ -665,14 +665,14 @@ +@@ -670,14 +670,14 @@ * * Enable Output Feedback mode (OFB) for symmetric ciphers. */ @@ -17,7 +17,7 @@ /** * \def MBEDTLS_CIPHER_NULL_CIPHER -@@ -790,20 +790,20 @@ +@@ -795,20 +795,20 @@ * Comment macros to disable the curve and functions for it */ /* Short Weierstrass curves (supporting ECP, ECDH, ECDSA) */ @@ -47,7 +47,7 @@ /** * \def MBEDTLS_ECP_NIST_OPTIM -@@ -956,7 +956,7 @@ +@@ -961,7 +961,7 @@ * See dhm.h for more details. * */ @@ -56,7 +56,7 @@ /** * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED -@@ -976,7 +976,7 @@ +@@ -981,7 +981,7 @@ * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA */ @@ -65,7 +65,7 @@ /** * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED -@@ -1001,7 +1001,7 @@ +@@ -1006,7 +1006,7 @@ * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA */ @@ -74,7 +74,7 @@ /** * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -@@ -1135,7 +1135,7 @@ +@@ -1140,7 +1140,7 @@ * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 */ @@ -83,7 +83,7 @@ /** * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED -@@ -1159,7 +1159,7 @@ +@@ -1164,7 +1164,7 @@ * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 */ @@ -92,7 +92,7 @@ /** * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED -@@ -1263,7 +1263,7 @@ +@@ -1268,7 +1268,7 @@ * This option is only useful if both MBEDTLS_SHA256_C and * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. */ @@ -101,7 +101,7 @@ /** * \def MBEDTLS_ENTROPY_NV_SEED -@@ -1478,14 +1478,14 @@ +@@ -1483,14 +1483,14 @@ * Uncomment this macro to disable the use of CRT in RSA. * */ @@ -118,7 +118,7 @@ /** * \def MBEDTLS_SHA256_SMALLER -@@ -1756,7 +1756,7 @@ +@@ -1761,7 +1761,7 @@ * configuration of this extension). * */ @@ -127,7 +127,7 @@ /** * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO -@@ -2017,7 +2017,7 @@ +@@ -2022,7 +2022,7 @@ * * Comment this macro to disable support for truncated HMAC in SSL */ @@ -136,7 +136,7 @@ /** * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT -@@ -2185,7 +2185,7 @@ +@@ -2201,7 +2201,7 @@ * * Comment this to disable run-time checking and save ROM space */ @@ -145,7 +145,7 @@ /** * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 -@@ -2534,7 +2534,7 @@ +@@ -2550,7 +2550,7 @@ * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 */ @@ -154,7 +154,7 @@ /** * \def MBEDTLS_ARIA_C -@@ -2600,7 +2600,7 @@ +@@ -2616,7 +2616,7 @@ * This module enables the AES-CCM ciphersuites, if other requisites are * enabled as well. */ @@ -163,7 +163,7 @@ /** * \def MBEDTLS_CERTS_C -@@ -2612,7 +2612,7 @@ +@@ -2628,7 +2628,7 @@ * * This module is used for testing (ssl_client/server). */ @@ -172,7 +172,7 @@ /** * \def MBEDTLS_CHACHA20_C -@@ -2725,7 +2725,7 @@ +@@ -2741,7 +2741,7 @@ * \warning DES is considered a weak cipher and its use constitutes a * security risk. We recommend considering stronger ciphers instead. */ @@ -181,7 +181,7 @@ /** * \def MBEDTLS_DHM_C -@@ -2890,7 +2890,7 @@ +@@ -2906,7 +2906,7 @@ * This module adds support for the Hashed Message Authentication Code * (HMAC)-based key derivation function (HKDF). */ @@ -190,7 +190,7 @@ /** * \def MBEDTLS_HMAC_DRBG_C -@@ -3203,7 +3203,7 @@ +@@ -3219,7 +3219,7 @@ * * This module enables abstraction of common (libc) functions. */ @@ -199,7 +199,7 @@ /** * \def MBEDTLS_POLY1305_C -@@ -3279,7 +3279,7 @@ +@@ -3295,7 +3295,7 @@ * Caller: library/md.c * */ @@ -208,7 +208,7 @@ /** * \def MBEDTLS_RSA_C -@@ -3486,7 +3486,7 @@ +@@ -3506,7 +3506,7 @@ * * This module provides run-time version information. */ @@ -217,12 +217,12 @@ /** * \def MBEDTLS_X509_USE_C -@@ -3596,7 +3596,7 @@ +@@ -3616,7 +3616,7 @@ * Module: library/xtea.c * Caller: */ -#define MBEDTLS_XTEA_C +//#define MBEDTLS_XTEA_C - /* \} name SECTION: mbed TLS modules */ + /** \} name SECTION: mbed TLS modules */ diff --git a/package/libs/popt/Makefile b/package/libs/popt/Makefile index 34ae4d7c61..5b8b870111 100644 --- a/package/libs/popt/Makefile +++ b/package/libs/popt/Makefile @@ -8,15 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=popt -PKG_VERSION:=1.16 -PKG_RELEASE:=2 +PKG_VERSION:=1.18 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:= \ - http://distfiles.gentoo.org/distfiles/ \ - http://distcache.freebsd.org/ports-distfiles/ \ - http://rpm5.org/files/popt/ -PKG_HASH:=e728ed296fe9f069a0e005003c3d6b2dde3d9cad453422a10d6558616d304cc8 +PKG_SOURCE_URL:=http://ftp.rpm.org/popt/releases/popt-1.x/ +PKG_HASH:=5159bc03a20b28ce363aa96765f37df99ea4d8850b1ece17d1e6ad5c24fdc5d1 PKG_LICENSE:=MIT PKG_FIXUP:=autoreconf @@ -33,7 +30,7 @@ define Package/libpopt SECTION:=libs CATEGORY:=Libraries TITLE:=A command line option parsing library - URL:=http://rpm5.org/files/popt/ + URL:=https://github.com/rpm-software-management/popt ABI_VERSION:=0 endef diff --git a/package/libs/wolfssl/Makefile b/package/libs/wolfssl/Makefile index b0e100673c..4554bce5df 100644 --- a/package/libs/wolfssl/Makefile +++ b/package/libs/wolfssl/Makefile @@ -25,6 +25,7 @@ PKG_MAINTAINER:=Eneas U de Queiroz PKG_CPE_ID:=cpe:/a:wolfssl:wolfssl PKG_CONFIG_DEPENDS:=\ + CONFIG_PACKAGE_libwolfssl-benchmark \ CONFIG_WOLFSSL_HAS_AES_CCM \ CONFIG_WOLFSSL_HAS_ARC4 \ CONFIG_WOLFSSL_HAS_CERTGEN \ diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index ed451518f2..488b9db2b0 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2022-08-19 -PKG_SOURCE_VERSION:=bfa039c414bc6613cc5361aaf5fa6baf5fa0264b -PKG_MIRROR_HASH:=f2fef3b61ffeecb116f63a4d53838d1d754f7c52750fd30e3304d26aa578d778 +PKG_SOURCE_DATE:=2022-08-25 +PKG_SOURCE_VERSION:=76d2d41b7355e02f95fbfa79affbd232fb090595 +PKG_MIRROR_HASH:=cd754decce7d9f9c69e0ad8c6801f306fa37dd6c8a7039aea610c1c71d06b8f9 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 97ffcda43f..22dca6cef7 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -892,7 +892,7 @@ hostapd_set_bss_options() { json_get_vars mobility_domain ft_psk_generate_local ft_over_ds reassociation_deadline set_default mobility_domain "$(echo "$ssid" | md5sum | head -c 4)" - set_default ft_over_ds 1 + set_default ft_over_ds 0 set_default reassociation_deadline 1000 case "$auth_type" in diff --git a/package/network/services/unetd/Makefile b/package/network/services/unetd/Makefile new file mode 100644 index 0000000000..f692f26974 --- /dev/null +++ b/package/network/services/unetd/Makefile @@ -0,0 +1,97 @@ +# +# Copyright (C) 2022 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=unetd +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=$(PROJECT_GIT)/project/unetd.git +PKG_SOURCE_DATE:=2022-08-29 +PKG_SOURCE_VERSION:=0041fcacb62492653a1054098ec7d811d8eaacbf +PKG_MIRROR_HASH:=1aad05af0c4015dc7c07936e504a2c03ceacf676c5c15902c2049a63fab60428 + +PKG_LICENSE:=GPL-2.0 +PKG_MAINTAINER:=Felix Fietkau + +PKG_BUILD_DEPENDS:=bpf-headers + +PKG_BUILD_PARALLEL:=1 + +PKG_CONFIG_DEPENDS += CONFIG_UNETD_VXLAN_SUPPORT + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk +include $(INCLUDE_DIR)/bpf.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/unetd + SECTION:=net + CATEGORY:=Network + TITLE:=WireGuard based VPN connection manager for OpenWrt + DEPENDS:=+libubox +libubus +libblobmsg-json +libnl-tiny +kmod-wireguard +UNETD_VXLAN_SUPPORT:libbpf +endef + +define Package/unetd/config + config UNETD_VXLAN_SUPPORT + bool "VXLAN support" + depends on PACKAGE_unetd + depends on HAS_BPF_TOOLCHAIN + default y + +endef + +define Package/unet-cli + SECTION:=net + CATEGORY:=Network + DEPENDS:=unetd +ucode +ucode-mod-fs + TITLE:=unetd administration command line utility +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include/libnl-tiny \ + -I$(STAGING_DIR)/usr/include + +CMAKE_OPTIONS += \ + -DLIBNL_LIBS=-lnl-tiny \ + -DVXLAN_SUPPORT=$(if $(CONFIG_UNETD_VXLAN_SUPPORT),ON,OFF) + +ifdef CONFIG_UNETD_VXLAN_SUPPORT + define Build/Compile + $(call CompileBPF,$(PKG_BUILD_DIR)/mss-bpf.c) + $(call Build/Compile/Default,) + endef +endif + +define Package/unetd/conffiles +/etc/unetd +endef + +define Package/unetd/install + $(INSTALL_DIR) \ + $(1)/etc/unetd \ + $(1)/lib/bpf \ + $(1)/etc/init.d \ + $(1)/lib/netifd/proto \ + $(1)/usr/sbin \ + $(1)/usr/lib + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libunet.so* $(1)/usr/lib/ + $(INSTALL_BIN) \ + $(PKG_INSTALL_DIR)/usr/sbin/unetd \ + $(PKG_INSTALL_DIR)/usr/sbin/unet-tool \ + $(1)/usr/sbin/ + $(if $(CONFIG_UNETD_VXLAN_SUPPORT),$(INSTALL_DATA) $(PKG_BUILD_DIR)/mss-bpf.o $(1)/lib/bpf/mss.o) + $(INSTALL_BIN) ./files/unetd.init $(1)/etc/init.d/unetd + $(INSTALL_BIN) ./files/unetd.sh $(1)/lib/netifd/proto +endef + +define Package/unet-cli/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/scripts/unet-cli $(1)/usr/sbin +endef + +$(eval $(call BuildPackage,unetd)) +$(eval $(call BuildPackage,unet-cli)) diff --git a/package/network/services/unetd/files/unetd.init b/package/network/services/unetd/files/unetd.init new file mode 100644 index 0000000000..0ec48b2b92 --- /dev/null +++ b/package/network/services/unetd/files/unetd.init @@ -0,0 +1,17 @@ +#!/bin/sh /etc/rc.common +# Copyright (c) 2022 OpenWrt.org + +START=19 + +USE_PROCD=1 +PROG=/usr/sbin/unetd + +start_service() { + mkdir -p /var/run/unetd /etc/unetd + + procd_open_instance + procd_set_param command "$PROG" -h /var/run/unetd/hosts + procd_set_param respawn + procd_set_param limits core="unlimited" + procd_close_instance +} diff --git a/package/network/services/unetd/files/unetd.sh b/package/network/services/unetd/files/unetd.sh new file mode 100644 index 0000000000..8e56fbd869 --- /dev/null +++ b/package/network/services/unetd/files/unetd.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +[ -x /usr/sbin/unetd ] || exit 0 + +. /lib/functions.sh +. /lib/functions/network.sh +. ../netifd-proto.sh + +init_proto "$@" + +proto_unet_init_config() { + proto_config_add_string device + proto_config_add_string type + proto_config_add_string auth_key + proto_config_add_string key + proto_config_add_string file + proto_config_add_int keepalive + proto_config_add_string domain + proto_config_add_string "tunnels:list(string)" + proto_config_add_string "connect:list(string)" + no_device=1 + available=1 + no_proto_task=1 +} + +proto_unet_setup() { + local config="$1" + + local device type key file keepalive domain tunnels + json_get_vars device type auth_key key file keepalive domain tunnels connect + device="${device:-$config}" + + [ -n "$auth_key" ] && type="${type:-dynamic}" + [ -n "$file" ] && type="${type:-file}" + + json_init + json_add_string name "$device" + json_add_string type "$type" + json_add_string interface "$config" + json_add_string auth_key "$auth_key" + json_add_string key "$key" + json_add_string file "$file" + [ -n "$keepalive" ] && json_add_int keepalive "$keepalive" + json_add_string domain "$domain" + + json_add_object tunnels + for t in $tunnels; do + local ifname="${t%%=*}" + local service="${t#*=}" + [ -n "$ifname" -a -n "$service" -a "$ifname" != "$t" ] || continue + json_add_string "$ifname" "$service" + done + json_close_object + + json_add_array auth_connect + for c in $connect; do + json_add_string "" "$c" + done + json_close_array + + ip link del dev "$device" >/dev/null 2>&1 + ip link add dev "$device" type wireguard || { + echo "Could not create wireguard device $device" + proto_setup_failed "$config" + exit 1 + } + + ubus call unetd network_add "$(json_dump)" +} + +proto_unet_teardown() { + local config="$1" + local iface="$2" + + local device + json_get_vars device + device="${device:-$iface}" + + json_init + json_add_string name "$device" + + ip link del dev "$device" + + ubus call unetd network_del "$(json_dump)" +} + +add_protocol unet diff --git a/package/network/utils/ethtool/Makefile b/package/network/utils/ethtool/Makefile index dffcab357c..5e684ceedf 100644 --- a/package/network/utils/ethtool/Makefile +++ b/package/network/utils/ethtool/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ethtool -PKG_VERSION:=5.18 +PKG_VERSION:=5.19 PKG_RELEASE:=1 PKG_MAINTAINER:=Felix Fietkau PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/software/network/ethtool -PKG_HASH:=9577b2ffbce710b659fb239598ec92bced1ca400ca0f1286762bfa44e4784270 +PKG_HASH:=3b752a3329827907ac3812f2831dfecf51c8c41c55d2d69cfb9c53ca06449fc6 PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING diff --git a/package/network/utils/iproute2/patches/010-ipstats-Add-param.h-for-musl.patch b/package/network/utils/iproute2/patches/010-ipstats-Add-param.h-for-musl.patch new file mode 100644 index 0000000000..d99ae6e65c --- /dev/null +++ b/package/network/utils/iproute2/patches/010-ipstats-Add-param.h-for-musl.patch @@ -0,0 +1,23 @@ +From cf6b60c504d4be5e1df2b2745e55d677967831d0 Mon Sep 17 00:00:00 2001 +From: Changhyeok Bae +Date: Tue, 9 Aug 2022 04:01:05 +0000 +Subject: [PATCH 1/5] ipstats: Add param.h for musl + +Fix build error for musl +| /usr/src/debug/iproute2/5.19.0-r0/iproute2-5.19.0/ip/ipstats.c:231: undefined reference to `MIN' + +Signed-off-by: Changhyeok Bae +--- + ip/ipstats.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/ip/ipstats.c ++++ b/ip/ipstats.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0+ + #include + #include ++#include + + #include "list.h" + #include "utils.h" diff --git a/package/network/utils/iproute2/patches/105-ipstats-Define-MIN-function-to-fix-undefined-referen.patch b/package/network/utils/iproute2/patches/105-ipstats-Define-MIN-function-to-fix-undefined-referen.patch deleted file mode 100644 index 7bf55dd57b..0000000000 --- a/package/network/utils/iproute2/patches/105-ipstats-Define-MIN-function-to-fix-undefined-referen.patch +++ /dev/null @@ -1,27 +0,0 @@ -From c69e8e474936795a2cd7638b11ce3e99ff4d5ae7 Mon Sep 17 00:00:00 2001 -From: Nick Hainke -Date: Sat, 6 Aug 2022 10:00:20 +0200 -Subject: [PATCH] ipstats: Define MIN function to fix undefined references - -Fixes errors in the form of: - in function `ipstats_show_64': - :(.text+0x4e30): undefined reference to `MIN' - -Signed-off-by: Nick Hainke ---- - ip/ipstats.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/ip/ipstats.c -+++ b/ip/ipstats.c -@@ -6,6 +6,10 @@ - #include "utils.h" - #include "ip_common.h" - -+#ifndef MIN -+#define MIN(a, b) ((a) < (b) ? (a) : (b)) -+#endif -+ - struct ipstats_stat_dump_filters { - /* mask[0] filters outer attributes. Then individual nests have their - * filtering mask at the index of the nested attribute. diff --git a/package/network/utils/iptables/Makefile b/package/network/utils/iptables/Makefile index 20a3fad582..dc57bb55d0 100644 --- a/package/network/utils/iptables/Makefile +++ b/package/network/utils/iptables/Makefile @@ -750,11 +750,11 @@ $(eval $(call BuildPackage,libiptext)) $(eval $(call BuildPackage,libiptext6)) $(eval $(call BuildPackage,libiptext-nft)) $(eval $(call BuildPackage,xtables-legacy)) -$(eval $(call BuildPackage,iptables-zz-legacy)) $(eval $(call BuildPackage,xtables-nft)) $(eval $(call BuildPackage,arptables-nft)) $(eval $(call BuildPackage,ebtables-nft)) $(eval $(call BuildPackage,iptables-nft)) +$(eval $(call BuildPackage,iptables-zz-legacy)) $(eval $(call BuildPlugin,iptables-mod-conntrack-extra,$(IPT_CONNTRACK_EXTRA-m))) $(eval $(call BuildPlugin,iptables-mod-conntrack-label,$(IPT_CONNTRACK_LABEL-m))) $(eval $(call BuildPlugin,iptables-mod-extra,$(IPT_EXTRA-m))) @@ -777,8 +777,8 @@ $(eval $(call BuildPlugin,iptables-mod-nflog,$(IPT_NFLOG-m))) $(eval $(call BuildPlugin,iptables-mod-trace,$(IPT_DEBUG-m))) $(eval $(call BuildPlugin,iptables-mod-nfqueue,$(IPT_NFQUEUE-m))) $(eval $(call BuildPlugin,iptables-mod-checksum,$(IPT_CHECKSUM-m))) -$(eval $(call BuildPackage,ip6tables-zz-legacy)) $(eval $(call BuildPackage,ip6tables-nft)) +$(eval $(call BuildPackage,ip6tables-zz-legacy)) $(eval $(call BuildPlugin,ip6tables-extra,$(IPT_IPV6_EXTRA-m))) $(eval $(call BuildPlugin,ip6tables-mod-nat,$(IPT_NAT6-m))) diff --git a/package/network/utils/nftables/Makefile b/package/network/utils/nftables/Makefile index 850355df8d..fd53e3faa1 100644 --- a/package/network/utils/nftables/Makefile +++ b/package/network/utils/nftables/Makefile @@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nftables -PKG_VERSION:=1.0.4 -PKG_RELEASE:=2 +PKG_VERSION:=1.0.5 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files -PKG_HASH:=927fb1fea1f685a328c10cf791eb655d7e1ed49d310eea5cb3101dfd8d6cba35 +PKG_HASH:=8d1b4b18393af43698d10baa25d2b9b6397969beecac7816c35dd0714e4de50a PKG_MAINTAINER:= PKG_LICENSE:=GPL-2.0 diff --git a/package/network/utils/nftables/patches/0001-meta-don-t-use-non-POSIX-formats-in-strptime.patch b/package/network/utils/nftables/patches/0001-meta-don-t-use-non-POSIX-formats-in-strptime.patch deleted file mode 100644 index a9d0ee5451..0000000000 --- a/package/network/utils/nftables/patches/0001-meta-don-t-use-non-POSIX-formats-in-strptime.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 1af8aabccd65e11caa397c4706353075f623cd01 Mon Sep 17 00:00:00 2001 -From: Jo-Philipp Wich -Date: Mon, 8 Aug 2022 23:57:03 +0200 -Subject: [PATCH] meta: don't use non-POSIX formats in strptime() - -The current strptime() invocations in meta.c use the `%F` format which -is not specified by POSIX and thus unimplemented by some libc flavors -such as musl libc. - -Replace all occurrences of `%F` with an equivalent `%Y-%m-%d` format -in order to be able to properly parse user supplied dates in such -environments. - -Signed-off-by: Jo-Philipp Wich ---- - src/meta.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/meta.c b/src/meta.c -index 80ace25b..257bbc9f 100644 ---- a/src/meta.c -+++ b/src/meta.c -@@ -399,7 +399,7 @@ static void date_type_print(const struct expr *expr, struct output_ctx *octx) - tstamp += cur_tm->tm_gmtoff; - - if ((tm = gmtime((time_t *) &tstamp)) != NULL && -- strftime(timestr, sizeof(timestr) - 1, "%F %T", tm)) -+ strftime(timestr, sizeof(timestr) - 1, "%Y-%m-%d %T", tm)) - nft_print(octx, "\"%s\"", timestr); - else - nft_print(octx, "Error converting timestamp to printed time"); -@@ -412,11 +412,11 @@ static bool parse_iso_date(uint64_t *tstamp, const char *sym) - - memset(&tm, 0, sizeof(struct tm)); - -- if (strptime(sym, "%F %T", &tm)) -+ if (strptime(sym, "%Y-%m-%d %T", &tm)) - goto success; -- if (strptime(sym, "%F %R", &tm)) -+ if (strptime(sym, "%Y-%m-%d %R", &tm)) - goto success; -- if (strptime(sym, "%F", &tm)) -+ if (strptime(sym, "%Y-%m-%d", &tm)) - goto success; - - return false; --- -2.35.1 - diff --git a/package/network/utils/wireguard-tools/Makefile b/package/network/utils/wireguard-tools/Makefile index 717ec2bbb1..8218171fcd 100644 --- a/package/network/utils/wireguard-tools/Makefile +++ b/package/network/utils/wireguard-tools/Makefile @@ -11,12 +11,12 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=wireguard-tools -PKG_VERSION:=1.0.20210424 +PKG_VERSION:=1.0.20210914 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=wireguard-tools-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-tools/snapshot/ -PKG_HASH:=b288b0c43871d919629d7e77846ef0b47f8eeaa9ebc9cedeee8233fc6cc376ad +PKG_HASH:=97ff31489217bb265b7ae850d3d0f335ab07d2652ba1feec88b734bc96bd05ac PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING diff --git a/package/utils/ucode/Makefile b/package/utils/ucode/Makefile index 210a4c7f3c..025f997387 100644 --- a/package/utils/ucode/Makefile +++ b/package/utils/ucode/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://github.com/jow-/ucode.git -PKG_SOURCE_DATE:=2022-08-24 -PKG_SOURCE_VERSION:=bcdd2cb33797412cce1f1014d265a71461676cff -PKG_MIRROR_HASH:=9ad0f4060654d002b67150bb655d9f455cf4672a8a406004fa7b45acbd53b3fa +PKG_SOURCE_DATE:=2022-08-29 +PKG_SOURCE_VERSION:=344fa9e69da43ecdc4d8f7768d85d42639352405 +PKG_MIRROR_HASH:=94e1ae6779536b2bd8957db8c2922ec32dcef75258401707505b1d34b6f16d0b PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=ISC diff --git a/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts b/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts new file mode 100644 index 0000000000..8b1477b593 --- /dev/null +++ b/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca955x.dtsi" + +#include +#include + +/ { + compatible = "extreme-networks,ws-ap3805i", "qca,qca9557"; + model = "Extreme Networks AP3805i"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_amber; + led-running = &led_power_green; + led-upgrade = &led_power_amber; + label-mac-device = ð0; + }; + + leds { + compatible = "gpio-leds"; + + led_power_green: power_green { + label = "green:power"; + gpios = <&gpio 19 GPIO_ACTIVE_LOW>; + }; + + led_power_amber: power_amber { + label = "amber:power"; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; + }; + + wlan5 { + label = "green:wlan5"; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + wlan2 { + label = "green:wlan2"; + gpios = <&gpio 22 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <20000>; + always-running; + }; +}; + +&wdt { + status = "disabled"; +}; + +&wmac { + status = "okay"; + + qca,no-eeprom; +}; + +&pcie0 { + status = "okay"; + + wifi@0,0,0 { + compatible = "qcom,ath10k"; + reg = <0x0 0 0 0 0>; + }; +}; + +&mdio0 { + status = "okay"; + + phy5: ethernet-phy@5 { + reg = <5>; + }; +}; + +ð0 { + status = "okay"; + + phy-handle = <&phy5>; + phy-mode = "rgmii-id"; + + pll-data = <0x82000000 0x80000101 0x80001313>; + + gmac-config { + device = <&gmac>; + rgmii-enabled = <1>; + }; +}; + +&spi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot-bak"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "u-boot"; + reg = <0x080000 0x80000>; + read-only; + }; + + partition@100000 { + label = "cfg1"; + reg = <0x100000 0x40000>; + read-only; + }; + + partition@140000 { + label = "cfg2"; + reg = <0x140000 0x40000>; + read-only; + }; + + partition@180000 { + label = "nvram4"; + reg = <0x180000 0x40000>; + read-only; + }; + + partition@1c0000 { + label = "nvram3"; + reg = <0x1c0000 0x40000>; + read-only; + }; + + partition@200000 { + label = "nvram2"; + reg = <0x200000 0x40000>; + read-only; + }; + + partition@240000 { + label = "nvram1"; + reg = <0x240000 0x40000>; + read-only; + }; + + partition@280000 { + label = "PriImg"; + reg = <0x280000 0x1000000>; + read-only; + }; + + partition@1280000 { + label = "SecImg"; + reg = <0x1280000 0x1000000>; + read-only; + }; + + partition@2280000 { + label = "firmware"; + compatible = "denx,uimage"; + reg = <0x2280000 0x1cc0000>; + }; + + partition@3f40000 { + label = "cert"; + reg = <0x3f40000 0x80000>; + read-only; + }; + + partition@3fc0000 { + label = "art"; + reg = <0x3fc0000 0x40000>; + read-only; + }; + }; + }; +}; diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network index c576dacee5..20dc564117 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/02_network +++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network @@ -43,6 +43,7 @@ ath79_setup_interfaces() engenius,ecb1750|\ engenius,ecb600|\ enterasys,ws-ap3705i|\ + extreme-networks,ws-ap3805i|\ glinet,gl-ar300m-lite|\ glinet,gl-usb150|\ hak5,wifi-pineapple-nano|\ diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom index 95439b9b27..df293c44db 100644 --- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom @@ -59,6 +59,10 @@ case "$FIRMWARE" in caldata_extract "calibrate" 0x1000 0x440 ath9k_patch_mac $(mtd_get_mac_ascii u-boot-env0 RADIOADDR1) ;; + extreme-networks,ws-ap3805i) + caldata_extract "art" 0x1000 0x440 + ath9k_patch_mac $(mtd_get_mac_ascii cfg1 RADIOADDR1) + ;; nec,wg800hp) caldata_extract "art" 0x1000 0x440 ath9k_patch_mac $(mtd_get_mac_text board_data 0x680) diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index 0aa3e006f6..9d25808307 100644 --- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -93,6 +93,10 @@ case "$FIRMWARE" in caldata_extract "art" 0x5000 0x844 ath10k_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) 1) ;; + extreme-networks,ws-ap3805i) + caldata_extract "art" 0x5000 0x844 + ath10k_patch_mac $(mtd_get_mac_ascii cfg1 RADIOADDR0) + ;; glinet,gl-ar750) caldata_extract "art" 0x5000 0x844 ath10k_patch_mac $(macaddr_add $(mtd_get_mac_binary art 0x0) 1) diff --git a/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh b/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh index c2c7913342..d9cb8d2b82 100644 --- a/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh +++ b/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh @@ -15,6 +15,7 @@ preinit_set_mac_address() { enterasys,ws-ap3705i) ip link set dev eth0 address $(mtd_get_mac_ascii u-boot-env0 ethaddr) ;; + extreme-networks,ws-ap3805i|\ siemens,ws-ap3610) ip link set dev eth0 address $(mtd_get_mac_ascii cfg1 ethaddr) ;; diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk index 5f26a3d73c..e6b55b64ba 100644 --- a/target/linux/ath79/image/generic.mk +++ b/target/linux/ath79/image/generic.mk @@ -1278,6 +1278,16 @@ define Device/etactica_eg200 endef TARGET_DEVICES += etactica_eg200 +define Device/extreme-networks_ws-ap3805i + SOC := qca9557 + BLOCKSIZE := 256k + DEVICE_VENDOR := Extreme Networks + DEVICE_MODEL := WS-AP3805i + DEVICE_PACKAGES := ath10k-firmware-qca988x-ct kmod-ath10k-ct + IMAGE_SIZE := 29440k +endef +TARGET_DEVICES += extreme-networks_ws-ap3805i + define Device/glinet_6408 $(Device/tplink-8mlzma) SOC := ar9331 diff --git a/target/linux/bcm27xx/patches-5.15/950-0424-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch b/target/linux/bcm27xx/patches-5.15/950-0424-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch index 55bd57a5d6..a9767bedfe 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0424-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0424-drm-vc4-Add-FKMS-as-an-acceptable-node-for-dma-range.patch @@ -17,9 +17,9 @@ Signed-off-by: Dave Stevenson --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -227,6 +227,7 @@ static const struct of_device_id vc4_dma - - const struct of_device_id vc4_dma_range_matches[] = { +@@ -219,6 +219,7 @@ static void vc4_match_add_drivers(struct + static const struct of_device_id vc4_dma_range_matches[] = { + { .compatible = "brcm,bcm2711-hvs" }, { .compatible = "brcm,bcm2835-hvs" }, + { .compatible = "raspberrypi,rpi-firmware-kms" }, { .compatible = "brcm,bcm2835-v3d" }, diff --git a/target/linux/bcm27xx/patches-5.15/950-0428-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch b/target/linux/bcm27xx/patches-5.15/950-0428-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch index 143fef749a..ca8bfb5070 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0428-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0428-drm-vc4-Add-the-2711-HVS-as-a-suitable-DMA-node.patch @@ -14,9 +14,9 @@ Signed-off-by: Dave Stevenson --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -227,6 +227,7 @@ static const struct of_device_id vc4_dma - - const struct of_device_id vc4_dma_range_matches[] = { +@@ -219,6 +219,7 @@ static void vc4_match_add_drivers(struct + static const struct of_device_id vc4_dma_range_matches[] = { + { .compatible = "brcm,bcm2711-hvs" }, { .compatible = "brcm,bcm2835-hvs" }, + { .compatible = "brcm,bcm2711-hvs" }, { .compatible = "raspberrypi,rpi-firmware-kms" }, diff --git a/target/linux/bcm27xx/patches-5.15/950-0452-drm-vc4-Add-firmware-kms-mode.patch b/target/linux/bcm27xx/patches-5.15/950-0452-drm-vc4-Add-firmware-kms-mode.patch index ccebf974a8..300beb53b4 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0452-drm-vc4-Add-firmware-kms-mode.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0452-drm-vc4-Add-firmware-kms-mode.patch @@ -104,7 +104,7 @@ Signed-off-by: Dom Cobley minor->debugfs_root, &vc4->load_tracker_enabled); --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -235,6 +235,18 @@ const struct of_device_id vc4_dma_range_ +@@ -227,6 +227,18 @@ static const struct of_device_id vc4_dma {} }; @@ -123,7 +123,7 @@ Signed-off-by: Dom Cobley static int vc4_drm_bind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); -@@ -308,7 +320,7 @@ static int vc4_drm_bind(struct device *d +@@ -290,7 +302,7 @@ static int vc4_drm_bind(struct device *d if (ret) return ret; @@ -132,7 +132,7 @@ Signed-off-by: Dom Cobley ret = rpi_firmware_property(firmware, RPI_FIRMWARE_NOTIFY_DISPLAY_DONE, NULL, 0); -@@ -322,16 +334,20 @@ static int vc4_drm_bind(struct device *d +@@ -304,16 +316,20 @@ static int vc4_drm_bind(struct device *d if (ret) return ret; @@ -158,7 +158,7 @@ Signed-off-by: Dom Cobley ret = drm_dev_register(drm, 0); if (ret < 0) -@@ -378,6 +394,7 @@ static struct platform_driver *const com +@@ -360,6 +376,7 @@ static struct platform_driver *const com &vc4_dsi_driver, &vc4_txp_driver, &vc4_crtc_driver, diff --git a/target/linux/bcm27xx/patches-5.15/950-0471-sound-usb-call-usb_autopm_get_interface-for-devices-.patch b/target/linux/bcm27xx/patches-5.15/950-0471-sound-usb-call-usb_autopm_get_interface-for-devices-.patch index d61c59b907..b195163196 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0471-sound-usb-call-usb_autopm_get_interface-for-devices-.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0471-sound-usb-call-usb_autopm_get_interface-for-devices-.patch @@ -19,7 +19,7 @@ Signed-off-by: Jonathan Bell --- a/sound/usb/card.c +++ b/sound/usb/card.c -@@ -817,8 +817,14 @@ static int usb_audio_probe(struct usb_in +@@ -825,8 +825,14 @@ static int usb_audio_probe(struct usb_in if (ignore_ctl_error) chip->quirk_flags |= QUIRK_FLAG_IGNORE_CTL_ERROR; diff --git a/target/linux/bcm27xx/patches-5.15/950-0898-drm-vc4-Consolidate-Hardware-Revision-Check.patch b/target/linux/bcm27xx/patches-5.15/950-0898-drm-vc4-Consolidate-Hardware-Revision-Check.patch index a331118b4b..ac22a96c3f 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0898-drm-vc4-Consolidate-Hardware-Revision-Check.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0898-drm-vc4-Consolidate-Hardware-Revision-Check.patch @@ -68,7 +68,7 @@ Signed-off-by: Maxime Ripard */ --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -255,10 +255,13 @@ static int vc4_drm_bind(struct device *d +@@ -247,10 +247,13 @@ static int vc4_drm_bind(struct device *d struct vc4_dev *vc4; struct device_node *node; struct drm_crtc *crtc; @@ -82,7 +82,7 @@ Signed-off-by: Maxime Ripard /* If VC4 V3D is missing, don't advertise render nodes. */ node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL); if (!node || !of_device_is_available(node)) -@@ -288,6 +291,7 @@ static int vc4_drm_bind(struct device *d +@@ -270,6 +273,7 @@ static int vc4_drm_bind(struct device *d vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base); if (IS_ERR(vc4)) return PTR_ERR(vc4); diff --git a/target/linux/bcm27xx/patches-5.15/950-0901-drm-vc4-drv-Register-a-different-driver-on-BCM2711.patch b/target/linux/bcm27xx/patches-5.15/950-0901-drm-vc4-drv-Register-a-different-driver-on-BCM2711.patch index c7e587ae16..81859f89df 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0901-drm-vc4-drv-Register-a-different-driver-on-BCM2711.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0901-drm-vc4-drv-Register-a-different-driver-on-BCM2711.patch @@ -83,7 +83,7 @@ Signed-off-by: Maxime Ripard static int compare_dev(struct device *dev, void *data) { return dev == data; -@@ -263,6 +297,7 @@ static bool firmware_kms(void) +@@ -255,6 +289,7 @@ static bool firmware_kms(void) static int vc4_drm_bind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -91,7 +91,7 @@ Signed-off-by: Maxime Ripard struct rpi_firmware *firmware = NULL; struct drm_device *drm; struct vc4_dev *vc4; -@@ -274,12 +309,10 @@ static int vc4_drm_bind(struct device *d +@@ -266,12 +301,10 @@ static int vc4_drm_bind(struct device *d dev->coherent_dma_mask = DMA_BIT_MASK(32); is_vc5 = of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5"); @@ -108,7 +108,7 @@ Signed-off-by: Maxime Ripard node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches, NULL); -@@ -301,7 +334,7 @@ static int vc4_drm_bind(struct device *d +@@ -283,7 +316,7 @@ static int vc4_drm_bind(struct device *d return ret; } @@ -117,7 +117,7 @@ Signed-off-by: Maxime Ripard if (IS_ERR(vc4)) return PTR_ERR(vc4); vc4->is_vc5 = is_vc5; -@@ -333,7 +366,7 @@ static int vc4_drm_bind(struct device *d +@@ -315,7 +348,7 @@ static int vc4_drm_bind(struct device *d return -EPROBE_DEFER; } diff --git a/target/linux/bcm27xx/patches-5.15/950-0904-drm-vc4-drv-Skip-BO-Backend-Initialization-on-BCM271.patch b/target/linux/bcm27xx/patches-5.15/950-0904-drm-vc4-drv-Skip-BO-Backend-Initialization-on-BCM271.patch index 297e871020..b61c0e156b 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0904-drm-vc4-drv-Skip-BO-Backend-Initialization-on-BCM271.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0904-drm-vc4-drv-Skip-BO-Backend-Initialization-on-BCM271.patch @@ -19,7 +19,7 @@ Signed-off-by: Maxime Ripard --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -343,19 +343,23 @@ static int vc4_drm_bind(struct device *d +@@ -325,19 +325,23 @@ static int vc4_drm_bind(struct device *d platform_set_drvdata(pdev, drm); INIT_LIST_HEAD(&vc4->debugfs_list); diff --git a/target/linux/bcm53xx/config-5.15 b/target/linux/bcm53xx/config-5.15 index 4941f16912..32ac9fb6cc 100644 --- a/target/linux/bcm53xx/config-5.15 +++ b/target/linux/bcm53xx/config-5.15 @@ -179,6 +179,7 @@ CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_WORK=y CONFIG_KMAP_LOCAL=y CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y +# CONFIG_LEDS_BCM63138 is not set CONFIG_LIBFDT=y CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_LOCK_SPIN_ON_OWNER=y diff --git a/target/linux/generic/backport-5.10/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch b/target/linux/generic/backport-5.10/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch index 5ab2718ecb..eea0aed6aa 100644 --- a/target/linux/generic/backport-5.10/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch +++ b/target/linux/generic/backport-5.10/610-v5.13-10-netfilter-nftables-update-table-flags-from-the-commi.patch @@ -34,7 +34,7 @@ Signed-off-by: Pablo Neira Ayuso struct nft_set *set; --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c -@@ -893,6 +893,12 @@ static void nf_tables_table_disable(stru +@@ -917,6 +917,12 @@ static void nf_tables_table_disable(stru nft_table_disable(net, table, 0); } @@ -47,7 +47,7 @@ Signed-off-by: Pablo Neira Ayuso static int nf_tables_updtable(struct nft_ctx *ctx) { struct nft_trans *trans; -@@ -916,19 +922,17 @@ static int nf_tables_updtable(struct nft +@@ -940,19 +946,17 @@ static int nf_tables_updtable(struct nft if ((flags & NFT_TABLE_F_DORMANT) && !(ctx->table->flags & NFT_TABLE_F_DORMANT)) { @@ -70,7 +70,7 @@ Signed-off-by: Pablo Neira Ayuso nft_trans_table_update(trans) = true; list_add_tail(&trans->list, &ctx->net->nft.commit_list); return 0; -@@ -7931,11 +7935,10 @@ static int nf_tables_commit(struct net * +@@ -7929,11 +7933,10 @@ static int nf_tables_commit(struct net * switch (trans->msg_type) { case NFT_MSG_NEWTABLE: if (nft_trans_table_update(trans)) { @@ -86,7 +86,7 @@ Signed-off-by: Pablo Neira Ayuso } else { nft_clear(net, trans->ctx.table); } -@@ -8148,11 +8151,9 @@ static int __nf_tables_abort(struct net +@@ -8147,11 +8150,9 @@ static int __nf_tables_abort(struct net switch (trans->msg_type) { case NFT_MSG_NEWTABLE: if (nft_trans_table_update(trans)) { diff --git a/target/linux/generic/backport-5.15/703-01-v5.16-net-phylink-add-MAC-phy_interface_t-bitmap.patch b/target/linux/generic/backport-5.15/703-01-v5.16-net-phylink-add-MAC-phy_interface_t-bitmap.patch new file mode 100644 index 0000000000..b72faec8d9 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-01-v5.16-net-phylink-add-MAC-phy_interface_t-bitmap.patch @@ -0,0 +1,24 @@ +From 38c310eb46f5f80213a92093af11af270c209a76 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 26 Oct 2021 11:06:06 +0100 +Subject: [PATCH] net: phylink: add MAC phy_interface_t bitmap + +Add a phy_interface_t bitmap so the MAC driver can specifiy which PHY +interface modes it supports. + +Signed-off-by: Russell King +Signed-off-by: David S. Miller +--- + include/linux/phylink.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -76,6 +76,7 @@ struct phylink_config { + bool ovr_an_inband; + void (*get_fixed_state)(struct phylink_config *config, + struct phylink_link_state *state); ++ DECLARE_PHY_INTERFACE_MASK(supported_interfaces); + }; + + /** diff --git a/target/linux/generic/backport-5.15/703-02-v5.16-net-phylink-use-supported_interfaces-for-phylink-val.patch b/target/linux/generic/backport-5.15/703-02-v5.16-net-phylink-use-supported_interfaces-for-phylink-val.patch new file mode 100644 index 0000000000..8996fc8d45 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-02-v5.16-net-phylink-use-supported_interfaces-for-phylink-val.patch @@ -0,0 +1,98 @@ +From d25f3a74f30aace819163dfa54f2a4b8ca1dc932 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 26 Oct 2021 11:06:11 +0100 +Subject: [PATCH] net: phylink: use supported_interfaces for phylink + validation + +If the network device supplies a supported interface bitmap, we can use +that during phylink's validation to simplify MAC drivers in two ways by +using the supported_interfaces bitmap to: + +1. reject unsupported interfaces before calling into the MAC driver. +2. generate the set of all supported link modes across all supported + interfaces (used mainly for SFP, but also some 10G PHYs.) + +Suggested-by: Sean Anderson +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 36 ++++++++++++++++++++++++++++++++++++ + include/linux/phylink.h | 12 ++++++++++-- + 2 files changed, 46 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -155,9 +155,45 @@ static const char *phylink_an_mode_str(u + return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; + } + ++static int phylink_validate_any(struct phylink *pl, unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, }; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(s); ++ struct phylink_link_state t; ++ int intf; ++ ++ for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) { ++ if (test_bit(intf, pl->config->supported_interfaces)) { ++ linkmode_copy(s, supported); ++ ++ t = *state; ++ t.interface = intf; ++ pl->mac_ops->validate(pl->config, s, &t); ++ linkmode_or(all_s, all_s, s); ++ linkmode_or(all_adv, all_adv, t.advertising); ++ } ++ } ++ ++ linkmode_copy(supported, all_s); ++ linkmode_copy(state->advertising, all_adv); ++ ++ return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; ++} ++ + static int phylink_validate(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state) + { ++ if (!phy_interface_empty(pl->config->supported_interfaces)) { ++ if (state->interface == PHY_INTERFACE_MODE_NA) ++ return phylink_validate_any(pl, supported, state); ++ ++ if (!test_bit(state->interface, ++ pl->config->supported_interfaces)) ++ return -EINVAL; ++ } ++ + pl->mac_ops->validate(pl->config, supported, state); + + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -67,6 +67,8 @@ enum phylink_op_type { + * @ovr_an_inband: if true, override PCS to MLO_AN_INBAND + * @get_fixed_state: callback to execute to determine the fixed link state, + * if MAC link is at %MLO_AN_FIXED mode. ++ * @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx ++ * are supported by the MAC/PCS. + */ + struct phylink_config { + struct device *dev; +@@ -134,8 +136,14 @@ struct phylink_mac_ops { + * based on @state->advertising and/or @state->speed and update + * @state->interface accordingly. See phylink_helper_basex_speed(). + * +- * When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the +- * MAC driver to return all supported link modes. ++ * When @config->supported_interfaces has been set, phylink will iterate ++ * over the supported interfaces to determine the full capability of the ++ * MAC. The validation function must not print errors if @state->interface ++ * is set to an unexpected value. ++ * ++ * When @config->supported_interfaces is empty, phylink will call this ++ * function with @state->interface set to %PHY_INTERFACE_MODE_NA, and ++ * expects the MAC driver to return all supported link modes. + * + * If the @state->interface mode is not supported, then the @supported + * mask must be cleared. diff --git a/target/linux/generic/backport-5.15/703-03-v5.16-net-dsa-populate-supported_interfaces-member.patch b/target/linux/generic/backport-5.15/703-03-v5.16-net-dsa-populate-supported_interfaces-member.patch new file mode 100644 index 0000000000..83d1f7ee7c --- /dev/null +++ b/target/linux/generic/backport-5.15/703-03-v5.16-net-dsa-populate-supported_interfaces-member.patch @@ -0,0 +1,63 @@ +From c07c6e8eb4b38bae921f9e2f108d1e7f8e14226e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Thu, 28 Oct 2021 18:00:14 +0100 +Subject: [PATCH] net: dsa: populate supported_interfaces member +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a new DSA switch operation, phylink_get_interfaces, which should +fill in which PHY_INTERFACE_MODE_* are supported by given port. + +Use this before phylink_create() to fill phylinks supported_interfaces +member, allowing phylink to determine which PHY_INTERFACE_MODEs are +supported. + +Signed-off-by: Marek Behún +[tweaked patch and description to add more complete support -- rmk] +Signed-off-by: Russell King +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + include/net/dsa.h | 2 ++ + net/dsa/port.c | 4 ++++ + net/dsa/slave.c | 4 ++++ + 3 files changed, 10 insertions(+) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -626,6 +626,8 @@ struct dsa_switch_ops { + /* + * PHYLINK integration + */ ++ void (*phylink_get_interfaces)(struct dsa_switch *ds, int port, ++ unsigned long *supported_interfaces); + void (*phylink_validate)(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state); +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1172,6 +1172,10 @@ static int dsa_port_phylink_register(str + dp->pl_config.type = PHYLINK_DEV; + dp->pl_config.pcs_poll = ds->pcs_poll; + ++ if (ds->ops->phylink_get_interfaces) ++ ds->ops->phylink_get_interfaces(ds, dp->index, ++ dp->pl_config.supported_interfaces); ++ + dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), + mode, &dsa_port_phylink_mac_ops); + if (IS_ERR(dp->pl)) { +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -1837,6 +1837,10 @@ static int dsa_slave_phy_setup(struct ne + dp->pl_config.poll_fixed_state = true; + } + ++ if (ds->ops->phylink_get_interfaces) ++ ds->ops->phylink_get_interfaces(ds, dp->index, ++ dp->pl_config.supported_interfaces); ++ + dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode, + &dsa_port_phylink_mac_ops); + if (IS_ERR(dp->pl)) { diff --git a/target/linux/generic/backport-5.15/703-04-v5.17-net-dsa-consolidate-phylink-creation.patch b/target/linux/generic/backport-5.15/703-04-v5.17-net-dsa-consolidate-phylink-creation.patch new file mode 100644 index 0000000000..8b58c83312 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-04-v5.17-net-dsa-consolidate-phylink-creation.patch @@ -0,0 +1,149 @@ +From 21bd64bd717dedac96f53b668144cbe37d3c12d4 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 30 Nov 2021 13:09:55 +0000 +Subject: [PATCH] net: dsa: consolidate phylink creation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The code in port.c and slave.c creating the phylink instance is very +similar - let's consolidate this into a single function. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Marek Behún +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + net/dsa/dsa_priv.h | 2 +- + net/dsa/port.c | 44 ++++++++++++++++++++++++++++---------------- + net/dsa/slave.c | 19 +++---------------- + 3 files changed, 32 insertions(+), 33 deletions(-) + +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -260,13 +260,13 @@ int dsa_port_mrp_add_ring_role(const str + const struct switchdev_obj_ring_role_mrp *mrp); + int dsa_port_mrp_del_ring_role(const struct dsa_port *dp, + const struct switchdev_obj_ring_role_mrp *mrp); ++int dsa_port_phylink_create(struct dsa_port *dp); + int dsa_port_link_register_of(struct dsa_port *dp); + void dsa_port_link_unregister_of(struct dsa_port *dp); + int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr); + void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr); + int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast); + void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid, bool broadcast); +-extern const struct phylink_mac_ops dsa_port_phylink_mac_ops; + + static inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp, + const struct net_device *dev) +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1076,7 +1076,7 @@ static void dsa_port_phylink_mac_link_up + speed, duplex, tx_pause, rx_pause); + } + +-const struct phylink_mac_ops dsa_port_phylink_mac_ops = { ++static const struct phylink_mac_ops dsa_port_phylink_mac_ops = { + .validate = dsa_port_phylink_validate, + .mac_pcs_get_state = dsa_port_phylink_mac_pcs_get_state, + .mac_config = dsa_port_phylink_mac_config, +@@ -1085,6 +1085,30 @@ const struct phylink_mac_ops dsa_port_ph + .mac_link_up = dsa_port_phylink_mac_link_up, + }; + ++int dsa_port_phylink_create(struct dsa_port *dp) ++{ ++ struct dsa_switch *ds = dp->ds; ++ phy_interface_t mode; ++ int err; ++ ++ err = of_get_phy_mode(dp->dn, &mode); ++ if (err) ++ mode = PHY_INTERFACE_MODE_NA; ++ ++ if (ds->ops->phylink_get_interfaces) ++ ds->ops->phylink_get_interfaces(ds, dp->index, ++ dp->pl_config.supported_interfaces); ++ ++ dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), ++ mode, &dsa_port_phylink_mac_ops); ++ if (IS_ERR(dp->pl)) { ++ pr_err("error creating PHYLINK: %ld\n", PTR_ERR(dp->pl)); ++ return PTR_ERR(dp->pl); ++ } ++ ++ return 0; ++} ++ + static int dsa_port_setup_phy_of(struct dsa_port *dp, bool enable) + { + struct dsa_switch *ds = dp->ds; +@@ -1161,27 +1185,15 @@ static int dsa_port_phylink_register(str + { + struct dsa_switch *ds = dp->ds; + struct device_node *port_dn = dp->dn; +- phy_interface_t mode; + int err; + +- err = of_get_phy_mode(port_dn, &mode); +- if (err) +- mode = PHY_INTERFACE_MODE_NA; +- + dp->pl_config.dev = ds->dev; + dp->pl_config.type = PHYLINK_DEV; + dp->pl_config.pcs_poll = ds->pcs_poll; + +- if (ds->ops->phylink_get_interfaces) +- ds->ops->phylink_get_interfaces(ds, dp->index, +- dp->pl_config.supported_interfaces); +- +- dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), +- mode, &dsa_port_phylink_mac_ops); +- if (IS_ERR(dp->pl)) { +- pr_err("error creating PHYLINK: %ld\n", PTR_ERR(dp->pl)); +- return PTR_ERR(dp->pl); +- } ++ err = dsa_port_phylink_create(dp); ++ if (err) ++ return err; + + err = phylink_of_phy_connect(dp->pl, port_dn, 0); + if (err && err != -ENODEV) { +--- a/net/dsa/slave.c ++++ b/net/dsa/slave.c +@@ -1817,14 +1817,9 @@ static int dsa_slave_phy_setup(struct ne + struct dsa_port *dp = dsa_slave_to_port(slave_dev); + struct device_node *port_dn = dp->dn; + struct dsa_switch *ds = dp->ds; +- phy_interface_t mode; + u32 phy_flags = 0; + int ret; + +- ret = of_get_phy_mode(port_dn, &mode); +- if (ret) +- mode = PHY_INTERFACE_MODE_NA; +- + dp->pl_config.dev = &slave_dev->dev; + dp->pl_config.type = PHYLINK_NETDEV; + +@@ -1837,17 +1832,9 @@ static int dsa_slave_phy_setup(struct ne + dp->pl_config.poll_fixed_state = true; + } + +- if (ds->ops->phylink_get_interfaces) +- ds->ops->phylink_get_interfaces(ds, dp->index, +- dp->pl_config.supported_interfaces); +- +- dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode, +- &dsa_port_phylink_mac_ops); +- if (IS_ERR(dp->pl)) { +- netdev_err(slave_dev, +- "error creating PHYLINK: %ld\n", PTR_ERR(dp->pl)); +- return PTR_ERR(dp->pl); +- } ++ ret = dsa_port_phylink_create(dp); ++ if (ret) ++ return ret; + + if (ds->ops->get_phy_flags) + phy_flags = ds->ops->get_phy_flags(ds, dp->index); diff --git a/target/linux/generic/backport-5.15/703-05-v5.17-net-dsa-replace-phylink_get_interfaces-with-phylink_.patch b/target/linux/generic/backport-5.15/703-05-v5.17-net-dsa-replace-phylink_get_interfaces-with-phylink_.patch new file mode 100644 index 0000000000..4cea5994da --- /dev/null +++ b/target/linux/generic/backport-5.15/703-05-v5.17-net-dsa-replace-phylink_get_interfaces-with-phylink_.patch @@ -0,0 +1,51 @@ +From 072eea6c22b2af680c3949e64f9adde278c71e68 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 30 Nov 2021 13:10:01 +0000 +Subject: [PATCH] net: dsa: replace phylink_get_interfaces() with + phylink_get_caps() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Phylink needs slightly more information than phylink_get_interfaces() +allows us to get from the DSA drivers - we need the MAC capabilities. +Replace the phylink_get_interfaces() method with phylink_get_caps() to +allow DSA drivers to fill in the phylink_config MAC capabilities field +as well. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Marek Behún +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 4 ++-- + net/dsa/port.c | 5 ++--- + 2 files changed, 4 insertions(+), 5 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -626,8 +626,8 @@ struct dsa_switch_ops { + /* + * PHYLINK integration + */ +- void (*phylink_get_interfaces)(struct dsa_switch *ds, int port, +- unsigned long *supported_interfaces); ++ void (*phylink_get_caps)(struct dsa_switch *ds, int port, ++ struct phylink_config *config); + void (*phylink_validate)(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state); +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1095,9 +1095,8 @@ int dsa_port_phylink_create(struct dsa_p + if (err) + mode = PHY_INTERFACE_MODE_NA; + +- if (ds->ops->phylink_get_interfaces) +- ds->ops->phylink_get_interfaces(ds, dp->index, +- dp->pl_config.supported_interfaces); ++ if (ds->ops->phylink_get_caps) ++ ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config); + + dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), + mode, &dsa_port_phylink_mac_ops); diff --git a/target/linux/generic/backport-5.15/703-06-v5.18-net-dsa-add-support-for-phylink-mac_select_pcs.patch b/target/linux/generic/backport-5.15/703-06-v5.18-net-dsa-add-support-for-phylink-mac_select_pcs.patch new file mode 100644 index 0000000000..a28d14d27a --- /dev/null +++ b/target/linux/generic/backport-5.15/703-06-v5.18-net-dsa-add-support-for-phylink-mac_select_pcs.patch @@ -0,0 +1,59 @@ +From bde018222c6b084ac32933a9f933581dd83da18e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 17 Feb 2022 18:30:35 +0000 +Subject: [PATCH] net: dsa: add support for phylink mac_select_pcs() + +Add DSA support for the phylink mac_select_pcs() method so DSA drivers +can return provide phylink with the appropriate PCS for the PHY +interface mode. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + include/net/dsa.h | 3 +++ + net/dsa/port.c | 15 +++++++++++++++ + 2 files changed, 18 insertions(+) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -631,6 +631,9 @@ struct dsa_switch_ops { + void (*phylink_validate)(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state); ++ struct phylink_pcs *(*phylink_mac_select_pcs)(struct dsa_switch *ds, ++ int port, ++ phy_interface_t iface); + int (*phylink_mac_link_state)(struct dsa_switch *ds, int port, + struct phylink_link_state *state); + void (*phylink_mac_config)(struct dsa_switch *ds, int port, +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1012,6 +1012,20 @@ static void dsa_port_phylink_mac_pcs_get + } + } + ++static struct phylink_pcs * ++dsa_port_phylink_mac_select_pcs(struct phylink_config *config, ++ phy_interface_t interface) ++{ ++ struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_switch *ds = dp->ds; ++ struct phylink_pcs *pcs = NULL; ++ ++ if (ds->ops->phylink_mac_select_pcs) ++ pcs = ds->ops->phylink_mac_select_pcs(ds, dp->index, interface); ++ ++ return pcs; ++} ++ + static void dsa_port_phylink_mac_config(struct phylink_config *config, + unsigned int mode, + const struct phylink_link_state *state) +@@ -1078,6 +1092,7 @@ static void dsa_port_phylink_mac_link_up + + static const struct phylink_mac_ops dsa_port_phylink_mac_ops = { + .validate = dsa_port_phylink_validate, ++ .mac_select_pcs = dsa_port_phylink_mac_select_pcs, + .mac_pcs_get_state = dsa_port_phylink_mac_pcs_get_state, + .mac_config = dsa_port_phylink_mac_config, + .mac_an_restart = dsa_port_phylink_mac_an_restart, diff --git a/target/linux/generic/backport-5.15/703-07-v5.16-net-phy-add-phy_interface_t-bitmap-support.patch b/target/linux/generic/backport-5.15/703-07-v5.16-net-phy-add-phy_interface_t-bitmap-support.patch new file mode 100644 index 0000000000..1a7817b0f9 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-07-v5.16-net-phy-add-phy_interface_t-bitmap-support.patch @@ -0,0 +1,61 @@ +From 8e20f591f204f8db7f1182918f8e2285d3f589e0 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 26 Oct 2021 11:06:01 +0100 +Subject: [PATCH] net: phy: add phy_interface_t bitmap support + +Add support for a bitmap for phy interface modes, which includes: +- a macro to declare the interface bitmap +- an inline helper to zero the interface bitmap +- an inline helper to detect an empty interface bitmap +- inline helpers to do a bitwise AND and OR operations on two interface + bitmaps + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + include/linux/phy.h | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -155,6 +155,40 @@ typedef enum { + PHY_INTERFACE_MODE_MAX, + } phy_interface_t; + ++/* PHY interface mode bitmap handling */ ++#define DECLARE_PHY_INTERFACE_MASK(name) \ ++ DECLARE_BITMAP(name, PHY_INTERFACE_MODE_MAX) ++ ++static inline void phy_interface_zero(unsigned long *intf) ++{ ++ bitmap_zero(intf, PHY_INTERFACE_MODE_MAX); ++} ++ ++static inline bool phy_interface_empty(const unsigned long *intf) ++{ ++ return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX); ++} ++ ++static inline void phy_interface_and(unsigned long *dst, const unsigned long *a, ++ const unsigned long *b) ++{ ++ bitmap_and(dst, a, b, PHY_INTERFACE_MODE_MAX); ++} ++ ++static inline void phy_interface_or(unsigned long *dst, const unsigned long *a, ++ const unsigned long *b) ++{ ++ bitmap_or(dst, a, b, PHY_INTERFACE_MODE_MAX); ++} ++ ++static inline void phy_interface_set_rgmii(unsigned long *intf) ++{ ++ __set_bit(PHY_INTERFACE_MODE_RGMII, intf); ++ __set_bit(PHY_INTERFACE_MODE_RGMII_ID, intf); ++ __set_bit(PHY_INTERFACE_MODE_RGMII_RXID, intf); ++ __set_bit(PHY_INTERFACE_MODE_RGMII_TXID, intf); ++} ++ + /* + * phy_supported_speeds - return all speeds currently supported by a PHY device + */ diff --git a/target/linux/generic/backport-5.15/703-08-v5.17-net-phylink-add-mac_select_pcs-method-to-phylink_mac.patch b/target/linux/generic/backport-5.15/703-08-v5.17-net-phylink-add-mac_select_pcs-method-to-phylink_mac.patch new file mode 100644 index 0000000000..e1cfc3f439 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-08-v5.17-net-phylink-add-mac_select_pcs-method-to-phylink_mac.patch @@ -0,0 +1,197 @@ +From d1e86325af377129adb7fc6f34eb044ca6068b47 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 15 Dec 2021 15:34:15 +0000 +Subject: [PATCH] net: phylink: add mac_select_pcs() method to phylink_mac_ops + +mac_select_pcs() allows us to have an explicit point to query which +PCS the MAC wishes to use for a particular PHY interface mode, thereby +allowing us to add support to validate the link settings with the PCS. + +Phylink will also use this to select the PCS to be used during a major +configuration event without the MAC driver needing to call +phylink_set_pcs(). + +Note that if mac_select_pcs() is present, the supported_interfaces +bitmap must be filled in; this avoids mac_select_pcs() being called +with PHY_INTERFACE_MODE_NA when we want to get support for all +interface types. Phylink will return an error in phylink_create() +unless this condition is satisfied. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 68 +++++++++++++++++++++++++++++++++------ + include/linux/phylink.h | 18 +++++++++++ + 2 files changed, 77 insertions(+), 9 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -155,6 +155,23 @@ static const char *phylink_an_mode_str(u + return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; + } + ++static int phylink_validate_mac_and_pcs(struct phylink *pl, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ struct phylink_pcs *pcs; ++ ++ if (pl->mac_ops->mac_select_pcs) { ++ pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); ++ if (IS_ERR(pcs)) ++ return PTR_ERR(pcs); ++ } ++ ++ pl->mac_ops->validate(pl->config, supported, state); ++ ++ return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; ++} ++ + static int phylink_validate_any(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state) + { +@@ -170,9 +187,10 @@ static int phylink_validate_any(struct p + + t = *state; + t.interface = intf; +- pl->mac_ops->validate(pl->config, s, &t); +- linkmode_or(all_s, all_s, s); +- linkmode_or(all_adv, all_adv, t.advertising); ++ if (!phylink_validate_mac_and_pcs(pl, s, &t)) { ++ linkmode_or(all_s, all_s, s); ++ linkmode_or(all_adv, all_adv, t.advertising); ++ } + } + } + +@@ -194,9 +212,7 @@ static int phylink_validate(struct phyli + return -EINVAL; + } + +- pl->mac_ops->validate(pl->config, supported, state); +- +- return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; ++ return phylink_validate_mac_and_pcs(pl, supported, state); + } + + static int phylink_parse_fixedlink(struct phylink *pl, +@@ -486,10 +502,21 @@ static void phylink_mac_pcs_an_restart(s + static void phylink_major_config(struct phylink *pl, bool restart, + const struct phylink_link_state *state) + { ++ struct phylink_pcs *pcs = NULL; + int err; + + phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); + ++ if (pl->mac_ops->mac_select_pcs) { ++ pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); ++ if (IS_ERR(pcs)) { ++ phylink_err(pl, ++ "mac_select_pcs unexpectedly failed: %pe\n", ++ pcs); ++ return; ++ } ++ } ++ + if (pl->mac_ops->mac_prepare) { + err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode, + state->interface); +@@ -500,6 +527,12 @@ static void phylink_major_config(struct + } + } + ++ /* If we have a new PCS, switch to the new PCS after preparing the MAC ++ * for the change. ++ */ ++ if (pcs) ++ phylink_set_pcs(pl, pcs); ++ + phylink_mac_config(pl, state); + + if (pl->pcs_ops) { +@@ -879,6 +912,14 @@ struct phylink *phylink_create(struct ph + struct phylink *pl; + int ret; + ++ /* Validate the supplied configuration */ ++ if (mac_ops->mac_select_pcs && ++ phy_interface_empty(config->supported_interfaces)) { ++ dev_err(config->dev, ++ "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ + pl = kzalloc(sizeof(*pl), GFP_KERNEL); + if (!pl) + return ERR_PTR(-ENOMEM); +@@ -946,9 +987,10 @@ EXPORT_SYMBOL_GPL(phylink_create); + * @pl: a pointer to a &struct phylink returned from phylink_create() + * @pcs: a pointer to the &struct phylink_pcs + * +- * Bind the MAC PCS to phylink. This may be called after phylink_create(), +- * in mac_prepare() or mac_config() methods if it is desired to dynamically +- * change the PCS. ++ * Bind the MAC PCS to phylink. This may be called after phylink_create(). ++ * If it is desired to dynamically change the PCS, then the preferred method ++ * is to use mac_select_pcs(), but it may also be called in mac_prepare() ++ * or mac_config(). + * + * Please note that there are behavioural changes with the mac_config() + * callback if a PCS is present (denoting a newer setup) so removing a PCS +@@ -959,6 +1001,14 @@ void phylink_set_pcs(struct phylink *pl, + { + pl->pcs = pcs; + pl->pcs_ops = pcs->ops; ++ ++ if (!pl->phylink_disable_state && ++ pl->cfg_link_an_mode == MLO_AN_INBAND) { ++ if (pl->config->pcs_poll || pcs->poll) ++ mod_timer(&pl->link_poll, jiffies + HZ); ++ else ++ del_timer(&pl->link_poll); ++ } + } + EXPORT_SYMBOL_GPL(phylink_set_pcs); + +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -84,6 +84,7 @@ struct phylink_config { + /** + * struct phylink_mac_ops - MAC operations structure. + * @validate: Validate and update the link configuration. ++ * @mac_select_pcs: Select a PCS for the interface mode. + * @mac_pcs_get_state: Read the current link state from the hardware. + * @mac_prepare: prepare for a major reconfiguration of the interface. + * @mac_config: configure the MAC for the selected mode and state. +@@ -98,6 +99,8 @@ struct phylink_mac_ops { + void (*validate)(struct phylink_config *config, + unsigned long *supported, + struct phylink_link_state *state); ++ struct phylink_pcs *(*mac_select_pcs)(struct phylink_config *config, ++ phy_interface_t interface); + void (*mac_pcs_get_state)(struct phylink_config *config, + struct phylink_link_state *state); + int (*mac_prepare)(struct phylink_config *config, unsigned int mode, +@@ -150,6 +153,21 @@ struct phylink_mac_ops { + */ + void validate(struct phylink_config *config, unsigned long *supported, + struct phylink_link_state *state); ++/** ++ * mac_select_pcs: Select a PCS for the interface mode. ++ * @config: a pointer to a &struct phylink_config. ++ * @interface: PHY interface mode for PCS ++ * ++ * Return the &struct phylink_pcs for the specified interface mode, or ++ * NULL if none is required, or an error pointer on error. ++ * ++ * This must not modify any state. It is used to query which PCS should ++ * be used. Phylink will use this during validation to ensure that the ++ * configuration is valid, and when setting a configuration to internally ++ * set the PCS that will be used. ++ */ ++struct phylink_pcs *mac_select_pcs(struct phylink_config *config, ++ phy_interface_t interface); + + /** + * mac_pcs_get_state() - Read the current inband link state from the hardware diff --git a/target/linux/generic/backport-5.15/703-09-v5.17-net-phylink-add-generic-validate-implementation.patch b/target/linux/generic/backport-5.15/703-09-v5.17-net-phylink-add-generic-validate-implementation.patch new file mode 100644 index 0000000000..73c8b414da --- /dev/null +++ b/target/linux/generic/backport-5.15/703-09-v5.17-net-phylink-add-generic-validate-implementation.patch @@ -0,0 +1,341 @@ +From 34ae2c09d46a2d0abd907e139b466f798e4095a8 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 15 Nov 2021 10:00:27 +0000 +Subject: [PATCH] net: phylink: add generic validate implementation + +Add a generic validate() implementation using the supported_interfaces +and a bitmask of MAC pause/speed/duplex capabilities. This allows us +to entirely eliminate many driver private validate() implementations. + +We expose the underlying phylink_get_linkmodes() function so that +drivers which have special needs can still benefit from conversion. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 252 ++++++++++++++++++++++++++++++++++++++ + include/linux/phylink.h | 31 +++++ + 2 files changed, 283 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -172,6 +172,258 @@ static int phylink_validate_mac_and_pcs( + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } + ++static void phylink_caps_to_linkmodes(unsigned long *linkmodes, ++ unsigned long caps) ++{ ++ if (caps & MAC_SYM_PAUSE) ++ __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes); ++ ++ if (caps & MAC_ASYM_PAUSE) ++ __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes); ++ ++ if (caps & MAC_10HD) ++ __set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, linkmodes); ++ ++ if (caps & MAC_10FD) ++ __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, linkmodes); ++ ++ if (caps & MAC_100HD) { ++ __set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_100FD) { ++ __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_1000HD) ++ __set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, linkmodes); ++ ++ if (caps & MAC_1000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_2500FD) { ++ __set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_5000FD) ++ __set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, linkmodes); ++ ++ if (caps & MAC_10000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_25000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_40000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_50000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_56000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_100000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_100000baseDR_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_200000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, linkmodes); ++ } ++ ++ if (caps & MAC_400000FD) { ++ __set_bit(ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT, ++ linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT, linkmodes); ++ __set_bit(ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT, linkmodes); ++ } ++} ++ ++/** ++ * phylink_get_linkmodes() - get acceptable link modes ++ * @linkmodes: ethtool linkmode mask (must be already initialised) ++ * @interface: phy interface mode defined by &typedef phy_interface_t ++ * @mac_capabilities: bitmask of MAC capabilities ++ * ++ * Set all possible pause, speed and duplex linkmodes in @linkmodes that ++ * are supported by the @interface mode and @mac_capabilities. @linkmodes ++ * must have been initialised previously. ++ */ ++void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface, ++ unsigned long mac_capabilities) ++{ ++ unsigned long caps = MAC_SYM_PAUSE | MAC_ASYM_PAUSE; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_USXGMII: ++ caps |= MAC_10000FD | MAC_5000FD | MAC_2500FD; ++ fallthrough; ++ ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_GMII: ++ caps |= MAC_1000HD | MAC_1000FD; ++ fallthrough; ++ ++ case PHY_INTERFACE_MODE_REVRMII: ++ case PHY_INTERFACE_MODE_RMII: ++ case PHY_INTERFACE_MODE_REVMII: ++ case PHY_INTERFACE_MODE_MII: ++ caps |= MAC_10HD | MAC_10FD; ++ fallthrough; ++ ++ case PHY_INTERFACE_MODE_100BASEX: ++ caps |= MAC_100HD | MAC_100FD; ++ break; ++ ++ case PHY_INTERFACE_MODE_TBI: ++ case PHY_INTERFACE_MODE_MOCA: ++ case PHY_INTERFACE_MODE_RTBI: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ caps |= MAC_1000HD; ++ fallthrough; ++ case PHY_INTERFACE_MODE_TRGMII: ++ caps |= MAC_1000FD; ++ break; ++ ++ case PHY_INTERFACE_MODE_2500BASEX: ++ caps |= MAC_2500FD; ++ break; ++ ++ case PHY_INTERFACE_MODE_5GBASER: ++ caps |= MAC_5000FD; ++ break; ++ ++ case PHY_INTERFACE_MODE_XGMII: ++ case PHY_INTERFACE_MODE_RXAUI: ++ case PHY_INTERFACE_MODE_XAUI: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_10GKR: ++ caps |= MAC_10000FD; ++ break; ++ ++ case PHY_INTERFACE_MODE_25GBASER: ++ caps |= MAC_25000FD; ++ break; ++ ++ case PHY_INTERFACE_MODE_XLGMII: ++ caps |= MAC_40000FD; ++ break; ++ ++ case PHY_INTERFACE_MODE_INTERNAL: ++ caps |= ~0; ++ break; ++ ++ case PHY_INTERFACE_MODE_NA: ++ case PHY_INTERFACE_MODE_MAX: ++ case PHY_INTERFACE_MODE_SMII: ++ break; ++ } ++ ++ phylink_caps_to_linkmodes(linkmodes, caps & mac_capabilities); ++} ++EXPORT_SYMBOL_GPL(phylink_get_linkmodes); ++ ++/** ++ * phylink_generic_validate() - generic validate() callback implementation ++ * @config: a pointer to a &struct phylink_config. ++ * @supported: ethtool bitmask for supported link modes. ++ * @state: a pointer to a &struct phylink_link_state. ++ * ++ * Generic implementation of the validate() callback that MAC drivers can ++ * use when they pass the range of supported interfaces and MAC capabilities. ++ * This makes use of phylink_get_linkmodes(). ++ */ ++void phylink_generic_validate(struct phylink_config *config, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; ++ ++ phylink_set_port_modes(mask); ++ phylink_set(mask, Autoneg); ++ phylink_get_linkmodes(mask, state->interface, config->mac_capabilities); ++ ++ linkmode_and(supported, supported, mask); ++ linkmode_and(state->advertising, state->advertising, mask); ++} ++EXPORT_SYMBOL_GPL(phylink_generic_validate); ++ + static int phylink_validate_any(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state) + { +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -20,6 +20,29 @@ enum { + MLO_AN_PHY = 0, /* Conventional PHY */ + MLO_AN_FIXED, /* Fixed-link mode */ + MLO_AN_INBAND, /* In-band protocol */ ++ ++ MAC_SYM_PAUSE = BIT(0), ++ MAC_ASYM_PAUSE = BIT(1), ++ MAC_10HD = BIT(2), ++ MAC_10FD = BIT(3), ++ MAC_10 = MAC_10HD | MAC_10FD, ++ MAC_100HD = BIT(4), ++ MAC_100FD = BIT(5), ++ MAC_100 = MAC_100HD | MAC_100FD, ++ MAC_1000HD = BIT(6), ++ MAC_1000FD = BIT(7), ++ MAC_1000 = MAC_1000HD | MAC_1000FD, ++ MAC_2500FD = BIT(8), ++ MAC_5000FD = BIT(9), ++ MAC_10000FD = BIT(10), ++ MAC_20000FD = BIT(11), ++ MAC_25000FD = BIT(12), ++ MAC_40000FD = BIT(13), ++ MAC_50000FD = BIT(14), ++ MAC_56000FD = BIT(15), ++ MAC_100000FD = BIT(16), ++ MAC_200000FD = BIT(17), ++ MAC_400000FD = BIT(18), + }; + + static inline bool phylink_autoneg_inband(unsigned int mode) +@@ -69,6 +92,7 @@ enum phylink_op_type { + * if MAC link is at %MLO_AN_FIXED mode. + * @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx + * are supported by the MAC/PCS. ++ * @mac_capabilities: MAC pause/speed/duplex capabilities. + */ + struct phylink_config { + struct device *dev; +@@ -79,6 +103,7 @@ struct phylink_config { + void (*get_fixed_state)(struct phylink_config *config, + struct phylink_link_state *state); + DECLARE_PHY_INTERFACE_MASK(supported_interfaces); ++ unsigned long mac_capabilities; + }; + + /** +@@ -460,6 +485,12 @@ void pcs_link_up(struct phylink_pcs *pcs + phy_interface_t interface, int speed, int duplex); + #endif + ++void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface, ++ unsigned long mac_capabilities); ++void phylink_generic_validate(struct phylink_config *config, ++ unsigned long *supported, ++ struct phylink_link_state *state); ++ + struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, + phy_interface_t iface, + const struct phylink_mac_ops *mac_ops); diff --git a/target/linux/generic/backport-5.15/703-10-v5.16-net-dsa-introduce-helpers-for-iterating-through-port.patch b/target/linux/generic/backport-5.15/703-10-v5.16-net-dsa-introduce-helpers-for-iterating-through-port.patch new file mode 100644 index 0000000000..a55623519c --- /dev/null +++ b/target/linux/generic/backport-5.15/703-10-v5.16-net-dsa-introduce-helpers-for-iterating-through-port.patch @@ -0,0 +1,68 @@ +From 82b318983c515f29b8b3a0dad9f6a5fe8a68a7f4 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Wed, 20 Oct 2021 20:49:49 +0300 +Subject: [PATCH] net: dsa: introduce helpers for iterating through ports using + dp + +Since the DSA conversion from the ds->ports array into the dst->ports +list, the DSA API has encouraged driver writers, as well as the core +itself, to write inefficient code. + +Currently, code that wants to filter by a specific type of port when +iterating, like {!unused, user, cpu, dsa}, uses the dsa_is_*_port helper. +Under the hood, this uses dsa_to_port which iterates again through +dst->ports. But the driver iterates through the port list already, so +the complexity is quadratic for the typical case of a single-switch +tree. + +This patch introduces some iteration helpers where the iterator is +already a struct dsa_port *dp, so that the other variant of the +filtering functions, dsa_port_is_{unused,user,cpu_dsa}, can be used +directly on the iterator. This eliminates the second lookup. + +These functions can be used both by the core and by drivers. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + include/net/dsa.h | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -476,6 +476,34 @@ static inline bool dsa_is_user_port(stru + return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_USER; + } + ++#define dsa_tree_for_each_user_port(_dp, _dst) \ ++ list_for_each_entry((_dp), &(_dst)->ports, list) \ ++ if (dsa_port_is_user((_dp))) ++ ++#define dsa_switch_for_each_port(_dp, _ds) \ ++ list_for_each_entry((_dp), &(_ds)->dst->ports, list) \ ++ if ((_dp)->ds == (_ds)) ++ ++#define dsa_switch_for_each_port_safe(_dp, _next, _ds) \ ++ list_for_each_entry_safe((_dp), (_next), &(_ds)->dst->ports, list) \ ++ if ((_dp)->ds == (_ds)) ++ ++#define dsa_switch_for_each_port_continue_reverse(_dp, _ds) \ ++ list_for_each_entry_continue_reverse((_dp), &(_ds)->dst->ports, list) \ ++ if ((_dp)->ds == (_ds)) ++ ++#define dsa_switch_for_each_available_port(_dp, _ds) \ ++ dsa_switch_for_each_port((_dp), (_ds)) \ ++ if (!dsa_port_is_unused((_dp))) ++ ++#define dsa_switch_for_each_user_port(_dp, _ds) \ ++ dsa_switch_for_each_port((_dp), (_ds)) \ ++ if (dsa_port_is_user((_dp))) ++ ++#define dsa_switch_for_each_cpu_port(_dp, _ds) \ ++ dsa_switch_for_each_port((_dp), (_ds)) \ ++ if (dsa_port_is_cpu((_dp))) ++ + static inline u32 dsa_user_ports(struct dsa_switch *ds) + { + u32 mask = 0; diff --git a/target/linux/generic/backport-5.15/703-11-v5.17-net-phylink-add-pcs_validate-method.patch b/target/linux/generic/backport-5.15/703-11-v5.17-net-phylink-add-pcs_validate-method.patch new file mode 100644 index 0000000000..add2e6e352 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-11-v5.17-net-phylink-add-pcs_validate-method.patch @@ -0,0 +1,106 @@ +From 0d22d4b626a4eaa3196019092eb6c1919e9f8caa Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 15 Dec 2021 15:34:20 +0000 +Subject: [PATCH] net: phylink: add pcs_validate() method + +Add a hook for PCS to validate the link parameters. This avoids MAC +drivers having to have knowledge of their PCS in their validate() +method, thereby allowing several MAC drivers to be simplfied. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 31 +++++++++++++++++++++++++++++++ + include/linux/phylink.h | 20 ++++++++++++++++++++ + 2 files changed, 51 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -160,13 +160,44 @@ static int phylink_validate_mac_and_pcs( + struct phylink_link_state *state) + { + struct phylink_pcs *pcs; ++ int ret; + ++ /* Get the PCS for this interface mode */ + if (pl->mac_ops->mac_select_pcs) { + pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); + if (IS_ERR(pcs)) + return PTR_ERR(pcs); ++ } else { ++ pcs = pl->pcs; + } + ++ if (pcs) { ++ /* The PCS, if present, must be setup before phylink_create() ++ * has been called. If the ops is not initialised, print an ++ * error and backtrace rather than oopsing the kernel. ++ */ ++ if (!pcs->ops) { ++ phylink_err(pl, "interface %s: uninitialised PCS\n", ++ phy_modes(state->interface)); ++ dump_stack(); ++ return -EINVAL; ++ } ++ ++ /* Validate the link parameters with the PCS */ ++ if (pcs->ops->pcs_validate) { ++ ret = pcs->ops->pcs_validate(pcs, supported, state); ++ if (ret < 0 || phylink_is_empty_linkmode(supported)) ++ return -EINVAL; ++ ++ /* Ensure the advertising mask is a subset of the ++ * supported mask. ++ */ ++ linkmode_and(state->advertising, state->advertising, ++ supported); ++ } ++ } ++ ++ /* Then validate the link parameters with the MAC */ + pl->mac_ops->validate(pl->config, supported, state); + + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -396,6 +396,7 @@ struct phylink_pcs { + + /** + * struct phylink_pcs_ops - MAC PCS operations structure. ++ * @pcs_validate: validate the link configuration. + * @pcs_get_state: read the current MAC PCS link state from the hardware. + * @pcs_config: configure the MAC PCS for the selected mode and state. + * @pcs_an_restart: restart 802.3z BaseX autonegotiation. +@@ -403,6 +404,8 @@ struct phylink_pcs { + * (where necessary). + */ + struct phylink_pcs_ops { ++ int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, ++ const struct phylink_link_state *state); + void (*pcs_get_state)(struct phylink_pcs *pcs, + struct phylink_link_state *state); + int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode, +@@ -416,6 +419,23 @@ struct phylink_pcs_ops { + + #if 0 /* For kernel-doc purposes only. */ + /** ++ * pcs_validate() - validate the link configuration. ++ * @pcs: a pointer to a &struct phylink_pcs. ++ * @supported: ethtool bitmask for supported link modes. ++ * @state: a const pointer to a &struct phylink_link_state. ++ * ++ * Validate the interface mode, and advertising's autoneg bit, removing any ++ * media ethtool link modes that would not be supportable from the supported ++ * mask. Phylink will propagate the changes to the advertising mask. See the ++ * &struct phylink_mac_ops validate() method. ++ * ++ * Returns -EINVAL if the interface mode/autoneg mode is not supported. ++ * Returns non-zero positive if the link state can be supported. ++ */ ++int pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, ++ const struct phylink_link_state *state); ++ ++/** + * pcs_get_state() - Read the current inband link state from the hardware + * @pcs: a pointer to a &struct phylink_pcs. + * @state: a pointer to a &struct phylink_link_state. diff --git a/target/linux/generic/backport-5.15/703-12-v5.17-net-phylink-add-legacy_pre_march2020-indicator.patch b/target/linux/generic/backport-5.15/703-12-v5.17-net-phylink-add-legacy_pre_march2020-indicator.patch new file mode 100644 index 0000000000..6fbde12507 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-12-v5.17-net-phylink-add-legacy_pre_march2020-indicator.patch @@ -0,0 +1,43 @@ +From 3e5b1feccea7db576353ffc302f78d522e4116e6 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 9 Dec 2021 13:11:32 +0000 +Subject: [PATCH] net: phylink: add legacy_pre_march2020 indicator + +Add a boolean to phylink_config to indicate whether a driver has not +been updated for the changes in commit 7cceb599d15d ("net: phylink: +avoid mac_config calls"), and thus are reliant on the old behaviour. + +We were currently keying the phylink behaviour on the presence of a +PCS, but this is sub-optimal for modern drivers that may not have a +PCS. + +This commit merely introduces the new flag, but does not add any use, +since we need all legacy drivers to set this flag before it can be +used. Once these legacy drivers have been updated, we can remove this +flag. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + include/linux/phylink.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -84,6 +84,8 @@ enum phylink_op_type { + * struct phylink_config - PHYLINK configuration structure + * @dev: a pointer to a struct device associated with the MAC + * @type: operation type of PHYLINK instance ++ * @legacy_pre_march2020: driver has not been updated for March 2020 updates ++ * (See commit 7cceb599d15d ("net: phylink: avoid mac_config calls") + * @pcs_poll: MAC PCS cannot provide link change interrupt + * @poll_fixed_state: if true, starts link_poll, + * if MAC link is at %MLO_AN_FIXED mode. +@@ -97,6 +99,7 @@ enum phylink_op_type { + struct phylink_config { + struct device *dev; + enum phylink_op_type type; ++ bool legacy_pre_march2020; + bool pcs_poll; + bool poll_fixed_state; + bool ovr_an_inband; diff --git a/target/linux/generic/backport-5.15/703-13-v5.17-net-dsa-mark-DSA-phylink-as-legacy_pre_march2020.patch b/target/linux/generic/backport-5.15/703-13-v5.17-net-dsa-mark-DSA-phylink-as-legacy_pre_march2020.patch new file mode 100644 index 0000000000..dff0db5db6 --- /dev/null +++ b/target/linux/generic/backport-5.15/703-13-v5.17-net-dsa-mark-DSA-phylink-as-legacy_pre_march2020.patch @@ -0,0 +1,36 @@ +From 0a9f0794d9bd67e590a9488afe87fbb0419d9539 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 9 Dec 2021 13:11:38 +0000 +Subject: [PATCH] net: dsa: mark DSA phylink as legacy_pre_march2020 + +The majority of DSA drivers do not make use of the PCS support, and +thus operate in legacy mode. In order to preserve this behaviour in +future, we need to set the legacy_pre_march2020 flag so phylink knows +this may require the legacy calls. + +There are some DSA drivers that do make use of PCS support, and these +will continue operating as before - legacy_pre_march2020 will not +prevent split-PCS support enabling the newer phylink behaviour. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + net/dsa/port.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1110,6 +1110,13 @@ int dsa_port_phylink_create(struct dsa_p + if (err) + mode = PHY_INTERFACE_MODE_NA; + ++ /* Presence of phylink_mac_link_state or phylink_mac_an_restart is ++ * an indicator of a legacy phylink driver. ++ */ ++ if (ds->ops->phylink_mac_link_state || ++ ds->ops->phylink_mac_an_restart) ++ dp->pl_config.legacy_pre_march2020 = true; ++ + if (ds->ops->phylink_get_caps) + ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config); + diff --git a/target/linux/generic/backport-5.15/703-14-v5.17-net-phylink-use-legacy_pre_march2020.patch b/target/linux/generic/backport-5.15/703-14-v5.17-net-phylink-use-legacy_pre_march2020.patch new file mode 100644 index 0000000000..361fa10d4d --- /dev/null +++ b/target/linux/generic/backport-5.15/703-14-v5.17-net-phylink-use-legacy_pre_march2020.patch @@ -0,0 +1,115 @@ +From 001f4261fe4d5ae710cf1f445b6cae6d9d3ae26e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 9 Dec 2021 13:11:48 +0000 +Subject: [PATCH] net: phylink: use legacy_pre_march2020 + +Use the legacy flag to indicate whether we should operate in legacy +mode. This allows us to stop using the presence of a PCS as an +indicator to the age of the phylink user, and make PCS presence +optional. + +Legacy mode involves: +1) calling mac_config() whenever the link comes up +2) calling mac_config() whenever the inband advertisement changes, + possibly followed by a call to mac_an_restart() +3) making use of mac_an_restart() +4) making use of mac_pcs_get_state() + +All the above functionality was moved to a seperate "PCS" block of +operations in March 2020. + +Update the documents to indicate that the differences that this flag +makes. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 12 ++++++------ + include/linux/phylink.h | 17 +++++++++++++++++ + 2 files changed, 23 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -777,7 +777,7 @@ static void phylink_mac_pcs_an_restart(s + phylink_autoneg_inband(pl->cur_link_an_mode)) { + if (pl->pcs_ops) + pl->pcs_ops->pcs_an_restart(pl->pcs); +- else ++ else if (pl->config->legacy_pre_march2020) + pl->mac_ops->mac_an_restart(pl->config); + } + } +@@ -855,7 +855,7 @@ static int phylink_change_inband_advert( + if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) + return 0; + +- if (!pl->pcs_ops) { ++ if (!pl->pcs_ops && pl->config->legacy_pre_march2020) { + /* Legacy method */ + phylink_mac_config(pl, &pl->link_config); + phylink_mac_pcs_an_restart(pl); +@@ -900,7 +900,8 @@ static void phylink_mac_pcs_get_state(st + + if (pl->pcs_ops) + pl->pcs_ops->pcs_get_state(pl->pcs, state); +- else if (pl->mac_ops->mac_pcs_get_state) ++ else if (pl->mac_ops->mac_pcs_get_state && ++ pl->config->legacy_pre_march2020) + pl->mac_ops->mac_pcs_get_state(pl->config, state); + else + state->link = 0; +@@ -1094,12 +1095,11 @@ static void phylink_resolve(struct work_ + } + phylink_major_config(pl, false, &link_state); + pl->link_config.interface = link_state.interface; +- } else if (!pl->pcs_ops) { ++ } else if (!pl->pcs_ops && pl->config->legacy_pre_march2020) { + /* The interface remains unchanged, only the speed, + * duplex or pause settings have changed. Call the + * old mac_config() method to configure the MAC/PCS +- * only if we do not have a PCS installed (an +- * unconverted user.) ++ * only if we do not have a legacy MAC driver. + */ + phylink_mac_config(pl, &link_state); + } +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -208,6 +208,10 @@ struct phylink_pcs *mac_select_pcs(struc + * negotiation completion state in @state->an_complete, and link up state + * in @state->link. If possible, @state->lp_advertising should also be + * populated. ++ * ++ * Note: This is a legacy method. This function will not be called unless ++ * legacy_pre_march2020 is set in &struct phylink_config and there is no ++ * PCS attached. + */ + void mac_pcs_get_state(struct phylink_config *config, + struct phylink_link_state *state); +@@ -248,6 +252,15 @@ int mac_prepare(struct phylink_config *c + * guaranteed to be correct, and so any mac_config() implementation must + * never reference these fields. + * ++ * Note: For legacy March 2020 drivers (drivers with legacy_pre_march2020 set ++ * in their &phylnk_config and which don't have a PCS), this function will be ++ * called on each link up event, and to also change the in-band advert. For ++ * non-legacy drivers, it will only be called to reconfigure the MAC for a ++ * "major" change in e.g. interface mode. It will not be called for changes ++ * in speed, duplex or pause modes or to change the in-band advertisement. ++ * In any case, it is strongly preferred that speed, duplex and pause settings ++ * are handled in the mac_link_up() method and not in this method. ++ * + * (this requires a rewrite - please refer to mac_link_up() for situations + * where the PCS and MAC are not tightly integrated.) + * +@@ -332,6 +345,10 @@ int mac_finish(struct phylink_config *co + /** + * mac_an_restart() - restart 802.3z BaseX autonegotiation + * @config: a pointer to a &struct phylink_config. ++ * ++ * Note: This is a legacy method. This function will not be called unless ++ * legacy_pre_march2020 is set in &struct phylink_config and there is no ++ * PCS attached. + */ + void mac_an_restart(struct phylink_config *config); + diff --git a/target/linux/generic/backport-5.15/704-01-v5.17-net-mtk_eth_soc-populate-supported_interfaces-member.patch b/target/linux/generic/backport-5.15/704-01-v5.17-net-mtk_eth_soc-populate-supported_interfaces-member.patch new file mode 100644 index 0000000000..43e1f9cc31 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-01-v5.17-net-mtk_eth_soc-populate-supported_interfaces-member.patch @@ -0,0 +1,43 @@ +From 83800d29f0c578e82554e7d4c6bfdbdf9b6cf428 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 16 Nov 2021 10:06:43 +0000 +Subject: [PATCH] net: mtk_eth_soc: populate supported_interfaces member + +Populate the phy interface mode bitmap for the Mediatek driver with +interfaces modes supported by the MAC. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3352,6 +3352,26 @@ static int mtk_add_mac(struct mtk_eth *e + + mac->phylink_config.dev = ð->netdev[id]->dev; + mac->phylink_config.type = PHYLINK_NETDEV; ++ __set_bit(PHY_INTERFACE_MODE_MII, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_GMII, ++ mac->phylink_config.supported_interfaces); ++ ++ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) ++ phy_interface_set_rgmii(mac->phylink_config.supported_interfaces); ++ ++ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id) ++ __set_bit(PHY_INTERFACE_MODE_TRGMII, ++ mac->phylink_config.supported_interfaces); ++ ++ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { ++ __set_bit(PHY_INTERFACE_MODE_SGMII, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, ++ mac->phylink_config.supported_interfaces); ++ } + + phylink = phylink_create(&mac->phylink_config, + of_fwnode_handle(mac->of_node), diff --git a/target/linux/generic/backport-5.15/704-02-v5.17-net-mtk_eth_soc-remove-interface-checks-in-mtk_valid.patch b/target/linux/generic/backport-5.15/704-02-v5.17-net-mtk_eth_soc-remove-interface-checks-in-mtk_valid.patch new file mode 100644 index 0000000000..05a84c4f67 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-02-v5.17-net-mtk_eth_soc-remove-interface-checks-in-mtk_valid.patch @@ -0,0 +1,75 @@ +From db81ca153814475d7e07365d46a4d1134bd122e2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 16 Nov 2021 10:06:48 +0000 +Subject: [PATCH] net: mtk_eth_soc: remove interface checks in mtk_validate() + +As phylink checks the interface mode against the supported_interfaces +bitmap, we no longer need to validate the interface mode, nor handle +PHY_INTERFACE_MODE_NA in the validation function. Remove these to +simplify the implementation. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 --------------------- + 1 file changed, 34 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -567,24 +567,8 @@ static void mtk_validate(struct phylink_ + unsigned long *supported, + struct phylink_link_state *state) + { +- struct mtk_mac *mac = container_of(config, struct mtk_mac, +- phylink_config); + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_MII && +- state->interface != PHY_INTERFACE_MODE_GMII && +- !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII) && +- phy_interface_mode_is_rgmii(state->interface)) && +- !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && +- !mac->id && state->interface == PHY_INTERFACE_MODE_TRGMII) && +- !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII) && +- (state->interface == PHY_INTERFACE_MODE_SGMII || +- phy_interface_mode_is_8023z(state->interface)))) { +- linkmode_zero(supported); +- return; +- } +- + phylink_set_port_modes(mask); + phylink_set(mask, Autoneg); + +@@ -611,7 +595,6 @@ static void mtk_validate(struct phylink_ + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_RMII: + case PHY_INTERFACE_MODE_REVMII: +- case PHY_INTERFACE_MODE_NA: + default: + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); +@@ -620,23 +603,6 @@ static void mtk_validate(struct phylink_ + break; + } + +- if (state->interface == PHY_INTERFACE_MODE_NA) { +- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseX_Full); +- phylink_set(mask, 2500baseX_Full); +- } +- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) { +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseT_Half); +- phylink_set(mask, 1000baseX_Full); +- } +- if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GEPHY)) { +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseT_Half); +- } +- } +- + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + diff --git a/target/linux/generic/backport-5.15/704-03-v5.17-net-mtk_eth_soc-drop-use-of-phylink_helper_basex_spe.patch b/target/linux/generic/backport-5.15/704-03-v5.17-net-mtk_eth_soc-drop-use-of-phylink_helper_basex_spe.patch new file mode 100644 index 0000000000..a3cfab7f88 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-03-v5.17-net-mtk_eth_soc-drop-use-of-phylink_helper_basex_spe.patch @@ -0,0 +1,42 @@ +From 71d927494463c4f016d828e1134da26b7e961af5 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 16 Nov 2021 10:06:53 +0000 +Subject: [PATCH] net: mtk_eth_soc: drop use of phylink_helper_basex_speed() + +Now that we have a better method to select SFP interface modes, we +no longer need to use phylink_helper_basex_speed() in a driver's +validation function, and we can also get rid of our hack to indicate +both 1000base-X and 2500base-X if the comphy is present to make that +work. Remove this hack and use of phylink_helper_basex_speed(). + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -577,8 +577,9 @@ static void mtk_validate(struct phylink_ + phylink_set(mask, 1000baseT_Full); + break; + case PHY_INTERFACE_MODE_1000BASEX: +- case PHY_INTERFACE_MODE_2500BASEX: + phylink_set(mask, 1000baseX_Full); ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: + phylink_set(mask, 2500baseX_Full); + break; + case PHY_INTERFACE_MODE_GMII: +@@ -608,11 +609,6 @@ static void mtk_validate(struct phylink_ + + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); +- +- /* We can only operate at 2500BaseX or 1000BaseX. If requested +- * to advertise both, only report advertising at 2500BaseX. +- */ +- phylink_helper_basex_speed(state); + } + + static const struct phylink_mac_ops mtk_phylink_ops = { diff --git a/target/linux/generic/backport-5.15/704-04-v5.17-net-mtk_eth_soc-use-phylink_generic_validate.patch b/target/linux/generic/backport-5.15/704-04-v5.17-net-mtk_eth_soc-use-phylink_generic_validate.patch new file mode 100644 index 0000000000..7f3734a765 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-04-v5.17-net-mtk_eth_soc-use-phylink_generic_validate.patch @@ -0,0 +1,84 @@ +From a4238f6ce151afa331375d74a5033b76da637644 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Tue, 16 Nov 2021 10:06:58 +0000 +Subject: [PATCH] net: mtk_eth_soc: use phylink_generic_validate() + +mtk_eth_soc has no special behaviour in its validation implementation, +so can be switched to phylink_generic_validate(). + +Signed-off-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 53 ++------------------- + 1 file changed, 4 insertions(+), 49 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -563,56 +563,8 @@ static void mtk_mac_link_up(struct phyli + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + +-static void mtk_validate(struct phylink_config *config, +- unsigned long *supported, +- struct phylink_link_state *state) +-{ +- __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; +- +- phylink_set_port_modes(mask); +- phylink_set(mask, Autoneg); +- +- switch (state->interface) { +- case PHY_INTERFACE_MODE_TRGMII: +- phylink_set(mask, 1000baseT_Full); +- break; +- case PHY_INTERFACE_MODE_1000BASEX: +- phylink_set(mask, 1000baseX_Full); +- break; +- case PHY_INTERFACE_MODE_2500BASEX: +- phylink_set(mask, 2500baseX_Full); +- break; +- case PHY_INTERFACE_MODE_GMII: +- case PHY_INTERFACE_MODE_RGMII: +- case PHY_INTERFACE_MODE_RGMII_ID: +- case PHY_INTERFACE_MODE_RGMII_RXID: +- case PHY_INTERFACE_MODE_RGMII_TXID: +- phylink_set(mask, 1000baseT_Half); +- fallthrough; +- case PHY_INTERFACE_MODE_SGMII: +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseX_Full); +- fallthrough; +- case PHY_INTERFACE_MODE_MII: +- case PHY_INTERFACE_MODE_RMII: +- case PHY_INTERFACE_MODE_REVMII: +- default: +- phylink_set(mask, 10baseT_Half); +- phylink_set(mask, 10baseT_Full); +- phylink_set(mask, 100baseT_Half); +- phylink_set(mask, 100baseT_Full); +- break; +- } +- +- phylink_set(mask, Pause); +- phylink_set(mask, Asym_Pause); +- +- linkmode_and(supported, supported, mask); +- linkmode_and(state->advertising, state->advertising, mask); +-} +- + static const struct phylink_mac_ops mtk_phylink_ops = { +- .validate = mtk_validate, ++ .validate = phylink_generic_validate, + .mac_pcs_get_state = mtk_mac_pcs_get_state, + .mac_an_restart = mtk_mac_an_restart, + .mac_config = mtk_mac_config, +@@ -3314,6 +3266,9 @@ static int mtk_add_mac(struct mtk_eth *e + + mac->phylink_config.dev = ð->netdev[id]->dev; + mac->phylink_config.type = PHYLINK_NETDEV; ++ mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; ++ + __set_bit(PHY_INTERFACE_MODE_MII, + mac->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_GMII, diff --git a/target/linux/generic/backport-5.15/704-05-v5.17-net-mtk_eth_soc-mark-as-a-legacy_pre_march2020-drive.patch b/target/linux/generic/backport-5.15/704-05-v5.17-net-mtk_eth_soc-mark-as-a-legacy_pre_march2020-drive.patch new file mode 100644 index 0000000000..6aa99acf77 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-05-v5.17-net-mtk_eth_soc-mark-as-a-legacy_pre_march2020-drive.patch @@ -0,0 +1,29 @@ +From b06515367facfadcf5e70cf6f39db749cf4eb5e3 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 9 Dec 2021 13:11:43 +0000 +Subject: [PATCH] net: mtk_eth_soc: mark as a legacy_pre_march2020 driver + +mtk_eth_soc has not been updated for commit 7cceb599d15d ("net: phylink: +avoid mac_config calls"), and makes use of state->speed and +state->duplex in contravention of the phylink documentation. This makes +reliant on the legacy behaviours, so mark it as a legacy driver. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3266,6 +3266,10 @@ static int mtk_add_mac(struct mtk_eth *e + + mac->phylink_config.dev = ð->netdev[id]->dev; + mac->phylink_config.type = PHYLINK_NETDEV; ++ /* This driver makes use of state->speed/state->duplex in ++ * mac_config ++ */ ++ mac->phylink_config.legacy_pre_march2020 = true; + mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; + diff --git a/target/linux/generic/backport-5.15/704-06-v5.19-eth-mtk_eth_soc-remove-a-copy-of-the-NAPI_POLL_WEIGH.patch b/target/linux/generic/backport-5.15/704-06-v5.19-eth-mtk_eth_soc-remove-a-copy-of-the-NAPI_POLL_WEIGH.patch new file mode 100644 index 0000000000..e5f70e36f0 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-06-v5.19-eth-mtk_eth_soc-remove-a-copy-of-the-NAPI_POLL_WEIGH.patch @@ -0,0 +1,40 @@ +From 889e3691b9d6573de133da1f5e78f590e52152cd Mon Sep 17 00:00:00 2001 +From: Jakub Kicinski +Date: Thu, 28 Apr 2022 14:23:13 -0700 +Subject: [PATCH] eth: mtk_eth_soc: remove a copy of the NAPI_POLL_WEIGHT + define + +Defining local versions of NAPI_POLL_WEIGHT with the same +values in the drivers just makes refactoring harder. + +Signed-off-by: Jakub Kicinski +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 - + 2 files changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3565,9 +3565,9 @@ static int mtk_probe(struct platform_dev + */ + init_dummy_netdev(ð->dummy_dev); + netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx, +- MTK_NAPI_WEIGHT); ++ NAPI_POLL_WEIGHT); + netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx, +- MTK_NAPI_WEIGHT); ++ NAPI_POLL_WEIGHT); + + platform_set_drvdata(pdev, eth); + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -25,7 +25,6 @@ + #define MTK_TX_DMA_BUF_LEN 0x3fff + #define MTK_TX_DMA_BUF_LEN_V2 0xffff + #define MTK_DMA_SIZE 512 +-#define MTK_NAPI_WEIGHT 64 + #define MTK_MAC_COUNT 2 + #define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) + #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) diff --git a/target/linux/generic/backport-5.15/704-07-v5.19-mtk_eth_soc-remove-unused-mac-mode.patch b/target/linux/generic/backport-5.15/704-07-v5.19-mtk_eth_soc-remove-unused-mac-mode.patch new file mode 100644 index 0000000000..4d896cdf39 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-07-v5.19-mtk_eth_soc-remove-unused-mac-mode.patch @@ -0,0 +1,35 @@ +From 0600bdde1fae75fb9bad72033d28edddc72b44b2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:54:31 +0100 +Subject: [PATCH 01/12] net: mtk_eth_soc: remove unused mac->mode + +mac->mode is only ever written to in one location, and is thus +superflous. Remove it. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 - + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 - + 2 files changed, 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3261,7 +3261,6 @@ static int mtk_add_mac(struct mtk_eth *e + + /* mac config is not set */ + mac->interface = PHY_INTERFACE_MODE_NA; +- mac->mode = MLO_AN_PHY; + mac->speed = SPEED_UNKNOWN; + + mac->phylink_config.dev = ð->netdev[id]->dev; +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1085,7 +1085,6 @@ struct mtk_eth { + struct mtk_mac { + int id; + phy_interface_t interface; +- unsigned int mode; + int speed; + struct device_node *of_node; + struct phylink *phylink; diff --git a/target/linux/generic/backport-5.15/704-08-v5.19-net-mtk_eth_soc-remove-unused-sgmii-flags.patch b/target/linux/generic/backport-5.15/704-08-v5.19-net-mtk_eth_soc-remove-unused-sgmii-flags.patch new file mode 100644 index 0000000000..39aa24157e --- /dev/null +++ b/target/linux/generic/backport-5.15/704-08-v5.19-net-mtk_eth_soc-remove-unused-sgmii-flags.patch @@ -0,0 +1,40 @@ +From 5a7a2f4b29d7546244da7d8bbc1962fce5b230f2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:54:36 +0100 +Subject: [PATCH 02/12] net: mtk_eth_soc: remove unused sgmii flags + +The "flags" member of struct mtk_sgmii appears to be unused, as are +the MTK_SGMII_PHYSPEED_* and MTK_HAS_FLAGS() macros. Remove them. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 -------- + 1 file changed, 8 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -956,23 +956,15 @@ struct mtk_soc_data { + /* currently no SoC has more than 2 macs */ + #define MTK_MAX_DEVS 2 + +-#define MTK_SGMII_PHYSPEED_AN BIT(31) +-#define MTK_SGMII_PHYSPEED_MASK GENMASK(2, 0) +-#define MTK_SGMII_PHYSPEED_1000 BIT(0) +-#define MTK_SGMII_PHYSPEED_2500 BIT(1) +-#define MTK_HAS_FLAGS(flags, _x) (((flags) & (_x)) == (_x)) +- + /* struct mtk_sgmii - This is the structure holding sgmii regmap and its + * characteristics + * @regmap: The register map pointing at the range used to setup + * SGMII modes +- * @flags: The enum refers to which mode the sgmii wants to run on + * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap + */ + + struct mtk_sgmii { + struct regmap *regmap[MTK_MAX_DEVS]; +- u32 flags[MTK_MAX_DEVS]; + u32 ana_rgc3; + }; + diff --git a/target/linux/generic/backport-5.15/704-09-v5.19-net-mtk_eth_soc-add-mask-and-update-PCS-speed-defini.patch b/target/linux/generic/backport-5.15/704-09-v5.19-net-mtk_eth_soc-add-mask-and-update-PCS-speed-defini.patch new file mode 100644 index 0000000000..f2e1f86bac --- /dev/null +++ b/target/linux/generic/backport-5.15/704-09-v5.19-net-mtk_eth_soc-add-mask-and-update-PCS-speed-defini.patch @@ -0,0 +1,40 @@ +From bc5e93e0cd22e360eda23859b939280205567580 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:54:42 +0100 +Subject: [PATCH 03/12] net: mtk_eth_soc: add mask and update PCS speed + definitions + +The PCS speed setting is a two bit field, but it is defined as two +separate bits. Add a bitfield mask for the speed definitions, an + use the FIELD_PREP() macro to define each PCS speed. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include "mtk_ppe.h" + + #define MTK_QDMA_PAGE_SIZE 2048 +@@ -473,9 +474,10 @@ + #define SGMSYS_SGMII_MODE 0x20 + #define SGMII_IF_MODE_BIT0 BIT(0) + #define SGMII_SPEED_DUPLEX_AN BIT(1) +-#define SGMII_SPEED_10 0x0 +-#define SGMII_SPEED_100 BIT(2) +-#define SGMII_SPEED_1000 BIT(3) ++#define SGMII_SPEED_MASK GENMASK(3, 2) ++#define SGMII_SPEED_10 FIELD_PREP(SGMII_SPEED_MASK, 0) ++#define SGMII_SPEED_100 FIELD_PREP(SGMII_SPEED_MASK, 1) ++#define SGMII_SPEED_1000 FIELD_PREP(SGMII_SPEED_MASK, 2) + #define SGMII_DUPLEX_FULL BIT(4) + #define SGMII_IF_MODE_BIT5 BIT(5) + #define SGMII_REMOTE_FAULT_DIS BIT(8) diff --git a/target/linux/generic/backport-5.15/704-10-v5.19-net-mtk_eth_soc-correct-802.3z-speed-setting.patch b/target/linux/generic/backport-5.15/704-10-v5.19-net-mtk_eth_soc-correct-802.3z-speed-setting.patch new file mode 100644 index 0000000000..fb1ee4e310 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-10-v5.19-net-mtk_eth_soc-correct-802.3z-speed-setting.patch @@ -0,0 +1,60 @@ +From 7da3f901f8ecb425105fad39a0f5de73306abe52 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:54:47 +0100 +Subject: [PATCH 04/12] net: mtk_eth_soc: correct 802.3z speed setting + +Phylink does not guarantee that state->speed will be set correctly in +the mac_config() call, so it's a bug that the driver makes use of it. +Moreover, it is making use of it in a function that is only ever called +for 1000BASE-X and 2500BASE-X which operate at a fixed speed which +happens to be the same setting irrespective of the interface mode. We +can simply remove the switch statement and just set the SGMII interface +speed. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -34,6 +34,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + return 0; + } + ++/* For SGMII interface mode */ + int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id) + { + unsigned int val; +@@ -60,6 +61,9 @@ int mtk_sgmii_setup_mode_an(struct mtk_s + return 0; + } + ++/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a ++ * fixed speed. ++ */ + int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, + const struct phylink_link_state *state) + { +@@ -82,19 +86,7 @@ int mtk_sgmii_setup_mode_force(struct mt + /* SGMII force mode setting */ + regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); + val &= ~SGMII_IF_MODE_MASK; +- +- switch (state->speed) { +- case SPEED_10: +- val |= SGMII_SPEED_10; +- break; +- case SPEED_100: +- val |= SGMII_SPEED_100; +- break; +- case SPEED_2500: +- case SPEED_1000: +- val |= SGMII_SPEED_1000; +- break; +- } ++ val |= SGMII_SPEED_1000; + + if (state->duplex == DUPLEX_FULL) + val |= SGMII_DUPLEX_FULL; diff --git a/target/linux/generic/backport-5.15/704-11-v5.19-net-mtk_eth_soc-correct-802.3z-duplex-setting.patch b/target/linux/generic/backport-5.15/704-11-v5.19-net-mtk_eth_soc-correct-802.3z-duplex-setting.patch new file mode 100644 index 0000000000..140ff3cab5 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-11-v5.19-net-mtk_eth_soc-correct-802.3z-duplex-setting.patch @@ -0,0 +1,101 @@ +From a459187390bb221827f9c07866c3a5ffbdf9622b Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Wed, 18 May 2022 15:54:52 +0100 +Subject: [PATCH 05/12] net: mtk_eth_soc: correct 802.3z duplex setting + +Phylink does not guarantee that state->duplex will be set correctly in +the mac_config() call, so it's a bug that the driver makes use of it. + +Move the 802.3z PCS duplex configuration to mac_link_up(). + +Signed-off-by: Russell King +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 16 +++++++++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + + drivers/net/ethernet/mediatek/mtk_sgmii.c | 22 +++++++++++++++------ + 3 files changed, 29 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -532,8 +532,18 @@ static void mtk_mac_link_up(struct phyli + { + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); +- u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); ++ u32 mcr; + ++ if (phy_interface_mode_is_8023z(interface)) { ++ struct mtk_eth *eth = mac->hw; ++ ++ /* Decide how GMAC and SGMIISYS be mapped */ ++ int sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? ++ 0 : mac->id; ++ mtk_sgmii_link_up(eth->sgmii, sid, speed, duplex); ++ } ++ ++ mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 | + MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC | + MAC_MCR_FORCE_RX_FC); +@@ -3265,9 +3275,7 @@ static int mtk_add_mac(struct mtk_eth *e + + mac->phylink_config.dev = ð->netdev[id]->dev; + mac->phylink_config.type = PHYLINK_NETDEV; +- /* This driver makes use of state->speed/state->duplex in +- * mac_config +- */ ++ /* This driver makes use of state->speed in mac_config */ + mac->phylink_config.legacy_pre_march2020 = true; + mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1103,6 +1103,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id); + int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, + const struct phylink_link_state *state); ++void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex); + void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id); + + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -83,14 +83,10 @@ int mtk_sgmii_setup_mode_force(struct mt + val &= ~SGMII_AN_ENABLE; + regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val); + +- /* SGMII force mode setting */ ++ /* Set the speed etc but leave the duplex unchanged */ + regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); +- val &= ~SGMII_IF_MODE_MASK; ++ val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK; + val |= SGMII_SPEED_1000; +- +- if (state->duplex == DUPLEX_FULL) +- val |= SGMII_DUPLEX_FULL; +- + regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val); + + /* Release PHYA power down state */ +@@ -101,6 +97,20 @@ int mtk_sgmii_setup_mode_force(struct mt + return 0; + } + ++/* For 1000BASE-X and 2500BASE-X interface modes */ ++void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex) ++{ ++ unsigned int val; ++ ++ /* SGMII force duplex setting */ ++ regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); ++ val &= ~SGMII_DUPLEX_FULL; ++ if (duplex == DUPLEX_FULL) ++ val |= SGMII_DUPLEX_FULL; ++ ++ regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val); ++} ++ + void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id) + { + struct mtk_sgmii *ss = eth->sgmii; diff --git a/target/linux/generic/backport-5.15/704-12-v5.19-net-mtk_eth_soc-stop-passing-phylink-state-to-sgmii-.patch b/target/linux/generic/backport-5.15/704-12-v5.19-net-mtk_eth_soc-stop-passing-phylink-state-to-sgmii-.patch new file mode 100644 index 0000000000..56b5e43e53 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-12-v5.19-net-mtk_eth_soc-stop-passing-phylink-state-to-sgmii-.patch @@ -0,0 +1,60 @@ +From 4ce5a0bd3958ed248f0325bfcb95339f7c74feb2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:54:57 +0100 +Subject: [PATCH 06/12] net: mtk_eth_soc: stop passing phylink state to sgmii + setup + +Now that mtk_sgmii_setup_mode_force() only uses the interface mode +from the phylink state, pass just the interface mode into this +function. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -437,7 +437,7 @@ static void mtk_mac_config(struct phylin + /* Setup SGMIISYS with the determined property */ + if (state->interface != PHY_INTERFACE_MODE_SGMII) + err = mtk_sgmii_setup_mode_force(eth->sgmii, sid, +- state); ++ state->interface); + else if (phylink_autoneg_inband(mode)) + err = mtk_sgmii_setup_mode_an(eth->sgmii, sid); + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1102,7 +1102,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + u32 ana_rgc3); + int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id); + int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, +- const struct phylink_link_state *state); ++ phy_interface_t interface); + void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex); + void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id); + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -65,7 +65,7 @@ int mtk_sgmii_setup_mode_an(struct mtk_s + * fixed speed. + */ + int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, +- const struct phylink_link_state *state) ++ phy_interface_t interface) + { + unsigned int val; + +@@ -74,7 +74,7 @@ int mtk_sgmii_setup_mode_force(struct mt + + regmap_read(ss->regmap[id], ss->ana_rgc3, &val); + val &= ~RG_PHY_SPEED_MASK; +- if (state->interface == PHY_INTERFACE_MODE_2500BASEX) ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) + val |= RG_PHY_SPEED_3_125G; + regmap_write(ss->regmap[id], ss->ana_rgc3, val); + diff --git a/target/linux/generic/backport-5.15/704-13-v5.19-net-mtk_eth_soc-provide-mtk_sgmii_config.patch b/target/linux/generic/backport-5.15/704-13-v5.19-net-mtk_eth_soc-provide-mtk_sgmii_config.patch new file mode 100644 index 0000000000..4c91cf68f4 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-13-v5.19-net-mtk_eth_soc-provide-mtk_sgmii_config.patch @@ -0,0 +1,89 @@ +From 1ec619ee4a052fb9ac48b57554ac2722a0bfe73c Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:55:02 +0100 +Subject: [PATCH 07/12] net: mtk_eth_soc: provide mtk_sgmii_config() + +Provide mtk_sgmii_config() to wrap up the decisions about which SGMII +configuration will be called. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +------ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 ++--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 20 +++++++++++++++++--- + 3 files changed, 20 insertions(+), 12 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -435,12 +435,7 @@ static void mtk_mac_config(struct phylin + 0 : mac->id; + + /* Setup SGMIISYS with the determined property */ +- if (state->interface != PHY_INTERFACE_MODE_SGMII) +- err = mtk_sgmii_setup_mode_force(eth->sgmii, sid, +- state->interface); +- else if (phylink_autoneg_inband(mode)) +- err = mtk_sgmii_setup_mode_an(eth->sgmii, sid); +- ++ err = mtk_sgmii_config(eth->sgmii, sid, mode, state->interface); + if (err) + goto init_err; + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1100,9 +1100,8 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne + + int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np, + u32 ana_rgc3); +-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id); +-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, +- phy_interface_t interface); ++int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode, ++ phy_interface_t interface); + void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex); + void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id); + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -35,7 +35,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + } + + /* For SGMII interface mode */ +-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id) ++static int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id) + { + unsigned int val; + +@@ -64,8 +64,8 @@ int mtk_sgmii_setup_mode_an(struct mtk_s + /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a + * fixed speed. + */ +-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, +- phy_interface_t interface) ++static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, ++ phy_interface_t interface) + { + unsigned int val; + +@@ -97,6 +97,20 @@ int mtk_sgmii_setup_mode_force(struct mt + return 0; + } + ++int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode, ++ phy_interface_t interface) ++{ ++ int err = 0; ++ ++ /* Setup SGMIISYS with the determined property */ ++ if (interface != PHY_INTERFACE_MODE_SGMII) ++ err = mtk_sgmii_setup_mode_force(ss, id, interface); ++ else if (phylink_autoneg_inband(mode)) ++ err = mtk_sgmii_setup_mode_an(ss, id); ++ ++ return err; ++} ++ + /* For 1000BASE-X and 2500BASE-X interface modes */ + void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex) + { diff --git a/target/linux/generic/backport-5.15/704-14-v5.19-net-mtk_eth_soc-add-fixme-comment-for-state-speed-us.patch b/target/linux/generic/backport-5.15/704-14-v5.19-net-mtk_eth_soc-add-fixme-comment-for-state-speed-us.patch new file mode 100644 index 0000000000..8080a2ca44 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-14-v5.19-net-mtk_eth_soc-add-fixme-comment-for-state-speed-us.patch @@ -0,0 +1,38 @@ +From 650a49bc65df6b0e0051a8f62d7c22d95a8f350d Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:55:07 +0100 +Subject: [PATCH 08/12] net: mtk_eth_soc: add fixme comment for state->speed + use + +Add a fixme comment for the last remaining incorrect usage of +state->speed in the mac_config() method, which is strangely in a code +path which is only run when the PHY interface mode changes. + +This means if we are in RGMII mode, changes in state->speed will not +cause the INTF_MODE, TRGMII_RCK_CTRL and TRGMII_TCK_CTRL registers to +be set according to the speed, nor will the TRGPLL clock be set to the +correct value. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -374,6 +374,14 @@ static void mtk_mac_config(struct phylin + state->interface)) + goto err_phy; + } else { ++ /* FIXME: this is incorrect. Not only does it ++ * use state->speed (which is not guaranteed ++ * to be correct) but it also makes use of it ++ * in a code path that will only be reachable ++ * when the PHY interface mode changes, not ++ * when the speed changes. Consequently, RGMII ++ * is probably broken. ++ */ + mtk_gmac0_rgmii_adjust(mac->hw, + state->interface, + state->speed); diff --git a/target/linux/generic/backport-5.15/704-15-v5.19-net-mtk_eth_soc-move-MAC_MCR-setting-to-mac_finish.patch b/target/linux/generic/backport-5.15/704-15-v5.19-net-mtk_eth_soc-move-MAC_MCR-setting-to-mac_finish.patch new file mode 100644 index 0000000000..368db4cca2 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-15-v5.19-net-mtk_eth_soc-move-MAC_MCR-setting-to-mac_finish.patch @@ -0,0 +1,79 @@ +From 0e37ad71b2ff772009595002da2860999e98e14e Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:55:12 +0100 +Subject: [PATCH 09/12] net: mtk_eth_soc: move MAC_MCR setting to mac_finish() + +Move the setting of the MTK_MAC_MCR register from the end of mac_config +into the phylink mac_finish() method, to keep it as the very last write +that is done during configuration. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 33 ++++++++++++++------- + 1 file changed, 22 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -316,8 +316,8 @@ static void mtk_mac_config(struct phylin + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); + struct mtk_eth *eth = mac->hw; +- u32 mcr_cur, mcr_new, sid, i; + int val, ge_mode, err = 0; ++ u32 sid, i; + + /* MT76x8 has no hardware settings between for the MAC */ + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && +@@ -455,16 +455,6 @@ static void mtk_mac_config(struct phylin + return; + } + +- /* Setup gmac */ +- mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); +- mcr_new = mcr_cur; +- mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | +- MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK; +- +- /* Only update control register when needed! */ +- if (mcr_new != mcr_cur) +- mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); +- + return; + + err_phy: +@@ -477,6 +467,26 @@ init_err: + mac->id, phy_modes(state->interface), err); + } + ++static int mtk_mac_finish(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct mtk_mac *mac = container_of(config, struct mtk_mac, ++ phylink_config); ++ u32 mcr_cur, mcr_new; ++ ++ /* Setup gmac */ ++ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); ++ mcr_new = mcr_cur; ++ mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE | ++ MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK; ++ ++ /* Only update control register when needed! */ ++ if (mcr_new != mcr_cur) ++ mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id)); ++ ++ return 0; ++} ++ + static void mtk_mac_pcs_get_state(struct phylink_config *config, + struct phylink_link_state *state) + { +@@ -581,6 +591,7 @@ static const struct phylink_mac_ops mtk_ + .mac_pcs_get_state = mtk_mac_pcs_get_state, + .mac_an_restart = mtk_mac_an_restart, + .mac_config = mtk_mac_config, ++ .mac_finish = mtk_mac_finish, + .mac_link_down = mtk_mac_link_down, + .mac_link_up = mtk_mac_link_up, + }; diff --git a/target/linux/generic/backport-5.15/704-16-v5.19-net-mtk_eth_soc-move-restoration-of-SYSCFG0-to-mac_f.patch b/target/linux/generic/backport-5.15/704-16-v5.19-net-mtk_eth_soc-move-restoration-of-SYSCFG0-to-mac_f.patch new file mode 100644 index 0000000000..ad6ec60288 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-16-v5.19-net-mtk_eth_soc-move-restoration-of-SYSCFG0-to-mac_f.patch @@ -0,0 +1,57 @@ +From 21089867278deb2a110b685e3cd33f64f9ce41e2 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:55:17 +0100 +Subject: [PATCH 10/12] net: mtk_eth_soc: move restoration of SYSCFG0 to + mac_finish() + +The SGMIISYS configuration is performed while ETHSYS_SYSCFG0 is in a +disabled state. In order to preserve this when we switch to phylink_pcs +we need to move the restoration of this register to the mac_finish() +callback. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 +++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + + 2 files changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -447,8 +447,8 @@ static void mtk_mac_config(struct phylin + if (err) + goto init_err; + +- regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, +- SYSCFG0_SGMII_MASK, val); ++ /* Save the syscfg0 value for mac_finish */ ++ mac->syscfg0 = val; + } else if (phylink_autoneg_inband(mode)) { + dev_err(eth->dev, + "In-band mode not supported in non SGMII mode!\n"); +@@ -472,8 +472,15 @@ static int mtk_mac_finish(struct phylink + { + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); ++ struct mtk_eth *eth = mac->hw; + u32 mcr_cur, mcr_new; + ++ /* Enable SGMII */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ phy_interface_mode_is_8023z(interface)) ++ regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, ++ SYSCFG0_SGMII_MASK, mac->syscfg0); ++ + /* Setup gmac */ + mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + mcr_new = mcr_cur; +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1087,6 +1087,7 @@ struct mtk_mac { + struct mtk_hw_stats *hw_stats; + __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; + int hwlro_ip_cnt; ++ unsigned int syscfg0; + }; + + /* the struct describing the SoC. these are declared in the soc_xyz.c files */ diff --git a/target/linux/generic/backport-5.15/704-17-v5.19-net-mtk_eth_soc-convert-code-structure-to-suit-split.patch b/target/linux/generic/backport-5.15/704-17-v5.19-net-mtk_eth_soc-convert-code-structure-to-suit-split.patch new file mode 100644 index 0000000000..623658f459 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-17-v5.19-net-mtk_eth_soc-convert-code-structure-to-suit-split.patch @@ -0,0 +1,254 @@ +From 901f3fbe13c3e56f0742e02717ccbfabbc95c463 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:55:22 +0100 +Subject: [PATCH 11/12] net: mtk_eth_soc: convert code structure to suit split + PCS support + +Provide a mtk_pcs structure which encapsulates everything that the PCS +functions need (the regmap and ana_rgc3 offset), and use this in the +PCS functions. Provide shim functions to convert from the existing +"mtk_sgmii_*" interface to the converted PCS functions. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 15 ++- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 123 +++++++++++--------- + 2 files changed, 79 insertions(+), 59 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -958,16 +958,23 @@ struct mtk_soc_data { + /* currently no SoC has more than 2 macs */ + #define MTK_MAX_DEVS 2 + +-/* struct mtk_sgmii - This is the structure holding sgmii regmap and its +- * characteristics ++/* struct mtk_pcs - This structure holds each sgmii regmap and associated ++ * data + * @regmap: The register map pointing at the range used to setup + * SGMII modes + * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap + */ ++struct mtk_pcs { ++ struct regmap *regmap; ++ u32 ana_rgc3; ++}; + ++/* struct mtk_sgmii - This is the structure holding sgmii regmap and its ++ * characteristics ++ * @pcs Array of individual PCS structures ++ */ + struct mtk_sgmii { +- struct regmap *regmap[MTK_MAX_DEVS]; +- u32 ana_rgc3; ++ struct mtk_pcs pcs[MTK_MAX_DEVS]; + }; + + /* struct mtk_eth - This is the main datasructure for holding the state +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -9,90 +9,71 @@ + + #include + #include ++#include + #include + + #include "mtk_eth_soc.h" + +-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) +-{ +- struct device_node *np; +- int i; +- +- ss->ana_rgc3 = ana_rgc3; +- +- for (i = 0; i < MTK_MAX_DEVS; i++) { +- np = of_parse_phandle(r, "mediatek,sgmiisys", i); +- if (!np) +- break; +- +- ss->regmap[i] = syscon_node_to_regmap(np); +- of_node_put(np); +- if (IS_ERR(ss->regmap[i])) +- return PTR_ERR(ss->regmap[i]); +- } +- +- return 0; +-} +- + /* For SGMII interface mode */ +-static int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id) ++static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) + { + unsigned int val; + +- if (!ss->regmap[id]) ++ if (!mpcs->regmap) + return -EINVAL; + + /* Setup the link timer and QPHY power up inside SGMIISYS */ +- regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER, ++ regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, + SGMII_LINK_TIMER_DEFAULT); + +- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); ++ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); + val |= SGMII_REMOTE_FAULT_DIS; +- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val); ++ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + +- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val); ++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); + val |= SGMII_AN_RESTART; +- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val); ++ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + +- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val); ++ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); + val &= ~SGMII_PHYA_PWD; +- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); + + return 0; ++ + } + + /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a + * fixed speed. + */ +-static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id, +- phy_interface_t interface) ++static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs, ++ phy_interface_t interface) + { + unsigned int val; + +- if (!ss->regmap[id]) ++ if (!mpcs->regmap) + return -EINVAL; + +- regmap_read(ss->regmap[id], ss->ana_rgc3, &val); ++ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); + val &= ~RG_PHY_SPEED_MASK; + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val |= RG_PHY_SPEED_3_125G; +- regmap_write(ss->regmap[id], ss->ana_rgc3, val); ++ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val); + + /* Disable SGMII AN */ +- regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val); ++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); + val &= ~SGMII_AN_ENABLE; +- regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val); ++ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + + /* Set the speed etc but leave the duplex unchanged */ +- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); ++ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); + val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK; + val |= SGMII_SPEED_1000; +- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val); ++ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + + /* Release PHYA power down state */ +- regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val); ++ regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); + val &= ~SGMII_PHYA_PWD; +- regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); + + return 0; + } +@@ -100,44 +81,76 @@ static int mtk_sgmii_setup_mode_force(st + int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode, + phy_interface_t interface) + { ++ struct mtk_pcs *mpcs = &ss->pcs[id]; + int err = 0; + + /* Setup SGMIISYS with the determined property */ + if (interface != PHY_INTERFACE_MODE_SGMII) +- err = mtk_sgmii_setup_mode_force(ss, id, interface); ++ err = mtk_pcs_setup_mode_force(mpcs, interface); + else if (phylink_autoneg_inband(mode)) +- err = mtk_sgmii_setup_mode_an(ss, id); ++ err = mtk_pcs_setup_mode_an(mpcs); + + return err; + } + +-/* For 1000BASE-X and 2500BASE-X interface modes */ +-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex) ++static void mtk_pcs_restart_an(struct mtk_pcs *mpcs) ++{ ++ unsigned int val; ++ ++ if (!mpcs->regmap) ++ return; ++ ++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); ++ val |= SGMII_AN_RESTART; ++ regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); ++} ++ ++static void mtk_pcs_link_up(struct mtk_pcs *mpcs, int speed, int duplex) + { + unsigned int val; + + /* SGMII force duplex setting */ +- regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val); ++ regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); + val &= ~SGMII_DUPLEX_FULL; + if (duplex == DUPLEX_FULL) + val |= SGMII_DUPLEX_FULL; + +- regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val); ++ regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); ++} ++ ++/* For 1000BASE-X and 2500BASE-X interface modes */ ++void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex) ++{ ++ mtk_pcs_link_up(&ss->pcs[id], speed, duplex); ++} ++ ++int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) ++{ ++ struct device_node *np; ++ int i; ++ ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ np = of_parse_phandle(r, "mediatek,sgmiisys", i); ++ if (!np) ++ break; ++ ++ ss->pcs[i].ana_rgc3 = ana_rgc3; ++ ss->pcs[i].regmap = syscon_node_to_regmap(np); ++ of_node_put(np); ++ if (IS_ERR(ss->pcs[i].regmap)) ++ return PTR_ERR(ss->pcs[i].regmap); ++ } ++ ++ return 0; + } + + void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id) + { +- struct mtk_sgmii *ss = eth->sgmii; +- unsigned int val, sid; ++ unsigned int sid; + + /* Decide how GMAC and SGMIISYS be mapped */ + sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? + 0 : mac_id; + +- if (!ss->regmap[sid]) +- return; +- +- regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val); +- val |= SGMII_AN_RESTART; +- regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val); ++ mtk_pcs_restart_an(ð->sgmii->pcs[sid]); + } diff --git a/target/linux/generic/backport-5.15/704-18-v5.19-net-mtk_eth_soc-partially-convert-to-phylink_pcs.patch b/target/linux/generic/backport-5.15/704-18-v5.19-net-mtk_eth_soc-partially-convert-to-phylink_pcs.patch new file mode 100644 index 0000000000..df675e2899 --- /dev/null +++ b/target/linux/generic/backport-5.15/704-18-v5.19-net-mtk_eth_soc-partially-convert-to-phylink_pcs.patch @@ -0,0 +1,262 @@ +From 14a44ab0330d290fade1403a920e299cc56d7300 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 18 May 2022 15:55:28 +0100 +Subject: [PATCH 12/12] net: mtk_eth_soc: partially convert to phylink_pcs + +Partially convert mtk_eth_soc to phylink_pcs, moving the configuration, +link up and AN restart over. However, it seems mac_pcs_get_state() +doesn't actually get the state from the PCS, so we can't convert that +over without a better understanding of the hardware. + +Signed-off-by: Russell King (Oracle) +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++++++++---------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 55 +++++++++++---------- + 3 files changed, 53 insertions(+), 58 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -310,6 +310,25 @@ static void mtk_gmac0_rgmii_adjust(struc + mtk_w32(eth, val, TRGMII_TCK_CTRL); + } + ++static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, ++ phy_interface_t interface) ++{ ++ struct mtk_mac *mac = container_of(config, struct mtk_mac, ++ phylink_config); ++ struct mtk_eth *eth = mac->hw; ++ unsigned int sid; ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ phy_interface_mode_is_8023z(interface)) { ++ sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? ++ 0 : mac->id; ++ ++ return mtk_sgmii_select_pcs(eth->sgmii, sid); ++ } ++ ++ return NULL; ++} ++ + static void mtk_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) + { +@@ -317,7 +336,7 @@ static void mtk_mac_config(struct phylin + phylink_config); + struct mtk_eth *eth = mac->hw; + int val, ge_mode, err = 0; +- u32 sid, i; ++ u32 i; + + /* MT76x8 has no hardware settings between for the MAC */ + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && +@@ -438,15 +457,6 @@ static void mtk_mac_config(struct phylin + SYSCFG0_SGMII_MASK, + ~(u32)SYSCFG0_SGMII_MASK); + +- /* Decide how GMAC and SGMIISYS be mapped */ +- sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? +- 0 : mac->id; +- +- /* Setup SGMIISYS with the determined property */ +- err = mtk_sgmii_config(eth->sgmii, sid, mode, state->interface); +- if (err) +- goto init_err; +- + /* Save the syscfg0 value for mac_finish */ + mac->syscfg0 = val; + } else if (phylink_autoneg_inband(mode)) { +@@ -526,14 +536,6 @@ static void mtk_mac_pcs_get_state(struct + state->pause |= MLO_PAUSE_TX; + } + +-static void mtk_mac_an_restart(struct phylink_config *config) +-{ +- struct mtk_mac *mac = container_of(config, struct mtk_mac, +- phylink_config); +- +- mtk_sgmii_restart_an(mac->hw, mac->id); +-} +- + static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) + { +@@ -554,15 +556,6 @@ static void mtk_mac_link_up(struct phyli + phylink_config); + u32 mcr; + +- if (phy_interface_mode_is_8023z(interface)) { +- struct mtk_eth *eth = mac->hw; +- +- /* Decide how GMAC and SGMIISYS be mapped */ +- int sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? +- 0 : mac->id; +- mtk_sgmii_link_up(eth->sgmii, sid, speed, duplex); +- } +- + mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); + mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 | + MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC | +@@ -595,8 +588,8 @@ static void mtk_mac_link_up(struct phyli + + static const struct phylink_mac_ops mtk_phylink_ops = { + .validate = phylink_generic_validate, ++ .mac_select_pcs = mtk_mac_select_pcs, + .mac_pcs_get_state = mtk_mac_pcs_get_state, +- .mac_an_restart = mtk_mac_an_restart, + .mac_config = mtk_mac_config, + .mac_finish = mtk_mac_finish, + .mac_link_down = mtk_mac_link_down, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -963,10 +963,12 @@ struct mtk_soc_data { + * @regmap: The register map pointing at the range used to setup + * SGMII modes + * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap ++ * @pcs: Phylink PCS structure + */ + struct mtk_pcs { + struct regmap *regmap; + u32 ana_rgc3; ++ struct phylink_pcs pcs; + }; + + /* struct mtk_sgmii - This is the structure holding sgmii regmap and its +@@ -1106,12 +1108,9 @@ void mtk_stats_update_mac(struct mtk_mac + void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); + u32 mtk_r32(struct mtk_eth *eth, unsigned reg); + ++struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id); + int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np, + u32 ana_rgc3); +-int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode, +- phy_interface_t interface); +-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex); +-void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id); + + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -14,14 +14,16 @@ + + #include "mtk_eth_soc.h" + ++static struct mtk_pcs *pcs_to_mtk_pcs(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct mtk_pcs, pcs); ++} ++ + /* For SGMII interface mode */ + static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) + { + unsigned int val; + +- if (!mpcs->regmap) +- return -EINVAL; +- + /* Setup the link timer and QPHY power up inside SGMIISYS */ + regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, + SGMII_LINK_TIMER_DEFAULT); +@@ -50,9 +52,6 @@ static int mtk_pcs_setup_mode_force(stru + { + unsigned int val; + +- if (!mpcs->regmap) +- return -EINVAL; +- + regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); + val &= ~RG_PHY_SPEED_MASK; + if (interface == PHY_INTERFACE_MODE_2500BASEX) +@@ -78,10 +77,12 @@ static int mtk_pcs_setup_mode_force(stru + return 0; + } + +-int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode, +- phy_interface_t interface) ++static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) + { +- struct mtk_pcs *mpcs = &ss->pcs[id]; ++ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); + int err = 0; + + /* Setup SGMIISYS with the determined property */ +@@ -93,22 +94,25 @@ int mtk_sgmii_config(struct mtk_sgmii *s + return err; + } + +-static void mtk_pcs_restart_an(struct mtk_pcs *mpcs) ++static void mtk_pcs_restart_an(struct phylink_pcs *pcs) + { ++ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); + unsigned int val; + +- if (!mpcs->regmap) +- return; +- + regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); + val |= SGMII_AN_RESTART; + regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + } + +-static void mtk_pcs_link_up(struct mtk_pcs *mpcs, int speed, int duplex) ++static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, int speed, int duplex) + { ++ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); + unsigned int val; + ++ if (!phy_interface_mode_is_8023z(interface)) ++ return; ++ + /* SGMII force duplex setting */ + regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); + val &= ~SGMII_DUPLEX_FULL; +@@ -118,11 +122,11 @@ static void mtk_pcs_link_up(struct mtk_p + regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + } + +-/* For 1000BASE-X and 2500BASE-X interface modes */ +-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex) +-{ +- mtk_pcs_link_up(&ss->pcs[id], speed, duplex); +-} ++static const struct phylink_pcs_ops mtk_pcs_ops = { ++ .pcs_config = mtk_pcs_config, ++ .pcs_an_restart = mtk_pcs_restart_an, ++ .pcs_link_up = mtk_pcs_link_up, ++}; + + int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) + { +@@ -139,18 +143,17 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + of_node_put(np); + if (IS_ERR(ss->pcs[i].regmap)) + return PTR_ERR(ss->pcs[i].regmap); ++ ++ ss->pcs[i].pcs.ops = &mtk_pcs_ops; + } + + return 0; + } + +-void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id) ++struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id) + { +- unsigned int sid; +- +- /* Decide how GMAC and SGMIISYS be mapped */ +- sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? +- 0 : mac_id; ++ if (!ss->pcs[id].regmap) ++ return NULL; + +- mtk_pcs_restart_an(ð->sgmii->pcs[sid]); ++ return &ss->pcs[id].pcs; + } diff --git a/target/linux/generic/backport-5.15/705-01-v5.17-net-dsa-mt7530-iterate-using-dsa_switch_for_each_use.patch b/target/linux/generic/backport-5.15/705-01-v5.17-net-dsa-mt7530-iterate-using-dsa_switch_for_each_use.patch new file mode 100644 index 0000000000..74567109c5 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-01-v5.17-net-dsa-mt7530-iterate-using-dsa_switch_for_each_use.patch @@ -0,0 +1,106 @@ +From 505560028b6deb9b4385cf6100f05ca6f4aacaf8 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Mon, 6 Dec 2021 18:57:49 +0200 +Subject: [PATCH 01/13] net: dsa: mt7530: iterate using + dsa_switch_for_each_user_port in bridging ops + +Avoid repeated calls to dsa_to_port() (some hidden behind dsa_is_user_port +and some in plain sight) by keeping two struct dsa_port references: one +to the port passed as argument, and another to the other ports of the +switch that we're iterating over. + +dsa_to_port(ds, i) gets replaced by other_dp, i gets replaced by +other_port which is derived from other_dp->index, dsa_is_user_port is +handled by the DSA iterator. + +Signed-off-by: Vladimir Oltean +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 52 +++++++++++++++++++++++----------------- + 1 file changed, 30 insertions(+), 22 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1188,27 +1188,31 @@ static int + mt7530_port_bridge_join(struct dsa_switch *ds, int port, + struct net_device *bridge) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; + u32 port_bitmap = BIT(MT7530_CPU_PORT); +- int i; ++ struct mt7530_priv *priv = ds->priv; + + mutex_lock(&priv->reg_mutex); + +- for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ dsa_switch_for_each_user_port(other_dp, ds) { ++ int other_port = other_dp->index; ++ ++ if (dp == other_dp) ++ continue; ++ + /* Add this port to the port matrix of the other ports in the + * same bridge. If the port is disabled, port matrix is kept + * and not being setup until the port becomes enabled. + */ +- if (dsa_is_user_port(ds, i) && i != port) { +- if (dsa_to_port(ds, i)->bridge_dev != bridge) +- continue; +- if (priv->ports[i].enable) +- mt7530_set(priv, MT7530_PCR_P(i), +- PCR_MATRIX(BIT(port))); +- priv->ports[i].pm |= PCR_MATRIX(BIT(port)); ++ if (other_dp->bridge_dev != bridge) ++ continue; + +- port_bitmap |= BIT(i); +- } ++ if (priv->ports[other_port].enable) ++ mt7530_set(priv, MT7530_PCR_P(other_port), ++ PCR_MATRIX(BIT(port))); ++ priv->ports[other_port].pm |= PCR_MATRIX(BIT(port)); ++ ++ port_bitmap |= BIT(other_port); + } + + /* Add the all other ports to this port matrix. */ +@@ -1301,24 +1305,28 @@ static void + mt7530_port_bridge_leave(struct dsa_switch *ds, int port, + struct net_device *bridge) + { ++ struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; + struct mt7530_priv *priv = ds->priv; +- int i; + + mutex_lock(&priv->reg_mutex); + +- for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ dsa_switch_for_each_user_port(other_dp, ds) { ++ int other_port = other_dp->index; ++ ++ if (dp == other_dp) ++ continue; ++ + /* Remove this port from the port matrix of the other ports + * in the same bridge. If the port is disabled, port matrix + * is kept and not being setup until the port becomes enabled. + */ +- if (dsa_is_user_port(ds, i) && i != port) { +- if (dsa_to_port(ds, i)->bridge_dev != bridge) +- continue; +- if (priv->ports[i].enable) +- mt7530_clear(priv, MT7530_PCR_P(i), +- PCR_MATRIX(BIT(port))); +- priv->ports[i].pm &= ~PCR_MATRIX(BIT(port)); +- } ++ if (other_dp->bridge_dev != bridge) ++ continue; ++ ++ if (priv->ports[other_port].enable) ++ mt7530_clear(priv, MT7530_PCR_P(other_port), ++ PCR_MATRIX(BIT(port))); ++ priv->ports[other_port].pm &= ~PCR_MATRIX(BIT(port)); + } + + /* Set the cpu port to be the only one in the port matrix of diff --git a/target/linux/generic/backport-5.15/705-02-v5.19-net-dsa-mt7530-populate-supported_interfaces-and-mac.patch b/target/linux/generic/backport-5.15/705-02-v5.19-net-dsa-mt7530-populate-supported_interfaces-and-mac.patch new file mode 100644 index 0000000000..690cc78fb5 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-02-v5.19-net-dsa-mt7530-populate-supported_interfaces-and-mac.patch @@ -0,0 +1,166 @@ +From a1da54bcd664fc27169386db966575675ac3ccb0 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:01 +0100 +Subject: [PATCH 02/13] net: dsa: mt7530: populate supported_interfaces and + mac_capabilities +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Populate the supported interfaces and MAC capabilities for mt7530, +mt7531 and mt7621 DSA switches. Filling this in will enable phylink +to pre-check the PHY interface mode against the the supported +interfaces bitmap prior to calling the validate function, and will +eventually allow us to convert to using the generic validation. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 74 ++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 2 ++ + 2 files changed, 76 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2385,6 +2385,32 @@ mt7531_setup(struct dsa_switch *ds) + return 0; + } + ++static void mt7530_mac_port_get_caps(struct dsa_switch *ds, int port, ++ struct phylink_config *config) ++{ ++ switch (port) { ++ case 0 ... 4: /* Internal phy */ ++ __set_bit(PHY_INTERFACE_MODE_GMII, ++ config->supported_interfaces); ++ break; ++ ++ case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ ++ phy_interface_set_rgmii(config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_MII, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_GMII, ++ config->supported_interfaces); ++ break; ++ ++ case 6: /* 1st cpu port */ ++ __set_bit(PHY_INTERFACE_MODE_RGMII, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_TRGMII, ++ config->supported_interfaces); ++ break; ++ } ++} ++ + static bool + mt7530_phy_mode_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) +@@ -2421,6 +2447,37 @@ static bool mt7531_is_rgmii_port(struct + return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); + } + ++static void mt7531_mac_port_get_caps(struct dsa_switch *ds, int port, ++ struct phylink_config *config) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ switch (port) { ++ case 0 ... 4: /* Internal phy */ ++ __set_bit(PHY_INTERFACE_MODE_GMII, ++ config->supported_interfaces); ++ break; ++ ++ case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ ++ if (mt7531_is_rgmii_port(priv, port)) { ++ phy_interface_set_rgmii(config->supported_interfaces); ++ break; ++ } ++ fallthrough; ++ ++ case 6: /* 1st cpu port supports sgmii/8023z only */ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, ++ config->supported_interfaces); ++ ++ config->mac_capabilities |= MAC_2500FD; ++ break; ++ } ++} ++ + static bool + mt7531_phy_mode_supported(struct dsa_switch *ds, int port, + const struct phylink_link_state *state) +@@ -2899,6 +2956,18 @@ mt7531_cpu_port_config(struct dsa_switch + return 0; + } + ++static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, ++ struct phylink_config *config) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ /* This switch only supports full-duplex at 1Gbps */ ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10 | MAC_100 | MAC_1000FD; ++ ++ priv->info->mac_port_get_caps(ds, port, config); ++} ++ + static void + mt7530_mac_port_validate(struct dsa_switch *ds, int port, + unsigned long *supported) +@@ -3134,6 +3203,7 @@ static const struct dsa_switch_ops mt753 + .port_vlan_del = mt7530_port_vlan_del, + .port_mirror_add = mt753x_port_mirror_add, + .port_mirror_del = mt753x_port_mirror_del, ++ .phylink_get_caps = mt753x_phylink_get_caps, + .phylink_validate = mt753x_phylink_validate, + .phylink_mac_link_state = mt753x_phylink_mac_link_state, + .phylink_mac_config = mt753x_phylink_mac_config, +@@ -3151,6 +3221,7 @@ static const struct mt753x_info mt753x_t + .phy_read = mt7530_phy_read, + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, ++ .mac_port_get_caps = mt7530_mac_port_get_caps, + .phy_mode_supported = mt7530_phy_mode_supported, + .mac_port_validate = mt7530_mac_port_validate, + .mac_port_get_state = mt7530_phylink_mac_link_state, +@@ -3162,6 +3233,7 @@ static const struct mt753x_info mt753x_t + .phy_read = mt7530_phy_read, + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, ++ .mac_port_get_caps = mt7530_mac_port_get_caps, + .phy_mode_supported = mt7530_phy_mode_supported, + .mac_port_validate = mt7530_mac_port_validate, + .mac_port_get_state = mt7530_phylink_mac_link_state, +@@ -3174,6 +3246,7 @@ static const struct mt753x_info mt753x_t + .phy_write = mt7531_ind_phy_write, + .pad_setup = mt7531_pad_setup, + .cpu_port_config = mt7531_cpu_port_config, ++ .mac_port_get_caps = mt7531_mac_port_get_caps, + .phy_mode_supported = mt7531_phy_mode_supported, + .mac_port_validate = mt7531_mac_port_validate, + .mac_port_get_state = mt7531_phylink_mac_link_state, +@@ -3236,6 +3309,7 @@ mt7530_probe(struct mdio_device *mdiodev + */ + if (!priv->info->sw_setup || !priv->info->pad_setup || + !priv->info->phy_read || !priv->info->phy_write || ++ !priv->info->mac_port_get_caps || + !priv->info->phy_mode_supported || + !priv->info->mac_port_validate || + !priv->info->mac_port_get_state || !priv->info->mac_port_config) +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -769,6 +769,8 @@ struct mt753x_info { + int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); + int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); + int (*cpu_port_config)(struct dsa_switch *ds, int port); ++ void (*mac_port_get_caps)(struct dsa_switch *ds, int port, ++ struct phylink_config *config); + bool (*phy_mode_supported)(struct dsa_switch *ds, int port, + const struct phylink_link_state *state); + void (*mac_port_validate)(struct dsa_switch *ds, int port, diff --git a/target/linux/generic/backport-5.15/705-03-v5.19-net-dsa-mt7530-remove-interface-checks.patch b/target/linux/generic/backport-5.15/705-03-v5.19-net-dsa-mt7530-remove-interface-checks.patch new file mode 100644 index 0000000000..60eee013d1 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-03-v5.19-net-dsa-mt7530-remove-interface-checks.patch @@ -0,0 +1,172 @@ +From e3f6719e2269868ca129b05da50cd55786848954 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:06 +0100 +Subject: [PATCH 03/13] net: dsa: mt7530: remove interface checks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As phylink checks the interface mode against the supported_interfaces +bitmap, we no longer need to validate the interface mode, nor handle +PHY_INTERFACE_MODE_NA in the validation function. Remove these to +simplify the implementation. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 82 ---------------------------------------- + drivers/net/dsa/mt7530.h | 2 - + 2 files changed, 84 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2411,37 +2411,6 @@ static void mt7530_mac_port_get_caps(str + } + } + +-static bool +-mt7530_phy_mode_supported(struct dsa_switch *ds, int port, +- const struct phylink_link_state *state) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- switch (port) { +- case 0 ... 4: /* Internal phy */ +- if (state->interface != PHY_INTERFACE_MODE_GMII) +- return false; +- break; +- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ +- if (!phy_interface_mode_is_rgmii(state->interface) && +- state->interface != PHY_INTERFACE_MODE_MII && +- state->interface != PHY_INTERFACE_MODE_GMII) +- return false; +- break; +- case 6: /* 1st cpu port */ +- if (state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_TRGMII) +- return false; +- break; +- default: +- dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, +- port); +- return false; +- } +- +- return true; +-} +- + static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port) + { + return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII); +@@ -2478,44 +2447,6 @@ static void mt7531_mac_port_get_caps(str + } + } + +-static bool +-mt7531_phy_mode_supported(struct dsa_switch *ds, int port, +- const struct phylink_link_state *state) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- switch (port) { +- case 0 ... 4: /* Internal phy */ +- if (state->interface != PHY_INTERFACE_MODE_GMII) +- return false; +- break; +- case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */ +- if (mt7531_is_rgmii_port(priv, port)) +- return phy_interface_mode_is_rgmii(state->interface); +- fallthrough; +- case 6: /* 1st cpu port supports sgmii/8023z only */ +- if (state->interface != PHY_INTERFACE_MODE_SGMII && +- !phy_interface_mode_is_8023z(state->interface)) +- return false; +- break; +- default: +- dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, +- port); +- return false; +- } +- +- return true; +-} +- +-static bool +-mt753x_phy_mode_supported(struct dsa_switch *ds, int port, +- const struct phylink_link_state *state) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- return priv->info->phy_mode_supported(ds, port, state); +-} +- + static int + mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) + { +@@ -2770,9 +2701,6 @@ mt753x_phylink_mac_config(struct dsa_swi + struct mt7530_priv *priv = ds->priv; + u32 mcr_cur, mcr_new; + +- if (!mt753x_phy_mode_supported(ds, port, state)) +- goto unsupported; +- + switch (port) { + case 0 ... 4: /* Internal phy */ + if (state->interface != PHY_INTERFACE_MODE_GMII) +@@ -2990,12 +2918,6 @@ mt753x_phylink_validate(struct dsa_switc + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + struct mt7530_priv *priv = ds->priv; + +- if (state->interface != PHY_INTERFACE_MODE_NA && +- !mt753x_phy_mode_supported(ds, port, state)) { +- linkmode_zero(supported); +- return; +- } +- + phylink_set_port_modes(mask); + + if (state->interface != PHY_INTERFACE_MODE_TRGMII && +@@ -3222,7 +3144,6 @@ static const struct mt753x_info mt753x_t + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, +- .phy_mode_supported = mt7530_phy_mode_supported, + .mac_port_validate = mt7530_mac_port_validate, + .mac_port_get_state = mt7530_phylink_mac_link_state, + .mac_port_config = mt7530_mac_config, +@@ -3234,7 +3155,6 @@ static const struct mt753x_info mt753x_t + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, +- .phy_mode_supported = mt7530_phy_mode_supported, + .mac_port_validate = mt7530_mac_port_validate, + .mac_port_get_state = mt7530_phylink_mac_link_state, + .mac_port_config = mt7530_mac_config, +@@ -3247,7 +3167,6 @@ static const struct mt753x_info mt753x_t + .pad_setup = mt7531_pad_setup, + .cpu_port_config = mt7531_cpu_port_config, + .mac_port_get_caps = mt7531_mac_port_get_caps, +- .phy_mode_supported = mt7531_phy_mode_supported, + .mac_port_validate = mt7531_mac_port_validate, + .mac_port_get_state = mt7531_phylink_mac_link_state, + .mac_port_config = mt7531_mac_config, +@@ -3310,7 +3229,6 @@ mt7530_probe(struct mdio_device *mdiodev + if (!priv->info->sw_setup || !priv->info->pad_setup || + !priv->info->phy_read || !priv->info->phy_write || + !priv->info->mac_port_get_caps || +- !priv->info->phy_mode_supported || + !priv->info->mac_port_validate || + !priv->info->mac_port_get_state || !priv->info->mac_port_config) + return -EINVAL; +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -771,8 +771,6 @@ struct mt753x_info { + int (*cpu_port_config)(struct dsa_switch *ds, int port); + void (*mac_port_get_caps)(struct dsa_switch *ds, int port, + struct phylink_config *config); +- bool (*phy_mode_supported)(struct dsa_switch *ds, int port, +- const struct phylink_link_state *state); + void (*mac_port_validate)(struct dsa_switch *ds, int port, + unsigned long *supported); + int (*mac_port_get_state)(struct dsa_switch *ds, int port, diff --git a/target/linux/generic/backport-5.15/705-04-v5.19-net-dsa-mt7530-drop-use-of-phylink_helper_basex_spee.patch b/target/linux/generic/backport-5.15/705-04-v5.19-net-dsa-mt7530-drop-use-of-phylink_helper_basex_spee.patch new file mode 100644 index 0000000000..22bb2068de --- /dev/null +++ b/target/linux/generic/backport-5.15/705-04-v5.19-net-dsa-mt7530-drop-use-of-phylink_helper_basex_spee.patch @@ -0,0 +1,34 @@ +From 58344a3b85f1bd5ffddfc2c11f6f2bf688b5f990 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:12 +0100 +Subject: [PATCH 04/13] net: dsa: mt7530: drop use of + phylink_helper_basex_speed() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Now that we have a better method to select SFP interface modes, we +no longer need to use phylink_helper_basex_speed() in a driver's +validation function. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2942,11 +2942,6 @@ mt753x_phylink_validate(struct dsa_switc + + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); +- +- /* We can only operate at 2500BaseX or 1000BaseX. If requested +- * to advertise both, only report advertising at 2500BaseX. +- */ +- phylink_helper_basex_speed(state); + } + + static int diff --git a/target/linux/generic/backport-5.15/705-05-v5.19-net-dsa-mt7530-only-indicate-linkmodes-that-can-be-s.patch b/target/linux/generic/backport-5.15/705-05-v5.19-net-dsa-mt7530-only-indicate-linkmodes-that-can-be-s.patch new file mode 100644 index 0000000000..d5d7c54974 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-05-v5.19-net-dsa-mt7530-only-indicate-linkmodes-that-can-be-s.patch @@ -0,0 +1,86 @@ +From 3c1d788a62dc648d1846049b66119ebb69dedd52 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:17 +0100 +Subject: [PATCH 05/13] net: dsa: mt7530: only indicate linkmodes that can be + supported +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Now that mt7530 is not using the basex helper, it becomes unnecessary to +indicate support for both 1000baseX and 2500baseX when one of the 803.3z +PHY interface modes is being selected. Ensure that the driver indicates +only those linkmodes that can actually be supported by the PHY interface +mode. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 12 ++++++++---- + drivers/net/dsa/mt7530.h | 1 + + 2 files changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2518,12 +2518,13 @@ static int mt7531_rgmii_setup(struct mt7 + } + + static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, ++ phy_interface_t interface, + unsigned long *supported) + { + /* Port5 supports ethier RGMII or SGMII. + * Port6 supports SGMII only. + */ +- if (port == 6) { ++ if (port == 6 && interface == PHY_INTERFACE_MODE_2500BASEX) { + phylink_set(supported, 2500baseX_Full); + phylink_set(supported, 2500baseT_Full); + } +@@ -2898,16 +2899,18 @@ static void mt753x_phylink_get_caps(stru + + static void + mt7530_mac_port_validate(struct dsa_switch *ds, int port, ++ phy_interface_t interface, + unsigned long *supported) + { + } + + static void mt7531_mac_port_validate(struct dsa_switch *ds, int port, ++ phy_interface_t interface, + unsigned long *supported) + { + struct mt7530_priv *priv = ds->priv; + +- mt7531_sgmii_validate(priv, port, supported); ++ mt7531_sgmii_validate(priv, port, interface, supported); + } + + static void +@@ -2930,12 +2933,13 @@ mt753x_phylink_validate(struct dsa_switc + } + + /* This switch only supports 1G full-duplex. */ +- if (state->interface != PHY_INTERFACE_MODE_MII) { ++ if (state->interface != PHY_INTERFACE_MODE_MII && ++ state->interface != PHY_INTERFACE_MODE_2500BASEX) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseX_Full); + } + +- priv->info->mac_port_validate(ds, port, mask); ++ priv->info->mac_port_validate(ds, port, state->interface, mask); + + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -772,6 +772,7 @@ struct mt753x_info { + void (*mac_port_get_caps)(struct dsa_switch *ds, int port, + struct phylink_config *config); + void (*mac_port_validate)(struct dsa_switch *ds, int port, ++ phy_interface_t interface, + unsigned long *supported); + int (*mac_port_get_state)(struct dsa_switch *ds, int port, + struct phylink_link_state *state); diff --git a/target/linux/generic/backport-5.15/705-06-v5.19-net-dsa-mt7530-switch-to-use-phylink_get_linkmodes.patch b/target/linux/generic/backport-5.15/705-06-v5.19-net-dsa-mt7530-switch-to-use-phylink_get_linkmodes.patch new file mode 100644 index 0000000000..4a2c2f151d --- /dev/null +++ b/target/linux/generic/backport-5.15/705-06-v5.19-net-dsa-mt7530-switch-to-use-phylink_get_linkmodes.patch @@ -0,0 +1,131 @@ +From 1c2211cb15dd3957fb26c0e1615eceb5db851ad6 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:22 +0100 +Subject: [PATCH 06/13] net: dsa: mt7530: switch to use phylink_get_linkmodes() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Switch mt7530 to use phylink_get_linkmodes() to generate the ethtool +linkmodes that can be supported. We are unable to use the generic +helper for this as pause modes are dependent on the interface as +the Autoneg bit depends on the interface mode. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 57 ++++------------------------------------ + 1 file changed, 5 insertions(+), 52 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2517,19 +2517,6 @@ static int mt7531_rgmii_setup(struct mt7 + return 0; + } + +-static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port, +- phy_interface_t interface, +- unsigned long *supported) +-{ +- /* Port5 supports ethier RGMII or SGMII. +- * Port6 supports SGMII only. +- */ +- if (port == 6 && interface == PHY_INTERFACE_MODE_2500BASEX) { +- phylink_set(supported, 2500baseX_Full); +- phylink_set(supported, 2500baseT_Full); +- } +-} +- + static void + mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface, +@@ -2898,51 +2885,21 @@ static void mt753x_phylink_get_caps(stru + } + + static void +-mt7530_mac_port_validate(struct dsa_switch *ds, int port, +- phy_interface_t interface, +- unsigned long *supported) +-{ +-} +- +-static void mt7531_mac_port_validate(struct dsa_switch *ds, int port, +- phy_interface_t interface, +- unsigned long *supported) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- mt7531_sgmii_validate(priv, port, interface, supported); +-} +- +-static void + mt753x_phylink_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; +- struct mt7530_priv *priv = ds->priv; ++ u32 caps; ++ ++ caps = dsa_to_port(ds, port)->pl_config.mac_capabilities; + + phylink_set_port_modes(mask); ++ phylink_get_linkmodes(mask, state->interface, caps); + + if (state->interface != PHY_INTERFACE_MODE_TRGMII && +- !phy_interface_mode_is_8023z(state->interface)) { +- phylink_set(mask, 10baseT_Half); +- phylink_set(mask, 10baseT_Full); +- phylink_set(mask, 100baseT_Half); +- phylink_set(mask, 100baseT_Full); ++ !phy_interface_mode_is_8023z(state->interface)) + phylink_set(mask, Autoneg); +- } +- +- /* This switch only supports 1G full-duplex. */ +- if (state->interface != PHY_INTERFACE_MODE_MII && +- state->interface != PHY_INTERFACE_MODE_2500BASEX) { +- phylink_set(mask, 1000baseT_Full); +- phylink_set(mask, 1000baseX_Full); +- } +- +- priv->info->mac_port_validate(ds, port, state->interface, mask); +- +- phylink_set(mask, Pause); +- phylink_set(mask, Asym_Pause); + + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); +@@ -3143,7 +3100,6 @@ static const struct mt753x_info mt753x_t + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, +- .mac_port_validate = mt7530_mac_port_validate, + .mac_port_get_state = mt7530_phylink_mac_link_state, + .mac_port_config = mt7530_mac_config, + }, +@@ -3154,7 +3110,6 @@ static const struct mt753x_info mt753x_t + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, +- .mac_port_validate = mt7530_mac_port_validate, + .mac_port_get_state = mt7530_phylink_mac_link_state, + .mac_port_config = mt7530_mac_config, + }, +@@ -3166,7 +3121,6 @@ static const struct mt753x_info mt753x_t + .pad_setup = mt7531_pad_setup, + .cpu_port_config = mt7531_cpu_port_config, + .mac_port_get_caps = mt7531_mac_port_get_caps, +- .mac_port_validate = mt7531_mac_port_validate, + .mac_port_get_state = mt7531_phylink_mac_link_state, + .mac_port_config = mt7531_mac_config, + .mac_pcs_an_restart = mt7531_sgmii_restart_an, +@@ -3228,7 +3182,6 @@ mt7530_probe(struct mdio_device *mdiodev + if (!priv->info->sw_setup || !priv->info->pad_setup || + !priv->info->phy_read || !priv->info->phy_write || + !priv->info->mac_port_get_caps || +- !priv->info->mac_port_validate || + !priv->info->mac_port_get_state || !priv->info->mac_port_config) + return -EINVAL; + diff --git a/target/linux/generic/backport-5.15/705-07-v5.19-net-dsa-mt7530-partially-convert-to-phylink_pcs.patch b/target/linux/generic/backport-5.15/705-07-v5.19-net-dsa-mt7530-partially-convert-to-phylink_pcs.patch new file mode 100644 index 0000000000..8a66b7fb0b --- /dev/null +++ b/target/linux/generic/backport-5.15/705-07-v5.19-net-dsa-mt7530-partially-convert-to-phylink_pcs.patch @@ -0,0 +1,385 @@ +From fd993fd59d96d5e2d5972ec4ca1f9651025c987b Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:27 +0100 +Subject: [PATCH 07/13] net: dsa: mt7530: partially convert to phylink_pcs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Partially convert the mt7530 driver to use phylink's PCS support. This +is a partial implementation as we don't move anything into the +pcs_config method yet - this driver supports SGMII or 1000BASE-X +without in-band. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 144 +++++++++++++++++++++++---------------- + drivers/net/dsa/mt7530.h | 21 +++--- + 2 files changed, 95 insertions(+), 70 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -24,6 +24,11 @@ + + #include "mt7530.h" + ++static struct mt753x_pcs *pcs_to_mt753x_pcs(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct mt753x_pcs, pcs); ++} ++ + /* String, offset, and register size in bytes if different from 4 bytes */ + static const struct mt7530_mib_desc mt7530_mib[] = { + MIB_DESC(1, 0x00, "TxDrop"), +@@ -2517,12 +2522,11 @@ static int mt7531_rgmii_setup(struct mt7 + return 0; + } + +-static void +-mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port, +- unsigned int mode, phy_interface_t interface, +- int speed, int duplex) ++static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, int speed, int duplex) + { +- struct mt7530_priv *priv = ds->priv; ++ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; ++ int port = pcs_to_mt753x_pcs(pcs)->port; + unsigned int val; + + /* For adjusting speed and duplex of SGMII force mode. */ +@@ -2548,6 +2552,9 @@ mt7531_sgmii_link_up_force(struct dsa_sw + + /* MT7531 SGMII 1G force mode can only work in full duplex mode, + * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not. ++ * ++ * The speed check is unnecessary as the MAC capabilities apply ++ * this restriction. --rmk + */ + if ((speed == SPEED_10 || speed == SPEED_100) && + duplex != DUPLEX_FULL) +@@ -2623,9 +2630,10 @@ static int mt7531_sgmii_setup_mode_an(st + return 0; + } + +-static void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port) ++static void mt7531_pcs_an_restart(struct phylink_pcs *pcs) + { +- struct mt7530_priv *priv = ds->priv; ++ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; ++ int port = pcs_to_mt753x_pcs(pcs)->port; + u32 val; + + /* Only restart AN when AN is enabled */ +@@ -2682,6 +2690,24 @@ mt753x_mac_config(struct dsa_switch *ds, + return priv->info->mac_port_config(ds, port, mode, state->interface); + } + ++static struct phylink_pcs * ++mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port, ++ phy_interface_t interface) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_TRGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return &priv->pcs[port].pcs; ++ ++ default: ++ return NULL; ++ } ++} ++ + static void + mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + const struct phylink_link_state *state) +@@ -2743,17 +2769,6 @@ unsupported: + mt7530_write(priv, MT7530_PMCR_P(port), mcr_new); + } + +-static void +-mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port) +-{ +- struct mt7530_priv *priv = ds->priv; +- +- if (!priv->info->mac_pcs_an_restart) +- return; +- +- priv->info->mac_pcs_an_restart(ds, port); +-} +- + static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface) +@@ -2763,16 +2778,13 @@ static void mt753x_phylink_mac_link_down + mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); + } + +-static void mt753x_mac_pcs_link_up(struct dsa_switch *ds, int port, +- unsigned int mode, phy_interface_t interface, +- int speed, int duplex) ++static void mt753x_phylink_pcs_link_up(struct phylink_pcs *pcs, ++ unsigned int mode, ++ phy_interface_t interface, ++ int speed, int duplex) + { +- struct mt7530_priv *priv = ds->priv; +- +- if (!priv->info->mac_pcs_link_up) +- return; +- +- priv->info->mac_pcs_link_up(ds, port, mode, interface, speed, duplex); ++ if (pcs->ops->pcs_link_up) ++ pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); + } + + static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, +@@ -2785,8 +2797,6 @@ static void mt753x_phylink_mac_link_up(s + struct mt7530_priv *priv = ds->priv; + u32 mcr; + +- mt753x_mac_pcs_link_up(ds, port, mode, interface, speed, duplex); +- + mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; + + /* MT753x MAC works in 1G full duplex mode for all up-clocked +@@ -2866,6 +2876,8 @@ mt7531_cpu_port_config(struct dsa_switch + return ret; + mt7530_write(priv, MT7530_PMCR_P(port), + PMCR_CPU_PORT_SETTING(priv->id)); ++ mt753x_phylink_pcs_link_up(&priv->pcs[port].pcs, MLO_AN_FIXED, ++ interface, speed, DUPLEX_FULL); + mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL, + speed, DUPLEX_FULL, true, true); + +@@ -2905,16 +2917,13 @@ mt753x_phylink_validate(struct dsa_switc + linkmode_and(state->advertising, state->advertising, mask); + } + +-static int +-mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port, +- struct phylink_link_state *state) ++static void mt7530_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) + { +- struct mt7530_priv *priv = ds->priv; ++ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; ++ int port = pcs_to_mt753x_pcs(pcs)->port; + u32 pmsr; + +- if (port < 0 || port >= MT7530_NUM_PORTS) +- return -EINVAL; +- + pmsr = mt7530_read(priv, MT7530_PMSR_P(port)); + + state->link = (pmsr & PMSR_LINK); +@@ -2941,8 +2950,6 @@ mt7530_phylink_mac_link_state(struct dsa + state->pause |= MLO_PAUSE_RX; + if (pmsr & PMSR_TX_FC) + state->pause |= MLO_PAUSE_TX; +- +- return 1; + } + + static int +@@ -2984,32 +2991,49 @@ mt7531_sgmii_pcs_get_state_an(struct mt7 + return 0; + } + +-static int +-mt7531_phylink_mac_link_state(struct dsa_switch *ds, int port, +- struct phylink_link_state *state) ++static void mt7531_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) + { +- struct mt7530_priv *priv = ds->priv; ++ struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv; ++ int port = pcs_to_mt753x_pcs(pcs)->port; + + if (state->interface == PHY_INTERFACE_MODE_SGMII) +- return mt7531_sgmii_pcs_get_state_an(priv, port, state); +- +- return -EOPNOTSUPP; ++ mt7531_sgmii_pcs_get_state_an(priv, port, state); ++ else ++ state->link = false; + } + +-static int +-mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port, +- struct phylink_link_state *state) ++static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) + { +- struct mt7530_priv *priv = ds->priv; ++ return 0; ++} + +- return priv->info->mac_port_get_state(ds, port, state); ++static void mt7530_pcs_an_restart(struct phylink_pcs *pcs) ++{ + } + ++static const struct phylink_pcs_ops mt7530_pcs_ops = { ++ .pcs_get_state = mt7530_pcs_get_state, ++ .pcs_config = mt753x_pcs_config, ++ .pcs_an_restart = mt7530_pcs_an_restart, ++}; ++ ++static const struct phylink_pcs_ops mt7531_pcs_ops = { ++ .pcs_get_state = mt7531_pcs_get_state, ++ .pcs_config = mt753x_pcs_config, ++ .pcs_an_restart = mt7531_pcs_an_restart, ++ .pcs_link_up = mt7531_pcs_link_up, ++}; ++ + static int + mt753x_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; + int ret = priv->info->sw_setup(ds); ++ int i; + + if (ret) + return ret; +@@ -3022,6 +3046,13 @@ mt753x_setup(struct dsa_switch *ds) + if (ret && priv->irq) + mt7530_free_irq_common(priv); + ++ /* Initialise the PCS devices */ ++ for (i = 0; i < priv->ds->num_ports; i++) { ++ priv->pcs[i].pcs.ops = priv->info->pcs_ops; ++ priv->pcs[i].priv = priv; ++ priv->pcs[i].port = i; ++ } ++ + return ret; + } + +@@ -3083,9 +3114,8 @@ static const struct dsa_switch_ops mt753 + .port_mirror_del = mt753x_port_mirror_del, + .phylink_get_caps = mt753x_phylink_get_caps, + .phylink_validate = mt753x_phylink_validate, +- .phylink_mac_link_state = mt753x_phylink_mac_link_state, ++ .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs, + .phylink_mac_config = mt753x_phylink_mac_config, +- .phylink_mac_an_restart = mt753x_phylink_mac_an_restart, + .phylink_mac_link_down = mt753x_phylink_mac_link_down, + .phylink_mac_link_up = mt753x_phylink_mac_link_up, + .get_mac_eee = mt753x_get_mac_eee, +@@ -3095,36 +3125,34 @@ static const struct dsa_switch_ops mt753 + static const struct mt753x_info mt753x_table[] = { + [ID_MT7621] = { + .id = ID_MT7621, ++ .pcs_ops = &mt7530_pcs_ops, + .sw_setup = mt7530_setup, + .phy_read = mt7530_phy_read, + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, +- .mac_port_get_state = mt7530_phylink_mac_link_state, + .mac_port_config = mt7530_mac_config, + }, + [ID_MT7530] = { + .id = ID_MT7530, ++ .pcs_ops = &mt7530_pcs_ops, + .sw_setup = mt7530_setup, + .phy_read = mt7530_phy_read, + .phy_write = mt7530_phy_write, + .pad_setup = mt7530_pad_clk_setup, + .mac_port_get_caps = mt7530_mac_port_get_caps, +- .mac_port_get_state = mt7530_phylink_mac_link_state, + .mac_port_config = mt7530_mac_config, + }, + [ID_MT7531] = { + .id = ID_MT7531, ++ .pcs_ops = &mt7531_pcs_ops, + .sw_setup = mt7531_setup, + .phy_read = mt7531_ind_phy_read, + .phy_write = mt7531_ind_phy_write, + .pad_setup = mt7531_pad_setup, + .cpu_port_config = mt7531_cpu_port_config, + .mac_port_get_caps = mt7531_mac_port_get_caps, +- .mac_port_get_state = mt7531_phylink_mac_link_state, + .mac_port_config = mt7531_mac_config, +- .mac_pcs_an_restart = mt7531_sgmii_restart_an, +- .mac_pcs_link_up = mt7531_sgmii_link_up_force, + }, + }; + +@@ -3182,7 +3210,7 @@ mt7530_probe(struct mdio_device *mdiodev + if (!priv->info->sw_setup || !priv->info->pad_setup || + !priv->info->phy_read || !priv->info->phy_write || + !priv->info->mac_port_get_caps || +- !priv->info->mac_port_get_state || !priv->info->mac_port_config) ++ !priv->info->mac_port_config) + return -EINVAL; + + priv->id = priv->info->id; +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -741,6 +741,12 @@ static const char *p5_intf_modes(unsigne + + struct mt7530_priv; + ++struct mt753x_pcs { ++ struct phylink_pcs pcs; ++ struct mt7530_priv *priv; ++ int port; ++}; ++ + /* struct mt753x_info - This is the main data structure for holding the specific + * part for each supported device + * @sw_setup: Holding the handler to a device initialization +@@ -752,18 +758,14 @@ struct mt7530_priv; + * port + * @mac_port_validate: Holding the way to set addition validate type for a + * certan MAC port +- * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain +- * MAC port + * @mac_port_config: Holding the way setting up the PHY attribute to a + * certain MAC port +- * @mac_pcs_an_restart Holding the way restarting PCS autonegotiation for a +- * certain MAC port +- * @mac_pcs_link_up: Holding the way setting up the PHY attribute to the pcs +- * of the certain MAC port + */ + struct mt753x_info { + enum mt753x_id id; + ++ const struct phylink_pcs_ops *pcs_ops; ++ + int (*sw_setup)(struct dsa_switch *ds); + int (*phy_read)(struct mt7530_priv *priv, int port, int regnum); + int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); +@@ -774,15 +776,9 @@ struct mt753x_info { + void (*mac_port_validate)(struct dsa_switch *ds, int port, + phy_interface_t interface, + unsigned long *supported); +- int (*mac_port_get_state)(struct dsa_switch *ds, int port, +- struct phylink_link_state *state); + int (*mac_port_config)(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface); +- void (*mac_pcs_an_restart)(struct dsa_switch *ds, int port); +- void (*mac_pcs_link_up)(struct dsa_switch *ds, int port, +- unsigned int mode, phy_interface_t interface, +- int speed, int duplex); + }; + + /* struct mt7530_priv - This is the main data structure for holding the state +@@ -824,6 +820,7 @@ struct mt7530_priv { + u8 mirror_tx; + + struct mt7530_port ports[MT7530_NUM_PORTS]; ++ struct mt753x_pcs pcs[MT7530_NUM_PORTS]; + /* protect among processes for registers access*/ + struct mutex reg_mutex; + int irq; diff --git a/target/linux/generic/backport-5.15/705-08-v5.19-net-dsa-mt7530-move-autoneg-handling-to-PCS-validati.patch b/target/linux/generic/backport-5.15/705-08-v5.19-net-dsa-mt7530-move-autoneg-handling-to-PCS-validati.patch new file mode 100644 index 0000000000..2d8b4d5d57 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-08-v5.19-net-dsa-mt7530-move-autoneg-handling-to-PCS-validati.patch @@ -0,0 +1,80 @@ +From 2b0ee6768f3ac09072e5fd60b36580924e1cfa1c Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:32 +0100 +Subject: [PATCH 08/13] net: dsa: mt7530: move autoneg handling to PCS + validation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move the autoneg bit handling to the PCS validation, which allows us to +get rid of mt753x_phylink_validate() and rely on the default +phylink_generic_validate() implementation for the MAC side. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 28 ++++++++++------------------ + 1 file changed, 10 insertions(+), 18 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2896,25 +2896,16 @@ static void mt753x_phylink_get_caps(stru + priv->info->mac_port_get_caps(ds, port, config); + } + +-static void +-mt753x_phylink_validate(struct dsa_switch *ds, int port, +- unsigned long *supported, +- struct phylink_link_state *state) +-{ +- __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; +- u32 caps; +- +- caps = dsa_to_port(ds, port)->pl_config.mac_capabilities; +- +- phylink_set_port_modes(mask); +- phylink_get_linkmodes(mask, state->interface, caps); ++static int mt753x_pcs_validate(struct phylink_pcs *pcs, ++ unsigned long *supported, ++ const struct phylink_link_state *state) ++{ ++ /* Autonegotiation is not supported in TRGMII nor 802.3z modes */ ++ if (state->interface == PHY_INTERFACE_MODE_TRGMII || ++ phy_interface_mode_is_8023z(state->interface)) ++ phylink_clear(supported, Autoneg); + +- if (state->interface != PHY_INTERFACE_MODE_TRGMII && +- !phy_interface_mode_is_8023z(state->interface)) +- phylink_set(mask, Autoneg); +- +- linkmode_and(supported, supported, mask); +- linkmode_and(state->advertising, state->advertising, mask); ++ return 0; + } + + static void mt7530_pcs_get_state(struct phylink_pcs *pcs, +@@ -3016,12 +3007,14 @@ static void mt7530_pcs_an_restart(struct + } + + static const struct phylink_pcs_ops mt7530_pcs_ops = { ++ .pcs_validate = mt753x_pcs_validate, + .pcs_get_state = mt7530_pcs_get_state, + .pcs_config = mt753x_pcs_config, + .pcs_an_restart = mt7530_pcs_an_restart, + }; + + static const struct phylink_pcs_ops mt7531_pcs_ops = { ++ .pcs_validate = mt753x_pcs_validate, + .pcs_get_state = mt7531_pcs_get_state, + .pcs_config = mt753x_pcs_config, + .pcs_an_restart = mt7531_pcs_an_restart, +@@ -3113,7 +3106,6 @@ static const struct dsa_switch_ops mt753 + .port_mirror_add = mt753x_port_mirror_add, + .port_mirror_del = mt753x_port_mirror_del, + .phylink_get_caps = mt753x_phylink_get_caps, +- .phylink_validate = mt753x_phylink_validate, + .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs, + .phylink_mac_config = mt753x_phylink_mac_config, + .phylink_mac_link_down = mt753x_phylink_mac_link_down, diff --git a/target/linux/generic/backport-5.15/705-09-v5.19-net-dsa-mt7530-mark-as-non-legacy.patch b/target/linux/generic/backport-5.15/705-09-v5.19-net-dsa-mt7530-mark-as-non-legacy.patch new file mode 100644 index 0000000000..849a9925a1 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-09-v5.19-net-dsa-mt7530-mark-as-non-legacy.patch @@ -0,0 +1,34 @@ +From 5bc26de9bfaa6bb5539c09d4435dced98f429cfc Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 11 Apr 2022 10:46:37 +0100 +Subject: [PATCH 09/13] net: dsa: mt7530: mark as non-legacy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The mt7530 driver does not make use of the speed, duplex, pause or +advertisement in its phylink_mac_config() implementation, so it can be +marked as a non-legacy driver. + +Tested-by: Marek Behún +Signed-off-by: Russell King (Oracle) +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2893,6 +2893,12 @@ static void mt753x_phylink_get_caps(stru + config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000FD; + ++ /* This driver does not make use of the speed, duplex, pause or the ++ * advertisement in its mac_config, so it is safe to mark this driver ++ * as non-legacy. ++ */ ++ config->legacy_pre_march2020 = false; ++ + priv->info->mac_port_get_caps(ds, port, config); + } + diff --git a/target/linux/generic/backport-5.15/705-10-v5.19-net-dsa-mt753x-fix-pcs-conversion-regression.patch b/target/linux/generic/backport-5.15/705-10-v5.19-net-dsa-mt753x-fix-pcs-conversion-regression.patch new file mode 100644 index 0000000000..89f6e7509b --- /dev/null +++ b/target/linux/generic/backport-5.15/705-10-v5.19-net-dsa-mt753x-fix-pcs-conversion-regression.patch @@ -0,0 +1,116 @@ +From 1f15b5e8733115cee65342bcaafeaf0368809fae Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Mon, 25 Apr 2022 22:28:02 +0100 +Subject: [PATCH 10/13] net: dsa: mt753x: fix pcs conversion regression + +Daniel Golle reports that the conversion of mt753x to phylink PCS caused +an oops as below. + +The problem is with the placement of the PCS initialisation, which +occurs after mt7531_setup() has been called. However, burited in this +function is a call to setup the CPU port, which requires the PCS +structure to be already setup. + +Fix this by changing the initialisation order. + +Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020 +Mem abort info: + ESR = 0x96000005 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x05: level 1 translation fault +Data abort info: + ISV = 0, ISS = 0x00000005 + CM = 0, WnR = 0 +user pgtable: 4k pages, 39-bit VAs, pgdp=0000000046057000 +[0000000000000020] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 +Internal error: Oops: 96000005 [#1] SMP +Modules linked in: +CPU: 0 PID: 32 Comm: kworker/u4:1 Tainted: G S 5.18.0-rc3-next-20220422+ #0 +Hardware name: Bananapi BPI-R64 (DT) +Workqueue: events_unbound deferred_probe_work_func +pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : mt7531_cpu_port_config+0xcc/0x1b0 +lr : mt7531_cpu_port_config+0xc0/0x1b0 +sp : ffffffc008d5b980 +x29: ffffffc008d5b990 x28: ffffff80060562c8 x27: 00000000f805633b +x26: ffffff80001a8880 x25: 00000000000009c4 x24: 0000000000000016 +x23: ffffff8005eb6470 x22: 0000000000003600 x21: ffffff8006948080 +x20: 0000000000000000 x19: 0000000000000006 x18: 0000000000000000 +x17: 0000000000000001 x16: 0000000000000001 x15: 02963607fcee069e +x14: 0000000000000000 x13: 0000000000000030 x12: 0101010101010101 +x11: ffffffc037302000 x10: 0000000000000870 x9 : ffffffc008d5b800 +x8 : ffffff800028f950 x7 : 0000000000000001 x6 : 00000000662b3000 +x5 : 00000000000002f0 x4 : 0000000000000000 x3 : ffffff800028f080 +x2 : 0000000000000000 x1 : ffffff800028f080 x0 : 0000000000000000 +Call trace: + mt7531_cpu_port_config+0xcc/0x1b0 + mt753x_cpu_port_enable+0x24/0x1f0 + mt7531_setup+0x49c/0x5c0 + mt753x_setup+0x20/0x31c + dsa_register_switch+0x8bc/0x1020 + mt7530_probe+0x118/0x200 + mdio_probe+0x30/0x64 + really_probe.part.0+0x98/0x280 + __driver_probe_device+0x94/0x140 + driver_probe_device+0x40/0x114 + __device_attach_driver+0xb0/0x10c + bus_for_each_drv+0x64/0xa0 + __device_attach+0xa8/0x16c + device_initial_probe+0x10/0x20 + bus_probe_device+0x94/0x9c + deferred_probe_work_func+0x80/0xb4 + process_one_work+0x200/0x3a0 + worker_thread+0x260/0x4c0 + kthread+0xd4/0xe0 + ret_from_fork+0x10/0x20 +Code: 9409e911 937b7e60 8b0002a0 f9405800 (f9401005) +---[ end trace 0000000000000000 ]--- + +Reported-by: Daniel Golle +Tested-by: Daniel Golle +Fixes: cbd1f243bc41 ("net: dsa: mt7530: partially convert to phylink_pcs") +Signed-off-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/E1nj6FW-007WZB-5Y@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3031,9 +3031,16 @@ static int + mt753x_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; +- int ret = priv->info->sw_setup(ds); +- int i; ++ int i, ret; + ++ /* Initialise the PCS devices */ ++ for (i = 0; i < priv->ds->num_ports; i++) { ++ priv->pcs[i].pcs.ops = priv->info->pcs_ops; ++ priv->pcs[i].priv = priv; ++ priv->pcs[i].port = i; ++ } ++ ++ ret = priv->info->sw_setup(ds); + if (ret) + return ret; + +@@ -3045,13 +3052,6 @@ mt753x_setup(struct dsa_switch *ds) + if (ret && priv->irq) + mt7530_free_irq_common(priv); + +- /* Initialise the PCS devices */ +- for (i = 0; i < priv->ds->num_ports; i++) { +- priv->pcs[i].pcs.ops = priv->info->pcs_ops; +- priv->pcs[i].priv = priv; +- priv->pcs[i].port = i; +- } +- + return ret; + } + diff --git a/target/linux/generic/backport-5.15/705-11-v6.0-net-dsa-mt7530-rework-mt7530_hw_vlan_-add-del.patch b/target/linux/generic/backport-5.15/705-11-v6.0-net-dsa-mt7530-rework-mt7530_hw_vlan_-add-del.patch new file mode 100644 index 0000000000..77b4fa1102 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-11-v6.0-net-dsa-mt7530-rework-mt7530_hw_vlan_-add-del.patch @@ -0,0 +1,87 @@ +From e26be16262e1fc1e9f1798c12762663bd9c265c6 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 10 Jun 2022 19:05:37 +0200 +Subject: [PATCH 11/13] net: dsa: mt7530: rework mt7530_hw_vlan_{add,del} + +Rework vlan_add/vlan_del functions in preparation for dynamic cpu port. + +Currently BIT(MT7530_CPU_PORT) is added to new_members, even though +mt7530_port_vlan_add() will be called on the CPU port too. + +Let DSA core decide when to call port_vlan_add for the CPU port, rather +than doing it implicitly. + +We can do autonomous forwarding in a certain VLAN, but not add br0 to that +VLAN and avoid flooding the CPU with those packets, if software knows it +doesn't need to process them. + +Suggested-by: Vladimir Oltean +Signed-off-by: Frank Wunderlich +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 30 ++++++++++++------------------ + 1 file changed, 12 insertions(+), 18 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1522,11 +1522,11 @@ static void + mt7530_hw_vlan_add(struct mt7530_priv *priv, + struct mt7530_hw_vlan_entry *entry) + { ++ struct dsa_port *dp = dsa_to_port(priv->ds, entry->port); + u8 new_members; + u32 val; + +- new_members = entry->old_members | BIT(entry->port) | +- BIT(MT7530_CPU_PORT); ++ new_members = entry->old_members | BIT(entry->port); + + /* Validate the entry with independent learning, create egress tag per + * VLAN and joining the port as one of the port members. +@@ -1537,22 +1537,20 @@ mt7530_hw_vlan_add(struct mt7530_priv *p + + /* Decide whether adding tag or not for those outgoing packets from the + * port inside the VLAN. +- */ +- val = entry->untagged ? MT7530_VLAN_EGRESS_UNTAG : +- MT7530_VLAN_EGRESS_TAG; +- mt7530_rmw(priv, MT7530_VAWD2, +- ETAG_CTRL_P_MASK(entry->port), +- ETAG_CTRL_P(entry->port, val)); +- +- /* CPU port is always taken as a tagged port for serving more than one ++ * CPU port is always taken as a tagged port for serving more than one + * VLANs across and also being applied with egress type stack mode for + * that VLAN tags would be appended after hardware special tag used as + * DSA tag. + */ ++ if (dsa_port_is_cpu(dp)) ++ val = MT7530_VLAN_EGRESS_STACK; ++ else if (entry->untagged) ++ val = MT7530_VLAN_EGRESS_UNTAG; ++ else ++ val = MT7530_VLAN_EGRESS_TAG; + mt7530_rmw(priv, MT7530_VAWD2, +- ETAG_CTRL_P_MASK(MT7530_CPU_PORT), +- ETAG_CTRL_P(MT7530_CPU_PORT, +- MT7530_VLAN_EGRESS_STACK)); ++ ETAG_CTRL_P_MASK(entry->port), ++ ETAG_CTRL_P(entry->port, val)); + } + + static void +@@ -1571,11 +1569,7 @@ mt7530_hw_vlan_del(struct mt7530_priv *p + return; + } + +- /* If certain member apart from CPU port is still alive in the VLAN, +- * the entry would be kept valid. Otherwise, the entry is got to be +- * disabled. +- */ +- if (new_members && new_members != BIT(MT7530_CPU_PORT)) { ++ if (new_members) { + val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | + VLAN_VALID; + mt7530_write(priv, MT7530_VAWD1, val); diff --git a/target/linux/generic/backport-5.15/705-12-v6.0-net-dsa-mt7530-rework-mt753-01-_setup.patch b/target/linux/generic/backport-5.15/705-12-v6.0-net-dsa-mt7530-rework-mt753-01-_setup.patch new file mode 100644 index 0000000000..2324336ed8 --- /dev/null +++ b/target/linux/generic/backport-5.15/705-12-v6.0-net-dsa-mt7530-rework-mt753-01-_setup.patch @@ -0,0 +1,75 @@ +From 1f0dfd443eea7fc3e818e96f7c8264913ba41859 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 10 Jun 2022 19:05:38 +0200 +Subject: [PATCH 12/13] net: dsa: mt7530: rework mt753[01]_setup + +Enumerate available cpu-ports instead of using hardcoded constant. + +Suggested-by: Vladimir Oltean +Signed-off-by: Frank Wunderlich +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 25 +++++++++++++++++++++---- + 1 file changed, 21 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2087,11 +2087,12 @@ static int + mt7530_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; ++ struct device_node *dn = NULL; + struct device_node *phy_node; + struct device_node *mac_np; + struct mt7530_dummy_poll p; + phy_interface_t interface; +- struct device_node *dn; ++ struct dsa_port *cpu_dp; + u32 id, val; + int ret, i; + +@@ -2099,7 +2100,19 @@ mt7530_setup(struct dsa_switch *ds) + * controller also is the container for two GMACs nodes representing + * as two netdev instances. + */ +- dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent; ++ dsa_switch_for_each_cpu_port(cpu_dp, ds) { ++ dn = cpu_dp->master->dev.of_node->parent; ++ /* It doesn't matter which CPU port is found first, ++ * their masters should share the same parent OF node ++ */ ++ break; ++ } ++ ++ if (!dn) { ++ dev_err(ds->dev, "parent OF node of DSA master not found"); ++ return -EINVAL; ++ } ++ + ds->assisted_learning_on_cpu_port = true; + ds->mtu_enforcement_ingress = true; + +@@ -2261,6 +2274,7 @@ mt7531_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; + struct mt7530_dummy_poll p; ++ struct dsa_port *cpu_dp; + u32 val, id; + int ret, i; + +@@ -2333,8 +2347,11 @@ mt7531_setup(struct dsa_switch *ds) + CORE_PLL_GROUP4, val); + + /* BPDU to CPU port */ +- mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK, +- BIT(MT7530_CPU_PORT)); ++ dsa_switch_for_each_cpu_port(cpu_dp, ds) { ++ mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK, ++ BIT(cpu_dp->index)); ++ break; ++ } + mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, + MT753X_BPDU_CPU_ONLY); + diff --git a/target/linux/generic/backport-5.15/705-13-v6.0-net-dsa-mt7530-get-cpu-port-via-dp-cpu_dp-instead-of.patch b/target/linux/generic/backport-5.15/705-13-v6.0-net-dsa-mt7530-get-cpu-port-via-dp-cpu_dp-instead-of.patch new file mode 100644 index 0000000000..3b5ce7363f --- /dev/null +++ b/target/linux/generic/backport-5.15/705-13-v6.0-net-dsa-mt7530-get-cpu-port-via-dp-cpu_dp-instead-of.patch @@ -0,0 +1,117 @@ +From ad2606f6fafae3a7d41c4f2af5554c8f6adecbc7 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 10 Jun 2022 19:05:39 +0200 +Subject: [PATCH 13/13] net: dsa: mt7530: get cpu-port via dp->cpu_dp instead + of constant + +Replace last occurences of hardcoded cpu-port by cpu_dp member of +dsa_port struct. + +Now the constant can be dropped. + +Suggested-by: Vladimir Oltean +Signed-off-by: Frank Wunderlich +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530.c | 27 ++++++++++++++++++++------- + drivers/net/dsa/mt7530.h | 1 - + 2 files changed, 20 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1038,6 +1038,7 @@ static int + mt7530_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phy) + { ++ struct dsa_port *dp = dsa_to_port(ds, port); + struct mt7530_priv *priv = ds->priv; + + mutex_lock(&priv->reg_mutex); +@@ -1046,7 +1047,11 @@ mt7530_port_enable(struct dsa_switch *ds + * restore the port matrix if the port is the member of a certain + * bridge. + */ +- priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT)); ++ if (dsa_port_is_user(dp)) { ++ struct dsa_port *cpu_dp = dp->cpu_dp; ++ ++ priv->ports[port].pm |= PCR_MATRIX(BIT(cpu_dp->index)); ++ } + priv->ports[port].enable = true; + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, + priv->ports[port].pm); +@@ -1194,7 +1199,8 @@ mt7530_port_bridge_join(struct dsa_switc + struct net_device *bridge) + { + struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; +- u32 port_bitmap = BIT(MT7530_CPU_PORT); ++ struct dsa_port *cpu_dp = dp->cpu_dp; ++ u32 port_bitmap = BIT(cpu_dp->index); + struct mt7530_priv *priv = ds->priv; + + mutex_lock(&priv->reg_mutex); +@@ -1271,9 +1277,12 @@ mt7530_port_set_vlan_unaware(struct dsa_ + * the CPU port get out of VLAN filtering mode. + */ + if (all_user_ports_removed) { +- mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT), ++ struct dsa_port *dp = dsa_to_port(ds, port); ++ struct dsa_port *cpu_dp = dp->cpu_dp; ++ ++ mt7530_write(priv, MT7530_PCR_P(cpu_dp->index), + PCR_MATRIX(dsa_user_ports(priv->ds))); +- mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT), PORT_SPEC_TAG ++ mt7530_write(priv, MT7530_PVC_P(cpu_dp->index), PORT_SPEC_TAG + | PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); + } + } +@@ -1311,6 +1320,7 @@ mt7530_port_bridge_leave(struct dsa_swit + struct net_device *bridge) + { + struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; ++ struct dsa_port *cpu_dp = dp->cpu_dp; + struct mt7530_priv *priv = ds->priv; + + mutex_lock(&priv->reg_mutex); +@@ -1339,8 +1349,8 @@ mt7530_port_bridge_leave(struct dsa_swit + */ + if (priv->ports[port].enable) + mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, +- PCR_MATRIX(BIT(MT7530_CPU_PORT))); +- priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); ++ PCR_MATRIX(BIT(cpu_dp->index))); ++ priv->ports[port].pm = PCR_MATRIX(BIT(cpu_dp->index)); + + /* When a port is removed from the bridge, the port would be set up + * back to the default as is at initial boot which is a VLAN-unaware +@@ -1503,6 +1513,9 @@ static int + mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, + struct netlink_ext_ack *extack) + { ++ struct dsa_port *dp = dsa_to_port(ds, port); ++ struct dsa_port *cpu_dp = dp->cpu_dp; ++ + if (vlan_filtering) { + /* The port is being kept as VLAN-unaware port when bridge is + * set up with vlan_filtering not being set, Otherwise, the +@@ -1510,7 +1523,7 @@ mt7530_port_vlan_filtering(struct dsa_sw + * for becoming a VLAN-aware port. + */ + mt7530_port_set_vlan_aware(ds, port); +- mt7530_port_set_vlan_aware(ds, MT7530_CPU_PORT); ++ mt7530_port_set_vlan_aware(ds, cpu_dp->index); + } else { + mt7530_port_set_vlan_unaware(ds, port); + } +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -8,7 +8,6 @@ + + #define MT7530_NUM_PORTS 7 + #define MT7530_NUM_PHYS 5 +-#define MT7530_CPU_PORT 6 + #define MT7530_NUM_FDB_RECORDS 2048 + #define MT7530_ALL_MEMBERS 0xff + diff --git a/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch index 1786bf0345..77cf63b809 100644 --- a/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch +++ b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch @@ -22,7 +22,7 @@ Signed-off-by: David S. Miller --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1986,13 +1986,6 @@ int dsa_slave_create(struct dsa_port *po +@@ -1977,13 +1977,6 @@ int dsa_slave_create(struct dsa_port *po port->slave = slave_dev; dsa_slave_setup_tagger(slave_dev); @@ -36,7 +36,7 @@ Signed-off-by: David S. Miller netif_carrier_off(slave_dev); ret = dsa_slave_phy_setup(slave_dev); -@@ -2004,6 +1997,13 @@ int dsa_slave_create(struct dsa_port *po +@@ -1995,6 +1988,13 @@ int dsa_slave_create(struct dsa_port *po } rtnl_lock(); diff --git a/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch index c2493a08fd..50aa5d8f0d 100644 --- a/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch +++ b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch @@ -16,7 +16,7 @@ Signed-off-by: David S. Miller --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -1997,14 +1997,12 @@ int dsa_slave_create(struct dsa_port *po +@@ -1988,14 +1988,12 @@ int dsa_slave_create(struct dsa_port *po } rtnl_lock(); diff --git a/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch index d73b745586..7c6a3a3f8d 100644 --- a/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch +++ b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch @@ -68,7 +68,7 @@ Signed-off-by: David S. Miller static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p) { return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED; -@@ -916,6 +926,13 @@ struct dsa_switch_ops { +@@ -949,6 +959,13 @@ struct dsa_switch_ops { int (*tag_8021q_vlan_add)(struct dsa_switch *ds, int port, u16 vid, u16 flags); int (*tag_8021q_vlan_del)(struct dsa_switch *ds, int port, u16 vid); @@ -175,7 +175,7 @@ Signed-off-by: David S. Miller --- a/net/dsa/slave.c +++ b/net/dsa/slave.c -@@ -2320,6 +2320,36 @@ static int dsa_slave_netdevice_event(str +@@ -2311,6 +2311,36 @@ static int dsa_slave_netdevice_event(str err = dsa_port_lag_change(dp, info->lower_state_info); return notifier_from_errno(err); } @@ -212,7 +212,7 @@ Signed-off-by: David S. Miller case NETDEV_GOING_DOWN: { struct dsa_port *dp, *cpu_dp; struct dsa_switch_tree *dst; -@@ -2331,6 +2361,8 @@ static int dsa_slave_netdevice_event(str +@@ -2322,6 +2352,8 @@ static int dsa_slave_netdevice_event(str cpu_dp = dev->dsa_ptr; dst = cpu_dp->ds->dst; diff --git a/target/linux/generic/hack-5.10/321-powerpc_crtsavres_prereq.patch b/target/linux/generic/hack-5.10/321-powerpc_crtsavres_prereq.patch index 4bb438295d..c4fd475b1f 100644 --- a/target/linux/generic/hack-5.10/321-powerpc_crtsavres_prereq.patch +++ b/target/linux/generic/hack-5.10/321-powerpc_crtsavres_prereq.patch @@ -16,7 +16,7 @@ Signed-off-by: Alexandros C. Couloumbis --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile -@@ -61,19 +61,6 @@ machine-$(CONFIG_PPC64) += 64 +@@ -44,19 +44,6 @@ machine-$(CONFIG_PPC64) += 64 machine-$(CONFIG_CPU_LITTLE_ENDIAN) += le UTS_MACHINE := $(subst $(space),,$(machine-y)) diff --git a/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch b/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch index 215528a90c..f1942e2037 100644 --- a/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch +++ b/target/linux/generic/hack-5.15/321-powerpc_crtsavres_prereq.patch @@ -16,7 +16,7 @@ Signed-off-by: Alexandros C. Couloumbis --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile -@@ -61,19 +61,6 @@ machine-$(CONFIG_PPC64) += 64 +@@ -44,19 +44,6 @@ machine-$(CONFIG_PPC64) += 64 machine-$(CONFIG_CPU_LITTLE_ENDIAN) += le UTS_MACHINE := $(subst $(space),,$(machine-y)) diff --git a/target/linux/generic/hack-5.15/790-SFP-GE-T-ignore-TX_FAULT.patch b/target/linux/generic/hack-5.15/790-SFP-GE-T-ignore-TX_FAULT.patch new file mode 100644 index 0000000000..bfb32d5381 --- /dev/null +++ b/target/linux/generic/hack-5.15/790-SFP-GE-T-ignore-TX_FAULT.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -1803,6 +1803,7 @@ static int sfp_sm_mod_probe(struct sfp * + struct sfp_eeprom_id id; + bool cotsworks_sfbg; + bool cotsworks; ++ bool oem_ge_t; + u8 check; + int ret; + +@@ -1851,6 +1852,10 @@ static int sfp_sm_mod_probe(struct sfp * + } + } + ++ /* Some cheap SFP-GE-T modules always indicate TX fault */ ++ oem_ge_t = !memcmp(id.base.vendor_name, "OEM ", 16) && ++ !memcmp(id.base.vendor_pn, "SFP-GE-T ", 12); ++ + /* Cotsworks do not seem to update the checksums when they + * do the final programming with the final module part number, + * serial number and date code. +@@ -1946,8 +1951,8 @@ static int sfp_sm_mod_probe(struct sfp * + else + sfp->module_t_start_up = T_START_UP; + +- if (!memcmp(id.base.vendor_name, "HUAWEI ", 16) && +- !memcmp(id.base.vendor_pn, "MA5671A ", 16)) ++ if ((!memcmp(id.base.vendor_name, "HUAWEI ", 16) && ++ !memcmp(id.base.vendor_pn, "MA5671A ", 16)) || oem_ge_t) + sfp->tx_fault_ignore = true; + else + sfp->tx_fault_ignore = false; +@@ -2404,10 +2409,12 @@ static void sfp_check_state(struct sfp * + mutex_lock(&sfp->st_mutex); + state = sfp_get_state(sfp); + changed = state ^ sfp->state; +- if (sfp->tx_fault_ignore) ++ if (sfp->tx_fault_ignore) { + changed &= SFP_F_PRESENT | SFP_F_LOS; +- else ++ state &= ~SFP_F_TX_FAULT; ++ } else { + changed &= SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT; ++ } + + for (i = 0; i < GPIO_MAX; i++) + if (changed & BIT(i)) diff --git a/target/linux/generic/pending-5.10/495-mtd-core-add-get_mtd_device_by_node.patch b/target/linux/generic/pending-5.10/495-mtd-core-add-get_mtd_device_by_node.patch deleted file mode 100644 index 66017e1648..0000000000 --- a/target/linux/generic/pending-5.10/495-mtd-core-add-get_mtd_device_by_node.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 1bd1b740f208d1cf4071932cc51860d37266c402 Mon Sep 17 00:00:00 2001 -From: Bernhard Frauendienst -Date: Sat, 1 Sep 2018 00:30:11 +0200 -Subject: [PATCH 495/497] mtd: core: add get_mtd_device_by_node - -Add function to retrieve a mtd device by its OF node. Since drivers can -assign arbitrary names to mtd devices in the absence of a label -property, there is no other reliable way to retrieve a mtd device for a -given OF node. - -Signed-off-by: Bernhard Frauendienst -Reviewed-by: Miquel Raynal ---- - drivers/mtd/mtdcore.c | 38 ++++++++++++++++++++++++++++++++++++++ - include/linux/mtd/mtd.h | 2 ++ - 2 files changed, 40 insertions(+) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -1145,6 +1145,44 @@ out_unlock: - } - EXPORT_SYMBOL_GPL(get_mtd_device_nm); - -+/** -+ * get_mtd_device_by_node - obtain a validated handle for an MTD device -+ * by of_node -+ * @of_node: OF node of MTD device to open -+ * -+ * This function returns MTD device description structure in case of -+ * success and an error code in case of failure. -+ */ -+struct mtd_info *get_mtd_device_by_node(const struct device_node *of_node) -+{ -+ int err = -ENODEV; -+ struct mtd_info *mtd = NULL, *other; -+ -+ mutex_lock(&mtd_table_mutex); -+ -+ mtd_for_each_device(other) { -+ if (of_node == other->dev.of_node) { -+ mtd = other; -+ break; -+ } -+ } -+ -+ if (!mtd) -+ goto out_unlock; -+ -+ err = __get_mtd_device(mtd); -+ if (err) -+ goto out_unlock; -+ -+ mutex_unlock(&mtd_table_mutex); -+ return mtd; -+ -+out_unlock: -+ mutex_unlock(&mtd_table_mutex); -+ return ERR_PTR(err); -+} -+EXPORT_SYMBOL_GPL(get_mtd_device_by_node); -+ - void put_mtd_device(struct mtd_info *mtd) - { - mutex_lock(&mtd_table_mutex); ---- a/include/linux/mtd/mtd.h -+++ b/include/linux/mtd/mtd.h -@@ -697,6 +697,8 @@ extern int __get_mtd_device(struct mtd_i - extern void __put_mtd_device(struct mtd_info *mtd); - extern struct mtd_info *of_get_mtd_device_by_node(struct device_node *np); - extern struct mtd_info *get_mtd_device_nm(const char *name); -+extern struct mtd_info *get_mtd_device_by_node( -+ const struct device_node *of_node); - extern void put_mtd_device(struct mtd_info *mtd); - - static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd) diff --git a/target/linux/generic/pending-5.10/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/target/linux/generic/pending-5.10/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch index 058cab09e5..9b938a43f8 100644 --- a/target/linux/generic/pending-5.10/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch +++ b/target/linux/generic/pending-5.10/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch @@ -165,7 +165,7 @@ Signed-off-by: Bernhard Frauendienst + platform_set_drvdata(pdev, info); + + of_for_each_phandle(&it, err, node, "devices", NULL, 0) { -+ mtd = get_mtd_device_by_node(it.node); ++ mtd = of_get_mtd_device_by_node(it.node); + if (IS_ERR(mtd)) { + of_node_put(it.node); + err = -EPROBE_DEFER; diff --git a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch b/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch deleted file mode 100644 index 3e14a1dd31..0000000000 --- a/target/linux/generic/pending-5.15/495-mtd-core-add-get_mtd_device_by_node.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 1bd1b740f208d1cf4071932cc51860d37266c402 Mon Sep 17 00:00:00 2001 -From: Bernhard Frauendienst -Date: Sat, 1 Sep 2018 00:30:11 +0200 -Subject: [PATCH 495/497] mtd: core: add get_mtd_device_by_node - -Add function to retrieve a mtd device by its OF node. Since drivers can -assign arbitrary names to mtd devices in the absence of a label -property, there is no other reliable way to retrieve a mtd device for a -given OF node. - -Signed-off-by: Bernhard Frauendienst -Reviewed-by: Miquel Raynal ---- - drivers/mtd/mtdcore.c | 38 ++++++++++++++++++++++++++++++++++++++ - include/linux/mtd/mtd.h | 2 ++ - 2 files changed, 40 insertions(+) - ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -1302,6 +1302,44 @@ out_unlock: - } - EXPORT_SYMBOL_GPL(get_mtd_device_nm); - -+/** -+ * get_mtd_device_by_node - obtain a validated handle for an MTD device -+ * by of_node -+ * @of_node: OF node of MTD device to open -+ * -+ * This function returns MTD device description structure in case of -+ * success and an error code in case of failure. -+ */ -+struct mtd_info *get_mtd_device_by_node(const struct device_node *of_node) -+{ -+ int err = -ENODEV; -+ struct mtd_info *mtd = NULL, *other; -+ -+ mutex_lock(&mtd_table_mutex); -+ -+ mtd_for_each_device(other) { -+ if (of_node == other->dev.of_node) { -+ mtd = other; -+ break; -+ } -+ } -+ -+ if (!mtd) -+ goto out_unlock; -+ -+ err = __get_mtd_device(mtd); -+ if (err) -+ goto out_unlock; -+ -+ mutex_unlock(&mtd_table_mutex); -+ return mtd; -+ -+out_unlock: -+ mutex_unlock(&mtd_table_mutex); -+ return ERR_PTR(err); -+} -+EXPORT_SYMBOL_GPL(get_mtd_device_by_node); -+ - void put_mtd_device(struct mtd_info *mtd) - { - mutex_lock(&mtd_table_mutex); ---- a/include/linux/mtd/mtd.h -+++ b/include/linux/mtd/mtd.h -@@ -704,6 +704,8 @@ extern int __get_mtd_device(struct mtd_i - extern void __put_mtd_device(struct mtd_info *mtd); - extern struct mtd_info *of_get_mtd_device_by_node(struct device_node *np); - extern struct mtd_info *get_mtd_device_nm(const char *name); -+extern struct mtd_info *get_mtd_device_by_node( -+ const struct device_node *of_node); - extern void put_mtd_device(struct mtd_info *mtd); - - static inline uint64_t mtdpart_get_offset(const struct mtd_info *mtd) diff --git a/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch index 321680154d..e0cbc4508b 100644 --- a/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch +++ b/target/linux/generic/pending-5.15/497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch @@ -165,7 +165,7 @@ Signed-off-by: Bernhard Frauendienst + platform_set_drvdata(pdev, info); + + of_for_each_phandle(&it, err, node, "devices", NULL, 0) { -+ mtd = get_mtd_device_by_node(it.node); ++ mtd = of_get_mtd_device_by_node(it.node); + if (IS_ERR(mtd)) { + of_node_put(it.node); + err = -EPROBE_DEFER; diff --git a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch index 4b5c474204..e3e338bd4f 100644 --- a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch +++ b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2443,8 +2443,8 @@ static irqreturn_t mtk_handle_irq_rx(int +@@ -2381,8 +2381,8 @@ static irqreturn_t mtk_handle_irq_rx(int eth->rx_events++; if (likely(napi_schedule_prep(ð->rx_napi))) { @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau } return IRQ_HANDLED; -@@ -2456,8 +2456,8 @@ static irqreturn_t mtk_handle_irq_tx(int +@@ -2394,8 +2394,8 @@ static irqreturn_t mtk_handle_irq_tx(int eth->tx_events++; if (likely(napi_schedule_prep(ð->tx_napi))) { @@ -30,12 +30,12 @@ Signed-off-by: Felix Fietkau } return IRQ_HANDLED; -@@ -3623,6 +3623,8 @@ static int mtk_probe(struct platform_dev +@@ -3585,6 +3585,8 @@ static int mtk_probe(struct platform_dev * for NAPI to work */ init_dummy_netdev(ð->dummy_dev); + eth->dummy_dev.threaded = 1; + strcpy(eth->dummy_dev.name, "mtk_eth"); netif_napi_add(ð->dummy_dev, ð->tx_napi, mtk_napi_tx, - MTK_NAPI_WEIGHT); + NAPI_POLL_WEIGHT); netif_napi_add(ð->dummy_dev, ð->rx_napi, mtk_napi_rx, diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch index 21c322b4f1..d6e7f40f3b 100644 --- a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1738,6 +1738,9 @@ void phy_detach(struct phy_device *phyde +@@ -1744,6 +1744,9 @@ void phy_detach(struct phy_device *phyde struct module *ndev_owner = NULL; struct mii_bus *bus; @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -789,6 +789,12 @@ struct phy_driver { +@@ -823,6 +823,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch b/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch new file mode 100644 index 0000000000..703a0b8b72 --- /dev/null +++ b/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch @@ -0,0 +1,101 @@ +From ace6abaa0f9203083fe4c0a6a74da2d96410b625 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Sat, 13 Aug 2022 12:49:33 +0200 +Subject: [PATCH 01/10] net: phy: realtek: rtl8221: allow to configure SERDES + mode + +The rtl8221 supports multiple SERDES modes: +- SGMII +- 2500base-x +- HiSGMII + +Further it supports rate adaption on SERDES links to allow +slow ethernet speeds (10/100/1000mbit) to work on 2500base-x/HiSGMII +links without reducing the SERDES speed. + +When operating without rate adapters the SERDES link will follow the +ethernet speed. + +Signed-off-by: Alexander Couzens +--- + drivers/net/phy/realtek.c | 48 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -53,6 +53,15 @@ + RTL8201F_ISR_LINK) + #define RTL8201F_IER 0x13 + ++#define RTL8221B_MMD_SERDES_CTRL MDIO_MMD_VEND1 ++#define RTL8221B_MMD_PHY_CTRL MDIO_MMD_VEND2 ++#define RTL8221B_SERDES_OPTION 0x697a ++#define RTL8221B_SERDES_OPTION_MODE_MASK GENMASK(5, 0) ++#define RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII 0 ++#define RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII 1 ++#define RTL8221B_SERDES_OPTION_MODE_2500BASEX 2 ++#define RTL8221B_SERDES_OPTION_MODE_HISGMII 3 ++ + #define RTL8366RB_POWER_SAVE 0x15 + #define RTL8366RB_POWER_SAVE_ON BIT(12) + +@@ -841,6 +850,43 @@ static irqreturn_t rtl9000a_handle_inter + return IRQ_HANDLED; + } + ++static int rtl8221b_config_init(struct phy_device *phydev) ++{ ++ u16 option_mode; ++ ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII; ++ break; ++ default: ++ return 0; ++ } ++ ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, ++ 0x75f3, 0); ++ ++ phy_modify_mmd_changed(phydev, RTL8221B_MMD_SERDES_CTRL, ++ RTL8221B_SERDES_OPTION, ++ RTL8221B_SERDES_OPTION_MODE_MASK, option_mode); ++ switch (option_mode) { ++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII: ++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX: ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd455); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); ++ break; ++ case RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII: ++ case RTL8221B_SERDES_OPTION_MODE_HISGMII: ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd433); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); ++ break; ++ } ++ ++ return 0; ++} ++ + static struct phy_driver realtek_drvs[] = { + { + PHY_ID_MATCH_EXACT(0x00008201), +@@ -981,6 +1027,7 @@ static struct phy_driver realtek_drvs[] + PHY_ID_MATCH_EXACT(0x001cc849), + .name = "RTL8221B-VB-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, ++ .config_init = rtl8221b_config_init, + .config_aneg = rtl822x_config_aneg, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, +@@ -992,6 +1039,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8221B-VM-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .config_init = rtl8221b_config_init, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, diff --git a/target/linux/generic/pending-5.15/722-net-mt7531-only-do-PLL-once-after-the-reset.patch b/target/linux/generic/pending-5.15/722-net-mt7531-only-do-PLL-once-after-the-reset.patch new file mode 100644 index 0000000000..6fd450d7f9 --- /dev/null +++ b/target/linux/generic/pending-5.15/722-net-mt7531-only-do-PLL-once-after-the-reset.patch @@ -0,0 +1,67 @@ +From 9fec662b54fc956b776df15c704e996c61292850 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Sat, 13 Aug 2022 13:05:09 +0200 +Subject: [PATCH 02/10] net: mt7531: only do PLL once after the reset + +Move the PLL init of the switch out of the pad configuration of the port +6 (usally cpu port). + +Fix a unidirectional 100 mbit limitation on 1 gbit or 2.5 gbit links for +outbound traffic on port 5 or port 6. + +Signed-off-by: Alexander Couzens +--- + drivers/net/dsa/mt7530.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -506,14 +506,19 @@ static bool mt7531_dual_sgmii_supported( + static int + mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface) + { +- struct mt7530_priv *priv = ds->priv; ++ return 0; ++} ++ ++static void ++mt7531_pll_setup(struct mt7530_priv *priv) ++{ + u32 top_sig; + u32 hwstrap; + u32 xtal; + u32 val; + + if (mt7531_dual_sgmii_supported(priv)) +- return 0; ++ return; + + val = mt7530_read(priv, MT7531_CREV); + top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR); +@@ -592,8 +597,6 @@ mt7531_pad_setup(struct dsa_switch *ds, + val |= EN_COREPLL; + mt7530_write(priv, MT7531_PLLGP_EN, val); + usleep_range(25, 35); +- +- return 0; + } + + static void +@@ -2326,6 +2329,8 @@ mt7531_setup(struct dsa_switch *ds) + SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | + SYS_CTRL_REG_RST); + ++ mt7531_pll_setup(priv); ++ + if (mt7531_dual_sgmii_supported(priv)) { + priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII; + +@@ -2882,8 +2887,6 @@ mt7531_cpu_port_config(struct dsa_switch + case 6: + interface = PHY_INTERFACE_MODE_2500BASEX; + +- mt7531_pad_setup(ds, interface); +- + priv->p6_interface = interface; + break; + default: diff --git a/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch b/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch new file mode 100644 index 0000000000..cc12d72110 --- /dev/null +++ b/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch @@ -0,0 +1,28 @@ +From 3fb8841513c4ec3a2e5d366df86230c45f239a57 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Sat, 13 Aug 2022 13:08:22 +0200 +Subject: [PATCH 03/10] net: mt7531: ensure all MACs are powered down before + reset + +The datasheet [1] explicit describes it as requirement for a reset. + +[1] MT7531 Reference Manual for Development Board rev 1.0, page 735 + +Signed-off-by: Alexander Couzens +--- + drivers/net/dsa/mt7530.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2324,6 +2324,10 @@ mt7531_setup(struct dsa_switch *ds) + return -ENODEV; + } + ++ /* all MACs must be forced link-down before sw reset */ ++ for (i = 0; i < MT7530_NUM_PORTS; i++) ++ mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK); ++ + /* Reset the switch through internal reset */ + mt7530_write(priv, MT7530_SYS_CTRL, + SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | diff --git a/target/linux/generic/pending-5.15/724-net-mtk_sgmii-implement-mtk_pcs_ops.patch b/target/linux/generic/pending-5.15/724-net-mtk_sgmii-implement-mtk_pcs_ops.patch new file mode 100644 index 0000000000..896f0169d2 --- /dev/null +++ b/target/linux/generic/pending-5.15/724-net-mtk_sgmii-implement-mtk_pcs_ops.patch @@ -0,0 +1,44 @@ +From cbfed00575d15eafd85efd9619b7ecc0836a4aa7 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Sat, 13 Aug 2022 14:42:12 +0200 +Subject: [PATCH 04/10] net: mtk_sgmii: implement mtk_pcs_ops + +Implement mtk_pcs_ops for the SGMII pcs to read the current state +of the hardware. + +Signed-off-by: Alexander Couzens +[added DUPLEX_FULL] +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -122,10 +122,26 @@ static void mtk_pcs_link_up(struct phyli + regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + } + ++static void mtk_pcs_get_state(struct phylink_pcs *pcs, struct phylink_link_state *state) ++{ ++ struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs); ++ unsigned int val; ++ ++ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); ++ state->speed = val & RG_PHY_SPEED_3_125G ? SPEED_2500 : SPEED_1000; ++ ++ regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); ++ state->an_complete = !!(val & SGMII_AN_COMPLETE); ++ state->link = !!(val & SGMII_LINK_STATYS); ++ state->duplex = DUPLEX_FULL; ++ state->pause = 0; ++} ++ + static const struct phylink_pcs_ops mtk_pcs_ops = { + .pcs_config = mtk_pcs_config, + .pcs_an_restart = mtk_pcs_restart_an, + .pcs_link_up = mtk_pcs_link_up, ++ .pcs_get_state = mtk_pcs_get_state, + }; + + int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3) diff --git a/target/linux/generic/pending-5.15/725-net-mtk_sgmii-fix-powering-up-the-SGMII-phy.patch b/target/linux/generic/pending-5.15/725-net-mtk_sgmii-fix-powering-up-the-SGMII-phy.patch new file mode 100644 index 0000000000..0fa357d48f --- /dev/null +++ b/target/linux/generic/pending-5.15/725-net-mtk_sgmii-fix-powering-up-the-SGMII-phy.patch @@ -0,0 +1,39 @@ +From 7f75f43fe2159123baa101fcc8c6faa0b0a4c598 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Sat, 13 Aug 2022 14:48:51 +0200 +Subject: [PATCH 05/10] net: mtk_sgmii: fix powering up the SGMII phy + +There are certain race condition when the SGMII_PHYA_PWD register still +contains 0x9 which prevents the SGMII from working properly. + +The SGMII still shows link but no traffic can flow. + +Signed-off-by: Alexander Couzens +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -36,9 +36,7 @@ static int mtk_pcs_setup_mode_an(struct + val |= SGMII_AN_RESTART; + regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + +- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); +- val &= ~SGMII_PHYA_PWD; +- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); + + return 0; + +@@ -70,9 +68,7 @@ static int mtk_pcs_setup_mode_force(stru + regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + + /* Release PHYA power down state */ +- regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val); +- val &= ~SGMII_PHYA_PWD; +- regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val); ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); + + return 0; + } diff --git a/target/linux/generic/pending-5.15/726-net-mtk_sgmii-ensure-the-SGMII-PHY-is-powered-down-o.patch b/target/linux/generic/pending-5.15/726-net-mtk_sgmii-ensure-the-SGMII-PHY-is-powered-down-o.patch new file mode 100644 index 0000000000..329b41cf03 --- /dev/null +++ b/target/linux/generic/pending-5.15/726-net-mtk_sgmii-ensure-the-SGMII-PHY-is-powered-down-o.patch @@ -0,0 +1,65 @@ +From 9daea9b71d060d93d7394ac465b2e5ee0b7e7bca Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Mon, 15 Aug 2022 16:02:01 +0200 +Subject: [PATCH 06/10] net: mtk_sgmii: ensure the SGMII PHY is powered down on + configuration + +The code expect the PHY to be in power down (which is only true after reset). +Allow the changes of SGMII parameters more than once. +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -7,6 +7,7 @@ + * + */ + ++#include + #include + #include + #include +@@ -24,6 +25,9 @@ static int mtk_pcs_setup_mode_an(struct + { + unsigned int val; + ++ /* PHYA power down */ ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ + /* Setup the link timer and QPHY power up inside SGMIISYS */ + regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, + SGMII_LINK_TIMER_DEFAULT); +@@ -36,6 +40,10 @@ static int mtk_pcs_setup_mode_an(struct + val |= SGMII_AN_RESTART; + regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + ++ /* Release PHYA power down state ++ * unknown how much the QPHY needs but it is racy without a sleep ++ */ ++ usleep_range(50, 100); + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); + + return 0; +@@ -50,6 +58,9 @@ static int mtk_pcs_setup_mode_force(stru + { + unsigned int val; + ++ /* PHYA power down */ ++ regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ + regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); + val &= ~RG_PHY_SPEED_MASK; + if (interface == PHY_INTERFACE_MODE_2500BASEX) +@@ -67,7 +78,10 @@ static int mtk_pcs_setup_mode_force(stru + val |= SGMII_SPEED_1000; + regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + +- /* Release PHYA power down state */ ++ /* Release PHYA power down state ++ * unknown how much the QPHY needs but it is racy without a sleep ++ */ ++ usleep_range(50, 100); + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); + + return 0; diff --git a/target/linux/generic/pending-5.15/727-net-mtk_sgmii-mtk_pcs_setup_mode_an-don-t-rely-on-re.patch b/target/linux/generic/pending-5.15/727-net-mtk_sgmii-mtk_pcs_setup_mode_an-don-t-rely-on-re.patch new file mode 100644 index 0000000000..5bc187cfc8 --- /dev/null +++ b/target/linux/generic/pending-5.15/727-net-mtk_sgmii-mtk_pcs_setup_mode_an-don-t-rely-on-re.patch @@ -0,0 +1,31 @@ +From e4dca7affb8c03438b63bdb5fddefd6ad2431cfd Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Mon, 15 Aug 2022 14:59:29 +0200 +Subject: [PATCH 07/10] net: mtk_sgmii: mtk_pcs_setup_mode_an: don't rely on + register defaults + +Ensure autonegotiation is enabled. + +Signed-off-by: Alexander Couzens +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -32,12 +32,13 @@ static int mtk_pcs_setup_mode_an(struct + regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, + SGMII_LINK_TIMER_DEFAULT); + ++ /* disable remote fault & enable auto neg */ + regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); +- val |= SGMII_REMOTE_FAULT_DIS; ++ val |= SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN; + regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val); + + regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val); +- val |= SGMII_AN_RESTART; ++ val |= SGMII_AN_RESTART | SGMII_AN_ENABLE; + regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + + /* Release PHYA power down state diff --git a/target/linux/generic/pending-5.15/728-net-mtk_sgmii-set-the-speed-according-to-the-phy-int.patch b/target/linux/generic/pending-5.15/728-net-mtk_sgmii-set-the-speed-according-to-the-phy-int.patch new file mode 100644 index 0000000000..0b17f77eef --- /dev/null +++ b/target/linux/generic/pending-5.15/728-net-mtk_sgmii-set-the-speed-according-to-the-phy-int.patch @@ -0,0 +1,47 @@ +From 952b64575613d26163a5afa5ff8bfdb57840091b Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Mon, 15 Aug 2022 15:00:14 +0200 +Subject: [PATCH 08/10] net: mtk_sgmii: set the speed according to the phy + interface in AN + +The non auto-negotioting code path is setting the correct speed for the +interface. Ensure auto-negotiation code path is doing it as well. + +Signed-off-by: Alexander Couzens +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -21,13 +21,20 @@ static struct mtk_pcs *pcs_to_mtk_pcs(st + } + + /* For SGMII interface mode */ +-static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs) ++static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs, phy_interface_t interface) + { + unsigned int val; + + /* PHYA power down */ + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); + ++ /* Set SGMII phy speed */ ++ regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val); ++ val &= ~RG_PHY_SPEED_MASK; ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ val |= RG_PHY_SPEED_3_125G; ++ regmap_write(mpcs->regmap, mpcs->ana_rgc3, val); ++ + /* Setup the link timer and QPHY power up inside SGMIISYS */ + regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, + SGMII_LINK_TIMER_DEFAULT); +@@ -100,7 +107,7 @@ static int mtk_pcs_config(struct phylink + if (interface != PHY_INTERFACE_MODE_SGMII) + err = mtk_pcs_setup_mode_force(mpcs, interface); + else if (phylink_autoneg_inband(mode)) +- err = mtk_pcs_setup_mode_an(mpcs); ++ err = mtk_pcs_setup_mode_an(mpcs, interface); + + return err; + } diff --git a/target/linux/generic/pending-5.15/729-net-mtk_eth_soc-improve-comment.patch b/target/linux/generic/pending-5.15/729-net-mtk_eth_soc-improve-comment.patch new file mode 100644 index 0000000000..80144850ec --- /dev/null +++ b/target/linux/generic/pending-5.15/729-net-mtk_eth_soc-improve-comment.patch @@ -0,0 +1,22 @@ +From 06773f19cffd6c9d34dcbc8320169afef5ab60ba Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Mon, 15 Aug 2022 13:58:07 +0200 +Subject: [PATCH 09/10] net: mtk_eth_soc: improve comment + +Signed-off-by: Alexander Couzens +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -80,7 +80,8 @@ static int mtk_pcs_setup_mode_force(stru + val &= ~SGMII_AN_ENABLE; + regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val); + +- /* Set the speed etc but leave the duplex unchanged */ ++ /* Set the speed etc but leave the duplex unchanged. ++ * The SGMII mode for 2.5gbit is the same as for 1gbit, expect the speed in ANA_RGC3 */ + regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val); + val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK; + val |= SGMII_SPEED_1000; diff --git a/target/linux/generic/pending-5.15/730-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch b/target/linux/generic/pending-5.15/730-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch new file mode 100644 index 0000000000..6c7fd6a6bf --- /dev/null +++ b/target/linux/generic/pending-5.15/730-mtk_sgmii-enable-PCS-polling-to-allow-SFP-work.patch @@ -0,0 +1,23 @@ +From 95dcd0f223d7cab6e25bc19088016e5eb4ca1804 Mon Sep 17 00:00:00 2001 +From: Alexander Couzens +Date: Tue, 16 Aug 2022 00:22:11 +0200 +Subject: [PATCH 10/10] mtk_sgmii: enable PCS polling to allow SFP work + +Currently there is no IRQ handling (even the SGMII supports it). +Enable polling to support SFP ports. + +Signed-off-by: Alexander Couzens +--- + drivers/net/ethernet/mediatek/mtk_sgmii.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c ++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c +@@ -180,6 +180,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss, + return PTR_ERR(ss->pcs[i].regmap); + + ss->pcs[i].pcs.ops = &mtk_pcs_ops; ++ ss->pcs[i].pcs.poll = 1; + } + + return 0; diff --git a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch index de28ebe73a..e180a385e1 100644 --- a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch +++ b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch @@ -33,7 +33,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -274,7 +274,6 @@ struct advk_pcie { +@@ -275,7 +275,6 @@ struct advk_pcie { u8 wins_count; struct irq_domain *rp_irq_domain; struct irq_domain *irq_domain; @@ -41,7 +41,7 @@ Signed-off-by: Marek Behún raw_spinlock_t irq_lock; struct irq_domain *msi_domain; struct irq_domain *msi_inner_domain; -@@ -1330,14 +1329,19 @@ static void advk_pcie_irq_unmask(struct +@@ -1345,14 +1344,19 @@ static void advk_pcie_irq_unmask(struct raw_spin_unlock_irqrestore(&pcie->irq_lock, flags); } @@ -63,7 +63,7 @@ Signed-off-by: Marek Behún irq_set_chip_data(virq, pcie); return 0; -@@ -1396,7 +1400,6 @@ static int advk_pcie_init_irq_domain(str +@@ -1411,7 +1415,6 @@ static int advk_pcie_init_irq_domain(str struct device *dev = &pcie->pdev->dev; struct device_node *node = dev->of_node; struct device_node *pcie_intc_node; @@ -71,7 +71,7 @@ Signed-off-by: Marek Behún int ret = 0; raw_spin_lock_init(&pcie->irq_lock); -@@ -1407,28 +1410,14 @@ static int advk_pcie_init_irq_domain(str +@@ -1422,28 +1425,14 @@ static int advk_pcie_init_irq_domain(str return -ENODEV; } diff --git a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch index 4425e3f86b..76b39452ad 100644 --- a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch +++ b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch @@ -23,7 +23,7 @@ Acked-by: Miquel Raynal --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1616,9 +1616,7 @@ static int advk_pcie_enable_phy(struct a +@@ -1631,9 +1631,7 @@ static int advk_pcie_enable_phy(struct a } ret = phy_power_on(pcie->phy); diff --git a/target/linux/mediatek/Makefile b/target/linux/mediatek/Makefile index da3cf18cf6..73da79eaa0 100644 --- a/target/linux/mediatek/Makefile +++ b/target/linux/mediatek/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk ARCH:=arm BOARD:=mediatek BOARDNAME:=MediaTek Ralink ARM -SUBTARGETS:=mt7622 mt7623 mt7629 +SUBTARGETS:=mt7622 mt7623 mt7629 filogic FEATURES:=dt-overlay emmc fpu gpio nand pci pcie rootfs-part separate_ramdisk squashfs usb KERNEL_PATCHVER:=5.15 diff --git a/target/linux/mediatek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr.sh b/target/linux/mediatek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr.sh index b078b8f8ce..5dec158a93 100644 --- a/target/linux/mediatek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr.sh +++ b/target/linux/mediatek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr.sh @@ -1,6 +1,6 @@ [ ! -e /etc/fw_env.config ] && exit 0 -. /lib/functions.sh +. /lib/functions/system.sh case "$(board_name)" in bananapi,bpi-r2|\ @@ -9,6 +9,12 @@ unielec,u7623-02) [ -z "$(fw_printenv -n ethaddr 2>/dev/null)" ] && fw_setenv ethaddr "$(cat /sys/class/net/eth0/address)" ;; +bananapi,bpi-r3) + [ -z "$(fw_printenv -n ethaddr 2>/dev/null)" ] && + fw_setenv ethaddr "$(cat /sys/class/net/eth0/address)" + [ -z "$(fw_printenv -n eth1addr 2>/dev/null)" ] && + fw_setenv eth1addr "$(macaddr_add $(cat /sys/class/net/eth0/address) 1)" + ;; esac exit 0 diff --git a/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-emmc-nor.dts b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-emmc-nor.dts new file mode 100644 index 0000000000..1c82782b1f --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-emmc-nor.dts @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; + + fragment@0 { + target-path = "/soc/mmc@11230000"; + __overlay__ { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + /delete-property/ cap-sd-highspeed; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x14014>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/soc/spi@1100a000"; + __overlay__ { + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x40000>; + }; + + partition@80000 { + label = "reserved2"; + reg = <0x80000 0x80000>; + }; + + partition@100000 { + label = "fip"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + label = "recovery"; + reg = <0x180000 0xa80000>; + }; + + partition@c00000 { + label = "fit"; + reg = <0xc00000 0x1400000>; + compatible = "denx,fit"; + }; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-emmc-snand.dts b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-emmc-snand.dts new file mode 100644 index 0000000000..2ca865d6e6 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-emmc-snand.dts @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; + + fragment@0 { + target-path = "/soc/mmc@11230000"; + __overlay__ { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + /delete-property/ cap-sd-highspeed; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x14014>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/soc/spi@1100a000"; + __overlay__ { + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <10000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "reserved"; + reg = <0x80000 0x300000>; + }; + + partition@380000 { + label = "fip"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x7a80000>; + }; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-nor.dts b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-nor.dts new file mode 100644 index 0000000000..f597b869ab --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-nor.dts @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; + + fragment@0 { + target-path = "/soc/spi@1100a000"; + __overlay__ { + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x40000>; + }; + + partition@80000 { + label = "reserved2"; + reg = <0x80000 0x80000>; + }; + + partition@100000 { + label = "fip"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + label = "recovery"; + reg = <0x180000 0xa80000>; + }; + + partition@c00000 { + label = "fit"; + reg = <0xc00000 0x1400000>; + compatible = "denx,fit"; + }; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-snand.dts b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-snand.dts new file mode 100644 index 0000000000..e29ea2adb0 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3-snand.dts @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; + + fragment@0 { + target-path = "/soc/spi@1100a000"; + __overlay__ { + nand-flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <10000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "reserved"; + reg = <0x80000 0x300000>; + }; + + partition@380000 { + label = "fip"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x7a80000>; + }; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3.dts b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3.dts new file mode 100644 index 0000000000..2d9b0ac3b1 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-bananapi-bpi-r3.dts @@ -0,0 +1,540 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include +#include + +#include "mt7986a.dtsi" + +/ { + model = "Bananapi BPI-R3"; + compatible = "bananapi,bpi-r3", "mediatek,mt7986a"; + + aliases { + serial0 = &uart0; + ethernet0 = &gmac0; + ethernet1 = &gmac1; + led-boot = &led_status_green; + led-failsafe = &led_status_green; + led-running = &led_status_green; + led-upgrade = &led_status_blue; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; + + keys { + compatible = "gpio-keys"; + + factory { + label = "reset"; + linux,code = ; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + wps { + label = "wps"; + linux,code = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_status_green: green { + label = "green:status"; + gpios = <&pio 69 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led_status_blue: blue { + label = "blue:status"; + gpios = <&pio 86 GPIO_ACTIVE_HIGH>; + }; + }; + + /* SFP1 cage (WAN) */ + i2c_sfp1: i2c-gpio-0 { + compatible = "i2c-gpio"; + sda-gpios = <&pio 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&pio 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp1: sfp1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c_sfp1>; + los-gpios = <&pio 46 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pio 49 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 7 GPIO_ACTIVE_HIGH>; + }; + + /* SFP2 cage (LAN) */ + i2c_sfp2: i2c-gpio-1 { + compatible = "i2c-gpio"; + sda-gpios = <&pio 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&pio 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp2: sfp2 { + compatible = "sff,sfp"; + i2c-bus = <&i2c_sfp2>; + los-gpios = <&pio 31 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&pio 47 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&pio 15 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&pio 48 GPIO_ACTIVE_HIGH>; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + sfp = <&sfp1>; + managed = "in-band-status"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + switch: switch@0 { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_LOW>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "wan"; + }; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@4 { + reg = <4>; + label = "lan4"; + }; + + port5: port@5 { + reg = <5>; + label = "sfp2"; + phy-mode = "2500base-x"; + sfp = <&sfp2>; + managed = "in-band-status"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +&mmc0 { + //sdcard + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <4>; + max-frequency = <52000000>; + cap-sd-highspeed; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&wmac { + status = "okay"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>, <&wf_led_pins>; + pinctrl-1 = <&wf_dbdc_pins>, <&wf_led_pins>; +}; + +&pio { + /* don't mess around with GPIO 419, 450, 451, 498, 510 in sysfs system will freeze. */ + mmc0_pins_default: mmc0-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_clk", "pcie_pereset"; //"pcie_wake" is unused + }; + }; + + spi_flash_pins: spi-flash-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1"; + }; + }; + + wf_led_pins: wf-led-pins { + mux { + function = "led"; + groups = "wifi_led"; + }; + }; + + wf_2g_5g_pins: wf-2g-5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf-dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + + status = "okay"; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&wmac { + mediatek,eeprom-data = <0x86790900 0xc4326 0x60000000 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x1000000 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x800 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x24649090 0x280000 0x5100000 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x21e00 0x21e0002 0x1e00021e 0x22800 0x2280002 0x28000228 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x8080 0x8080fdf7 + 0x903150d 0x80808080 0x80808080 0x5050d0d 0x1313c6c6 0xc3c3c200 0xc200c2 0x8182 + 0x8585c2c2 0x82828282 0x858500c2 0xc2000081 0x82858587 0x87c2c200 0x81818285 0x858787c2 + 0xc2000081 0x82858587 0x87c2c200 0x818285 0x858787c2 0xc2000081 0x82858587 0x87c4c4c2 + 0xc100c300 0xc3c3c100 0x818383c3 0xc3c3c100 0x81838300 0xc2c2c2c0 0x81828484 0xc3 + 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x838686c2 0xc2c2c081 0x82848486 0x86c3c3c3 + 0xc1008183 0x838686c3 0xc3c3c100 0x81838386 0x86c3c3c3 0xc1008183 0x83868622 0x28002228 + 0x222800 0x22280000 0xdddddddd 0xdddddddd 0xddbbbbbb 0xccccccdd 0xdddddddd 0xdddddddd + 0xeeeeeecc 0xccccdddd 0xdddddddd 0x4a5662 0x4a 0x56620000 0x4a5662 0x4a + 0x56620000 0x88888888 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 + 0x33333326 0x26262626 0x26262600 0x33333326 0x26262626 0x26262600 0x00 0xf0f0cc00 + 0x00 0xaaaa 0xaabbbbbb 0xcccccccc 0xccccbbbb 0xbbbbbbbb 0xbbbbbbaa 0xaaaabbbb + 0xbbaaaaaa 0x999999aa 0xaaaabbbb 0xbbcccccc 0x00 0xaaaa 0xaa000000 0xbbbbbbbb + 0xbbbbaaaa 0xaa999999 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb + 0x00 0x00 0x00 0x99999999 0x9999aaaa 0xaaaaaaaa 0x999999aa 0xaaaaaaaa + 0xaaaaaaaa 0xaaaaaaaa 0xaaaabbbb 0xbbbbbbbb 0x00 0xeeee 0xeeffffff 0xcccccccc + 0xccccdddd 0xddbbbbbb 0xccccccbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbbbbb 0xbbbbcccc 0xccdddddd + 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 + 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 + 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e + 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 + 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 + 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e 0x516200 0x686e0051 0x6200686e + 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 0x88888888 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x01 0x6000100 0x1050002 0xff0300 + 0xf900fe03 0x00 0x00 0x9b 0x6e370000 0x00 0xfc0009 0xa00fe00 + 0x60700fe 0x70800 0x5000b0a 0x00 0x00 0xe2 0x96460000 0x00 + 0x400f7 0xf8000300 0xfcfe0003 0xfbfc00 0xee00e3f2 0x00 0x00 0x11 + 0xbb550000 0x00 0x600f6 0xfc000300 0xfbfe0004 0xfafe00 0xf600ecf2 0x00 + 0x00 0x1f 0xbf580000 0x00 0x600f5 0xf6000400 0xf8f90004 0xf7f800 + 0xf700f0f4 0x00 0x00 0x24 0xbe570000 0x00 0x800f8 0xfe000600 + 0xf8fd0007 0xf9fe00 0xf500f0f4 0x00 0x00 0x2d 0xd6610000 0x00 + 0x400f7 0xfc000500 0xf7fc0005 0xf7fc00 0xf900f5f8 0x00 0x00 0x26 + 0xd96e0000 0x00 0x400f7 0xf9000600 0xf5f70005 0xf5f800 0xf900f4f7 0x00 + 0x00 0x1b 0xce690000 0x00 0x300f8 0xf8000600 0xf6f60004 0xf6f700 + 0xf900f4f7 0x00 0x00 0x18 0xd8720000 0x00 0x00 0x2404002 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0xc1c2c1c2 0x41c341c3 0x3fc13fc1 0x40c13fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c13fc2 + 0x3fc140c0 0x41c040c0 0x3fc33fc3 0x40c23fc2 0x3fc240c1 0x41c040c0 0x3fc23fc2 0x40c23fc2 + 0x3fc140c1 0x41c040c0 0x00 0x00 0x41c741c7 0xc1c7c1c7 0x00 0x00 + 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 + 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 0x3fc03fc0 + 0xa0ce00 0x00 0xb6840000 0x00 0x00 0x00 0x18181818 0x18181818 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x4b5763 0x4b 0x57630000 0x4b5763 0x4b 0x57630000 0x88888888 0x8474759 + 0x69780849 0x49596d7a 0x849495a 0x6d790848 0x48596c78 0x8484858 0x6a780848 0x48586a78 + 0x8484858 0x6c78084a 0x4a5b6d79 0x8474759 0x697a0848 0x48596b79 0x8484859 0x6c7a0848 + 0x48586c79 0x8484857 0x68770848 0x48576877 0x8484857 0x6a77084a 0x4a5a6a77 0x8464659 + 0x69790848 0x48586b79 0x8484858 0x6c7a0848 0x48596c79 0x8484857 0x68770848 0x48576877 + 0x8494958 0x6d7a084b 0x4b5c6c77 0x847475a 0x6a7b0849 0x495a6e7c 0x849495a 0x6e7c0849 + 0x495b6e7c 0x8494959 0x6a7a0849 0x49596a7a 0x84a4a5a 0x6f7d084b 0x4b5c6e7b 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x85848484 + 0xc3c4c4c5 0xc4c3c33f 0xc3c3c2c2 0xc2c2c03f 0xc3c3c3c4 0xc4c4c33f 0xc2c2c2c2 0xc1c3c1c1 + 0xc0c08282 0x83848686 0x88880000 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x1111 0x00 + 0x8080f703 0x10808080 0x80050d13 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0xa4 0xce000000 0xb684 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00>; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts new file mode 100644 index 0000000000..72b8923b41 --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nand.dts @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7986a-spim-snand-rfb"; + + fragment@0 { + target-path = "/soc/spi@1100a000"; + __overlay__ { + status = "okay"; + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <1>; + spi-max-frequency = <10000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0200000>; + }; + partition@380000 { + label = "FIP"; + reg = <0x380000 0x0200000>; + }; + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts new file mode 100644 index 0000000000..b847e48455 --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb-spim-nor.dts @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ + +/dts-v1/; +/plugin/; + +/ { + compatible = "mediatek,mt7986a-snor-rfb"; + + fragment@0 { + target-path = "/soc/spi@1100a000"; + __overlay__ { + status = "okay"; + spi_nor: spi_nor@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x0040000>; + }; + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x0010000>; + }; + factory: partition@50000 { + label = "Factory"; + reg = <0x50000 0x00B0000>; + }; + partition@100000 { + label = "FIP"; + reg = <0x100000 0x0080000>; + }; + partition@180000 { + label = "firmware"; + reg = <0x180000 0xE00000>; + }; + }; + }; + }; + }; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts new file mode 100644 index 0000000000..41ae5f171c --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7986a.dtsi" + +/ { + model = "MediaTek MT7986a RFB"; + compatible = "mediatek,mt7986a-rfb"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&wmac { + status = "okay"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; +}; + +&mdio { + phy5: phy@5 { + compatible = "ethernet-phy-id67c9.de0a"; + reg = <5>; + reset-gpios = <&pio 6 1>; + reset-deassert-us = <20000>; + phy-mode = "2500base-x"; + }; + + phy6: phy@6 { + compatible = "ethernet-phy-id67c9.de0a"; + reg = <6>; + phy-mode = "2500base-x"; + }; + + switch: switch@0 { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 0>; + }; +}; + +&crypto { + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <200000000>; + cap-mmc-highspeed; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + hs400-ds-delay = <0x14014>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + non-removable; + no-sd; + no-sdio; + status = "okay"; +}; + +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&pio { + mmc0_pins_default: mmc0-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; /* pull-down 50K */ + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; /* pull-up 10K */ + }; + }; + + pcie_pins: pcie-pins { + mux { + function = "pcie"; + groups = "pcie_clk", "pcie_wake", "pcie_pereset"; + }; + }; + + spic_pins_g2: spic-pins-29-to-32 { + mux { + function = "spi"; + groups = "spi1_2"; + }; + }; + + spi_flash_pins: spi-flash-pins-33-to-38 { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + mediatek,pull-down-adv = <0>; /* bias-disable */ + }; + }; + + uart1_pins: uart1-pins { + mux { + function = "uart"; + groups = "uart1"; + }; + }; + + uart2_pins: uart2-pins { + mux { + function = "uart"; + groups = "uart2"; + }; + }; + + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi_flash_pins>; + cs-gpios = <0>, <0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spic_pins_g2>; + status = "okay"; + + proslic_spi: proslic_spi@0 { + compatible = "silabs,proslic_spi"; + reg = <0>; + spi-max-frequency = <10000000>; + spi-cpha = <1>; + spi-cpol = <1>; + channel_count = <1>; + debug_level = <4>; /* 1 = TRC, 2 = DBG, 4 = ERR */ + reset_gpio = <&pio 7 0>; + ig,enable-spi = <1>; /* 1: Enable, 0: Disable */ + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan0"; + }; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a.dtsi new file mode 100644 index 0000000000..17adda1554 --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986a.dtsi @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +#include +#include +#include +#include +#include + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + clk40m: oscillator@0 { + compatible = "fixed-clock"; + clock-frequency = <40000000>; + #clock-cells = <0>; + clock-output-names = "clkxtal"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x0>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x1>; + #cooling-cells = <2>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + enable-method = "psci"; + reg = <0x2>; + #cooling-cells = <2>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + enable-method = "psci"; + compatible = "arm,cortex-a53"; + reg = <0x3>; + #cooling-cells = <2>; + }; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* 64 KiB reserved for ramoops/pstore */ + ramoops@42ff0000 { + compatible = "ramoops"; + reg = <0 0x42ff0000 0 0x10000>; + record-size = <0x1000>; + }; + + /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@43000000 { + reg = <0 0x43000000 0 0x30000>; + no-map; + }; + + wmcpu_emi: wmcpu-reserved@4fc00000 { + no-map; + reg = <0 0x4fc00000 0 0x00100000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + ranges; + + gic: interrupt-controller@c000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + interrupt-controller; + reg = <0 0x0c000000 0 0x10000>, /* GICD */ + <0 0x0c080000 0 0x80000>, /* GICR */ + <0 0x0c400000 0 0x2000>, /* GICC */ + <0 0x0c410000 0 0x1000>, /* GICH */ + <0 0x0c420000 0 0x2000>; /* GICV */ + interrupts = ; + }; + + infracfg: infracfg@10001000 { + compatible = "mediatek,mt7986-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + }; + + topckgen: topckgen@1001b000 { + compatible = "mediatek,mt7986-topckgen", "syscon"; + reg = <0 0x1001B000 0 0x1000>; + #clock-cells = <1>; + }; + + watchdog: watchdog@1001c000 { + compatible = "mediatek,mt7986-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x1001c000 0 0x1000>; + interrupts = ; + #reset-cells = <1>; + }; + + pio: pinctrl@1001f000 { + compatible = "mediatek,mt7986a-pinctrl"; + reg = <0 0x1001f000 0 0x1000>, + <0 0x11c30000 0 0x1000>, + <0 0x11c40000 0 0x1000>, + <0 0x11e20000 0 0x1000>, + <0 0x11e30000 0 0x1000>, + <0 0x11f00000 0 0x1000>, + <0 0x11f10000 0 0x1000>, + <0 0x1000b000 0 0x1000>; + reg-names = "gpio", "iocfg_rt", "iocfg_rb", "iocfg_lt", + "iocfg_lb", "iocfg_tr", "iocfg_tl", "eint"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pio 0 0 100>; + interrupt-controller; + interrupts = ; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + }; + + apmixedsys: apmixedsys@1001e000 { + compatible = "mediatek,mt7986-apmixedsys"; + reg = <0 0x1001E000 0 0x1000>; + #clock-cells = <1>; + }; + + sgmiisys0: syscon@10060000 { + compatible = "mediatek,mt7986-sgmiisys_0", + "syscon"; + reg = <0 0x10060000 0 0x1000>; + #clock-cells = <1>; + }; + + sgmiisys1: syscon@10070000 { + compatible = "mediatek,mt7986-sgmiisys_1", + "syscon"; + reg = <0 0x10070000 0 0x1000>; + #clock-cells = <1>; + }; + + trng: trng@1020f000 { + compatible = "mediatek,mt7986-rng"; + reg = <0 0x1020f000 0 0x100>; + clocks = <&infracfg CLK_INFRA_TRNG_CK>; + clock-names = "rng"; + status = "okay"; + }; + + crypto: crypto@10320000 { + compatible = "inside-secure,safexcel-eip97"; + reg = <0 0x10320000 0 0x40000>; + interrupts = , + , + , + ; + interrupt-names = "ring0", "ring1", "ring2", "ring3"; + clocks = <&infracfg CLK_INFRA_EIP97_CK>; + clock-names = "infra_eip97_ck"; + assigned-clocks = <&topckgen CLK_TOP_EIP_B_SEL>; + assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>; + status = "okay"; + }; + + uart0: serial@11002000 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11002000 0 0x400>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_UART0_SEL>, + <&infracfg CLK_INFRA_UART0_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_UART0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_XTAL>, + <&topckgen CLK_TOP_UART_SEL>; + status = "disabled"; + }; + + uart1: serial@11003000 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11003000 0 0x400>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_UART1_SEL>, + <&infracfg CLK_INFRA_UART1_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&infracfg CLK_INFRA_UART1_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_F26M_SEL>; + status = "disabled"; + }; + + uart2: serial@11004000 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11004000 0 0x400>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_UART2_SEL>, + <&infracfg CLK_INFRA_UART2_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&infracfg CLK_INFRA_UART2_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_F26M_SEL>; + status = "disabled"; + }; + + spi0: spi@1100a000 { + compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x1100a000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MPLL_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_SPI0_CK>, + <&infracfg CLK_INFRA_SPI0_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + status = "disabled"; + }; + + spi1: spi@1100b000 { + compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm"; + reg = <0 0x1100b000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MPLL_D2>, + <&topckgen CLK_TOP_SPIM_MST_SEL>, + <&infracfg CLK_INFRA_SPI1_CK>, + <&infracfg CLK_INFRA_SPI1_HCK_CK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk"; + status = "disabled"; + }; + + ssusb: usb@11200000 { + compatible = "mediatek,mt7986-xhci", + "mediatek,mtk-xhci"; + reg = <0 0x11200000 0 0x2e00>, + <0 0x11203e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts = ; + clocks = <&infracfg CLK_INFRA_IUSB_SYS_CK>, + <&topckgen CLK_TOP_U2U3_XHCI_SEL>, + <&infracfg CLK_INFRA_IUSB_CK>, + <&infracfg CLK_INFRA_IUSB_133_CK>, + <&infracfg CLK_INFRA_IUSB_66M_CK>; + clock-names = "sys_ck", + "xhci_ck", + "ref_ck", + "mcu_ck", + "dma_ck"; + phys = <&u2port0 PHY_TYPE_USB2>, + <&u3port0 PHY_TYPE_USB3>, + <&u2port1 PHY_TYPE_USB2>; + status = "disabled"; + }; + + mmc0: mmc@11230000 { + compatible = "mediatek,mt7986-mmc"; + reg = <0 0x11230000 0 0x1000>, + <0 0x11c20000 0 0x1000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_MSDC_CK>, + <&infracfg CLK_INFRA_MSDC_HCK_CK>, + <&infracfg CLK_INFRA_MSDC_66M_CK>, + <&infracfg CLK_INFRA_MSDC_133M_CK>; + clock-names = "source", "hclk", "axi_cg", "ahb_cg"; + assigned-clocks = <&topckgen CLK_TOP_EMMC_416M_SEL>, + <&topckgen CLK_TOP_EMMC_250M_SEL>; + assigned-clock-parents = <&apmixedsys CLK_APMIXED_MPLL>, + <&topckgen CLK_TOP_NET1PLL_D5_D2>; + status = "disabled"; + }; + + pcie: pcie@11280000 { + compatible = "mediatek,mt7986-pcie", + "mediatek,mt8192-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + reg = <0x00 0x11280000 0x00 0x4000>; + reg-names = "pcie-mac"; + interrupts = ; + bus-range = <0x00 0xff>; + ranges = <0x82000000 0x00 0x20000000 0x00 + 0x20000000 0x00 0x10000000>; + clocks = <&infracfg CLK_INFRA_PCIE_SEL>, + <&infracfg CLK_INFRA_IPCIE_CK>, + <&infracfg CLK_INFRA_IPCIE_PIPE_CK>, + <&infracfg CLK_INFRA_IPCIER_CK>, + <&infracfg CLK_INFRA_IPCIEB_CK>; + status = "disabled"; + + phys = <&pcie_port PHY_TYPE_PCIE>; + phy-names = "pcie-phy"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &pcie_intc 0>, + <0 0 0 2 &pcie_intc 1>, + <0 0 0 3 &pcie_intc 2>, + <0 0 0 4 &pcie_intc 3>; + pcie_intc: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + + pcie_phy: t-phy@11c00000 { + compatible = "mediatek,mt7986-tphy", + "mediatek,generic-tphy-v2"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + pcie_port: pcie-phy@11c00000 { + reg = <0 0x11c00000 0 0x20000>; + clocks = <&clk40m>; + clock-names = "ref"; + #phy-cells = <1>; + }; + }; + + usb_phy: t-phy@11e10000 { + compatible = "mediatek,mt7986-tphy", + "mediatek,generic-tphy-v2"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + u2port0: usb-phy@11e10000 { + reg = <0 0x11e10000 0 0x700>; + clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, + <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; + clock-names = "ref", "da_ref"; + #phy-cells = <1>; + }; + + u3port0: usb-phy@11e10700 { + reg = <0 0x11e10700 0 0x900>; + clocks = <&topckgen CLK_TOP_USB3_PHY_SEL>; + clock-names = "ref"; + #phy-cells = <1>; + }; + + u2port1: usb-phy@11e11000 { + reg = <0 0x11e11000 0 0x700>; + clocks = <&topckgen CLK_TOP_DA_U2_REFSEL>, + <&topckgen CLK_TOP_DA_U2_CK_1P_SEL>; + clock-names = "ref", "da_ref"; + #phy-cells = <1>; + }; + }; + + ethsys: syscon@15000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mediatek,mt7986-ethsys_ck", + "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + eth: ethernet@15100000 { + compatible = "mediatek,mt7986-eth"; + reg = <0 0x15100000 0 0x80000>; + interrupts = , + , + , + ; + clocks = <ðsys CLK_ETH_FE_EN>, + <ðsys CLK_ETH_GP2_EN>, + <ðsys CLK_ETH_GP1_EN>, + <ðsys CLK_ETH_WOCPU1_EN>, + <ðsys CLK_ETH_WOCPU0_EN>, + <&sgmiisys0 CLK_SGMII0_TX250M_EN>, + <&sgmiisys0 CLK_SGMII0_RX250M_EN>, + <&sgmiisys0 CLK_SGMII0_CDR_REF>, + <&sgmiisys0 CLK_SGMII0_CDR_FB>, + <&sgmiisys1 CLK_SGMII1_TX250M_EN>, + <&sgmiisys1 CLK_SGMII1_RX250M_EN>, + <&sgmiisys1 CLK_SGMII1_CDR_REF>, + <&sgmiisys1 CLK_SGMII1_CDR_FB>, + <&topckgen CLK_TOP_NETSYS_SEL>, + <&topckgen CLK_TOP_NETSYS_500M_SEL>; + clock-names = "fe", "gp2", "gp1", "wocpu1", "wocpu0", + "sgmii_tx250m", "sgmii_rx250m", + "sgmii_cdr_ref", "sgmii_cdr_fb", + "sgmii2_tx250m", "sgmii2_rx250m", + "sgmii2_cdr_ref", "sgmii2_cdr_fb", + "netsys0", "netsys1"; + assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, + <&topckgen CLK_TOP_SGM_325M_SEL>; + assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, + <&apmixedsys CLK_APMIXED_SGMPLL>; + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; + #reset-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + consys: consys@10000000 { + compatible = "mediatek,mt7986-consys"; + reg = <0 0x10000000 0 0x8600000>; + memory-region = <&wmcpu_emi>; + }; + + wmac: wmac@18000000 { + compatible = "mediatek,mt7986-wmac", "mediatek,wbsys"; + resets = <&watchdog MT7986_TOPRGU_CONSYS_RST>; + reset-names = "consys"; + reg = <0 0x18000000 0 0x1000000>, + <0 0x10003000 0 0x1000>, + <0 0x11d10000 0 0x1000>; + interrupts = , + , + , + ; + clocks = <&topckgen CLK_TOP_CONN_MCUSYS_SEL>, + <&topckgen CLK_TOP_AP2CNN_HOST_SEL>; + clock-names = "mcu", "ap2conn"; + memory-region = <&wmcpu_emi>; + status = "disabled"; + }; + }; + +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts new file mode 100644 index 0000000000..52b6c152fe --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7986b.dtsi" + +/ { + model = "MediaTek MT7986b RFB"; + compatible = "mediatek,mt7986b-rfb"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_5v: regulator-5v { + compatible = "regulator-fixed"; + regulator-name = "fixed-5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&ssusb { + vusb33-supply = <®_3p3v>; + vbus-supply = <®_5v>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; + +&wmac { + status = "okay"; + pinctrl-names = "default", "dbdc"; + pinctrl-0 = <&wf_2g_5g_pins>; + pinctrl-1 = <&wf_dbdc_pins>; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy5: phy@5 { + compatible = "ethernet-phy-id67c9.de0a"; + reg = <5>; + reset-gpios = <&pio 6 1>; + reset-deassert-us = <20000>; + phy-mode = "2500base-x"; + }; + + phy6: phy@6 { + compatible = "ethernet-phy-id67c9.de0a"; + reg = <6>; + phy-mode = "2500base-x"; + }; + + switch@0 { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan0"; + }; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&crypto { + status = "okay"; +}; + +&pio { + wf_2g_5g_pins: wf_2g_5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; + + wf_dbdc_pins: wf_dbdc-pins { + mux { + function = "wifi"; + groups = "wf_dbdc"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b.dtsi new file mode 100644 index 0000000000..23923b9f89 --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7986b.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam.Shih + */ + +#include "mt7986a.dtsi" + +&pio { + compatible = "mediatek,mt7986b-pinctrl"; + gpio-ranges = <&pio 0 0 41>, <&pio 66 66 35>; +}; diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-apmixed.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-apmixed.c new file mode 100644 index 0000000000..76c8ebdeae --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-apmixed.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-1.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih + * Author: Wenzhen Yu + */ + +#include +#include +#include +#include +#include +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" + +#include +#include + +#define MT7986_PLL_FMAX (2500UL * MHZ) +#define CON0_MT7986_RST_BAR BIT(27) + +#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + _div_table, _parent_name) \ + { \ + .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, .flags = _flags, \ + .rst_bar_mask = CON0_MT7986_RST_BAR, .fmax = MT7986_PLL_FMAX, \ + .pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, .div_table = _div_table, \ + .parent_name = _parent_name, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ + _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \ + PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \ + "clkxtal") + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, 0, 32, + 0x0200, 4, 0, 0x0204, 0), + PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32, + 0x0210, 4, 0, 0x0214, 0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32, + 0x0220, 4, 0, 0x0224, 0), + PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023c, 0x00000001, 0, 32, + 0x0230, 4, 0, 0x0234, 0), + PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024c, 0x00000001, 0, + 32, 0x0240, 4, 0, 0x0244, 0), + PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025c, 0x00000001, 0, 32, + 0x0250, 4, 0, 0x0254, 0), + PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, 0x0260, + 4, 0, 0x0264, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32, + 0x0278, 4, 0, 0x027c, 0), +}; + +static const struct of_device_id of_match_clk_mt7986_apmixed[] = { + { .compatible = "mediatek,mt7986-apmixedsys", }, + {} +}; + +static int clk_mt7986_apmixed_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_apmixed_data; + } + return r; + +free_apmixed_data: + mtk_free_clk_data(clk_data); + return r; +} + +static struct platform_driver clk_mt7986_apmixed_drv = { + .probe = clk_mt7986_apmixed_probe, + .driver = { + .name = "clk-mt7986-apmixed", + .of_match_table = of_match_clk_mt7986_apmixed, + }, +}; +builtin_platform_driver(clk_mt7986_apmixed_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-eth.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-eth.c new file mode 100644 index 0000000000..495d023cca --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-eth.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih + * Author: Wenzhen Yu + */ + +#include +#include +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs sgmii0_cg_regs = { + .set_ofs = 0xe4, + .clr_ofs = 0xe4, + .sta_ofs = 0xe4, +}; + +#define GATE_SGMII0(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &sgmii0_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate sgmii0_clks[] __initconst = { + GATE_SGMII0(CLK_SGMII0_TX250M_EN, "sgmii0_tx250m_en", "top_xtal", 2), + GATE_SGMII0(CLK_SGMII0_RX250M_EN, "sgmii0_rx250m_en", "top_xtal", 3), + GATE_SGMII0(CLK_SGMII0_CDR_REF, "sgmii0_cdr_ref", "top_xtal", 4), + GATE_SGMII0(CLK_SGMII0_CDR_FB, "sgmii0_cdr_fb", "top_xtal", 5), +}; + +static const struct mtk_gate_regs sgmii1_cg_regs = { + .set_ofs = 0xe4, + .clr_ofs = 0xe4, + .sta_ofs = 0xe4, +}; + +#define GATE_SGMII1(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &sgmii1_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate sgmii1_clks[] __initconst = { + GATE_SGMII1(CLK_SGMII1_TX250M_EN, "sgmii1_tx250m_en", "top_xtal", 2), + GATE_SGMII1(CLK_SGMII1_RX250M_EN, "sgmii1_rx250m_en", "top_xtal", 3), + GATE_SGMII1(CLK_SGMII1_CDR_REF, "sgmii1_cdr_ref", "top_xtal", 4), + GATE_SGMII1(CLK_SGMII1_CDR_FB, "sgmii1_cdr_fb", "top_xtal", 5), +}; + +static const struct mtk_gate_regs eth_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +#define GATE_ETH(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = ð_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate eth_clks[] __initconst = { + GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x_sel", 6), + GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m_sel", 7), + GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m_sel", 8), + GATE_ETH(CLK_ETH_WOCPU1_EN, "eth_wocpu1_en", "netsys_mcu_sel", 14), + GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_mcu_sel", 15), +}; + +static void __init mtk_sgmiisys_0_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); + + mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7986-sgmiisys_0", + mtk_sgmiisys_0_init); + +static void __init mtk_sgmiisys_1_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); + + mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7986-sgmiisys_1", + mtk_sgmiisys_1_init); + +static void __init mtk_ethsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks)); + + mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7986-ethsys_ck", mtk_ethsys_init); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-infracfg.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-infracfg.c new file mode 100644 index 0000000000..3be168c34f --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-infracfg.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-1.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih + * Author: Wenzhen Yu + */ + +#include +#include +#include +#include +#include +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" + +#include +#include + +static DEFINE_SPINLOCK(mt7986_clk_lock); + +static const struct mtk_fixed_factor infra_divs[] = { + FACTOR(CLK_INFRA_SYSAXI_D2, "infra_sysaxi_d2", "sysaxi_sel", 1, 2), +}; + +static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel", + "uart_sel" }; + +static const char *const infra_spi_parents[] __initconst = { "i2c_sel", + "spi_sel" }; + +static const char *const infra_pwm_bsel_parents[] __initconst = { + "top_rtc_32p7k", "csw_f26m_sel", "infra_sysaxi_d2", "pwm_sel" +}; + +static const char *const infra_pcie_parents[] __initconst = { + "top_rtc_32p7k", "csw_f26m_sel", "top_xtal", "pextp_tl_ck_sel" +}; + +static const struct mtk_mux infra_muxes[] = { + /* MODULE_CLK_SEL_0 */ + MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel", + infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel", + infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel", + infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel", + infra_spi_parents, 0x0018, 0x0010, 0x0014, 4, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel", + infra_spi_parents, 0x0018, 0x0010, 0x0014, 5, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel", + infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 9, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel", + infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 11, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel", + infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13, + 2, -1, -1, -1), + /* MODULE_CLK_SEL_1 */ + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel", + infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2, + -1, -1, -1), +}; + +static const struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +static const struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x50, + .clr_ofs = 0x54, + .sta_ofs = 0x58, +}; + +static const struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0x60, + .clr_ofs = 0x64, + .sta_ofs = 0x68, +}; + +#define GATE_INFRA0(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &infra0_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_INFRA1(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &infra1_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_INFRA2(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &infra2_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate infra_clks[] = { + /* INFRA0 */ + GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_sysaxi_d2", 0), + GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_sysaxi_d2", 1), + GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2), + GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3), + GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4), + GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi_sel", 6), + GATE_INFRA0(CLK_INFRA_EIP97_CK, "infra_eip97", "eip_b_sel", 7), + GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi_sel", 8), + GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9), + GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l_sel", 10), + GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys_sel", 11), + GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner_sel", 13), + GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel", + 14), + GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_sysaxi_d2", 15), + GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_sysaxi_d2", 16), + GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_sysaxi_d2", 24), + GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25), + GATE_INFRA0(CLK_INFRA_TRNG_CK, "infra_trng", "sysaxi_sel", 26), + /* INFRA1 */ + GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0), + GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_sel", 1), + GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2), + GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3), + GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4), + GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x_sel", 8), + GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_sel", 9), + GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_sysaxi_d2", + 10), + GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11), + GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12), + GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_sysaxi_d2", + 13), + GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_sysaxi_d2", + 14), + GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "top_rtc_32k", 15), + GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_416m_sel", 16), + GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_250m_sel", + 17), + GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi_sel", + 18), + GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "infra_sysaxi_d2", + 19), + GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "csw_f26m_sel", 20), + GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m_sel", 21), + GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x_sel", 23), + /* INFRA2 */ + GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi_sel", 0), + GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "infra_sysaxi_d2", + 1), + GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys_sel", 2), + GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_sel", 3), + GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl_ck_sel", 12), + GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "top_xtal", + 13), + GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m_sel", 14), + GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi_sel", 15), +}; + +static int clk_mt7986_infracfg_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + int nr = ARRAY_SIZE(infra_divs) + ARRAY_SIZE(infra_muxes) + + ARRAY_SIZE(infra_clks); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(nr); + + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); + mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, + &mt7986_clk_lock, clk_data); + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_infracfg_data; + } + return r; + +free_infracfg_data: + mtk_free_clk_data(clk_data); + return r; + +} + +static const struct of_device_id of_match_clk_mt7986_infracfg[] = { + { .compatible = "mediatek,mt7986-infracfg", }, + {} +}; + +static struct platform_driver clk_mt7986_infracfg_drv = { + .probe = clk_mt7986_infracfg_probe, + .driver = { + .name = "clk-mt7986-infracfg", + .of_match_table = of_match_clk_mt7986_infracfg, + }, +}; +builtin_platform_driver(clk_mt7986_infracfg_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-topckgen.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-topckgen.c new file mode 100644 index 0000000000..8550e2be77 --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7986-topckgen.c @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: GPL-1.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih + * Author: Wenzhen Yu + */ + +#include +#include +#include +#include +#include +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" + +#include +#include + +static DEFINE_SPINLOCK(mt7986_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000), + FIXED_CLK(CLK_TOP_JTAG, "top_jtag", "clkxtal", 50000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + /* XTAL */ + FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2), + FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250), + FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220), + /* MPLL */ + FACTOR(CLK_TOP_MPLL_D2, "top_mpll_d2", "mpll", 1, 2), + FACTOR(CLK_TOP_MPLL_D4, "top_mpll_d4", "mpll", 1, 4), + FACTOR(CLK_TOP_MPLL_D8, "top_mpll_d8", "mpll", 1, 8), + FACTOR(CLK_TOP_MPLL_D8_D2, "top_mpll_d8_d2", "mpll", 1, 16), + FACTOR(CLK_TOP_MPLL_D3_D2, "top_mpll_d3_d2", "mpll", 1, 6), + /* MMPLL */ + FACTOR(CLK_TOP_MMPLL_D2, "top_mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MMPLL_D4, "top_mmpll_d4", "mmpll", 1, 4), + FACTOR(CLK_TOP_MMPLL_D8, "top_mmpll_d8", "mmpll", 1, 8), + FACTOR(CLK_TOP_MMPLL_D8_D2, "top_mmpll_d8_d2", "mmpll", 1, 16), + FACTOR(CLK_TOP_MMPLL_D3_D8, "top_mmpll_d3_d8", "mmpll", 1, 24), + FACTOR(CLK_TOP_MMPLL_U2PHY, "top_mmpll_u2phy", "mmpll", 1, 30), + /* APLL2 */ + FACTOR(CLK_TOP_APLL2_D4, "top_apll2_d4", "apll2", 1, 4), + /* NET1PLL */ + FACTOR(CLK_TOP_NET1PLL_D4, "top_net1pll_d4", "net1pll", 1, 4), + FACTOR(CLK_TOP_NET1PLL_D5, "top_net1pll_d5", "net1pll", 1, 5), + FACTOR(CLK_TOP_NET1PLL_D5_D2, "top_net1pll_d5_d2", "net1pll", 1, 10), + FACTOR(CLK_TOP_NET1PLL_D5_D4, "top_net1pll_d5_d4", "net1pll", 1, 20), + FACTOR(CLK_TOP_NET1PLL_D8_D2, "top_net1pll_d8_d2", "net1pll", 1, 16), + FACTOR(CLK_TOP_NET1PLL_D8_D4, "top_net1pll_d8_d4", "net1pll", 1, 32), + /* NET2PLL */ + FACTOR(CLK_TOP_NET2PLL_D4, "top_net2pll_d4", "net2pll", 1, 4), + FACTOR(CLK_TOP_NET2PLL_D4_D2, "top_net2pll_d4_d2", "net2pll", 1, 8), + FACTOR(CLK_TOP_NET2PLL_D3_D2, "top_net2pll_d3_d2", "net2pll", 1, 2), + /* WEDMCUPLL */ + FACTOR(CLK_TOP_WEDMCUPLL_D5_D2, "top_wedmcupll_d5_d2", "wedmcupll", 1, + 10), +}; + +static const char *const nfi1x_parents[] __initconst = { "top_xtal", + "top_mmpll_d8", + "top_net1pll_d8_d2", + "top_net2pll_d3_d2", + "top_mpll_d4", + "top_mmpll_d8_d2", + "top_wedmcupll_d5_d2", + "top_mpll_d8" }; + +static const char *const spinfi_parents[] __initconst = { + "top_xtal_d2", "top_xtal", "top_net1pll_d5_d4", + "top_mpll_d4", "top_mmpll_d8_d2", "top_wedmcupll_d5_d2", + "top_mmpll_d3_d8", "top_mpll_d8" +}; + +static const char *const spi_parents[] __initconst = { + "top_xtal", "top_mpll_d2", "top_mmpll_d8", + "top_net1pll_d8_d2", "top_net2pll_d3_d2", "top_net1pll_d5_d4", + "top_mpll_d4", "top_wedmcupll_d5_d2" +}; + +static const char *const uart_parents[] __initconst = { "top_xtal", + "top_mpll_d8", + "top_mpll_d8_d2" }; + +static const char *const pwm_parents[] __initconst = { + "top_xtal", "top_net1pll_d8_d2", "top_net1pll_d5_d4", "top_mpll_d4" +}; + +static const char *const i2c_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d4", "top_mpll_d4", "top_net1pll_d8_d4" +}; + +static const char *const pextp_tl_ck_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d4", "top_net2pll_d4_d2", "top_rtc_32k" +}; + +static const char *const emmc_250m_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d2" +}; + +static const char *const emmc_416m_parents[] __initconst = { "top_xtal", + "mpll" }; + +static const char *const f_26m_adc_parents[] __initconst = { "top_xtal", + "top_mpll_d8_d2" }; + +static const char *const dramc_md32_parents[] __initconst = { "top_xtal", + "top_mpll_d2" }; + +static const char *const sysaxi_parents[] __initconst = { "top_xtal", + "top_net1pll_d8_d2", + "top_net2pll_d4" }; + +static const char *const sysapb_parents[] __initconst = { "top_xtal", + "top_mpll_d3_d2", + "top_net2pll_d4_d2" }; + +static const char *const arm_db_main_parents[] __initconst = { + "top_xtal", "top_net2pll_d3_d2" +}; + +static const char *const arm_db_jtsel_parents[] __initconst = { "top_jtag", + "top_xtal" }; + +static const char *const netsys_parents[] __initconst = { "top_xtal", + "top_mmpll_d4" }; + +static const char *const netsys_500m_parents[] __initconst = { + "top_xtal", "top_net1pll_d5" +}; + +static const char *const netsys_mcu_parents[] __initconst = { + "top_xtal", "wedmcupll", "top_mmpll_d2", "top_net1pll_d4", + "top_net1pll_d5" +}; + +static const char *const netsys_2x_parents[] __initconst = { + "top_xtal", "net2pll", "wedmcupll", "top_mmpll_d2" +}; + +static const char *const sgm_325m_parents[] __initconst = { "top_xtal", + "sgmpll" }; + +static const char *const sgm_reg_parents[] __initconst = { + "top_xtal", "top_net1pll_d8_d4" +}; + +static const char *const a1sys_parents[] __initconst = { "top_xtal", + "top_apll2_d4" }; + +static const char *const conn_mcusys_parents[] __initconst = { "top_xtal", + "top_mmpll_d2" }; + +static const char *const eip_b_parents[] __initconst = { "top_xtal", + "net2pll" }; + +static const char *const aud_l_parents[] __initconst = { "top_xtal", "apll2", + "top_mpll_d8_d2" }; + +static const char *const a_tuner_parents[] __initconst = { "top_xtal", + "top_apll2_d4", + "top_mpll_d8_d2" }; + +static const char *const u2u3_sys_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d4" +}; + +static const char *const da_u2_refsel_parents[] __initconst = { + "top_xtal", "top_mmpll_u2phy" +}; + +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, + 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, + 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000, + 0x004, 0x008, 16, 3, 23, 0x1C0, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, + 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010, + 0x014, 0x018, 0, 2, 7, 0x1C0, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010, + 0x014, 0x018, 8, 2, 15, 0x1C0, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010, + 0x014, 0x018, 16, 2, 23, 0x1C0, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", + pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, + 31, 0x1C0, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", + emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7, + 0x1C0, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel", + emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15, + 0x1C0, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", + f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, + 0x1C0, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, + 0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", + dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7, + 0x1C0, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, + 0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, + 0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", + arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, + 31, 0x1C0, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_JTSEL, "arm_db_jtsel", + arm_db_jtsel_parents, 0x040, 0x044, 0x048, 0, 1, 7, + 0x1C0, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, + 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", + netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, + 23, 0x1C0, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", + netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, + 0x1C0, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", + netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, + 0x1C0, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", + sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, + 0x1C0, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", + sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23, + 0x1C0, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, + 0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel", + conn_mcusys_parents, 0x060, 0x064, 0x068, 0, 1, 7, + 0x1C0, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents, + 0x060, 0x064, 0x068, 8, 1, 15, 0x1C0, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_PHY_SEL, "pcie_phy_sel", + f_26m_adc_parents, 0x060, 0x064, 0x068, 16, 1, 23, + 0x1C0, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel", + f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31, + 0x1C0, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel", + f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7, + 0x1C0, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, + 0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", + a_tuner_parents, 0x070, 0x074, 0x078, 16, 2, 23, + 0x1C0, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents, + 0x070, 0x074, 0x078, 24, 1, 31, 0x1C4, 0), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", + u2u3_sys_parents, 0x080, 0x084, 0x088, 0, 1, 7, + 0x1C4, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", + u2u3_sys_parents, 0x080, 0x084, 0x088, 8, 1, 15, + 0x1C4, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_REFSEL, "da_u2_refsel", + da_u2_refsel_parents, 0x080, 0x084, 0x088, 16, 1, + 23, 0x1C4, 3), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel", + da_u2_refsel_parents, 0x080, 0x084, 0x088, 24, 1, + 31, 0x1C4, 4), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", + sgm_reg_parents, 0x090, 0x094, 0x098, 0, 1, 7, + 0x1C4, 5), +}; + +static int clk_mt7986_topckgen_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) + + ARRAY_SIZE(top_muxes); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(nr); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, + &mt7986_clk_lock, clk_data); + + clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAXI_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAPB_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_MD32_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_F26M_SEL]); + clk_prepare_enable(clk_data->clks[CLK_TOP_SGM_REG_SEL]); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_topckgen_data; + } + return r; + +free_topckgen_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct of_device_id of_match_clk_mt7986_topckgen[] = { + { .compatible = "mediatek,mt7986-topckgen", }, + {} +}; + +static struct platform_driver clk_mt7986_topckgen_drv = { + .probe = clk_mt7986_topckgen_probe, + .driver = { + .name = "clk-mt7986-topckgen", + .of_match_table = of_match_clk_mt7986_topckgen, + }, +}; +builtin_platform_driver(clk_mt7986_topckgen_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7986.c new file mode 100644 index 0000000000..05a34e721e --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7986.c @@ -0,0 +1,933 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * The MT7986 driver based on Linux generic pinctrl binding. + * + * Copyright (C) 2021 MediaTek Inc. + * Author: Sam Shih + */ + +#include "pinctrl-moore.h" + +#define MT7986_PIN(_number, _name) MTK_PIN(_number, _name, 0, _number, DRV_GRP4) +#define MT7986_NOT_BALLOUT_PIN(_number) { .number = _number, .name = NULL } + +#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ + _x_bits) \ + PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ + _x_bits, 32, 0) + +/** + * enum - Locking variants of the iocfg bases + * + * MT7986 have multiple bases to program pin configuration listed as the below: + * iocfg_rt:0x11c30000, iocfg_rb:0x11c40000, iocfg_lt:0x11e20000, + * iocfg_lb:0x11e30000, iocfg_tr:0x11f00000, iocfg_tl:0x11f10000, + * _i_based could be used to indicate what base the pin should be mapped into. + * + * Each iocfg register base control different group of pads on the SoC + * + * + * chip carrier + * + * A B C D E F G H + * +------------------------+ + * 8 | o o o o o o o o | + * 7 | o o o o o o o o | + * 6 | o o o o o o o o | + * 5 | o o o o o o o o | + * 4 | o o o o o o o o | + * 3 | o o o o o o o o | + * 2 | o o o o o o o o | + * 1 | o o o o o o o o | + * +------------------------+ + * + * inside Chip carrier + * + * A B C D E F G H + * +------------------------+ + * 8 | | + * 7 | TL TR | + * 6 | +---------+ | + * 5 | LT | | RT | + * 4 | | | | + * 3 | LB | | RB | + * 2 | +---------+ | + * 1 | | + * +------------------------+ + * + */ + +enum { + GPIO_BASE, + IOCFG_RT_BASE, + IOCFG_RB_BASE, + IOCFG_LT_BASE, + IOCFG_LB_BASE, + IOCFG_TR_BASE, + IOCFG_TL_BASE, +}; + +static const char *const mt7986_pinctrl_register_base_names[] = { + "gpio", "iocfg_rt", "iocfg_rb", "iocfg_lt", "iocfg_lb", "iocfg_tr", + "iocfg_tl", +}; + +static const struct mtk_pin_field_calc mt7986_pin_mode_range[] = { + PIN_FIELD(0, 100, 0x300, 0x10, 0, 4), +}; + +static const struct mtk_pin_field_calc mt7986_pin_dir_range[] = { + PIN_FIELD(0, 100, 0x0, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_di_range[] = { + PIN_FIELD(0, 100, 0x200, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_do_range[] = { + PIN_FIELD(0, 100, 0x100, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_ies_range[] = { + PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x40, 0x10, 17, 1), + PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x20, 0x10, 10, 1), + PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x20, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x20, 0x10, 0, 1), + PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x40, 0x10, 8, 1), + PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x30, 0x10, 12, 1), + PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x30, 0x10, 18, 1), + PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x30, 0x10, 17, 1), + PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x30, 0x10, 15, 1), + PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x30, 0x10, 19, 1), + PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x30, 0x10, 23, 1), + PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x30, 0x10, 22, 1), + PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x30, 0x10, 21, 1), + PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x20, 0x10, 4, 1), + PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x20, 0x10, 8, 1), + PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x20, 0x10, 7, 1), + PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x20, 0x10, 5, 1), + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x20, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x40, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x40, 0x10, 12, 1), + PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x40, 0x10, 22, 1), + PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x40, 0x10, 20, 1), + PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x40, 0x10, 26, 1), + PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x40, 0x10, 24, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x30, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x30, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x30, 0x10, 0, 1), + PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x30, 0x10, 10, 1), + PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x40, 0x10, 15, 1), + PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x40, 0x10, 14, 1), + PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x40, 0x10, 13, 1), + PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x40, 0x10, 16, 1), + PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x20, 0x10, 2, 1), + PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x30, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x30, 0x10, 0, 1), + PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x30, 0x10, 16, 1), + PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x30, 0x10, 14, 1), + PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x30, 0x10, 4, 1), + PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x30, 0x10, 6, 1), + PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x30, 0x10, 2, 1), + PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x30, 0x10, 9, 1), + PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x30, 0x10, 5, 1), + PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x30, 0x10, 1, 1), + PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x30, 0x10, 0, 1), + PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x30, 0x10, 14, 1), + PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x30, 0x10, 12, 1), + PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x30, 0x10, 4, 1), + PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x30, 0x10, 2, 1), + PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x30, 0x10, 8, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_smt_range[] = { + PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0xf0, 0x10, 17, 1), + PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x90, 0x10, 10, 1), + PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x90, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0xf0, 0x10, 0, 1), + PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x90, 0x10, 0, 1), + PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0xf0, 0x10, 8, 1), + PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0xf0, 0x10, 2, 1), + PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0xc0, 0x10, 12, 1), + PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0xc0, 0x10, 18, 1), + PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0xc0, 0x10, 17, 1), + PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0xc0, 0x10, 15, 1), + PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0xc0, 0x10, 19, 1), + PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0xc0, 0x10, 23, 1), + PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0xc0, 0x10, 22, 1), + PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0xc0, 0x10, 21, 1), + PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x90, 0x10, 4, 1), + PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x90, 0x10, 8, 1), + PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x90, 0x10, 7, 1), + PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x90, 0x10, 5, 1), + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x90, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0xf0, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0xf0, 0x10, 12, 1), + PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0xf0, 0x10, 22, 1), + PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0xf0, 0x10, 20, 1), + PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0xf0, 0x10, 26, 1), + PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0xf0, 0x10, 24, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0xc0, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0xc0, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0xc0, 0x10, 0, 1), + PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0xc0, 0x10, 10, 1), + PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0xf0, 0x10, 15, 1), + PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0xf0, 0x10, 14, 1), + PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0xf0, 0x10, 13, 1), + PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0xf0, 0x10, 16, 1), + PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x90, 0x10, 2, 1), + PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x80, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x80, 0x10, 0, 1), + PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x80, 0x10, 16, 1), + PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x80, 0x10, 14, 1), + PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x80, 0x10, 4, 1), + PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x80, 0x10, 6, 1), + PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x80, 0x10, 2, 1), + PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x80, 0x10, 9, 1), + PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x80, 0x10, 5, 1), + PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x70, 0x10, 1, 1), + PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x70, 0x10, 14, 1), + PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x70, 0x10, 12, 1), + PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x70, 0x10, 4, 1), + PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x70, 0x10, 2, 1), + PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x70, 0x10, 8, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_pu_range[] = { + PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x50, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x50, 0x10, 16, 1), + PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x50, 0x10, 14, 1), + PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x50, 0x10, 4, 1), + PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x50, 0x10, 6, 1), + PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x50, 0x10, 9, 1), + PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x50, 0x10, 5, 1), + PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x50, 0x10, 1, 1), + PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x50, 0x10, 14, 1), + PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x50, 0x10, 12, 1), + PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x50, 0x10, 4, 1), + PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x50, 0x10, 8, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_pd_range[] = { + PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x40, 0x10, 1, 1), + PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x40, 0x10, 16, 1), + PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x40, 0x10, 14, 1), + PIN_FIELD_BASE(74, 74, IOCFG_TR_BASE, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(75, 77, IOCFG_TR_BASE, 0x40, 0x10, 6, 1), + PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(80, 84, IOCFG_TR_BASE, 0x40, 0x10, 9, 1), + PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x40, 0x10, 5, 1), + PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x40, 0x10, 1, 1), + PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x40, 0x10, 14, 1), + PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x40, 0x10, 12, 1), + PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(97, 100, IOCFG_TL_BASE, 0x40, 0x10, 8, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_drv_range[] = { + PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x10, 0x10, 21, 3), + PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x00, 0x10, 0, 1), + PIN_FIELD_BASE(5, 5, IOCFG_RB_BASE, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(6, 6, IOCFG_RB_BASE, 0x00, 0x10, 21, 3), + PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(11, 12, IOCFG_RB_BASE, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(13, 14, IOCFG_RB_BASE, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x10, 0x10, 6, 3), + PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x10, 0x10, 24, 3), + PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x10, 0x10, 21, 3), + PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x10, 0x10, 15, 3), + PIN_FIELD_BASE(28, 28, IOCFG_RT_BASE, 0x10, 0x10, 27, 3), + PIN_FIELD_BASE(29, 29, IOCFG_RT_BASE, 0x20, 0x10, 0, 3), + PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x20, 0x10, 9, 3), + PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x20, 0x10, 6, 3), + PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x20, 0x10, 3, 3), + PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x00, 0x10, 12, 3), + PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x00, 0x10, 21, 3), + PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x00, 0x10, 15, 3), + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x00, 0x10, 27, 3), + PIN_FIELD_BASE(39, 39, IOCFG_RB_BASE, 0x10, 0x10, 27, 3), + PIN_FIELD_BASE(40, 40, IOCFG_RB_BASE, 0x20, 0x10, 0, 3), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x10, 0x10, 6, 3), + PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x20, 0x10, 9, 3), + PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x20, 0x10, 3, 3), + PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x20, 0x10, 21, 3), + PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x20, 0x10, 15, 3), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x00, 0x10, 6, 3), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x10, 0x10, 15, 3), + PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x10, 0x10, 12, 3), + PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x10, 0x10, 9, 3), + PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x10, 0x10, 18, 3), + PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x00, 0x10, 2, 3), + PIN_FIELD_BASE(69, 69, IOCFG_TR_BASE, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(70, 70, IOCFG_TR_BASE, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(71, 71, IOCFG_TR_BASE, 0x10, 0x10, 18, 3), + PIN_FIELD_BASE(72, 73, IOCFG_TR_BASE, 0x10, 0x10, 12, 3), + PIN_FIELD_BASE(74, 77, IOCFG_TR_BASE, 0x00, 0x10, 15, 3), + PIN_FIELD_BASE(78, 79, IOCFG_TR_BASE, 0x00, 0x10, 6, 3), + PIN_FIELD_BASE(80, 80, IOCFG_TR_BASE, 0x00, 0x10, 27, 3), + PIN_FIELD_BASE(81, 84, IOCFG_TR_BASE, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(85, 85, IOCFG_TR_BASE, 0x00, 0x10, 12, 3), + PIN_FIELD_BASE(86, 86, IOCFG_TL_BASE, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(87, 87, IOCFG_TL_BASE, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(88, 88, IOCFG_TL_BASE, 0x10, 0x10, 12, 3), + PIN_FIELD_BASE(89, 90, IOCFG_TL_BASE, 0x10, 0x10, 6, 3), + PIN_FIELD_BASE(91, 94, IOCFG_TL_BASE, 0x00, 0x10, 12, 3), + PIN_FIELD_BASE(95, 96, IOCFG_TL_BASE, 0x00, 0x10, 6, 3), + PIN_FIELD_BASE(97, 98, IOCFG_TL_BASE, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(99, 100, IOCFG_TL_BASE, 0x10, 0x10, 2, 3), +}; + +static const struct mtk_pin_field_calc mt7986_pin_pupd_range[] = { + PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x60, 0x10, 17, 1), + PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x30, 0x10, 10, 1), + PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x30, 0x10, 0, 1), + PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x60, 0x10, 8, 1), + PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x60, 0x10, 2, 1), + PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x40, 0x10, 12, 1), + PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x40, 0x10, 18, 1), + PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x40, 0x10, 17, 1), + PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x40, 0x10, 15, 1), + PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x40, 0x10, 19, 1), + PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x40, 0x10, 23, 1), + PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x40, 0x10, 22, 1), + PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x40, 0x10, 21, 1), + PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x30, 0x10, 4, 1), + PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x30, 0x10, 8, 1), + PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x30, 0x10, 7, 1), + PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x30, 0x10, 5, 1), + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x30, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x60, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x60, 0x10, 12, 1), + PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x60, 0x10, 22, 1), + PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x60, 0x10, 20, 1), + PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x60, 0x10, 26, 1), + PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x60, 0x10, 24, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x40, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x40, 0x10, 10, 1), + PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x60, 0x10, 15, 1), + PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x60, 0x10, 14, 1), + PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x60, 0x10, 13, 1), + PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x60, 0x10, 16, 1), + PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x40, 0x10, 2, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_r0_range[] = { + PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x70, 0x10, 17, 1), + PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x40, 0x10, 10, 1), + PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x70, 0x10, 8, 1), + PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x70, 0x10, 2, 1), + PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x50, 0x10, 12, 1), + PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x50, 0x10, 18, 1), + PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x50, 0x10, 17, 1), + PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x50, 0x10, 15, 1), + PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x50, 0x10, 19, 1), + PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x50, 0x10, 23, 1), + PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x50, 0x10, 22, 1), + PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x50, 0x10, 21, 1), + PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x40, 0x10, 8, 1), + PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x40, 0x10, 7, 1), + PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x40, 0x10, 5, 1), + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x40, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x70, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x70, 0x10, 12, 1), + PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x70, 0x10, 22, 1), + PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x70, 0x10, 20, 1), + PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x70, 0x10, 26, 1), + PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x70, 0x10, 24, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x50, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x50, 0x10, 10, 1), + PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x70, 0x10, 15, 1), + PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x70, 0x10, 14, 1), + PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x70, 0x10, 13, 1), + PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x70, 0x10, 16, 1), + PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x50, 0x10, 2, 1), +}; + +static const struct mtk_pin_field_calc mt7986_pin_r1_range[] = { + PIN_FIELD_BASE(0, 0, IOCFG_RB_BASE, 0x80, 0x10, 17, 1), + PIN_FIELD_BASE(1, 2, IOCFG_LT_BASE, 0x50, 0x10, 10, 1), + PIN_FIELD_BASE(3, 4, IOCFG_LB_BASE, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, IOCFG_RB_BASE, 0x80, 0x10, 0, 1), + PIN_FIELD_BASE(7, 10, IOCFG_LT_BASE, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(11, 14, IOCFG_RB_BASE, 0x80, 0x10, 8, 1), + PIN_FIELD_BASE(15, 20, IOCFG_RB_BASE, 0x80, 0x10, 2, 1), + PIN_FIELD_BASE(21, 23, IOCFG_RT_BASE, 0x60, 0x10, 12, 1), + PIN_FIELD_BASE(24, 24, IOCFG_RT_BASE, 0x60, 0x10, 18, 1), + PIN_FIELD_BASE(25, 25, IOCFG_RT_BASE, 0x60, 0x10, 17, 1), + PIN_FIELD_BASE(26, 27, IOCFG_RT_BASE, 0x60, 0x10, 15, 1), + PIN_FIELD_BASE(28, 29, IOCFG_RT_BASE, 0x60, 0x10, 19, 1), + PIN_FIELD_BASE(30, 30, IOCFG_RT_BASE, 0x60, 0x10, 23, 1), + PIN_FIELD_BASE(31, 31, IOCFG_RT_BASE, 0x60, 0x10, 22, 1), + PIN_FIELD_BASE(32, 32, IOCFG_RT_BASE, 0x60, 0x10, 21, 1), + PIN_FIELD_BASE(33, 33, IOCFG_LT_BASE, 0x50, 0x10, 4, 1), + PIN_FIELD_BASE(34, 34, IOCFG_LT_BASE, 0x50, 0x10, 8, 1), + PIN_FIELD_BASE(35, 35, IOCFG_LT_BASE, 0x50, 0x10, 7, 1), + PIN_FIELD_BASE(36, 37, IOCFG_LT_BASE, 0x50, 0x10, 5, 1), + PIN_FIELD_BASE(38, 38, IOCFG_LT_BASE, 0x50, 0x10, 9, 1), + PIN_FIELD_BASE(39, 40, IOCFG_RB_BASE, 0x80, 0x10, 18, 1), + PIN_FIELD_BASE(41, 41, IOCFG_RB_BASE, 0x80, 0x10, 12, 1), + PIN_FIELD_BASE(42, 43, IOCFG_RB_BASE, 0x80, 0x10, 22, 1), + PIN_FIELD_BASE(44, 45, IOCFG_RB_BASE, 0x80, 0x10, 20, 1), + PIN_FIELD_BASE(46, 47, IOCFG_RB_BASE, 0x80, 0x10, 26, 1), + PIN_FIELD_BASE(48, 49, IOCFG_RB_BASE, 0x80, 0x10, 24, 1), + PIN_FIELD_BASE(50, 57, IOCFG_RT_BASE, 0x60, 0x10, 2, 1), + PIN_FIELD_BASE(58, 58, IOCFG_RT_BASE, 0x60, 0x10, 1, 1), + PIN_FIELD_BASE(59, 59, IOCFG_RT_BASE, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(60, 61, IOCFG_RT_BASE, 0x60, 0x10, 10, 1), + PIN_FIELD_BASE(62, 62, IOCFG_RB_BASE, 0x80, 0x10, 15, 1), + PIN_FIELD_BASE(63, 63, IOCFG_RB_BASE, 0x80, 0x10, 14, 1), + PIN_FIELD_BASE(64, 64, IOCFG_RB_BASE, 0x80, 0x10, 13, 1), + PIN_FIELD_BASE(65, 65, IOCFG_RB_BASE, 0x80, 0x10, 16, 1), + PIN_FIELD_BASE(66, 68, IOCFG_LB_BASE, 0x60, 0x10, 2, 1), +}; + +static const struct mtk_pin_reg_calc mt7986_reg_cals[] = { + [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7986_pin_mode_range), + [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7986_pin_dir_range), + [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7986_pin_di_range), + [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7986_pin_do_range), + [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7986_pin_smt_range), + [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7986_pin_ies_range), + [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7986_pin_drv_range), + [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7986_pin_pu_range), + [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7986_pin_pd_range), + [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7986_pin_pupd_range), + [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7986_pin_r0_range), + [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7986_pin_r1_range), +}; + +static const struct mtk_pin_desc mt7986a_pins[] = { + MT7986_PIN(0, "SYS_WATCHDOG"), + MT7986_PIN(1, "WF2G_LED"), + MT7986_PIN(2, "WF5G_LED"), + MT7986_PIN(3, "I2C_SCL"), + MT7986_PIN(4, "I2C_SDA"), + MT7986_PIN(5, "GPIO_0"), + MT7986_PIN(6, "GPIO_1"), + MT7986_PIN(7, "GPIO_2"), + MT7986_PIN(8, "GPIO_3"), + MT7986_PIN(9, "GPIO_4"), + MT7986_PIN(10, "GPIO_5"), + MT7986_PIN(11, "GPIO_6"), + MT7986_PIN(12, "GPIO_7"), + MT7986_PIN(13, "GPIO_8"), + MT7986_PIN(14, "GPIO_9"), + MT7986_PIN(15, "GPIO_10"), + MT7986_PIN(16, "GPIO_11"), + MT7986_PIN(17, "GPIO_12"), + MT7986_PIN(18, "GPIO_13"), + MT7986_PIN(19, "GPIO_14"), + MT7986_PIN(20, "GPIO_15"), + MT7986_PIN(21, "PWM0"), + MT7986_PIN(22, "PWM1"), + MT7986_PIN(23, "SPI0_CLK"), + MT7986_PIN(24, "SPI0_MOSI"), + MT7986_PIN(25, "SPI0_MISO"), + MT7986_PIN(26, "SPI0_CS"), + MT7986_PIN(27, "SPI0_HOLD"), + MT7986_PIN(28, "SPI0_WP"), + MT7986_PIN(29, "SPI1_CLK"), + MT7986_PIN(30, "SPI1_MOSI"), + MT7986_PIN(31, "SPI1_MISO"), + MT7986_PIN(32, "SPI1_CS"), + MT7986_PIN(33, "SPI2_CLK"), + MT7986_PIN(34, "SPI2_MOSI"), + MT7986_PIN(35, "SPI2_MISO"), + MT7986_PIN(36, "SPI2_CS"), + MT7986_PIN(37, "SPI2_HOLD"), + MT7986_PIN(38, "SPI2_WP"), + MT7986_PIN(39, "UART0_RXD"), + MT7986_PIN(40, "UART0_TXD"), + MT7986_PIN(41, "PCIE_PERESET_N"), + MT7986_PIN(42, "UART1_RXD"), + MT7986_PIN(43, "UART1_TXD"), + MT7986_PIN(44, "UART1_CTS"), + MT7986_PIN(45, "UART1_RTS"), + MT7986_PIN(46, "UART2_RXD"), + MT7986_PIN(47, "UART2_TXD"), + MT7986_PIN(48, "UART2_CTS"), + MT7986_PIN(49, "UART2_RTS"), + MT7986_PIN(50, "EMMC_DATA_0"), + MT7986_PIN(51, "EMMC_DATA_1"), + MT7986_PIN(52, "EMMC_DATA_2"), + MT7986_PIN(53, "EMMC_DATA_3"), + MT7986_PIN(54, "EMMC_DATA_4"), + MT7986_PIN(55, "EMMC_DATA_5"), + MT7986_PIN(56, "EMMC_DATA_6"), + MT7986_PIN(57, "EMMC_DATA_7"), + MT7986_PIN(58, "EMMC_CMD"), + MT7986_PIN(59, "EMMC_CK"), + MT7986_PIN(60, "EMMC_DSL"), + MT7986_PIN(61, "EMMC_RSTB"), + MT7986_PIN(62, "PCM_DTX"), + MT7986_PIN(63, "PCM_DRX"), + MT7986_PIN(64, "PCM_CLK"), + MT7986_PIN(65, "PCM_FS"), + MT7986_PIN(66, "MT7531_INT"), + MT7986_PIN(67, "SMI_MDC"), + MT7986_PIN(68, "SMI_MDIO"), + MT7986_PIN(69, "WF0_DIG_RESETB"), + MT7986_PIN(70, "WF0_CBA_RESETB"), + MT7986_PIN(71, "WF0_XO_REQ"), + MT7986_PIN(72, "WF0_TOP_CLK"), + MT7986_PIN(73, "WF0_TOP_DATA"), + MT7986_PIN(74, "WF0_HB1"), + MT7986_PIN(75, "WF0_HB2"), + MT7986_PIN(76, "WF0_HB3"), + MT7986_PIN(77, "WF0_HB4"), + MT7986_PIN(78, "WF0_HB0"), + MT7986_PIN(79, "WF0_HB0_B"), + MT7986_PIN(80, "WF0_HB5"), + MT7986_PIN(81, "WF0_HB6"), + MT7986_PIN(82, "WF0_HB7"), + MT7986_PIN(83, "WF0_HB8"), + MT7986_PIN(84, "WF0_HB9"), + MT7986_PIN(85, "WF0_HB10"), + MT7986_PIN(86, "WF1_DIG_RESETB"), + MT7986_PIN(87, "WF1_CBA_RESETB"), + MT7986_PIN(88, "WF1_XO_REQ"), + MT7986_PIN(89, "WF1_TOP_CLK"), + MT7986_PIN(90, "WF1_TOP_DATA"), + MT7986_PIN(91, "WF1_HB1"), + MT7986_PIN(92, "WF1_HB2"), + MT7986_PIN(93, "WF1_HB3"), + MT7986_PIN(94, "WF1_HB4"), + MT7986_PIN(95, "WF1_HB0"), + MT7986_PIN(96, "WF1_HB0_B"), + MT7986_PIN(97, "WF1_HB5"), + MT7986_PIN(98, "WF1_HB6"), + MT7986_PIN(99, "WF1_HB7"), + MT7986_PIN(100, "WF1_HB8"), +}; + +static const struct mtk_pin_desc mt7986b_pins[] = { + MT7986_PIN(0, "SYS_WATCHDOG"), + MT7986_PIN(1, "WF2G_LED"), + MT7986_PIN(2, "WF5G_LED"), + MT7986_PIN(3, "I2C_SCL"), + MT7986_PIN(4, "I2C_SDA"), + MT7986_PIN(5, "GPIO_0"), + MT7986_PIN(6, "GPIO_1"), + MT7986_PIN(7, "GPIO_2"), + MT7986_PIN(8, "GPIO_3"), + MT7986_PIN(9, "GPIO_4"), + MT7986_PIN(10, "GPIO_5"), + MT7986_PIN(11, "GPIO_6"), + MT7986_PIN(12, "GPIO_7"), + MT7986_PIN(13, "GPIO_8"), + MT7986_PIN(14, "GPIO_9"), + MT7986_PIN(15, "GPIO_10"), + MT7986_PIN(16, "GPIO_11"), + MT7986_PIN(17, "GPIO_12"), + MT7986_PIN(18, "GPIO_13"), + MT7986_PIN(19, "GPIO_14"), + MT7986_PIN(20, "GPIO_15"), + MT7986_PIN(21, "PWM0"), + MT7986_PIN(22, "PWM1"), + MT7986_PIN(23, "SPI0_CLK"), + MT7986_PIN(24, "SPI0_MOSI"), + MT7986_PIN(25, "SPI0_MISO"), + MT7986_PIN(26, "SPI0_CS"), + MT7986_PIN(27, "SPI0_HOLD"), + MT7986_PIN(28, "SPI0_WP"), + MT7986_PIN(29, "SPI1_CLK"), + MT7986_PIN(30, "SPI1_MOSI"), + MT7986_PIN(31, "SPI1_MISO"), + MT7986_PIN(32, "SPI1_CS"), + MT7986_PIN(33, "SPI2_CLK"), + MT7986_PIN(34, "SPI2_MOSI"), + MT7986_PIN(35, "SPI2_MISO"), + MT7986_PIN(36, "SPI2_CS"), + MT7986_PIN(37, "SPI2_HOLD"), + MT7986_PIN(38, "SPI2_WP"), + MT7986_PIN(39, "UART0_RXD"), + MT7986_PIN(40, "UART0_TXD"), + MT7986_NOT_BALLOUT_PIN(41), + MT7986_NOT_BALLOUT_PIN(42), + MT7986_NOT_BALLOUT_PIN(43), + MT7986_NOT_BALLOUT_PIN(44), + MT7986_NOT_BALLOUT_PIN(45), + MT7986_NOT_BALLOUT_PIN(46), + MT7986_NOT_BALLOUT_PIN(47), + MT7986_NOT_BALLOUT_PIN(48), + MT7986_NOT_BALLOUT_PIN(49), + MT7986_NOT_BALLOUT_PIN(50), + MT7986_NOT_BALLOUT_PIN(51), + MT7986_NOT_BALLOUT_PIN(52), + MT7986_NOT_BALLOUT_PIN(53), + MT7986_NOT_BALLOUT_PIN(54), + MT7986_NOT_BALLOUT_PIN(55), + MT7986_NOT_BALLOUT_PIN(56), + MT7986_NOT_BALLOUT_PIN(57), + MT7986_NOT_BALLOUT_PIN(58), + MT7986_NOT_BALLOUT_PIN(59), + MT7986_NOT_BALLOUT_PIN(60), + MT7986_NOT_BALLOUT_PIN(61), + MT7986_NOT_BALLOUT_PIN(62), + MT7986_NOT_BALLOUT_PIN(63), + MT7986_NOT_BALLOUT_PIN(64), + MT7986_NOT_BALLOUT_PIN(65), + MT7986_PIN(66, "MT7531_INT"), + MT7986_PIN(67, "SMI_MDC"), + MT7986_PIN(68, "SMI_MDIO"), + MT7986_PIN(69, "WF0_DIG_RESETB"), + MT7986_PIN(70, "WF0_CBA_RESETB"), + MT7986_PIN(71, "WF0_XO_REQ"), + MT7986_PIN(72, "WF0_TOP_CLK"), + MT7986_PIN(73, "WF0_TOP_DATA"), + MT7986_PIN(74, "WF0_HB1"), + MT7986_PIN(75, "WF0_HB2"), + MT7986_PIN(76, "WF0_HB3"), + MT7986_PIN(77, "WF0_HB4"), + MT7986_PIN(78, "WF0_HB0"), + MT7986_PIN(79, "WF0_HB0_B"), + MT7986_PIN(80, "WF0_HB5"), + MT7986_PIN(81, "WF0_HB6"), + MT7986_PIN(82, "WF0_HB7"), + MT7986_PIN(83, "WF0_HB8"), + MT7986_PIN(84, "WF0_HB9"), + MT7986_PIN(85, "WF0_HB10"), + MT7986_PIN(86, "WF1_DIG_RESETB"), + MT7986_PIN(87, "WF1_CBA_RESETB"), + MT7986_PIN(88, "WF1_XO_REQ"), + MT7986_PIN(89, "WF1_TOP_CLK"), + MT7986_PIN(90, "WF1_TOP_DATA"), + MT7986_PIN(91, "WF1_HB1"), + MT7986_PIN(92, "WF1_HB2"), + MT7986_PIN(93, "WF1_HB3"), + MT7986_PIN(94, "WF1_HB4"), + MT7986_PIN(95, "WF1_HB0"), + MT7986_PIN(96, "WF1_HB0_B"), + MT7986_PIN(97, "WF1_HB5"), + MT7986_PIN(98, "WF1_HB6"), + MT7986_PIN(99, "WF1_HB7"), + MT7986_PIN(100, "WF1_HB8"), +}; + +/* List all groups consisting of these pins dedicated to the enablement of + * certain hardware block and the corresponding mode for all of the pins. + * The hardware probably has multiple combinations of these pinouts. + */ + +static int mt7986_watchdog_pins[] = { 0, }; +static int mt7986_watchdog_funcs[] = { 1, }; + +static int mt7986_wifi_led_pins[] = { 1, 2, }; +static int mt7986_wifi_led_funcs[] = { 1, 1, }; + +static int mt7986_i2c_pins[] = { 3, 4, }; +static int mt7986_i2c_funcs[] = { 1, 1, }; + +static int mt7986_uart1_0_pins[] = { 7, 8, 9, 10, }; +static int mt7986_uart1_0_funcs[] = { 3, 3, 3, 3, }; + +static int mt7986_spi1_0_pins[] = { 11, 12, 13, 14, }; +static int mt7986_spi1_0_funcs[] = { 3, 3, 3, 3, }; + +static int mt7986_pwm1_1_pins[] = { 20, }; +static int mt7986_pwm1_1_funcs[] = { 2, }; + +static int mt7986_pwm0_pins[] = { 21, }; +static int mt7986_pwm0_funcs[] = { 1, }; + +static int mt7986_pwm1_0_pins[] = { 22, }; +static int mt7986_pwm1_0_funcs[] = { 1, }; + +static int mt7986_emmc_45_pins[] = { + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, }; +static int mt7986_emmc_45_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; + +static int mt7986_snfi_pins[] = { 23, 24, 25, 26, 27, 28, }; +static int mt7986_snfi_funcs[] = { 1, 1, 1, 1, 1, 1, }; + +static int mt7986_spi1_1_pins[] = { 23, 24, 25, 26, }; +static int mt7986_spi1_1_funcs[] = { 3, 3, 3, 3, }; + +static int mt7986_uart1_1_pins[] = { 23, 24, 25, 26, }; +static int mt7986_uart1_1_funcs[] = { 4, 4, 4, 4, }; + +static int mt7986_spi1_2_pins[] = { 29, 30, 31, 32, }; +static int mt7986_spi1_2_funcs[] = { 1, 1, 1, 1, }; + +static int mt7986_uart1_2_pins[] = { 29, 30, 31, 32, }; +static int mt7986_uart1_2_funcs[] = { 3, 3, 3, 3, }; + +static int mt7986_uart2_0_pins[] = { 29, 30, 31, 32, }; +static int mt7986_uart2_0_funcs[] = { 4, 4, 4, 4, }; + +static int mt7986_spi0_pins[] = { 33, 34, 35, 36, }; +static int mt7986_spi0_funcs[] = { 1, 1, 1, 1, }; + +static int mt7986_spi0_wp_hold_pins[] = { 37, 38, }; +static int mt7986_spi0_wp_hold_funcs[] = { 1, 1, }; + +static int mt7986_uart2_1_pins[] = { 33, 34, 35, 36, }; +static int mt7986_uart2_1_funcs[] = { 3, 3, 3, 3, }; + +static int mt7986_uart1_3_rx_tx_pins[] = { 35, 36, }; +static int mt7986_uart1_3_rx_tx_funcs[] = { 2, 2, }; + +static int mt7986_uart1_3_cts_rts_pins[] = { 37, 38, }; +static int mt7986_uart1_3_cts_rts_funcs[] = { 2, 2, }; + +static int mt7986_spi1_3_pins[] = { 33, 34, 35, 36, }; +static int mt7986_spi1_3_funcs[] = { 4, 4, 4, 4, }; + +static int mt7986_uart0_pins[] = { 39, 40, }; +static int mt7986_uart0_funcs[] = { 1, 1, }; + +static int mt7986_pcie_reset_pins[] = { 41, }; +static int mt7986_pcie_reset_funcs[] = { 1, }; + +static int mt7986_uart1_pins[] = { 42, 43, 44, 45, }; +static int mt7986_uart1_funcs[] = { 1, 1, 1, 1, }; + +static int mt7986_uart2_pins[] = { 46, 47, 48, 49, }; +static int mt7986_uart2_funcs[] = { 1, 1, 1, 1, }; + +static int mt7986_emmc_51_pins[] = { + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, }; +static int mt7986_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; + +static int mt7986_pcm_pins[] = { 62, 63, 64, 65, }; +static int mt7986_pcm_funcs[] = { 1, 1, 1, 1, }; + +static int mt7986_i2s_pins[] = { 62, 63, 64, 65, }; +static int mt7986_i2s_funcs[] = { 1, 1, 1, 1, }; + +static int mt7986_switch_int_pins[] = { 66, }; +static int mt7986_switch_int_funcs[] = { 1, }; + +static int mt7986_mdc_mdio_pins[] = { 67, 68, }; +static int mt7986_mdc_mdio_funcs[] = { 1, 1, }; + +static int mt7986_wf_2g_pins[] = {74, 75, 76, 77, 78, 79, 80, 81, 82, 83, }; +static int mt7986_wf_2g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; + +static int mt7986_wf_5g_pins[] = {91, 92, 93, 94, 95, 96, 97, 98, 99, 100, }; +static int mt7986_wf_5g_funcs[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; + +static int mt7986_wf_dbdc_pins[] = { + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, }; +static int mt7986_wf_dbdc_funcs[] = { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; + +static int mt7986_pcie_clk_pins[] = { 9, }; +static int mt7986_pcie_clk_funcs[] = { 1, }; + +static int mt7986_pcie_wake_pins[] = { 10, }; +static int mt7986_pcie_wake_funcs[] = { 1, }; + +static int mt7986_jtag_pins[] = { 11, 12, 13, 14, 15}; +static int mt7986_jtag_funcs[] = { 1, 1, 1, 1, 1}; + +static const struct group_desc mt7986_groups[] = { + PINCTRL_PIN_GROUP("watchdog", mt7986_watchdog), + PINCTRL_PIN_GROUP("wifi_led", mt7986_wifi_led), + PINCTRL_PIN_GROUP("i2c", mt7986_i2c), + PINCTRL_PIN_GROUP("uart1_0", mt7986_uart1_0), + PINCTRL_PIN_GROUP("pcie_clk", mt7986_pcie_clk), + PINCTRL_PIN_GROUP("pcie_wake", mt7986_pcie_wake), + PINCTRL_PIN_GROUP("spi1_0", mt7986_spi1_0), + PINCTRL_PIN_GROUP("pwm1_1", mt7986_pwm1_1), + PINCTRL_PIN_GROUP("pwm0", mt7986_pwm0), + PINCTRL_PIN_GROUP("pwm1_0", mt7986_pwm1_0), + PINCTRL_PIN_GROUP("emmc_45", mt7986_emmc_45), + PINCTRL_PIN_GROUP("snfi", mt7986_snfi), + PINCTRL_PIN_GROUP("spi1_1", mt7986_spi1_1), + PINCTRL_PIN_GROUP("uart1_1", mt7986_uart1_1), + PINCTRL_PIN_GROUP("spi1_2", mt7986_spi1_2), + PINCTRL_PIN_GROUP("uart1_2", mt7986_uart1_2), + PINCTRL_PIN_GROUP("uart2_0", mt7986_uart2_0), + PINCTRL_PIN_GROUP("spi0", mt7986_spi0), + PINCTRL_PIN_GROUP("spi0_wp_hold", mt7986_spi0_wp_hold), + PINCTRL_PIN_GROUP("uart2_1", mt7986_uart2_1), + PINCTRL_PIN_GROUP("uart1_3_rx_tx", mt7986_uart1_3_rx_tx), + PINCTRL_PIN_GROUP("uart1_3_cts_rts", mt7986_uart1_3_cts_rts), + PINCTRL_PIN_GROUP("spi1_3", mt7986_spi1_3), + PINCTRL_PIN_GROUP("uart0", mt7986_uart0), + PINCTRL_PIN_GROUP("switch_int", mt7986_switch_int), + PINCTRL_PIN_GROUP("mdc_mdio", mt7986_mdc_mdio), + PINCTRL_PIN_GROUP("pcie_pereset", mt7986_pcie_reset), + PINCTRL_PIN_GROUP("uart1", mt7986_uart1), + PINCTRL_PIN_GROUP("uart2", mt7986_uart2), + PINCTRL_PIN_GROUP("emmc_51", mt7986_emmc_51), + PINCTRL_PIN_GROUP("pcm", mt7986_pcm), + PINCTRL_PIN_GROUP("i2s", mt7986_i2s), + PINCTRL_PIN_GROUP("wf_2g", mt7986_wf_2g), + PINCTRL_PIN_GROUP("wf_5g", mt7986_wf_5g), + PINCTRL_PIN_GROUP("wf_dbdc", mt7986_wf_dbdc), + PINCTRL_PIN_GROUP("jtag", mt7986_jtag), +}; + +/* Joint those groups owning the same capability in user point of view which + * allows that people tend to use through the device tree. + */ + +static const char *mt7986_audio_groups[] = { "pcm", "i2s" }; +static const char *mt7986_emmc_groups[] = { + "emmc_45", "emmc_51", }; +static const char *mt7986_ethernet_groups[] = { + "switch_int", "mdc_mdio", }; +static const char *mt7986_i2c_groups[] = { "i2c", }; +static const char *mt7986_led_groups[] = { "wifi_led", }; +static const char *mt7986_flash_groups[] = { "snfi", }; +static const char *mt7986_pcie_groups[] = { + "pcie_clk", "pcie_wake", "pcie_pereset" }; +static const char *mt7986_pwm_groups[] = { "pwm0", "pwm1_0", "pwm1_1", }; +static const char *mt7986_spi_groups[] = { + "spi0", "spi0_wp_hold", "spi1_0", "spi1_1", "spi1_2", "spi1_3", }; +static const char *mt7986_uart_groups[] = { + "uart1_0", "uart1_1", "uart1_2", "uart1_3_rx_tx", "uart1_3_cts_rts", + "uart2_0", "uart2_1", "uart0", "uart1", "uart2", +}; +static const char *mt7986_wdt_groups[] = { "watchdog", }; +static const char *mt7986_wf_groups[] = { "wf_2g", "wf_5g", "wf_dbdc", }; +static const char *mt7986_jtag_groups[] = { "jtag", }; + +static const struct function_desc mt7986_functions[] = { + {"audio", mt7986_audio_groups, ARRAY_SIZE(mt7986_audio_groups)}, + {"emmc", mt7986_emmc_groups, ARRAY_SIZE(mt7986_emmc_groups)}, + {"eth", mt7986_ethernet_groups, ARRAY_SIZE(mt7986_ethernet_groups)}, + {"i2c", mt7986_i2c_groups, ARRAY_SIZE(mt7986_i2c_groups)}, + {"led", mt7986_led_groups, ARRAY_SIZE(mt7986_led_groups)}, + {"flash", mt7986_flash_groups, ARRAY_SIZE(mt7986_flash_groups)}, + {"pcie", mt7986_pcie_groups, ARRAY_SIZE(mt7986_pcie_groups)}, + {"pwm", mt7986_pwm_groups, ARRAY_SIZE(mt7986_pwm_groups)}, + {"spi", mt7986_spi_groups, ARRAY_SIZE(mt7986_spi_groups)}, + {"uart", mt7986_uart_groups, ARRAY_SIZE(mt7986_uart_groups)}, + {"watchdog", mt7986_wdt_groups, ARRAY_SIZE(mt7986_wdt_groups)}, + {"wifi", mt7986_wf_groups, ARRAY_SIZE(mt7986_wf_groups)}, + {"jtag", mt7986_jtag_groups, ARRAY_SIZE(mt7986_jtag_groups)}, +}; + +static const struct mtk_eint_hw mt7986a_eint_hw = { + .port_mask = 7, + .ports = 7, + .ap_num = ARRAY_SIZE(mt7986a_pins), + .db_cnt = 16, +}; + +static const struct mtk_eint_hw mt7986b_eint_hw = { + .port_mask = 7, + .ports = 7, + .ap_num = ARRAY_SIZE(mt7986b_pins), + .db_cnt = 16, +}; + +static struct mtk_pin_soc mt7986a_data = { + .reg_cal = mt7986_reg_cals, + .pins = mt7986a_pins, + .npins = ARRAY_SIZE(mt7986a_pins), + .grps = mt7986_groups, + .ngrps = ARRAY_SIZE(mt7986_groups), + .funcs = mt7986_functions, + .nfuncs = ARRAY_SIZE(mt7986_functions), + .eint_hw = &mt7986a_eint_hw, + .gpio_m = 0, + .ies_present = false, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .drive_set = mtk_pinconf_drive_set_rev1, + .drive_get = mtk_pinconf_drive_get_rev1, + .adv_pull_get = mtk_pinconf_adv_pull_get, + .adv_pull_set = mtk_pinconf_adv_pull_set, +}; + +static struct mtk_pin_soc mt7986b_data = { + .reg_cal = mt7986_reg_cals, + .pins = mt7986b_pins, + .npins = ARRAY_SIZE(mt7986b_pins), + .grps = mt7986_groups, + .ngrps = ARRAY_SIZE(mt7986_groups), + .funcs = mt7986_functions, + .nfuncs = ARRAY_SIZE(mt7986_functions), + .eint_hw = &mt7986b_eint_hw, + .gpio_m = 0, + .ies_present = false, + .base_names = mt7986_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .drive_set = mtk_pinconf_drive_set_rev1, + .drive_get = mtk_pinconf_drive_get_rev1, + .adv_pull_get = mtk_pinconf_adv_pull_get, + .adv_pull_set = mtk_pinconf_adv_pull_set, +}; + +static const struct of_device_id mt7986a_pinctrl_of_match[] = { + {.compatible = "mediatek,mt7986a-pinctrl",}, + {} +}; + +static const struct of_device_id mt7986b_pinctrl_of_match[] = { + {.compatible = "mediatek,mt7986b-pinctrl",}, + {} +}; + +static int mt7986a_pinctrl_probe(struct platform_device *pdev) +{ + return mtk_moore_pinctrl_probe(pdev, &mt7986a_data); +} + +static int mt7986b_pinctrl_probe(struct platform_device *pdev) +{ + return mtk_moore_pinctrl_probe(pdev, &mt7986b_data); +} + +static struct platform_driver mt7986a_pinctrl_driver = { + .driver = { + .name = "mt7986a-pinctrl", + .of_match_table = mt7986a_pinctrl_of_match, + }, + .probe = mt7986a_pinctrl_probe, +}; + +static struct platform_driver mt7986b_pinctrl_driver = { + .driver = { + .name = "mt7986b-pinctrl", + .of_match_table = mt7986b_pinctrl_of_match, + }, + .probe = mt7986b_pinctrl_probe, +}; + +static int __init mt7986a_pinctrl_init(void) +{ + return platform_driver_register(&mt7986a_pinctrl_driver); +} + +static int __init mt7986b_pinctrl_init(void) +{ + return platform_driver_register(&mt7986b_pinctrl_driver); +} + +arch_initcall(mt7986a_pinctrl_init); +arch_initcall(mt7986b_pinctrl_init); diff --git a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mt7986-clk.h b/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mt7986-clk.h new file mode 100644 index 0000000000..5a9b169324 --- /dev/null +++ b/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mt7986-clk.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih + */ + +#ifndef _DT_BINDINGS_CLK_MT7986_H +#define _DT_BINDINGS_CLK_MT7986_H + +/* APMIXEDSYS */ + +#define CLK_APMIXED_ARMPLL 0 +#define CLK_APMIXED_NET2PLL 1 +#define CLK_APMIXED_MMPLL 2 +#define CLK_APMIXED_SGMPLL 3 +#define CLK_APMIXED_WEDMCUPLL 4 +#define CLK_APMIXED_NET1PLL 5 +#define CLK_APMIXED_MPLL 6 +#define CLK_APMIXED_APLL2 7 + +/* TOPCKGEN */ + +#define CLK_TOP_XTAL 0 +#define CLK_TOP_XTAL_D2 1 +#define CLK_TOP_RTC_32K 2 +#define CLK_TOP_RTC_32P7K 3 +#define CLK_TOP_MPLL_D2 4 +#define CLK_TOP_MPLL_D4 5 +#define CLK_TOP_MPLL_D8 6 +#define CLK_TOP_MPLL_D8_D2 7 +#define CLK_TOP_MPLL_D3_D2 8 +#define CLK_TOP_MMPLL_D2 9 +#define CLK_TOP_MMPLL_D4 10 +#define CLK_TOP_MMPLL_D8 11 +#define CLK_TOP_MMPLL_D8_D2 12 +#define CLK_TOP_MMPLL_D3_D8 13 +#define CLK_TOP_MMPLL_U2PHY 14 +#define CLK_TOP_APLL2_D4 15 +#define CLK_TOP_NET1PLL_D4 16 +#define CLK_TOP_NET1PLL_D5 17 +#define CLK_TOP_NET1PLL_D5_D2 18 +#define CLK_TOP_NET1PLL_D5_D4 19 +#define CLK_TOP_NET1PLL_D8_D2 20 +#define CLK_TOP_NET1PLL_D8_D4 21 +#define CLK_TOP_NET2PLL_D4 22 +#define CLK_TOP_NET2PLL_D4_D2 23 +#define CLK_TOP_NET2PLL_D3_D2 24 +#define CLK_TOP_WEDMCUPLL_D5_D2 25 +#define CLK_TOP_NFI1X_SEL 26 +#define CLK_TOP_SPINFI_SEL 27 +#define CLK_TOP_SPI_SEL 28 +#define CLK_TOP_SPIM_MST_SEL 29 +#define CLK_TOP_UART_SEL 30 +#define CLK_TOP_PWM_SEL 31 +#define CLK_TOP_I2C_SEL 32 +#define CLK_TOP_PEXTP_TL_SEL 33 +#define CLK_TOP_EMMC_250M_SEL 34 +#define CLK_TOP_EMMC_416M_SEL 35 +#define CLK_TOP_F_26M_ADC_SEL 36 +#define CLK_TOP_DRAMC_SEL 37 +#define CLK_TOP_DRAMC_MD32_SEL 38 +#define CLK_TOP_SYSAXI_SEL 39 +#define CLK_TOP_SYSAPB_SEL 40 +#define CLK_TOP_ARM_DB_MAIN_SEL 41 +#define CLK_TOP_ARM_DB_JTSEL 42 +#define CLK_TOP_NETSYS_SEL 43 +#define CLK_TOP_NETSYS_500M_SEL 44 +#define CLK_TOP_NETSYS_MCU_SEL 45 +#define CLK_TOP_NETSYS_2X_SEL 46 +#define CLK_TOP_SGM_325M_SEL 47 +#define CLK_TOP_SGM_REG_SEL 48 +#define CLK_TOP_A1SYS_SEL 49 +#define CLK_TOP_CONN_MCUSYS_SEL 50 +#define CLK_TOP_EIP_B_SEL 51 +#define CLK_TOP_PCIE_PHY_SEL 52 +#define CLK_TOP_USB3_PHY_SEL 53 +#define CLK_TOP_F26M_SEL 54 +#define CLK_TOP_AUD_L_SEL 55 +#define CLK_TOP_A_TUNER_SEL 56 +#define CLK_TOP_U2U3_SEL 57 +#define CLK_TOP_U2U3_SYS_SEL 58 +#define CLK_TOP_U2U3_XHCI_SEL 59 +#define CLK_TOP_DA_U2_REFSEL 60 +#define CLK_TOP_DA_U2_CK_1P_SEL 61 +#define CLK_TOP_AP2CNN_HOST_SEL 62 +#define CLK_TOP_JTAG 63 + +/* INFRACFG */ + +#define CLK_INFRA_SYSAXI_D2 0 +#define CLK_INFRA_UART0_SEL 1 +#define CLK_INFRA_UART1_SEL 2 +#define CLK_INFRA_UART2_SEL 3 +#define CLK_INFRA_SPI0_SEL 4 +#define CLK_INFRA_SPI1_SEL 5 +#define CLK_INFRA_PWM1_SEL 6 +#define CLK_INFRA_PWM2_SEL 7 +#define CLK_INFRA_PWM_BSEL 8 +#define CLK_INFRA_PCIE_SEL 9 +#define CLK_INFRA_GPT_STA 10 +#define CLK_INFRA_PWM_HCK 11 +#define CLK_INFRA_PWM_STA 12 +#define CLK_INFRA_PWM1_CK 13 +#define CLK_INFRA_PWM2_CK 14 +#define CLK_INFRA_CQ_DMA_CK 15 +#define CLK_INFRA_EIP97_CK 16 +#define CLK_INFRA_AUD_BUS_CK 17 +#define CLK_INFRA_AUD_26M_CK 18 +#define CLK_INFRA_AUD_L_CK 19 +#define CLK_INFRA_AUD_AUD_CK 20 +#define CLK_INFRA_AUD_EG2_CK 21 +#define CLK_INFRA_DRAMC_26M_CK 22 +#define CLK_INFRA_DBG_CK 23 +#define CLK_INFRA_AP_DMA_CK 24 +#define CLK_INFRA_SEJ_CK 25 +#define CLK_INFRA_SEJ_13M_CK 26 +#define CLK_INFRA_THERM_CK 27 +#define CLK_INFRA_I2C0_CK 28 +#define CLK_INFRA_UART0_CK 29 +#define CLK_INFRA_UART1_CK 30 +#define CLK_INFRA_UART2_CK 31 +#define CLK_INFRA_NFI1_CK 32 +#define CLK_INFRA_SPINFI1_CK 33 +#define CLK_INFRA_NFI_HCK_CK 34 +#define CLK_INFRA_SPI0_CK 35 +#define CLK_INFRA_SPI1_CK 36 +#define CLK_INFRA_SPI0_HCK_CK 37 +#define CLK_INFRA_SPI1_HCK_CK 38 +#define CLK_INFRA_FRTC_CK 39 +#define CLK_INFRA_MSDC_CK 40 +#define CLK_INFRA_MSDC_HCK_CK 41 +#define CLK_INFRA_MSDC_133M_CK 42 +#define CLK_INFRA_MSDC_66M_CK 43 +#define CLK_INFRA_ADC_26M_CK 44 +#define CLK_INFRA_ADC_FRC_CK 45 +#define CLK_INFRA_FBIST2FPC_CK 46 +#define CLK_INFRA_IUSB_133_CK 47 +#define CLK_INFRA_IUSB_66M_CK 48 +#define CLK_INFRA_IUSB_SYS_CK 49 +#define CLK_INFRA_IUSB_CK 50 +#define CLK_INFRA_IPCIE_CK 51 +#define CLK_INFRA_IPCIE_PIPE_CK 52 +#define CLK_INFRA_IPCIER_CK 53 +#define CLK_INFRA_IPCIEB_CK 54 +#define CLK_INFRA_TRNG_CK 55 + +/* SGMIISYS_0 */ + +#define CLK_SGMII0_TX250M_EN 0 +#define CLK_SGMII0_RX250M_EN 1 +#define CLK_SGMII0_CDR_REF 2 +#define CLK_SGMII0_CDR_FB 3 + +/* SGMIISYS_1 */ + +#define CLK_SGMII1_TX250M_EN 0 +#define CLK_SGMII1_RX250M_EN 1 +#define CLK_SGMII1_CDR_REF 2 +#define CLK_SGMII1_CDR_FB 3 + +/* ETHSYS */ + +#define CLK_ETH_FE_EN 0 +#define CLK_ETH_GP2_EN 1 +#define CLK_ETH_GP1_EN 2 +#define CLK_ETH_WOCPU1_EN 3 +#define CLK_ETH_WOCPU0_EN 4 + +#endif /* _DT_BINDINGS_CLK_MT7986_H */ diff --git a/target/linux/mediatek/files-5.15/include/dt-bindings/reset/mt7986-resets.h b/target/linux/mediatek/files-5.15/include/dt-bindings/reset/mt7986-resets.h new file mode 100644 index 0000000000..1bdfe34a7a --- /dev/null +++ b/target/linux/mediatek/files-5.15/include/dt-bindings/reset/mt7986-resets.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021 MediaTek Inc. */ + +#ifndef _DT_BINDINGS_RESET_MT7986 +#define _DT_BINDINGS_RESET_MT7986 + +#define MT7986_TOPRGU_CONSYS_RST 23 +#define MT7986_TOPRGU_SW_RST_NUM 32 + +#endif /* _DT_BINDINGS_RESET_MT7986 */ diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network new file mode 100644 index 0000000000..13afc2a3dc --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -0,0 +1,30 @@ + +. /lib/functions.sh +. /lib/functions/uci-defaults.sh +. /lib/functions/system.sh + +mediatek_setup_interfaces() +{ + local board="$1" + + case $board in + mediatek,mt7986a-rfb|\ + mediatek,mt7986b-rfb) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" wan + ;; + bananapi,bpi-r3) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 sfp2" "eth1 wan" + ucidef_set_interface_macaddr "wan" "$(macaddr_add $(cat /sys/class/net/eth0/address) 1)" + ;; + *) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" wan + ;; + esac +} + +board_config_update +board=$(board_name) +mediatek_setup_interfaces $board +board_config_flush + +exit 0 diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh new file mode 100755 index 0000000000..13b5b64fb6 --- /dev/null +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -0,0 +1,69 @@ +REQUIRE_IMAGE_METADATA=1 + +platform_do_upgrade() { + local board=$(board_name) + local file_type=$(identify $1) + + case "$board" in + bananapi,bpi-r3) + export_bootdevice + export_partdevice rootdev 0 + case "$rootdev" in + mmc*) + CI_ROOTDEV="$rootdev" + CI_KERNPART="production" + emmc_do_upgrade "$1" + ;; + mtdblock*) + PART_NAME="fit" + default_do_upgrade "$1" + ;; + ubiblock*) + CI_KERNPART="fit" + nand_do_upgrade "$1" + ;; + esac + ;; + *) + ;; + esac +} + +PART_NAME=firmware + +platform_check_image() { + local board=$(board_name) + local magic="$(get_magic_long "$1")" + + [ "$#" -gt 1 ] && return 1 + + case "$board" in + bananapi,bpi-r3) + [ "$magic" != "d00dfeed" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; + *) + nand_do_platform_check "$board" "$1" + return 0 + ;; + esac + + return 0 +} + +platform_copy_config() { + case "$(board_name)" in + bananapi,bpi-r3) + export_bootdevice + export_partdevice rootdev 0 + case "$rootdev" in + mmc*) + emmc_copy_config + ;; + esac + ;; + esac +} diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 new file mode 100644 index 0000000000..3c73e003c9 --- /dev/null +++ b/target/linux/mediatek/filogic/config-5.15 @@ -0,0 +1,434 @@ +CONFIG_64BIT=y +# CONFIG_AHCI_MTK is not set +CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MEDIATEK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_CNP is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_MODULE_PLTS=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +CONFIG_ARM_MEDIATEK_CPUFREQ=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ATA=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_MEDIATEK=y +# CONFIG_COMMON_CLK_MT2712 is not set +# CONFIG_COMMON_CLK_MT6779 is not set +# CONFIG_COMMON_CLK_MT6797 is not set +# CONFIG_COMMON_CLK_MT7622 is not set +CONFIG_COMMON_CLK_MT7986=y +CONFIG_COMMON_CLK_MT7986_ETHSYS=y +# CONFIG_COMMON_CLK_MT8173 is not set +# CONFIG_COMMON_CLK_MT8183 is not set +# CONFIG_COMMON_CLK_MT8516 is not set +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +# CONFIG_CPUFREQ_DT is not set +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CRC16=y +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_BLAKE2S=y +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ECC=y +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_MISC=y +CONFIG_DIMLIB=y +CONFIG_DMADEVICES=y +CONFIG_DMATEST=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ENGINE_RAID=y +CONFIG_DMA_OF=y +CONFIG_DMA_REMAP=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EINT_MTK=y +CONFIG_EXT4_FS=y +CONFIG_F2FS_FS=y +CONFIG_FIT_PARTITION=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_CDEV=y +CONFIG_GRO_CELLS=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MTK=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MT65XX=y +CONFIG_ICPLUS_PHY=y +CONFIG_IIO=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IO_URING=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_JUMP_LABEL=y +# CONFIG_LEDS_UBNT_LEDBAR is not set +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEDIATEK_GE_PHY=y +CONFIG_MEDIATEK_MT6577_AUXADC=y +CONFIG_MEDIATEK_WATCHDOG=y +CONFIG_MEMFD_CREATE=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_MEDIATEK=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MTK=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_PARSER_TRX=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_MTK_CMDQ is not set +# CONFIG_MTK_CQDMA is not set +CONFIG_MTK_EFUSE=y +CONFIG_MTK_HSDMA=y +CONFIG_MTK_INFRACFG=y +CONFIG_MTK_PMIC_WRAP=y +CONFIG_MTK_SCPSYS=y +CONFIG_MTK_SCPSYS_PM_DOMAINS=y +CONFIG_MTK_THERMAL=y +CONFIG_MTK_TIMER=y +# CONFIG_MTK_UART_APDMA is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_TAG_MTK=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_MEDIATEK_SOC_WED=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_VENDOR_MEDIATEK=y +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_PADATA=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +# CONFIG_PCIE_MEDIATEK is not set +CONFIG_PCIE_MEDIATEK_GEN3=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DEBUG=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PERF_EVENTS=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_MTK_TPHY=y +# CONFIG_PHY_MTK_UFS is not set +# CONFIG_PHY_MTK_XSPHY is not set +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6797 is not set +# CONFIG_PINCTRL_MT7622 is not set +CONFIG_PINCTRL_MT7986=y +# CONFIG_PINCTRL_MT8173 is not set +# CONFIG_PINCTRL_MT8183 is not set +CONFIG_PINCTRL_MT8516=y +CONFIG_PINCTRL_MTK=y +CONFIG_PINCTRL_MTK_MOORE=y +CONFIG_PINCTRL_MTK_V2=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PRINTK_TIME=y +CONFIG_PSTORE=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_DEFLATE_COMPRESS=y +CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_MEDIATEK=y +# CONFIG_PWM_MTK_DISP is not set +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REALTEK_PHY=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_MT6380=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_MT7622=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTL8367S_GSW=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCHED_MC=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_MT6577=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_MT65XX=y +CONFIG_SPI_MTK_NOR=y +CONFIG_SPI_MTK_SNFI=y +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UCLAMP_TASK is not set +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MTK=y +# CONFIG_USB_XHCI_PLATFORM is not set +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +CONFIG_WATCHDOG_SYSFS=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/mediatek/filogic/target.mk b/target/linux/mediatek/filogic/target.mk new file mode 100644 index 0000000000..0c5bf4844e --- /dev/null +++ b/target/linux/mediatek/filogic/target.mk @@ -0,0 +1,10 @@ +ARCH:=aarch64 +SUBTARGET:=filogic +BOARDNAME:=Filogic 830 (MT7986) +CPU_TYPE:=cortex-a53 +DEFAULT_PACKAGES += kmod-crypto-hw-safexcel kmod-mt7915e kmod-mt7986-firmware wpad-basic-wolfssl uboot-envtools +KERNELNAME:=Image dtbs + +define Target/Description + Build firmware images for MediaTek Filogic ARM based boards. +endef diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk new file mode 100644 index 0000000000..dfc71bbb14 --- /dev/null +++ b/target/linux/mediatek/image/filogic.mk @@ -0,0 +1,122 @@ +DTS_DIR := $(DTS_DIR)/mediatek + +KERNEL_LOADADDR := 0x44000000 + +define Image/Prepare + # For UBI we want only one extra block + rm -f $(KDIR)/ubi_mark + echo -ne '\xde\xad\xc0\xde' > $(KDIR)/ubi_mark +endef + +define Build/bl2 + cat $(STAGING_DIR_IMAGE)/mt7986-$1-bl2.img >> $@ +endef + +define Build/bl31-uboot + cat $(STAGING_DIR_IMAGE)/mt7986_$1-u-boot.fip >> $@ +endef + +define Build/mt7986-gpt + cp $@ $@.tmp 2>/dev/null || true + ptgen -g -o $@.tmp -a 1 -l 1024 \ + $(if $(findstring sdmmc,$1), \ + -H \ + -t 0x83 -N bl2 -r -p 4079k@17k \ + ) \ + -t 0x83 -N ubootenv -r -p 512k@4M \ + -t 0x83 -N factory -r -p 2M@4608k \ + -t 0xef -N fip -r -p 4M@6656k \ + -N recovery -r -p 32M@12M \ + $(if $(findstring sdmmc,$1), \ + -N install -r -p 20M@44M \ + -t 0x2e -N production -p $(CONFIG_TARGET_ROOTFS_PARTSIZE)M@64M \ + ) \ + $(if $(findstring emmc,$1), \ + -t 0x2e -N production -p $(CONFIG_TARGET_ROOTFS_PARTSIZE)M@64M \ + ) + cat $@.tmp >> $@ + rm $@.tmp +endef + +define Device/bananapi_bpi-r3 + DEVICE_VENDOR := Bananapi + DEVICE_MODEL := BPi-R3 + DEVICE_DTS := mt7986a-bananapi-bpi-r3 + DEVICE_DTS_CONFIG := config-mt7986a-bananapi-bpi-r3 + DEVICE_DTS_OVERLAY:= mt7986a-bananapi-bpi-r3-nor mt7986a-bananapi-bpi-r3-emmc-nor mt7986a-bananapi-bpi-r3-emmc-snand mt7986a-bananapi-bpi-r3-snand + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-btmtkuart kmod-usb3 kmod-i2c-gpio kmod-sfp e2fsprogs f2fsck mkf2fs + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + ARTIFACTS := \ + emmc-preloader.bin emmc-bl31-uboot.fip \ + nor-preloader.bin nor-bl31-uboot.fip \ + sdcard.img.gz \ + snand-preloader.bin snand-bl31-uboot.fip + ARTIFACT/emmc-preloader.bin := bl2 emmc-ddr4 + ARTIFACT/emmc-bl31-uboot.fip := bl31-uboot bananapi_bpi-r3-emmc + ARTIFACT/nor-preloader.bin := bl2 nor-ddr4 + ARTIFACT/nor-bl31-uboot.fip := bl31-uboot bananapi_bpi-r3-nor + ARTIFACT/snand-preloader.bin := bl2 spim-nand-ddr4 + ARTIFACT/snand-bl31-uboot.fip := bl31-uboot bananapi_bpi-r3-snand + ARTIFACT/sdcard.img.gz := mt7986-gpt sdmmc |\ + pad-to 17k | bl2 sdmmc-ddr4 |\ + pad-to 6656k | bl31-uboot bananapi_bpi-r3-sdmmc |\ + pad-to 12M | append-image-stage initramfs-recovery.itb |\ + pad-to 44M | bl2 spim-nand-ddr4 |\ + pad-to 45M | bl31-uboot bananapi_bpi-r3-snand |\ + pad-to 49M | bl2 nor-ddr4 |\ + pad-to 50M | bl31-uboot bananapi_bpi-r3-nor |\ + pad-to 51M | bl2 emmc-ddr4 |\ + pad-to 52M | bl31-uboot bananapi_bpi-r3-emmc |\ + pad-to 56M | mt7986-gpt emmc |\ + pad-to 64M | append-image squashfs-sysupgrade.itb | gzip + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | pad-rootfs | append-metadata + DTC_FLAGS += -@ --space 32768 +endef +TARGET_DEVICES += bananapi_bpi-r3 + +define Device/mediatek_mt7986a-rfb + DEVICE_VENDOR := MediaTek + DEVICE_MODEL := MTK7986 rfba AP + DEVICE_DTS := mt7986a-rfb + DEVICE_DTS_DIR := $(DTS_DIR)/ + KERNEL_LOADADDR := 0x48000000 + DEVICE_DTS_OVERLAY := mt7986a-rfb-spim-nand mt7986a-rfb-spim-nor + SUPPORTED_DEVICES := mediatek,mt7986a-rfb + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + KERNEL_IN_UBI := 1 + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + KERNEL = kernel-bin | lzma | \ + fit lzma $$(KDIR)/$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS = kernel-bin | lzma | \ + fit lzma $$(KDIR)/$$(firstword $$(DEVICE_DTS)).dtb with-initrd + DTC_FLAGS += -@ --space 32768 +endef +TARGET_DEVICES += mediatek_mt7986a-rfb + +define Device/mediatek_mt7986b-rfb + DEVICE_VENDOR := MediaTek + DEVICE_MODEL := MTK7986 rfbb AP + DEVICE_DTS := mt7986b-rfb + DEVICE_DTS_DIR := $(DTS_DIR)/ + KERNEL_LOADADDR := 0x48000000 + SUPPORTED_DEVICES := mediatek,mt7986b-rfb + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + KERNEL_IN_UBI := 1 + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += mediatek_mt7986b-rfb diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 55c0aa704c..25c55ff45f 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -70,6 +70,7 @@ CONFIG_COMMON_CLK_MT7622=y CONFIG_COMMON_CLK_MT7622_AUDSYS=y CONFIG_COMMON_CLK_MT7622_ETHSYS=y CONFIG_COMMON_CLK_MT7622_HIFSYS=y +# CONFIG_COMMON_CLK_MT7986 is not set # CONFIG_COMMON_CLK_MT8173 is not set CONFIG_COMMON_CLK_MT8183=y # CONFIG_COMMON_CLK_MT8183_AUDIOSYS is not set @@ -256,6 +257,7 @@ CONFIG_MTD_PARSER_TRX=y CONFIG_MTD_RAW_NAND=y CONFIG_MTD_SPI_NAND=y CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_SPLIT_FIT_FW=y CONFIG_MTD_UBI=y @@ -334,6 +336,7 @@ CONFIG_PINCTRL=y # CONFIG_PINCTRL_MT6765 is not set # CONFIG_PINCTRL_MT6797 is not set CONFIG_PINCTRL_MT7622=y +# CONFIG_PINCTRL_MT7986 is not set # CONFIG_PINCTRL_MT8173 is not set # CONFIG_PINCTRL_MT8183 is not set CONFIG_PINCTRL_MT8516=y diff --git a/target/linux/mediatek/mt7623/config-5.15 b/target/linux/mediatek/mt7623/config-5.15 index 8d18bb6f3f..7e87d27ca5 100644 --- a/target/linux/mediatek/mt7623/config-5.15 +++ b/target/linux/mediatek/mt7623/config-5.15 @@ -67,6 +67,7 @@ CONFIG_COMMON_CLK_MT2701_MMSYS=y CONFIG_COMMON_CLK_MT2701_VDECSYS=y # CONFIG_COMMON_CLK_MT7622 is not set # CONFIG_COMMON_CLK_MT7629 is not set +# CONFIG_COMMON_CLK_MT7986 is not set # CONFIG_COMMON_CLK_MT8135 is not set # CONFIG_COMMON_CLK_MT8173 is not set CONFIG_COMMON_CLK_MT8516=y @@ -429,6 +430,7 @@ CONFIG_PINCTRL=y CONFIG_PINCTRL_MT2701=y CONFIG_PINCTRL_MT6397=y CONFIG_PINCTRL_MT7623=y +# CONFIG_PINCTRL_MT7986 is not set CONFIG_PINCTRL_MTK=y CONFIG_PINCTRL_MTK_MOORE=y CONFIG_PINCTRL_MTK_V2=y diff --git a/target/linux/mediatek/mt7623/target.mk b/target/linux/mediatek/mt7623/target.mk index cc5ff3f27d..1338b091e3 100644 --- a/target/linux/mediatek/mt7623/target.mk +++ b/target/linux/mediatek/mt7623/target.mk @@ -9,7 +9,7 @@ CPU_TYPE:=cortex-a7 CPU_SUBTYPE:=neon-vfpv4 KERNELNAME:=Image dtbs zImage FEATURES+=display usbgadget -DEFAULT_PACKAGES+=uboot-envtools +DEFAULT_PACKAGES+=kmod-crypto-hw-safexcel uboot-envtools define Target/Description Build firmware images for MediaTek mt7623 ARM based boards. diff --git a/target/linux/mediatek/mt7629/config-5.15 b/target/linux/mediatek/mt7629/config-5.15 index d5164bf443..3f781e5544 100644 --- a/target/linux/mediatek/mt7629/config-5.15 +++ b/target/linux/mediatek/mt7629/config-5.15 @@ -51,6 +51,7 @@ CONFIG_COMMON_CLK_MEDIATEK=y CONFIG_COMMON_CLK_MT7629=y CONFIG_COMMON_CLK_MT7629_ETHSYS=y CONFIG_COMMON_CLK_MT7629_HIFSYS=y +# CONFIG_COMMON_CLK_MT7986 is not set # CONFIG_COMMON_CLK_MT8135 is not set # CONFIG_COMMON_CLK_MT8173 is not set CONFIG_COMMON_CLK_MT8516=y @@ -239,6 +240,7 @@ CONFIG_PHY_MTK_TPHY=y # CONFIG_PHY_MTK_XSPHY is not set CONFIG_PINCTRL=y CONFIG_PINCTRL_MT7629=y +# CONFIG_PINCTRL_MT7986 is not set CONFIG_PINCTRL_MTK_MOORE=y CONFIG_PINCTRL_MTK_V2=y CONFIG_PM=y diff --git a/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch index a443404fff..5b63bf4226 100644 --- a/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch +++ b/target/linux/mediatek/patches-5.15/150-dts-mt7623-eip97-inside-secure-support.patch @@ -1,6 +1,6 @@ --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi -@@ -951,17 +951,14 @@ +@@ -951,17 +951,15 @@ }; crypto: crypto@1b240000 { @@ -18,6 +18,7 @@ - clock-names = "cryp"; - power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; - status = "disabled"; ++ status = "okay"; }; bdpsys: syscon@1c000000 { diff --git a/target/linux/mediatek/patches-5.15/210-pinctrl-mediatek-add-support-for-MT7986-SoC.patch b/target/linux/mediatek/patches-5.15/210-pinctrl-mediatek-add-support-for-MT7986-SoC.patch new file mode 100644 index 0000000000..0761e1da18 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/210-pinctrl-mediatek-add-support-for-MT7986-SoC.patch @@ -0,0 +1,26 @@ +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -120,6 +120,13 @@ config PINCTRL_MT7622 + default ARM64 && ARCH_MEDIATEK + select PINCTRL_MTK_MOORE + ++config PINCTRL_MT7986 ++ bool "Mediatek MT7986 pin control" ++ depends on OF ++ depends on ARM64 || COMPILE_TEST ++ default ARM64 && ARCH_MEDIATEK ++ select PINCTRL_MTK_MOORE ++ + config PINCTRL_MT8167 + bool "Mediatek MT8167 pin control" + depends on OF +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_MT6797) += pinctrl- + obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o + obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o + obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o ++obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o + obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o + obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o + obj-$(CONFIG_PINCTRL_MT8183) += pinctrl-mt8183.o diff --git a/target/linux/mediatek/patches-5.15/211-clk-mediatek-Add-API-for-clock-resource-recycle.patch b/target/linux/mediatek/patches-5.15/211-clk-mediatek-Add-API-for-clock-resource-recycle.patch new file mode 100644 index 0000000000..15de8aa3d4 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/211-clk-mediatek-Add-API-for-clock-resource-recycle.patch @@ -0,0 +1,28 @@ +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -43,6 +43,15 @@ err_out: + return NULL; + } + ++void mtk_free_clk_data(struct clk_onecell_data *clk_data) ++{ ++ if (!clk_data) ++ return; ++ ++ kfree(clk_data->clks); ++ kfree(clk_data); ++} ++ + void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, + int num, struct clk_onecell_data *clk_data) + { +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -202,6 +202,7 @@ void mtk_clk_register_dividers(const str + struct clk_onecell_data *clk_data); + + struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); ++void mtk_free_clk_data(struct clk_onecell_data *clk_data); + + #define HAVE_RST_BAR BIT(0) + #define PLL_AO BIT(1) diff --git a/target/linux/mediatek/patches-5.15/212-clk-mediatek-add-mt7986-clock-support.patch b/target/linux/mediatek/patches-5.15/212-clk-mediatek-add-mt7986-clock-support.patch new file mode 100644 index 0000000000..8e2365a498 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/212-clk-mediatek-add-mt7986-clock-support.patch @@ -0,0 +1,39 @@ +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -344,6 +344,23 @@ config COMMON_CLK_MT7629_HIFSYS + This driver supports MediaTek MT7629 HIFSYS clocks providing + to PCI-E and USB. + ++config COMMON_CLK_MT7986 ++ bool "Clock driver for MediaTek MT7986" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ select COMMON_CLK_MEDIATEK ++ default ARCH_MEDIATEK ++ help ++ This driver supports MediaTek MT7986 basic clocks and clocks ++ required for various periperals found on MediaTek. ++ ++config COMMON_CLK_MT7986_ETHSYS ++ bool "Clock driver for MediaTek MT7986 ETHSYS" ++ depends on COMMON_CLK_MT7986 ++ default COMMON_CLK_MT7986 ++ help ++ This driver add support for clocks for Ethernet and SGMII ++ required on MediaTek MT7986 SoC. ++ + config COMMON_CLK_MT8135 + bool "Clock driver for MediaTek MT8135" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST +--- a/drivers/clk/mediatek/Makefile ++++ b/drivers/clk/mediatek/Makefile +@@ -46,6 +46,10 @@ obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) + + obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o + obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o + obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o ++obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o ++obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o ++obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o ++obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o + obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o + obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o + obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o diff --git a/target/linux/mediatek/patches-5.15/213-spi-mediatek-add-mt7986-spi-support b/target/linux/mediatek/patches-5.15/213-spi-mediatek-add-mt7986-spi-support new file mode 100644 index 0000000000..f10d57a785 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/213-spi-mediatek-add-mt7986-spi-support @@ -0,0 +1,917 @@ +From 7d99750f96fc6904d54affebdc8c9b0bfae1e9e8 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sun, 17 Apr 2022 11:40:22 +0800 +Subject: [PATCH] spi: mediatek: backport document and driver to support mt7986 + spi design + +this patch add the support of ipm design and upgrade devicetree binding + +The patch is comming from following threads +- https://lore.kernel.org/all/20220315032411.2826-1-leilk.liu@mediatek.com/ +- https://lore.kernel.org/all/20220401071616.8874-1-leilk.liu@mediatek.com/ + +Signed-off-by: Sam Shih +--- + .../bindings/spi/mediatek,spi-mt65xx.yaml | 111 ++++ + drivers/spi/spi-mt65xx.c | 509 ++++++++++++++++-- + 2 files changed, 572 insertions(+), 48 deletions(-) + create mode 100644 Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/mediatek,spi-mt65xx.yaml +@@ -0,0 +1,111 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/spi/mediatek,spi-mt65xx.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: SPI Bus controller for MediaTek ARM SoCs ++ ++maintainers: ++ - Leilk Liu ++ ++allOf: ++ - $ref: "/schemas/spi/spi-controller.yaml#" ++ ++properties: ++ compatible: ++ oneOf: ++ - items: ++ - enum: ++ - mediatek,mt7629-spi ++ - const: mediatek,mt7622-spi ++ - items: ++ - enum: ++ - mediatek,mt8516-spi ++ - const: mediatek,mt2712-spi ++ - items: ++ - enum: ++ - mediatek,mt6779-spi ++ - mediatek,mt8186-spi ++ - mediatek,mt8192-spi ++ - mediatek,mt8195-spi ++ - const: mediatek,mt6765-spi ++ - items: ++ - enum: ++ - mediatek,mt7986-spi-ipm ++ - const: mediatek,spi-ipm ++ - items: ++ - enum: ++ - mediatek,mt2701-spi ++ - mediatek,mt2712-spi ++ - mediatek,mt6589-spi ++ - mediatek,mt6765-spi ++ - mediatek,mt6893-spi ++ - mediatek,mt7622-spi ++ - mediatek,mt8135-spi ++ - mediatek,mt8173-spi ++ - mediatek,mt8183-spi ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 3 ++ items: ++ - description: clock used for the parent clock ++ - description: clock used for the muxes clock ++ - description: clock used for the clock gate ++ - description: clock used for the AHB bus, this clock is optional ++ ++ clock-names: ++ minItems: 3 ++ items: ++ - const: parent-clk ++ - const: sel-clk ++ - const: spi-clk ++ - const: hclk ++ ++ mediatek,pad-select: ++ $ref: /schemas/types.yaml#/definitions/uint32-array ++ minItems: 1 ++ maxItems: 4 ++ items: ++ enum: [0, 1, 2, 3] ++ description: ++ specify which pins group(ck/mi/mo/cs) spi controller used. ++ This is an array. ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ - '#address-cells' ++ - '#size-cells' ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ #include ++ ++ spi@1100a000 { ++ compatible = "mediatek,mt8173-spi"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x1100a000 0x1000>; ++ interrupts = ; ++ clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, ++ <&topckgen CLK_TOP_SPI_SEL>, ++ <&pericfg CLK_PERI_SPI0>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk"; ++ cs-gpios = <&pio 105 GPIO_ACTIVE_LOW>, <&pio 72 GPIO_ACTIVE_LOW>; ++ mediatek,pad-select = <1>, <0>; ++ }; +--- a/drivers/spi/spi-mt65xx.c ++++ b/drivers/spi/spi-mt65xx.c +@@ -12,11 +12,12 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include + #include ++#include + #include + + #define SPI_CFG0_REG 0x0000 +@@ -31,6 +32,7 @@ + #define SPI_CFG2_REG 0x0028 + #define SPI_TX_SRC_REG_64 0x002c + #define SPI_RX_DST_REG_64 0x0030 ++#define SPI_CFG3_IPM_REG 0x0040 + + #define SPI_CFG0_SCK_HIGH_OFFSET 0 + #define SPI_CFG0_SCK_LOW_OFFSET 8 +@@ -51,6 +53,7 @@ + #define SPI_CFG1_CS_IDLE_MASK 0xff + #define SPI_CFG1_PACKET_LOOP_MASK 0xff00 + #define SPI_CFG1_PACKET_LENGTH_MASK 0x3ff0000 ++#define SPI_CFG1_IPM_PACKET_LENGTH_MASK GENMASK(31, 16) + #define SPI_CFG2_SCK_HIGH_OFFSET 0 + #define SPI_CFG2_SCK_LOW_OFFSET 16 + +@@ -71,6 +74,24 @@ + #define SPI_CMD_TX_ENDIAN BIT(15) + #define SPI_CMD_FINISH_IE BIT(16) + #define SPI_CMD_PAUSE_IE BIT(17) ++#define SPI_CMD_IPM_NONIDLE_MODE BIT(19) ++#define SPI_CMD_IPM_SPIM_LOOP BIT(21) ++#define SPI_CMD_IPM_GET_TICKDLY_OFFSET 22 ++ ++#define SPI_CMD_IPM_GET_TICKDLY_MASK GENMASK(24, 22) ++ ++#define PIN_MODE_CFG(x) ((x) / 2) ++ ++#define SPI_CFG3_IPM_HALF_DUPLEX_DIR BIT(2) ++#define SPI_CFG3_IPM_HALF_DUPLEX_EN BIT(3) ++#define SPI_CFG3_IPM_XMODE_EN BIT(4) ++#define SPI_CFG3_IPM_NODATA_FLAG BIT(5) ++#define SPI_CFG3_IPM_CMD_BYTELEN_OFFSET 8 ++#define SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET 12 ++ ++#define SPI_CFG3_IPM_CMD_PIN_MODE_MASK GENMASK(1, 0) ++#define SPI_CFG3_IPM_CMD_BYTELEN_MASK GENMASK(11, 8) ++#define SPI_CFG3_IPM_ADDR_BYTELEN_MASK GENMASK(15, 12) + + #define MT8173_SPI_MAX_PAD_SEL 3 + +@@ -81,6 +102,9 @@ + + #define MTK_SPI_MAX_FIFO_SIZE 32U + #define MTK_SPI_PACKET_SIZE 1024 ++#define MTK_SPI_IPM_PACKET_SIZE SZ_64K ++#define MTK_SPI_IPM_PACKET_LOOP SZ_256 ++ + #define MTK_SPI_32BITS_MASK (0xffffffff) + + #define DMA_ADDR_EXT_BITS (36) +@@ -96,6 +120,8 @@ struct mtk_spi_compatible { + bool dma_ext; + /* some IC no need unprepare SPI clk */ + bool no_need_unprepare; ++ /* IPM design adjust and extend register to support more features */ ++ bool ipm_design; + }; + + struct mtk_spi { +@@ -103,7 +129,7 @@ struct mtk_spi { + u32 state; + int pad_num; + u32 *pad_sel; +- struct clk *parent_clk, *sel_clk, *spi_clk; ++ struct clk *parent_clk, *sel_clk, *spi_clk, *spi_hclk; + struct spi_transfer *cur_transfer; + u32 xfer_len; + u32 num_xfered; +@@ -111,6 +137,11 @@ struct mtk_spi { + u32 tx_sgl_len, rx_sgl_len; + const struct mtk_spi_compatible *dev_comp; + u32 spi_clk_hz; ++ struct completion spimem_done; ++ bool use_spimem; ++ struct device *dev; ++ dma_addr_t tx_dma; ++ dma_addr_t rx_dma; + }; + + static const struct mtk_spi_compatible mtk_common_compat; +@@ -119,6 +150,12 @@ static const struct mtk_spi_compatible m + .must_tx = true, + }; + ++static const struct mtk_spi_compatible mtk_ipm_compat = { ++ .enhance_timing = true, ++ .dma_ext = true, ++ .ipm_design = true, ++}; ++ + static const struct mtk_spi_compatible mt6765_compat = { + .need_pad_sel = true, + .must_tx = true, +@@ -160,6 +197,9 @@ static const struct mtk_chip_config mtk_ + }; + + static const struct of_device_id mtk_spi_of_match[] = { ++ { .compatible = "mediatek,spi-ipm", ++ .data = (void *)&mtk_ipm_compat, ++ }, + { .compatible = "mediatek,mt2701-spi", + .data = (void *)&mtk_common_compat, + }, +@@ -278,12 +318,11 @@ static int mtk_spi_set_hw_cs_timing(stru + return 0; + } + +-static int mtk_spi_prepare_message(struct spi_master *master, +- struct spi_message *msg) ++static int mtk_spi_hw_init(struct spi_master *master, ++ struct spi_device *spi) + { + u16 cpha, cpol; + u32 reg_val; +- struct spi_device *spi = msg->spi; + struct mtk_chip_config *chip_config = spi->controller_data; + struct mtk_spi *mdata = spi_master_get_devdata(master); + +@@ -291,6 +330,15 @@ static int mtk_spi_prepare_message(struc + cpol = spi->mode & SPI_CPOL ? 1 : 0; + + reg_val = readl(mdata->base + SPI_CMD_REG); ++ if (mdata->dev_comp->ipm_design) { ++ /* SPI transfer without idle time until packet length done */ ++ reg_val |= SPI_CMD_IPM_NONIDLE_MODE; ++ if (spi->mode & SPI_LOOP) ++ reg_val |= SPI_CMD_IPM_SPIM_LOOP; ++ else ++ reg_val &= ~SPI_CMD_IPM_SPIM_LOOP; ++ } ++ + if (cpha) + reg_val |= SPI_CMD_CPHA; + else +@@ -348,23 +396,39 @@ static int mtk_spi_prepare_message(struc + mdata->base + SPI_PAD_SEL_REG); + + /* tick delay */ +- reg_val = readl(mdata->base + SPI_CFG1_REG); + if (mdata->dev_comp->enhance_timing) { +- reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; +- reg_val |= ((chip_config->tick_delay & 0x7) +- << SPI_CFG1_GET_TICK_DLY_OFFSET); ++ if (mdata->dev_comp->ipm_design) { ++ reg_val = readl(mdata->base + SPI_CMD_REG); ++ reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK; ++ reg_val |= ((chip_config->tick_delay & 0x7) ++ << SPI_CMD_IPM_GET_TICKDLY_OFFSET); ++ writel(reg_val, mdata->base + SPI_CMD_REG); ++ } else { ++ reg_val = readl(mdata->base + SPI_CFG1_REG); ++ reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; ++ reg_val |= ((chip_config->tick_delay & 0x7) ++ << SPI_CFG1_GET_TICK_DLY_OFFSET); ++ writel(reg_val, mdata->base + SPI_CFG1_REG); ++ } + } else { ++ reg_val = readl(mdata->base + SPI_CFG1_REG); + reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1; + reg_val |= ((chip_config->tick_delay & 0x3) + << SPI_CFG1_GET_TICK_DLY_OFFSET_V1); ++ writel(reg_val, mdata->base + SPI_CFG1_REG); + } +- writel(reg_val, mdata->base + SPI_CFG1_REG); + + /* set hw cs timing */ + mtk_spi_set_hw_cs_timing(spi); + return 0; + } + ++static int mtk_spi_prepare_message(struct spi_master *master, ++ struct spi_message *msg) ++{ ++ return mtk_spi_hw_init(master, msg->spi); ++} ++ + static void mtk_spi_set_cs(struct spi_device *spi, bool enable) + { + u32 reg_val; +@@ -386,13 +450,13 @@ static void mtk_spi_set_cs(struct spi_de + } + + static void mtk_spi_prepare_transfer(struct spi_master *master, +- struct spi_transfer *xfer) ++ u32 speed_hz) + { + u32 div, sck_time, reg_val; + struct mtk_spi *mdata = spi_master_get_devdata(master); + +- if (xfer->speed_hz < mdata->spi_clk_hz / 2) +- div = DIV_ROUND_UP(mdata->spi_clk_hz, xfer->speed_hz); ++ if (speed_hz < mdata->spi_clk_hz / 2) ++ div = DIV_ROUND_UP(mdata->spi_clk_hz, speed_hz); + else + div = 1; + +@@ -423,12 +487,24 @@ static void mtk_spi_setup_packet(struct + u32 packet_size, packet_loop, reg_val; + struct mtk_spi *mdata = spi_master_get_devdata(master); + +- packet_size = min_t(u32, mdata->xfer_len, MTK_SPI_PACKET_SIZE); ++ if (mdata->dev_comp->ipm_design) ++ packet_size = min_t(u32, ++ mdata->xfer_len, ++ MTK_SPI_IPM_PACKET_SIZE); ++ else ++ packet_size = min_t(u32, ++ mdata->xfer_len, ++ MTK_SPI_PACKET_SIZE); ++ + packet_loop = mdata->xfer_len / packet_size; + + reg_val = readl(mdata->base + SPI_CFG1_REG); +- reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK | SPI_CFG1_PACKET_LOOP_MASK); ++ if (mdata->dev_comp->ipm_design) ++ reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK; ++ else ++ reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK; + reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; ++ reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK; + reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET; + writel(reg_val, mdata->base + SPI_CFG1_REG); + } +@@ -523,7 +599,7 @@ static int mtk_spi_fifo_transfer(struct + mdata->cur_transfer = xfer; + mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len); + mdata->num_xfered = 0; +- mtk_spi_prepare_transfer(master, xfer); ++ mtk_spi_prepare_transfer(master, xfer->speed_hz); + mtk_spi_setup_packet(master); + + if (xfer->tx_buf) { +@@ -556,7 +632,7 @@ static int mtk_spi_dma_transfer(struct s + mdata->cur_transfer = xfer; + mdata->num_xfered = 0; + +- mtk_spi_prepare_transfer(master, xfer); ++ mtk_spi_prepare_transfer(master, xfer->speed_hz); + + cmd = readl(mdata->base + SPI_CMD_REG); + if (xfer->tx_buf) +@@ -591,6 +667,19 @@ static int mtk_spi_transfer_one(struct s + struct spi_device *spi, + struct spi_transfer *xfer) + { ++ struct mtk_spi *mdata = spi_master_get_devdata(spi->master); ++ u32 reg_val = 0; ++ ++ /* prepare xfer direction and duplex mode */ ++ if (mdata->dev_comp->ipm_design) { ++ if (!xfer->tx_buf || !xfer->rx_buf) { ++ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN; ++ if (xfer->rx_buf) ++ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR; ++ } ++ writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); ++ } ++ + if (master->can_dma(master, spi, xfer)) + return mtk_spi_dma_transfer(master, spi, xfer); + else +@@ -614,8 +703,9 @@ static int mtk_spi_setup(struct spi_devi + if (!spi->controller_data) + spi->controller_data = (void *)&mtk_default_chip_info; + +- if (mdata->dev_comp->need_pad_sel && gpio_is_valid(spi->cs_gpio)) +- gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); ++ if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) ++ /* CS de-asserted, gpiolib will handle inversion */ ++ gpiod_direction_output(spi->cs_gpiod, 0); + + return 0; + } +@@ -633,6 +723,12 @@ static irqreturn_t mtk_spi_interrupt(int + else + mdata->state = MTK_SPI_IDLE; + ++ /* SPI-MEM ops */ ++ if (mdata->use_spimem) { ++ complete(&mdata->spimem_done); ++ return IRQ_HANDLED; ++ } ++ + if (!master->can_dma(master, NULL, trans)) { + if (trans->rx_buf) { + cnt = mdata->xfer_len / 4; +@@ -716,6 +812,274 @@ static irqreturn_t mtk_spi_interrupt(int + return IRQ_HANDLED; + } + ++static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, ++ struct spi_mem_op *op) ++{ ++ int opcode_len; ++ ++ if (op->data.dir != SPI_MEM_NO_DATA) { ++ opcode_len = 1 + op->addr.nbytes + op->dummy.nbytes; ++ if (opcode_len + op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { ++ op->data.nbytes = MTK_SPI_IPM_PACKET_SIZE - opcode_len; ++ /* force data buffer dma-aligned. */ ++ op->data.nbytes -= op->data.nbytes % 4; ++ } ++ } ++ ++ return 0; ++} ++ ++static bool mtk_spi_mem_supports_op(struct spi_mem *mem, ++ const struct spi_mem_op *op) ++{ ++ if (!spi_mem_default_supports_op(mem, op)) ++ return false; ++ ++ if (op->addr.nbytes && op->dummy.nbytes && ++ op->addr.buswidth != op->dummy.buswidth) ++ return false; ++ ++ if (op->addr.nbytes + op->dummy.nbytes > 16) ++ return false; ++ ++ if (op->data.nbytes > MTK_SPI_IPM_PACKET_SIZE) { ++ if (op->data.nbytes / MTK_SPI_IPM_PACKET_SIZE > ++ MTK_SPI_IPM_PACKET_LOOP || ++ op->data.nbytes % MTK_SPI_IPM_PACKET_SIZE != 0) ++ return false; ++ } ++ ++ return true; ++} ++ ++static void mtk_spi_mem_setup_dma_xfer(struct spi_master *master, ++ const struct spi_mem_op *op) ++{ ++ struct mtk_spi *mdata = spi_master_get_devdata(master); ++ ++ writel((u32)(mdata->tx_dma & MTK_SPI_32BITS_MASK), ++ mdata->base + SPI_TX_SRC_REG); ++#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT ++ if (mdata->dev_comp->dma_ext) ++ writel((u32)(mdata->tx_dma >> 32), ++ mdata->base + SPI_TX_SRC_REG_64); ++#endif ++ ++ if (op->data.dir == SPI_MEM_DATA_IN) { ++ writel((u32)(mdata->rx_dma & MTK_SPI_32BITS_MASK), ++ mdata->base + SPI_RX_DST_REG); ++#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT ++ if (mdata->dev_comp->dma_ext) ++ writel((u32)(mdata->rx_dma >> 32), ++ mdata->base + SPI_RX_DST_REG_64); ++#endif ++ } ++} ++ ++static int mtk_spi_transfer_wait(struct spi_mem *mem, ++ const struct spi_mem_op *op) ++{ ++ struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master); ++ /* ++ * For each byte we wait for 8 cycles of the SPI clock. ++ * Since speed is defined in Hz and we want milliseconds, ++ * so it should be 8 * 1000. ++ */ ++ u64 ms = 8000LL; ++ ++ if (op->data.dir == SPI_MEM_NO_DATA) ++ ms *= 32; /* prevent we may get 0 for short transfers. */ ++ else ++ ms *= op->data.nbytes; ++ ms = div_u64(ms, mem->spi->max_speed_hz); ++ ms += ms + 1000; /* 1s tolerance */ ++ ++ if (ms > UINT_MAX) ++ ms = UINT_MAX; ++ ++ if (!wait_for_completion_timeout(&mdata->spimem_done, ++ msecs_to_jiffies(ms))) { ++ dev_err(mdata->dev, "spi-mem transfer timeout\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int mtk_spi_mem_exec_op(struct spi_mem *mem, ++ const struct spi_mem_op *op) ++{ ++ struct mtk_spi *mdata = spi_master_get_devdata(mem->spi->master); ++ u32 reg_val, nio, tx_size; ++ char *tx_tmp_buf, *rx_tmp_buf; ++ int ret = 0; ++ ++ mdata->use_spimem = true; ++ reinit_completion(&mdata->spimem_done); ++ ++ mtk_spi_reset(mdata); ++ mtk_spi_hw_init(mem->spi->master, mem->spi); ++ mtk_spi_prepare_transfer(mem->spi->master, mem->spi->max_speed_hz); ++ ++ reg_val = readl(mdata->base + SPI_CFG3_IPM_REG); ++ /* opcode byte len */ ++ reg_val &= ~SPI_CFG3_IPM_CMD_BYTELEN_MASK; ++ reg_val |= 1 << SPI_CFG3_IPM_CMD_BYTELEN_OFFSET; ++ ++ /* addr & dummy byte len */ ++ reg_val &= ~SPI_CFG3_IPM_ADDR_BYTELEN_MASK; ++ if (op->addr.nbytes || op->dummy.nbytes) ++ reg_val |= (op->addr.nbytes + op->dummy.nbytes) << ++ SPI_CFG3_IPM_ADDR_BYTELEN_OFFSET; ++ ++ /* data byte len */ ++ if (op->data.dir == SPI_MEM_NO_DATA) { ++ reg_val |= SPI_CFG3_IPM_NODATA_FLAG; ++ writel(0, mdata->base + SPI_CFG1_REG); ++ } else { ++ reg_val &= ~SPI_CFG3_IPM_NODATA_FLAG; ++ mdata->xfer_len = op->data.nbytes; ++ mtk_spi_setup_packet(mem->spi->master); ++ } ++ ++ if (op->addr.nbytes || op->dummy.nbytes) { ++ if (op->addr.buswidth == 1 || op->dummy.buswidth == 1) ++ reg_val |= SPI_CFG3_IPM_XMODE_EN; ++ else ++ reg_val &= ~SPI_CFG3_IPM_XMODE_EN; ++ } ++ ++ if (op->addr.buswidth == 2 || ++ op->dummy.buswidth == 2 || ++ op->data.buswidth == 2) ++ nio = 2; ++ else if (op->addr.buswidth == 4 || ++ op->dummy.buswidth == 4 || ++ op->data.buswidth == 4) ++ nio = 4; ++ else ++ nio = 1; ++ ++ reg_val &= ~SPI_CFG3_IPM_CMD_PIN_MODE_MASK; ++ reg_val |= PIN_MODE_CFG(nio); ++ ++ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN; ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR; ++ else ++ reg_val &= ~SPI_CFG3_IPM_HALF_DUPLEX_DIR; ++ writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); ++ ++ tx_size = 1 + op->addr.nbytes + op->dummy.nbytes; ++ if (op->data.dir == SPI_MEM_DATA_OUT) ++ tx_size += op->data.nbytes; ++ ++ tx_size = max_t(u32, tx_size, 32); ++ ++ tx_tmp_buf = kzalloc(tx_size, GFP_KERNEL | GFP_DMA); ++ if (!tx_tmp_buf) { ++ mdata->use_spimem = false; ++ return -ENOMEM; ++ } ++ ++ tx_tmp_buf[0] = op->cmd.opcode; ++ ++ if (op->addr.nbytes) { ++ int i; ++ ++ for (i = 0; i < op->addr.nbytes; i++) ++ tx_tmp_buf[i + 1] = op->addr.val >> ++ (8 * (op->addr.nbytes - i - 1)); ++ } ++ ++ if (op->dummy.nbytes) ++ memset(tx_tmp_buf + op->addr.nbytes + 1, ++ 0xff, ++ op->dummy.nbytes); ++ ++ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) ++ memcpy(tx_tmp_buf + op->dummy.nbytes + op->addr.nbytes + 1, ++ op->data.buf.out, ++ op->data.nbytes); ++ ++ mdata->tx_dma = dma_map_single(mdata->dev, tx_tmp_buf, ++ tx_size, DMA_TO_DEVICE); ++ if (dma_mapping_error(mdata->dev, mdata->tx_dma)) { ++ ret = -ENOMEM; ++ goto err_exit; ++ } ++ ++ if (op->data.dir == SPI_MEM_DATA_IN) { ++ if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) { ++ rx_tmp_buf = kzalloc(op->data.nbytes, ++ GFP_KERNEL | GFP_DMA); ++ if (!rx_tmp_buf) { ++ ret = -ENOMEM; ++ goto unmap_tx_dma; ++ } ++ } else { ++ rx_tmp_buf = op->data.buf.in; ++ } ++ ++ mdata->rx_dma = dma_map_single(mdata->dev, ++ rx_tmp_buf, ++ op->data.nbytes, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(mdata->dev, mdata->rx_dma)) { ++ ret = -ENOMEM; ++ goto kfree_rx_tmp_buf; ++ } ++ } ++ ++ reg_val = readl(mdata->base + SPI_CMD_REG); ++ reg_val |= SPI_CMD_TX_DMA; ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ reg_val |= SPI_CMD_RX_DMA; ++ writel(reg_val, mdata->base + SPI_CMD_REG); ++ ++ mtk_spi_mem_setup_dma_xfer(mem->spi->master, op); ++ ++ mtk_spi_enable_transfer(mem->spi->master); ++ ++ /* Wait for the interrupt. */ ++ ret = mtk_spi_transfer_wait(mem, op); ++ if (ret) ++ goto unmap_rx_dma; ++ ++ /* spi disable dma */ ++ reg_val = readl(mdata->base + SPI_CMD_REG); ++ reg_val &= ~SPI_CMD_TX_DMA; ++ if (op->data.dir == SPI_MEM_DATA_IN) ++ reg_val &= ~SPI_CMD_RX_DMA; ++ writel(reg_val, mdata->base + SPI_CMD_REG); ++ ++unmap_rx_dma: ++ if (op->data.dir == SPI_MEM_DATA_IN) { ++ dma_unmap_single(mdata->dev, mdata->rx_dma, ++ op->data.nbytes, DMA_FROM_DEVICE); ++ if (!IS_ALIGNED((size_t)op->data.buf.in, 4)) ++ memcpy(op->data.buf.in, rx_tmp_buf, op->data.nbytes); ++ } ++kfree_rx_tmp_buf: ++ if (op->data.dir == SPI_MEM_DATA_IN && ++ !IS_ALIGNED((size_t)op->data.buf.in, 4)) ++ kfree(rx_tmp_buf); ++unmap_tx_dma: ++ dma_unmap_single(mdata->dev, mdata->tx_dma, ++ tx_size, DMA_TO_DEVICE); ++err_exit: ++ kfree(tx_tmp_buf); ++ mdata->use_spimem = false; ++ ++ return ret; ++} ++ ++static const struct spi_controller_mem_ops mtk_spi_mem_ops = { ++ .adjust_op_size = mtk_spi_mem_adjust_op_size, ++ .supports_op = mtk_spi_mem_supports_op, ++ .exec_op = mtk_spi_mem_exec_op, ++}; ++ + static int mtk_spi_probe(struct platform_device *pdev) + { + struct spi_master *master; +@@ -739,6 +1103,7 @@ static int mtk_spi_probe(struct platform + master->can_dma = mtk_spi_can_dma; + master->setup = mtk_spi_setup; + master->set_cs_timing = mtk_spi_set_hw_cs_timing; ++ master->use_gpio_descriptors = true; + + of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node); + if (!of_id) { +@@ -755,6 +1120,14 @@ static int mtk_spi_probe(struct platform + + if (mdata->dev_comp->must_tx) + master->flags = SPI_MASTER_MUST_TX; ++ if (mdata->dev_comp->ipm_design) ++ master->mode_bits |= SPI_LOOP; ++ ++ if (mdata->dev_comp->ipm_design) { ++ mdata->dev = &pdev->dev; ++ master->mem_ops = &mtk_spi_mem_ops; ++ init_completion(&mdata->spimem_done); ++ } + + if (mdata->dev_comp->need_pad_sel) { + mdata->pad_num = of_property_count_u32_elems( +@@ -831,25 +1204,40 @@ static int mtk_spi_probe(struct platform + goto err_put_master; + } + ++ mdata->spi_hclk = devm_clk_get_optional(&pdev->dev, "hclk"); ++ if (IS_ERR(mdata->spi_hclk)) { ++ ret = PTR_ERR(mdata->spi_hclk); ++ dev_err(&pdev->dev, "failed to get hclk: %d\n", ret); ++ goto err_put_master; ++ } ++ ++ ret = clk_prepare_enable(mdata->spi_hclk); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to enable hclk (%d)\n", ret); ++ goto err_put_master; ++ } ++ + ret = clk_prepare_enable(mdata->spi_clk); + if (ret < 0) { + dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret); +- goto err_put_master; ++ goto err_disable_spi_hclk; + } + + ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk); + if (ret < 0) { + dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); +- clk_disable_unprepare(mdata->spi_clk); +- goto err_put_master; ++ goto err_disable_spi_clk; + } + + mdata->spi_clk_hz = clk_get_rate(mdata->spi_clk); + +- if (mdata->dev_comp->no_need_unprepare) ++ if (mdata->dev_comp->no_need_unprepare) { + clk_disable(mdata->spi_clk); +- else ++ clk_disable(mdata->spi_hclk); ++ } else { + clk_disable_unprepare(mdata->spi_clk); ++ clk_disable_unprepare(mdata->spi_hclk); ++ } + + pm_runtime_enable(&pdev->dev); + +@@ -862,25 +1250,12 @@ static int mtk_spi_probe(struct platform + goto err_disable_runtime_pm; + } + +- if (!master->cs_gpios && master->num_chipselect > 1) { ++ if (!master->cs_gpiods && master->num_chipselect > 1) { + dev_err(&pdev->dev, + "cs_gpios not specified and num_chipselect > 1\n"); + ret = -EINVAL; + goto err_disable_runtime_pm; + } +- +- if (master->cs_gpios) { +- for (i = 0; i < master->num_chipselect; i++) { +- ret = devm_gpio_request(&pdev->dev, +- master->cs_gpios[i], +- dev_name(&pdev->dev)); +- if (ret) { +- dev_err(&pdev->dev, +- "can't get CS GPIO %i\n", i); +- goto err_disable_runtime_pm; +- } +- } +- } + } + + if (mdata->dev_comp->dma_ext) +@@ -902,6 +1277,10 @@ static int mtk_spi_probe(struct platform + + err_disable_runtime_pm: + pm_runtime_disable(&pdev->dev); ++err_disable_spi_clk: ++ clk_disable_unprepare(mdata->spi_clk); ++err_disable_spi_hclk: ++ clk_disable_unprepare(mdata->spi_hclk); + err_put_master: + spi_master_put(master); + +@@ -917,8 +1296,10 @@ static int mtk_spi_remove(struct platfor + + mtk_spi_reset(mdata); + +- if (mdata->dev_comp->no_need_unprepare) ++ if (mdata->dev_comp->no_need_unprepare) { + clk_unprepare(mdata->spi_clk); ++ clk_unprepare(mdata->spi_hclk); ++ } + + return 0; + } +@@ -934,8 +1315,10 @@ static int mtk_spi_suspend(struct device + if (ret) + return ret; + +- if (!pm_runtime_suspended(dev)) ++ if (!pm_runtime_suspended(dev)) { + clk_disable_unprepare(mdata->spi_clk); ++ clk_disable_unprepare(mdata->spi_hclk); ++ } + + return ret; + } +@@ -952,11 +1335,20 @@ static int mtk_spi_resume(struct device + dev_err(dev, "failed to enable spi_clk (%d)\n", ret); + return ret; + } ++ ++ ret = clk_prepare_enable(mdata->spi_hclk); ++ if (ret < 0) { ++ dev_err(dev, "failed to enable spi_hclk (%d)\n", ret); ++ clk_disable_unprepare(mdata->spi_clk); ++ return ret; ++ } + } + + ret = spi_master_resume(master); +- if (ret < 0) ++ if (ret < 0) { + clk_disable_unprepare(mdata->spi_clk); ++ clk_disable_unprepare(mdata->spi_hclk); ++ } + + return ret; + } +@@ -968,10 +1360,13 @@ static int mtk_spi_runtime_suspend(struc + struct spi_master *master = dev_get_drvdata(dev); + struct mtk_spi *mdata = spi_master_get_devdata(master); + +- if (mdata->dev_comp->no_need_unprepare) ++ if (mdata->dev_comp->no_need_unprepare) { + clk_disable(mdata->spi_clk); +- else ++ clk_disable(mdata->spi_hclk); ++ } else { + clk_disable_unprepare(mdata->spi_clk); ++ clk_disable_unprepare(mdata->spi_hclk); ++ } + + return 0; + } +@@ -982,13 +1377,31 @@ static int mtk_spi_runtime_resume(struct + struct mtk_spi *mdata = spi_master_get_devdata(master); + int ret; + +- if (mdata->dev_comp->no_need_unprepare) ++ if (mdata->dev_comp->no_need_unprepare) { + ret = clk_enable(mdata->spi_clk); +- else ++ if (ret < 0) { ++ dev_err(dev, "failed to enable spi_clk (%d)\n", ret); ++ return ret; ++ } ++ ret = clk_enable(mdata->spi_hclk); ++ if (ret < 0) { ++ dev_err(dev, "failed to enable spi_hclk (%d)\n", ret); ++ clk_disable(mdata->spi_clk); ++ return ret; ++ } ++ } else { + ret = clk_prepare_enable(mdata->spi_clk); +- if (ret < 0) { +- dev_err(dev, "failed to enable spi_clk (%d)\n", ret); +- return ret; ++ if (ret < 0) { ++ dev_err(dev, "failed to prepare_enable spi_clk (%d)\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(mdata->spi_hclk); ++ if (ret < 0) { ++ dev_err(dev, "failed to prepare_enable spi_hclk (%d)\n", ret); ++ clk_disable_unprepare(mdata->spi_clk); ++ return ret; ++ } + } + + return 0; diff --git a/target/linux/mediatek/patches-5.15/320-mmc-mediatek-add-support-for-MT7986-SoC.patch b/target/linux/mediatek/patches-5.15/320-mmc-mediatek-add-support-for-MT7986-SoC.patch new file mode 100644 index 0000000000..56ffa73c00 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/320-mmc-mediatek-add-support-for-MT7986-SoC.patch @@ -0,0 +1,44 @@ +From 1a7963e9843f6f1e4b02a30926d20b314c03e4df Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Sat, 25 Jun 2022 02:10:13 +0800 +Subject: [PATCH] mmc: mediatek: add support for MT7986 SoC + +Adding mt7986 own characteristics and of_device_id to have support +of MT7986 SoC. + +Signed-off-by: Sam Shih +Change-Id: I07cf8406cbe8c1a7114b304f35fc3e689e512e5a +--- + drivers/mmc/host/mtk-sd.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -540,6 +540,19 @@ static const struct mtk_mmc_compatible m + .support_64g = false, + }; + ++static const struct mtk_mmc_compatible mt7986_compat = { ++ .clk_div_bits = 12, ++ .recheck_sdio_irq = true, ++ .hs400_tune = false, ++ .pad_tune_reg = MSDC_PAD_TUNE0, ++ .async_fifo = true, ++ .data_tune = true, ++ .busy_check = true, ++ .stop_clk_fix = true, ++ .enhance_rx = true, ++ .support_64g = true, ++}; ++ + static const struct mtk_mmc_compatible mt8516_compat = { + .clk_div_bits = 12, + .recheck_sdio_irq = true, +@@ -584,6 +597,7 @@ static const struct of_device_id msdc_of + { .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat}, + { .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat}, + { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, ++ { .compatible = "mediatek,mt7986-mmc", .data = &mt7986_compat}, + { .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat}, + { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, + { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat}, diff --git a/target/linux/mediatek/patches-5.15/405-mt7986-trng-add-rng-support.patch b/target/linux/mediatek/patches-5.15/405-mt7986-trng-add-rng-support.patch new file mode 100644 index 0000000000..332f17bae7 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/405-mt7986-trng-add-rng-support.patch @@ -0,0 +1,41 @@ +From f6ba5e17bee38f8ffe118c47fbfef3cf90eb87ff Mon Sep 17 00:00:00 2001 +From: "Mingming.Su" +Date: Wed, 30 Jun 2021 16:59:32 +0800 +Subject: [PATCH] mt7986: trng: add rng support + +1. Add trng compatible name for MT7986 +2. Fix mtk_rng_wait_ready() function + +Signed-off-by: Mingming.Su +--- + drivers/char/hw_random/mtk-rng.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/char/hw_random/mtk-rng.c ++++ b/drivers/char/hw_random/mtk-rng.c +@@ -22,7 +22,7 @@ + #define RNG_AUTOSUSPEND_TIMEOUT 100 + + #define USEC_POLL 2 +-#define TIMEOUT_POLL 20 ++#define TIMEOUT_POLL 60 + + #define RNG_CTRL 0x00 + #define RNG_EN BIT(0) +@@ -77,7 +77,7 @@ static bool mtk_rng_wait_ready(struct hw + readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready, + ready & RNG_READY, USEC_POLL, + TIMEOUT_POLL); +- return !!ready; ++ return !!(ready & RNG_READY); + } + + static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) +@@ -179,6 +179,7 @@ static const struct dev_pm_ops mtk_rng_p + #endif /* CONFIG_PM */ + + static const struct of_device_id mtk_rng_match[] = { ++ { .compatible = "mediatek,mt7986-rng" }, + { .compatible = "mediatek,mt7623-rng" }, + {}, + }; diff --git a/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch b/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch index deb25e652d..4c0d1001e0 100644 --- a/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch +++ b/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch @@ -14,7 +14,7 @@ Signed-off-by: Frank Wunderlich --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3675,6 +3675,7 @@ static const struct mtk_soc_data mt2701_ +@@ -3637,6 +3637,7 @@ static const struct mtk_soc_data mt2701_ .hw_features = MTK_HW_FEATURES, .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, diff --git a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch index 45c650b34a..de1079ffae 100644 --- a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch +++ b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch @@ -103,7 +103,7 @@ Signed-off-by: David S. Miller ret = mtk_mdio_busy_wait(eth); if (ret < 0) -@@ -683,6 +726,7 @@ static int mtk_mdio_init(struct mtk_eth +@@ -621,6 +664,7 @@ static int mtk_mdio_init(struct mtk_eth eth->mii_bus->name = "mdio"; eth->mii_bus->read = mtk_mdio_read; eth->mii_bus->write = mtk_mdio_write; diff --git a/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch b/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch deleted file mode 100644 index a7878ecb1b..0000000000 --- a/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -667,6 +667,7 @@ static void mtk_validate(struct phylink_ - if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { - phylink_set(mask, 1000baseT_Full); - phylink_set(mask, 1000baseX_Full); -+ phylink_set(mask, 2500baseT_Full); - phylink_set(mask, 2500baseX_Full); - } - if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) { diff --git a/target/linux/mediatek/patches-5.15/920-watchdog-add-mt7986-assert.patch b/target/linux/mediatek/patches-5.15/920-watchdog-add-mt7986-assert.patch new file mode 100644 index 0000000000..699161458c --- /dev/null +++ b/target/linux/mediatek/patches-5.15/920-watchdog-add-mt7986-assert.patch @@ -0,0 +1,57 @@ +--- a/drivers/watchdog/mtk_wdt.c ++++ b/drivers/watchdog/mtk_wdt.c +@@ -9,6 +9,7 @@ + * Based on sunxi_wdt.c + */ + ++#include + #include + #include + #include +@@ -65,6 +66,7 @@ struct mtk_wdt_dev { + void __iomem *wdt_base; + spinlock_t lock; /* protects WDT_SWSYSRST reg */ + struct reset_controller_dev rcdev; ++ bool disable_wdt_extrst; + }; + + struct mtk_wdt_data { +@@ -87,6 +89,10 @@ static const struct mtk_wdt_data mt8195_ + .toprgu_sw_rst_num = MT8195_TOPRGU_SW_RST_NUM, + }; + ++static const struct mtk_wdt_data mt7986_data = { ++ .toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM, ++}; ++ + static int toprgu_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) + { +@@ -256,6 +262,8 @@ static int mtk_wdt_start(struct watchdog + reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + else + reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); ++ if (mtk_wdt->disable_wdt_extrst) ++ reg &= ~WDT_MODE_EXRST_EN; + reg |= (WDT_MODE_EN | WDT_MODE_KEY); + iowrite32(reg, wdt_base + WDT_MODE); + +@@ -381,6 +389,10 @@ static int mtk_wdt_probe(struct platform + if (err) + return err; + } ++ ++ mtk_wdt->disable_wdt_extrst = ++ of_property_read_bool(dev->of_node, "mediatek,disable-extrst"); ++ + return 0; + } + +@@ -414,6 +426,7 @@ static const struct of_device_id mtk_wdt + { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data }, + { .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data }, + { .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data }, ++ { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids); diff --git a/target/linux/mediatek/patches-5.15/921-mt7986-add-mmc-support.patch b/target/linux/mediatek/patches-5.15/921-mt7986-add-mmc-support.patch new file mode 100644 index 0000000000..18b6e97d06 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/921-mt7986-add-mmc-support.patch @@ -0,0 +1,47 @@ +From 0f8a0dd620b2fb5f9c852844ce5f445bb0bd6d52 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Wed, 4 May 2022 10:27:43 +0800 +Subject: [PATCH 5/5] mediatek: add mt7986a mmc support + +Add mt7986a boot mmc support + +Signed-off-by: Sam Shih +--- + ...-mmc-mediatek-add-mt7986-mmc-support.patch | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + create mode 100644 target/linux/mediatek/patches-5.15/0704-mmc-mediatek-add-mt7986-mmc-support.patch + +--- /dev/null ++++ b/target/linux/mediatek/patches-5.15/0704-mmc-mediatek-add-mt7986-mmc-support.patch +@@ -0,0 +1,31 @@ ++diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c ++index 1ac9201..a32349c 100644 ++--- a/drivers/mmc/host/mtk-sd.c +++++ b/drivers/mmc/host/mtk-sd.c ++@@ -540,6 +540,18 @@ static const struct mtk_mmc_compatible mt7622_compat = { ++ .support_64g = false, ++ }; ++ +++static const struct mtk_mmc_compatible mt7986_compat = { +++ .clk_div_bits = 12, +++ .hs400_tune = false, +++ .pad_tune_reg = MSDC_PAD_TUNE0, +++ .async_fifo = true, +++ .data_tune = true, +++ .busy_check = true, +++ .stop_clk_fix = true, +++ .enhance_rx = true, +++ .support_64g = true, +++}; +++ ++ static const struct mtk_mmc_compatible mt8516_compat = { ++ .clk_div_bits = 12, ++ .recheck_sdio_irq = true, ++@@ -584,6 +596,7 @@ static const struct of_device_id msdc_of_ids[] = { ++ { .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat}, ++ { .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat}, ++ { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, +++ { .compatible = "mediatek,mt7986-mmc", .data = &mt7986_compat}, ++ { .compatible = "mediatek,mt8516-mmc", .data = &mt8516_compat}, ++ { .compatible = "mediatek,mt7620-mmc", .data = &mt7620_compat}, ++ { .compatible = "mediatek,mt6779-mmc", .data = &mt6779_compat}, diff --git a/target/linux/mediatek/patches-5.15/922-PCI-mediatek-gen3-change-driver-name-to-mtk-pcie-gen.patch b/target/linux/mediatek/patches-5.15/922-PCI-mediatek-gen3-change-driver-name-to-mtk-pcie-gen.patch new file mode 100644 index 0000000000..44aed2207d --- /dev/null +++ b/target/linux/mediatek/patches-5.15/922-PCI-mediatek-gen3-change-driver-name-to-mtk-pcie-gen.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau +Date: Wed, 4 May 2022 12:03:42 +0200 +Subject: [PATCH] PCI: mediatek-gen3: change driver name to mtk-pcie-gen3 + +This allows it to coexist with the other mtk pcie driver in the same kernel + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -1025,7 +1025,7 @@ static struct platform_driver mtk_pcie_d + .probe = mtk_pcie_probe, + .remove = mtk_pcie_remove, + .driver = { +- .name = "mtk-pcie", ++ .name = "mtk-pcie-gen3", + .of_match_table = mtk_pcie_of_match, + .pm = &mtk_pcie_pm_ops, + }, diff --git a/target/linux/octeon/patches-5.10/130-itus_shield_support.patch b/target/linux/octeon/patches-5.10/130-itus_shield_support.patch index 15f514209d..a041331c20 100644 --- a/target/linux/octeon/patches-5.10/130-itus_shield_support.patch +++ b/target/linux/octeon/patches-5.10/130-itus_shield_support.patch @@ -20,7 +20,7 @@ } --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c -@@ -773,7 +773,7 @@ int __init octeon_prune_device_tree(void +@@ -774,7 +774,7 @@ int __init octeon_prune_device_tree(void if (fdt_check_header(initial_boot_params)) panic("Corrupt Device Tree."); diff --git a/target/linux/octeon/patches-5.10/150-ubnt_usg_support.patch b/target/linux/octeon/patches-5.10/150-ubnt_usg_support.patch index 721f657978..88aa1c406f 100644 --- a/target/linux/octeon/patches-5.10/150-ubnt_usg_support.patch +++ b/target/linux/octeon/patches-5.10/150-ubnt_usg_support.patch @@ -18,7 +18,7 @@ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_ITUS_SHIELD) --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c -@@ -634,6 +634,7 @@ static void __init octeon_rx_tx_delay(in +@@ -635,6 +635,7 @@ static void __init octeon_rx_tx_delay(in } break; case CVMX_BOARD_TYPE_UBNT_E100: diff --git a/target/linux/octeon/patches-5.15/130-add_itus_support.patch b/target/linux/octeon/patches-5.15/130-add_itus_support.patch index 8efaec4a28..e51153096c 100644 --- a/target/linux/octeon/patches-5.15/130-add_itus_support.patch +++ b/target/linux/octeon/patches-5.15/130-add_itus_support.patch @@ -1,6 +1,6 @@ --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c -@@ -773,7 +773,7 @@ int __init octeon_prune_device_tree(void +@@ -774,7 +774,7 @@ int __init octeon_prune_device_tree(void if (fdt_check_header(initial_boot_params)) panic("Corrupt Device Tree."); diff --git a/target/linux/octeon/patches-5.15/150-ubnt_usg_support.patch b/target/linux/octeon/patches-5.15/150-ubnt_usg_support.patch index 721f657978..88aa1c406f 100644 --- a/target/linux/octeon/patches-5.15/150-ubnt_usg_support.patch +++ b/target/linux/octeon/patches-5.15/150-ubnt_usg_support.patch @@ -18,7 +18,7 @@ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_ITUS_SHIELD) --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c -@@ -634,6 +634,7 @@ static void __init octeon_rx_tx_delay(in +@@ -635,6 +635,7 @@ static void __init octeon_rx_tx_delay(in } break; case CVMX_BOARD_TYPE_UBNT_E100: diff --git a/target/linux/octeontx/patches-5.10/0004-PCI-add-quirk-for-Gateworks-PLX-PEX860x-switch-with-.patch b/target/linux/octeontx/patches-5.10/0004-PCI-add-quirk-for-Gateworks-PLX-PEX860x-switch-with-.patch index 76e97ccbeb..28502d393f 100644 --- a/target/linux/octeontx/patches-5.10/0004-PCI-add-quirk-for-Gateworks-PLX-PEX860x-switch-with-.patch +++ b/target/linux/octeontx/patches-5.10/0004-PCI-add-quirk-for-Gateworks-PLX-PEX860x-switch-with-.patch @@ -22,7 +22,7 @@ Signed-off-by: Tim Harvey #include #include #include -@@ -5784,3 +5785,34 @@ static void nvidia_ion_ahci_fixup(struct +@@ -5787,3 +5788,34 @@ static void nvidia_ion_ahci_fixup(struct pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING; } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup); diff --git a/target/linux/ramips/dts/mt7621_yuncore_ax820.dts b/target/linux/ramips/dts/mt7621_yuncore_ax820.dts index 75fe3cf581..6ea3c922db 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_ax820.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_ax820.dts @@ -4,6 +4,7 @@ #include #include +#include / { compatible = "yuncore,ax820", "mediatek,mt7621-soc"; @@ -47,6 +48,18 @@ gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1radio"; }; + + wan { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&switch0 0 GPIO_ACTIVE_LOW>; + }; + + lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&switch0 3 GPIO_ACTIVE_LOW>; + }; }; watchdog { @@ -147,6 +160,9 @@ }; &switch0 { + gpio-controller; + #gpio-cells = <2>; + ports { port@1 { status = "okay"; diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index 0e8244772d..5e1e707930 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -162,6 +162,10 @@ xiaomi,redmi-router-ac2100) youhua,wr1200js) ucidef_set_led_netdev "internet" "INTERNET" "green:wan" "wan" ;; +yuncore,ax820) + ucidef_set_led_netdev "lan" "LAN" "green:lan" "lan" + ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan" + ;; zbtlink,zbt-wg1608-16m) ucidef_set_led_netdev "lan1" "LAN1" "green:lan-1" "lan1" ucidef_set_led_netdev "lan2" "LAN2" "green:lan-2" "lan2" diff --git a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch index f6ac8360ee..8a39c81e01 100644 --- a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch +++ b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch @@ -14,7 +14,7 @@ Signed-off-by: René van Dorst --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -3290,6 +3290,7 @@ static const struct net_device_ops mtk_n +@@ -3228,6 +3228,7 @@ static const struct net_device_ops mtk_n static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) { @@ -22,7 +22,7 @@ Signed-off-by: René van Dorst const __be32 *_id = of_get_property(np, "reg", NULL); phy_interface_t phy_mode; struct phylink *phylink; -@@ -3385,6 +3386,9 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -3347,6 +3348,9 @@ static int mtk_add_mac(struct mtk_eth *e else eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN; diff --git a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch index 6db8296743..063b317fd5 100644 --- a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch +++ b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch @@ -71,7 +71,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c break; --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1023,14 +1023,16 @@ struct phy_device *phy_find_first(struct +@@ -1029,14 +1029,16 @@ struct phy_device *phy_find_first(struct } EXPORT_SYMBOL(phy_find_first); @@ -95,7 +95,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c phydev->mii_ts->link_state(phydev->mii_ts, phydev); --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -946,7 +946,8 @@ void phylink_destroy(struct phylink *pl) +@@ -1315,7 +1315,8 @@ void phylink_destroy(struct phylink *pl) } EXPORT_SYMBOL_GPL(phylink_destroy); @@ -107,7 +107,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c bool tx_pause, rx_pause; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -669,7 +669,7 @@ struct phy_device { +@@ -703,7 +703,7 @@ struct phy_device { u8 mdix; u8 mdix_ctrl; diff --git a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch index 97086fa950..365bdc6880 100644 --- a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch +++ b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch @@ -37,7 +37,7 @@ Signed-off-by: John Crispin break; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -586,6 +586,7 @@ struct phy_device { +@@ -620,6 +620,7 @@ struct phy_device { unsigned downshifted_rate:1; unsigned is_on_sfp_module:1; unsigned mac_managed_pm:1; diff --git a/target/linux/realtek/dts-5.10/rtl8380_tplink_sg2008p-v1.dts b/target/linux/realtek/dts-5.10/rtl8380_tplink_sg2008p-v1.dts index 2cce03bde1..d464921e50 100644 --- a/target/linux/realtek/dts-5.10/rtl8380_tplink_sg2008p-v1.dts +++ b/target/linux/realtek/dts-5.10/rtl8380_tplink_sg2008p-v1.dts @@ -53,9 +53,9 @@ #address-cells = <1>; #size-cells = <0>; - tps23861@30 { + tps23861@28 { compatible = "ti,tps23861"; - reg = <0x30>; + reg = <0x28>; shunt-resistor-micro-ohms = <255000>; }; }; @@ -161,14 +161,14 @@ #address-cells = <1>; #size-cells = <0>; - SWITCH_PORT(8, 1, internal) - SWITCH_PORT(9, 2, internal) - SWITCH_PORT(10, 3, internal) - SWITCH_PORT(11, 4, internal) - SWITCH_PORT(12, 5, internal) - SWITCH_PORT(13, 6, internal) - SWITCH_PORT(14, 7, internal) - SWITCH_PORT(15, 8, internal) + SWITCH_PORT(15, 1, internal) + SWITCH_PORT(14, 2, internal) + SWITCH_PORT(13, 3, internal) + SWITCH_PORT(12, 4, internal) + SWITCH_PORT(11, 5, internal) + SWITCH_PORT(10, 6, internal) + SWITCH_PORT(9, 7, internal) + SWITCH_PORT(8, 8, internal) port@28 { ethernet = <ðernet0>; diff --git a/target/linux/realtek/dts-5.10/rtl838x.dtsi b/target/linux/realtek/dts-5.10/rtl838x.dtsi index 41fdbdae20..f92af17ef1 100644 --- a/target/linux/realtek/dts-5.10/rtl838x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl838x.dtsi @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT +#include + /dts-v1/; #define STRINGIZE(s) #s @@ -60,14 +62,58 @@ compatible = "realtek,rtl838x-soc"; + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + ccu: clock-controller { + compatible = "realtek,rtl8380-clock"; + #clock-cells = <1>; + clocks = <&osc>; + clock-names = "ref_clk"; + }; + cpus { #address-cells = <1>; #size-cells = <0>; - frequency = <500000000>; cpu@0 { compatible = "mips,mips4KEc"; reg = <0>; + clocks = <&ccu CLK_CPU>; + operating-points-v2 = <&cpu_opp_table>; + }; + }; + + cpu_opp_table: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <325000000>; + }; + opp01 { + opp-hz = /bits/ 64 <350000000>; + }; + opp02 { + opp-hz = /bits/ 64 <375000000>; + }; + opp03 { + opp-hz = /bits/ 64 <400000000>; + }; + opp04 { + opp-hz = /bits/ 64 <425000000>; + }; + opp05 { + opp-hz = /bits/ 64 <450000000>; + }; + opp06 { + opp-hz = /bits/ 64 <475000000>; + }; + opp07 { + opp-hz = /bits/ 64 <500000000>; }; }; @@ -75,12 +121,6 @@ bootargs = "console=ttyS0,115200"; }; - lx_clk: lx_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <200000000>; - }; - cpuintc: cpuintc { compatible = "mti,cpu-interrupt-controller"; #address-cells = <0>; @@ -116,7 +156,7 @@ compatible = "ns16550a"; reg = <0x2000 0x100>; - clocks = <&lx_clk>; + clocks = <&ccu CLK_LXB>; interrupt-parent = <&intc>; interrupts = <31 1>; @@ -134,7 +174,7 @@ compatible = "ns16550a"; reg = <0x2100 0x100>; - clocks = <&lx_clk>; + clocks = <&ccu CLK_LXB>; interrupt-parent = <&intc>; interrupts = <30 0>; @@ -153,7 +193,7 @@ realtek,reset-mode = "soc"; - clocks = <&lx_clk>; + clocks = <&ccu CLK_LXB>; timeout-sec = <30>; interrupt-parent = <&intc>; @@ -220,6 +260,14 @@ }; }; + sram0: sram@9f000000 { + compatible = "mmio-sram"; + reg = <0x9f000000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x9f000000 0x10000>; + }; + switch0: switch@1b000000 { compatible = "realtek,rtl83xx-switch"; diff --git a/target/linux/realtek/dts-5.10/rtl839x.dtsi b/target/linux/realtek/dts-5.10/rtl839x.dtsi index cfed68eb95..b40ca83ac3 100644 --- a/target/linux/realtek/dts-5.10/rtl839x.dtsi +++ b/target/linux/realtek/dts-5.10/rtl839x.dtsi @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT +#include + /dts-v1/; #define STRINGIZE(s) #s @@ -53,14 +55,83 @@ compatible = "realtek,rtl839x-soc"; + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + ccu: clock-controller { + compatible = "realtek,rtl8390-clock"; + #clock-cells = <1>; + clocks = <&osc>; + clock-names = "ref_clk"; + }; + cpus { #address-cells = <1>; #size-cells = <0>; - frequency = <700000000>; cpu@0 { compatible = "mips,mips34Kc"; reg = <0>; + clocks = <&ccu CLK_CPU>; + operating-points-v2 = <&cpu_opp_table>; + }; + + cpu@1 { + compatible = "mips,mips34Kc"; + reg = <1>; + clocks = <&ccu CLK_CPU>; + operating-points-v2 = <&cpu_opp_table>; + }; + }; + + cpu_opp_table: opp-table-0 { + compatible = "operating-points-v2"; + opp-shared; + + opp00 { + opp-hz = /bits/ 64 <425000000>; + }; + opp01 { + opp-hz = /bits/ 64 <450000000>; + }; + opp02 { + opp-hz = /bits/ 64 <475000000>; + }; + opp03 { + opp-hz = /bits/ 64 <500000000>; + }; + opp04 { + opp-hz = /bits/ 64 <525000000>; + }; + opp05 { + opp-hz = /bits/ 64 <550000000>; + }; + opp06 { + opp-hz = /bits/ 64 <575000000>; + }; + opp07 { + opp-hz = /bits/ 64 <600000000>; + }; + opp08 { + opp-hz = /bits/ 64 <625000000>; + }; + opp09 { + opp-hz = /bits/ 64 <650000000>; + }; + opp10 { + opp-hz = /bits/ 64 <675000000>; + }; + opp11 { + opp-hz = /bits/ 64 <700000000>; + }; + opp12 { + opp-hz = /bits/ 64 <725000000>; + }; + opp13 { + opp-hz = /bits/ 64 <750000000>; }; }; @@ -68,12 +139,6 @@ bootargs = "console=ttyS0,115200"; }; - lx_clk: lx_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <200000000>; - }; - cpuintc: cpuintc { compatible = "mti,cpu-interrupt-controller"; #address-cells = <0>; @@ -109,7 +174,7 @@ compatible = "ns16550a"; reg = <0x2000 0x100>; - clocks = <&lx_clk>; + clocks = <&ccu CLK_LXB>; interrupt-parent = <&intc>; interrupts = <31 1>; @@ -127,7 +192,7 @@ compatible = "ns16550a"; reg = <0x2100 0x100>; - clocks = <&lx_clk>; + clocks = <&ccu CLK_LXB>; interrupt-parent = <&intc>; interrupts = <30 2>; @@ -160,7 +225,7 @@ realtek,reset-mode = "soc"; - clocks = <&lx_clk>; + clocks = <&ccu CLK_LXB>; timeout-sec = <30>; interrupt-parent = <&intc>; @@ -215,6 +280,14 @@ }; }; + sram0: sram@9f000000 { + compatible = "mmio-sram"; + reg = <0x9f000000 0x18000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x9f000000 0x18000>; + }; + switch0: switch@1b000000 { status = "okay"; compatible = "realtek,rtl83xx-switch"; diff --git a/target/linux/realtek/files-5.10/drivers/clk/realtek/Kconfig b/target/linux/realtek/files-5.10/drivers/clk/realtek/Kconfig new file mode 100644 index 0000000000..4cf3cd9633 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/clk/realtek/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only + +menuconfig COMMON_CLK_REALTEK + bool "Support for Realtek's clock controllers" + depends on RTL83XX + +if COMMON_CLK_REALTEK + +config COMMON_CLK_RTL83XX + bool "Clock driver for Realtek RTL83XX" + depends on RTL83XX + select SRAM + help + This driver adds support for the Realtek RTL83xx series basic clocks. + This includes chips in the RTL838x series, such as RTL8380, RTL8381, + RTL832, as well as chips from the RTL839x series, such as RTL8390, + RT8391, RTL8392, RTL8393 and RTL8396. + +endif diff --git a/target/linux/realtek/files-5.10/drivers/clk/realtek/Makefile b/target/linux/realtek/files-5.10/drivers/clk/realtek/Makefile new file mode 100644 index 0000000000..7bc4ed910c --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/clk/realtek/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_COMMON_CLK_RTL83XX) += clk-rtl83xx.o clk-rtl838x-sram.o clk-rtl839x-sram.o diff --git a/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl838x-sram.S b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl838x-sram.S new file mode 100644 index 0000000000..527436bbab --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl838x-sram.S @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Realtek RTL838X SRAM clock setters + * Copyright (C) 2022 Markus Stockhausen + */ + +#include + +#include "clk-rtl83xx.h" + +#define rGLB $t0 +#define rCTR $t1 +#define rMSK $t2 +#define rSLP $t3 +#define rTMP $t4 + +.set noreorder + +.globl rtcl_838x_dram_start +rtcl_838x_dram_start: + +/* + * Functions start here and should avoid access to normal memory. REMARK! Do not forget about + * stack pointer and dirty caches that might interfere. + */ + +.globl rtcl_838x_dram_set_rate +.ent rtcl_838x_dram_set_rate +rtcl_838x_dram_set_rate: + +#ifdef CONFIG_RTL838X + + li rCTR, RTL_SW_CORE_BASE + addiu rGLB, rCTR, RTL838X_PLL_GLB_CTRL + ori rTMP, $0, CLK_CPU + beq $a0, rTMP, pre_cpu + ori rTMP, $0, CLK_MEM + beq $a0, rTMP, pre_mem + nop +pre_lxb: + ori rSLP, $0, RTL838X_GLB_CTRL_LXB_PLL_READY_MASK + addiu rCTR, rCTR, RTL838X_PLL_LXB_CTRL0 + b main_set + ori rMSK, $0, RTL838X_GLB_CTRL_EN_LXB_PLL_MASK +pre_mem: + /* simple 64K data cache flush to avoid unexpected memory access */ + li rMSK, RTL_SRAM_BASE + li rTMP, 2048 +pre_flush: + lw $0, 0(rMSK) + addiu rMSK, rMSK, 32 + addiu rTMP, rTMP, -1 + bne rTMP, $0, pre_flush + lw $0, -4(rMSK) + + ori rSLP, $0, RTL838X_GLB_CTRL_MEM_PLL_READY_MASK + addiu rCTR, rCTR, RTL838X_PLL_MEM_CTRL0 + b main_set + ori rMSK, $0, RTL838X_GLB_CTRL_EN_MEM_PLL_MASK +pre_cpu: + /* switch CPU to LXB clock */ + ori rMSK, $0, RTL838X_GLB_CTRL_CPU_PLL_SC_MUX_MASK + nor rMSK, rMSK, $0 + sync + lw rTMP, 0(rGLB) + and rTMP, rTMP, rMSK + sw rTMP, 0(rGLB) + sync + + ori rSLP, $0, RTL838X_GLB_CTRL_CPU_PLL_READY_MASK + addiu rCTR, rCTR, RTL838X_PLL_CPU_CTRL0 + ori rMSK, $0, RTL838X_GLB_CTRL_EN_CPU_PLL_MASK +main_set: + /* disable PLL */ + nor rMSK, rMSK, 0 + sync + lw rTMP, 0(rGLB) + sync + and rTMP, rTMP, rMSK + sync + sw rTMP, 0(rGLB) + + /* set new PLL values */ + sync + sw $a1, 0(rCTR) + sw $a2, 4(rCTR) + sync + + /* enable PLL (will reset it and clear ready status) */ + nor rMSK, rMSK, 0 + sync + lw rTMP, 0(rGLB) + sync + or rTMP, rTMP, rMSK + sync + sw rTMP, 0(rGLB) + + /* wait for PLL to become ready */ +wait_ready: + lw rTMP, 0(rGLB) + and rTMP, rTMP, rSLP + bne rTMP, $0, wait_ready + sync + + /* branch to post processing */ + ori rTMP, $0, CLK_CPU + beq $a0, rTMP, post_cpu + ori rTMP, $0, CLK_MEM + beq $a0, rTMP, post_mem + nop +post_lxb: + jr $ra + nop +post_mem: + jr $ra + nop +post_cpu: + /* stabilize clock to avoid crash, empirically determined */ + ori rSLP, $0, 0x3000 +wait_cpu: + bnez rSLP, wait_cpu + addiu rSLP, rSLP, -1 + + /* switch CPU to PLL clock */ + ori rMSK, $0, RTL838X_GLB_CTRL_CPU_PLL_SC_MUX_MASK + sync + lw rTMP, 0(rGLB) + or rTMP, rTMP, rMSK + sw rTMP, 0(rGLB) + sync + jr $ra + nop + +#else /* !CONFIG_RTL838X */ + + jr $ra + nop + +#endif + +.end rtcl_838x_dram_set_rate + +/* + * End marker. Do not delete. + */ + .word RTL_SRAM_MARKER +.globl rtcl_838x_dram_size +rtcl_838x_dram_size: + .word .-rtcl_838x_dram_start + diff --git a/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl839x-sram.S b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl839x-sram.S new file mode 100644 index 0000000000..cd43dfaabd --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl839x-sram.S @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Realtek RTL839X SRAM clock setters + * Copyright (C) 2022 Markus Stockhausen + */ + +#include +#include + +#include "clk-rtl83xx.h" + +#define rGLB $t0 +#define rCTR $t1 +#define rMSK $t2 +#define rSLP1 $t3 +#define rSLP2 $t4 +#define rSLP3 $t5 +#define rTMP $t6 +#define rCP0 $t7 + +.set noreorder + +.globl rtcl_839x_dram_start +rtcl_839x_dram_start: + +/* + * Functions start here and should avoid access to normal memory. REMARK! Do not forget about + * stack pointer and dirty caches that might interfere. + */ + +.globl rtcl_839x_dram_set_rate +.ent rtcl_839x_dram_set_rate +rtcl_839x_dram_set_rate: + +#ifdef CONFIG_RTL839X + + /* disable MIPS 34K branch and return prediction */ + mfc0 rCP0, CP0_CONFIG, 7 + ori rTMP, rCP0, 0xc + mtc0 rTMP, CP0_CONFIG, 7 + + li rCTR, RTL_SW_CORE_BASE + addiu rGLB, rCTR, RTL839X_PLL_GLB_CTRL + ori rTMP, $0, CLK_CPU + beq $a0, rTMP, pre_cpu + ori rTMP, $0, CLK_MEM + beq $a0, rTMP, pre_mem + nop +pre_lxb: + li rSLP1, 0x400000 + li rSLP2, 0x400000 + li rSLP3, 0x400000 + addiu rCTR, rCTR, RTL839X_PLL_LXB_CTRL0 + b main_set + ori rMSK, $0, RTL839X_GLB_CTRL_LXB_CLKSEL_MASK +pre_mem: + /* try to avoid memory access with simple 64K data cache flush */ + li rMSK, RTL_SRAM_BASE + li rTMP, 2048 +pre_flush: + lw $0, 0(rMSK) + addiu rMSK, rMSK, 32 + addiu rTMP, rTMP, -1 + bne rTMP, $0, pre_flush + lw $0, -4(rMSK) + + li rSLP1, 0x10000 + li rSLP2, 0x10000 + li rSLP3, 0x10000 + addiu rCTR, rCTR, RTL839X_PLL_MEM_CTRL0 + b main_set + ori rMSK, $0, RTL839X_GLB_CTRL_MEM_CLKSEL_MASK +pre_cpu: + li rSLP1, 0x1000 + li rSLP2, 0x1000 + li rSLP3, 0x200 + addiu rCTR, rCTR, RTL839X_PLL_CPU_CTRL0 + ori rMSK, $0, RTL839X_GLB_CTRL_CPU_CLKSEL_MASK +main_set: + /* switch to fixed clock */ + sync + lw rTMP, 0(rGLB) + sync + or rTMP, rTMP, rMSK + sync + sw rTMP, 0(rGLB) + + /* wait until fixed clock in use */ + or rTMP, rSLP1, $0 +wait_fixclock: + bnez rTMP, wait_fixclock + addiu rTMP, rTMP, -1 + + /* set new PLL values */ + sync + sw $a1, 0(rCTR) + sw $a2, 4(rCTR) + sync + + /* wait for value takeover */ + or rTMP, rSLP2, $0 +wait_pll: + bnez rTMP, wait_pll + addiu rTMP, rTMP, -1 + + /* switch back to PLL clock*/ + nor rMSK, rMSK, $0 + sync + lw rTMP, 0(rGLB) + sync + and rTMP, rTMP, rMSK + sync + sw rTMP, 0(rGLB) + + /* wait until PLL clock in use */ + or rTMP, rSLP3, $0 +wait_pllclock: + bnez rTMP, wait_pllclock + addiu rTMP, rTMP, -1 + + /* restore branch prediction */ + mtc0 rCP0, CP0_CONFIG, 7 + jr $ra + nop + +#else /* !CONFIG_RTL839X */ + + jr $ra + nop + +#endif + +.end rtcl_839x_dram_set_rate + +/* + * End marker. Do not delete. + */ + .word RTL_SRAM_MARKER +.globl rtcl_839x_dram_size +rtcl_839x_dram_size: + .word .-rtcl_839x_dram_start + diff --git a/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl83xx.c b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl83xx.c new file mode 100644 index 0000000000..c3eb270f6e --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl83xx.c @@ -0,0 +1,763 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Realtek RTL83XX clock driver + * Copyright (C) 2022 Markus Stockhausen + * + * This driver provides basic clock support for the central core clock unit (CCU) and its PLLs + * inside the RTL838X and RTL8389X SOC. Currently CPU, memory and LXB clock information can be + * accessed. To make use of the driver add the following devices and configurations at the + * appropriate locations to the DT. + * + * #include + * + * sram0: sram@9f000000 { + * compatible = "mmio-sram"; + * reg = <0x9f000000 0x18000>; + * #address-cells = <1>; + * #size-cells = <1>; + * ranges = <0 0x9f000000 0x18000>; + * }; + * + * osc: oscillator { + * compatible = "fixed-clock"; + * #clock-cells = <0>; + * clock-frequency = <25000000>; + * }; + * + * ccu: clock-controller { + * compatible = "realtek,rtl8380-clock"; + * #clock-cells = <1>; + * clocks = <&osc>; + * clock-names = "ref_clk"; + * }; + * + * + * The SRAM part is needed to be able to set clocks. When changing clocks the code must not run + * from DRAM. Otherwise system might freeze. Take care to adjust CCU compatibility, SRAM address + * and size to the target SOC device. Afterwards one can access/identify the clocks in the other + * DT devices with <&ccu CLK_CPU>, <&ccu CLK_MEM> or <&ccu CLK_LXB>. Additionally the clocks can + * be used inside the kernel with + * + * cpu_clk = clk_get(NULL, "cpu_clk"); + * mem_clk = clk_get(NULL, "mem_clk"); + * lxb_clk = clk_get(NULL, "lxb_clk"); + * + * This driver can be directly used by the DT based cpufreq driver (CONFIG_CPUFREQ_DT) if CPU + * references the right clock and sane operating points (OPP) are provided. E.g. + * + * cpu@0 { + * compatible = "mips,mips4KEc"; + * reg = <0>; + * clocks = <&ccu CLK_CPU>; + * operating-points-v2 = <&cpu_opp_table>; + * }; + * + * cpu_opp_table: opp-table-0 { + * compatible = "operating-points-v2"; + * opp-shared; + * opp00 { + * opp-hz = /bits/ 64 <425000000>; + * }; + * ... + * } + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-rtl83xx.h" + +#define read_sw(reg) ioread32(((void *)RTL_SW_CORE_BASE) + reg) +#define read_soc(reg) ioread32(((void *)RTL_SOC_BASE) + reg) + +#define write_sw(val, reg) iowrite32(val, ((void *)RTL_SW_CORE_BASE) + reg) +#define write_soc(val, reg) iowrite32(val, ((void *)RTL_SOC_BASE) + reg) + +/* + * some hardware specific definitions + */ + +#define SOC_RTL838X 0 +#define SOC_RTL839X 1 +#define SOC_COUNT 2 + +#define MEM_DDR1 1 +#define MEM_DDR2 2 +#define MEM_DDR3 3 + +#define REG_CTRL0 0 +#define REG_CTRL1 1 +#define REG_COUNT 2 + +#define OSC_RATE 25000000 + +static const int rtcl_regs[SOC_COUNT][REG_COUNT][CLK_COUNT] = { + { + { RTL838X_PLL_CPU_CTRL0, RTL838X_PLL_MEM_CTRL0, RTL838X_PLL_LXB_CTRL0 }, + { RTL838X_PLL_CPU_CTRL1, RTL838X_PLL_MEM_CTRL1, RTL838X_PLL_LXB_CTRL1 }, + }, { + { RTL839X_PLL_CPU_CTRL0, RTL839X_PLL_MEM_CTRL0, RTL839X_PLL_LXB_CTRL0 }, + { RTL839X_PLL_CPU_CTRL1, RTL839X_PLL_MEM_CTRL1, RTL839X_PLL_LXB_CTRL1 }, + } +}; + +#define RTCL_REG_SET(_rate, _ctrl0, _ctrl1) \ + { \ + .rate = _rate, \ + .ctrl0 = _ctrl0, \ + .ctrl1 = _ctrl1, \ + } + +struct rtcl_reg_set { + unsigned int rate; + unsigned int ctrl0; + unsigned int ctrl1; +}; + +/* + * The following configuration tables are valid operation points for their corresponding PLLs. + * The magic numbers are precalculated mulitpliers and dividers to keep the driver simple. They + * also provide rates outside the allowed physical specifications. E.g. DDR3 memory has a lower + * limit of 303 MHz or the CPU might get unstable if set to anything above its startup frequency. + * Additionally the Realtek SOCs tend to expect CPU speed > MEM speed > LXB speed. The caller or + * DT configuration must take care that only valid operating points are selected. + */ + +static const struct rtcl_reg_set rtcl_838x_cpu_reg_set[] = { + RTCL_REG_SET(300000000, 0x045c8, 0x1414530e), + RTCL_REG_SET(325000000, 0x04648, 0x1414530e), + RTCL_REG_SET(350000000, 0x046c8, 0x1414530e), + RTCL_REG_SET(375000000, 0x04748, 0x1414530e), + RTCL_REG_SET(400000000, 0x045c8, 0x0c14530e), + RTCL_REG_SET(425000000, 0x04628, 0x0c14530e), + RTCL_REG_SET(450000000, 0x04688, 0x0c14530e), + RTCL_REG_SET(475000000, 0x046e8, 0x0c14530e), + RTCL_REG_SET(500000000, 0x04748, 0x0c14530e), + RTCL_REG_SET(525000000, 0x047a8, 0x0c14530e), + RTCL_REG_SET(550000000, 0x04808, 0x0c14530e), + RTCL_REG_SET(575000000, 0x04868, 0x0c14530e), + RTCL_REG_SET(600000000, 0x048c8, 0x0c14530e), + RTCL_REG_SET(625000000, 0x04928, 0x0c14530e) +}; + +static const struct rtcl_reg_set rtcl_838x_mem_reg_set[] = { + RTCL_REG_SET(200000000, 0x041bc, 0x14018C80), + RTCL_REG_SET(225000000, 0x0417c, 0x0c018C80), + RTCL_REG_SET(250000000, 0x041ac, 0x0c018C80), + RTCL_REG_SET(275000000, 0x0412c, 0x04018C80), + RTCL_REG_SET(300000000, 0x0414c, 0x04018c80), + RTCL_REG_SET(325000000, 0x0416c, 0x04018c80), + RTCL_REG_SET(350000000, 0x0418c, 0x04018c80), + RTCL_REG_SET(375000000, 0x041ac, 0x04018c80) +}; + +static const struct rtcl_reg_set rtcl_838x_lxb_reg_set[] = { + RTCL_REG_SET(100000000, 0x043c8, 0x001ad30e), + RTCL_REG_SET(125000000, 0x043c8, 0x001ad30e), + RTCL_REG_SET(150000000, 0x04508, 0x1c1ad30e), + RTCL_REG_SET(175000000, 0x04508, 0x1c1ad30e), + RTCL_REG_SET(200000000, 0x047c8, 0x001ad30e) +}; + +static const struct rtcl_reg_set rtcl_839x_cpu_reg_set[] = { + RTCL_REG_SET(400000000, 0x0414c, 0x00000005), + RTCL_REG_SET(425000000, 0x041ec, 0x00000006), + RTCL_REG_SET(450000000, 0x0417c, 0x00000005), + RTCL_REG_SET(475000000, 0x0422c, 0x00000006), + RTCL_REG_SET(500000000, 0x041ac, 0x00000005), + RTCL_REG_SET(525000000, 0x0426c, 0x00000006), + RTCL_REG_SET(550000000, 0x0412c, 0x00000004), + RTCL_REG_SET(575000000, 0x042ac, 0x00000006), + RTCL_REG_SET(600000000, 0x0414c, 0x00000004), + RTCL_REG_SET(625000000, 0x042ec, 0x00000006), + RTCL_REG_SET(650000000, 0x0416c, 0x00000004), + RTCL_REG_SET(675000000, 0x04324, 0x00000006), + RTCL_REG_SET(700000000, 0x0418c, 0x00000004), + RTCL_REG_SET(725000000, 0x0436c, 0x00000006), + RTCL_REG_SET(750000000, 0x0438c, 0x00000006), + RTCL_REG_SET(775000000, 0x043ac, 0x00000006), + RTCL_REG_SET(800000000, 0x043cc, 0x00000006), + RTCL_REG_SET(825000000, 0x043ec, 0x00000006), + RTCL_REG_SET(850000000, 0x0440c, 0x00000006) +}; + +static const struct rtcl_reg_set rtcl_839x_mem_reg_set[] = { + RTCL_REG_SET(100000000, 0x041cc, 0x00000000), + RTCL_REG_SET(125000000, 0x041ac, 0x00000007), + RTCL_REG_SET(150000000, 0x0414c, 0x00000006), + RTCL_REG_SET(175000000, 0x0418c, 0x00000006), + RTCL_REG_SET(200000000, 0x041cc, 0x00000006), + RTCL_REG_SET(225000000, 0x0417c, 0x00000005), + RTCL_REG_SET(250000000, 0x041ac, 0x00000005), + RTCL_REG_SET(275000000, 0x0412c, 0x00000004), + RTCL_REG_SET(300000000, 0x0414c, 0x00000004), + RTCL_REG_SET(325000000, 0x0416c, 0x00000004), + RTCL_REG_SET(350000000, 0x0418c, 0x00000004), + RTCL_REG_SET(375000000, 0x041ac, 0x00000004), + RTCL_REG_SET(400000000, 0x041cc, 0x00000004) +}; + +static const struct rtcl_reg_set rtcl_839x_lxb_reg_set[] = { + RTCL_REG_SET(50000000, 0x1414c, 0x00000003), + RTCL_REG_SET(100000000, 0x0814c, 0x00000003), + RTCL_REG_SET(150000000, 0x0414c, 0x00000003), + RTCL_REG_SET(200000000, 0x0414c, 0x00000007) +}; + +struct rtcl_rtab_set { + int count; + const struct rtcl_reg_set *rset; +}; + +#define RTCL_RTAB_SET(_rset) \ + { \ + .count = ARRAY_SIZE(_rset), \ + .rset = _rset, \ + } + +static const struct rtcl_rtab_set rtcl_rtab_set[SOC_COUNT][CLK_COUNT] = { + { + RTCL_RTAB_SET(rtcl_838x_cpu_reg_set), + RTCL_RTAB_SET(rtcl_838x_mem_reg_set), + RTCL_RTAB_SET(rtcl_838x_lxb_reg_set) + }, { + RTCL_RTAB_SET(rtcl_839x_cpu_reg_set), + RTCL_RTAB_SET(rtcl_839x_mem_reg_set), + RTCL_RTAB_SET(rtcl_839x_lxb_reg_set) + } +}; + +#define RTCL_ROUND_SET(_min, _max, _step) \ + { \ + .min = _min, \ + .max = _max, \ + .step = _step, \ + } + +struct rtcl_round_set { + unsigned long min; + unsigned long max; + unsigned long step; +}; + +static const struct rtcl_round_set rtcl_round_set[SOC_COUNT][CLK_COUNT] = { + { + RTCL_ROUND_SET(300000000, 625000000, 25000000), + RTCL_ROUND_SET(200000000, 375000000, 25000000), + RTCL_ROUND_SET(100000000, 200000000, 25000000) + }, { + RTCL_ROUND_SET(400000000, 850000000, 25000000), + RTCL_ROUND_SET(100000000, 400000000, 25000000), + RTCL_ROUND_SET(50000000, 200000000, 50000000) + } +}; + +static const int rtcl_divn3[] = { 2, 3, 4, 6 }; +static const int rtcl_xdiv[] = { 2, 4, 2 }; + +/* + * module data structures + */ + +#define RTCL_CLK_INFO(_idx, _name, _pname, _dname) \ + { \ + .idx = _idx, \ + .name = _name, \ + .parent_name = _pname, \ + .display_name = _dname, \ + } + +struct rtcl_clk_info { + unsigned int idx; + const char *name; + const char *parent_name; + const char *display_name; +}; + +struct rtcl_clk { + struct clk_hw hw; + unsigned int idx; + unsigned long min; + unsigned long max; + unsigned long rate; + unsigned long startup; +}; + +static const struct rtcl_clk_info rtcl_clk_info[CLK_COUNT] = { + RTCL_CLK_INFO(CLK_CPU, "cpu_clk", "ref_clk", "CPU"), + RTCL_CLK_INFO(CLK_MEM, "mem_clk", "ref_clk", "MEM"), + RTCL_CLK_INFO(CLK_LXB, "lxb_clk", "ref_clk", "LXB") +}; + +struct rtcl_dram { + int type; + int buswidth; +}; + +struct rtcl_sram { + int *pmark; + unsigned long vbase; +}; + +struct rtcl_ccu { + spinlock_t lock; + unsigned int soc; + struct rtcl_sram sram; + struct rtcl_dram dram; + struct device_node *np; + struct platform_device *pdev; + struct rtcl_clk clks[CLK_COUNT]; +}; + +struct rtcl_ccu *rtcl_ccu; + +#define rtcl_hw_to_clk(_hw) container_of(_hw, struct rtcl_clk, hw) + +/* + * SRAM relocatable assembler functions. The dram() parts point to normal kernel memory while + * the sram() parts are the same functions but relocated to SRAM. + */ + +extern void rtcl_838x_dram_start(void); +extern int rtcl_838x_dram_size; + +extern void (*rtcl_838x_dram_set_rate)(int clk_idx, int ctrl0, int ctrl1); +static void (*rtcl_838x_sram_set_rate)(int clk_idx, int ctrl0, int ctrl1); + +extern void rtcl_839x_dram_start(void); +extern int rtcl_839x_dram_size; + +extern void (*rtcl_839x_dram_set_rate)(int clk_idx, int ctrl0, int ctrl1); +static void (*rtcl_839x_sram_set_rate)(int clk_idx, int ctrl0, int ctrl1); + +/* + * clock setter/getter functions + */ + +static unsigned long rtcl_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct rtcl_clk *clk = rtcl_hw_to_clk(hw); + unsigned int ctrl0, ctrl1, div1, div2, cmu_ncode_in; + unsigned int cmu_sel_prediv, cmu_sel_div4, cmu_divn2, cmu_divn2_selb, cmu_divn3_sel; + + if ((clk->idx >= CLK_COUNT) || (!rtcl_ccu) || (rtcl_ccu->soc >= SOC_COUNT)) + return 0; + + ctrl0 = read_sw(rtcl_regs[rtcl_ccu->soc][REG_CTRL0][clk->idx]); + ctrl1 = read_sw(rtcl_regs[rtcl_ccu->soc][REG_CTRL1][clk->idx]); + + cmu_sel_prediv = 1 << RTL_PLL_CTRL0_CMU_SEL_PREDIV(ctrl0); + cmu_sel_div4 = RTL_PLL_CTRL0_CMU_SEL_DIV4(ctrl0) ? 4 : 1; + cmu_ncode_in = RTL_PLL_CTRL0_CMU_NCODE_IN(ctrl0) + 4; + cmu_divn2 = RTL_PLL_CTRL0_CMU_DIVN2(ctrl0) + 4; + + switch (rtcl_ccu->soc) { + case SOC_RTL838X: + cmu_divn2_selb = RTL838X_PLL_CTRL1_CMU_DIVN2_SELB(ctrl1); + cmu_divn3_sel = rtcl_divn3[RTL838X_PLL_CTRL1_CMU_DIVN3_SEL(ctrl1)]; + break; + case SOC_RTL839X: + cmu_divn2_selb = RTL839X_PLL_CTRL1_CMU_DIVN2_SELB(ctrl1); + cmu_divn3_sel = rtcl_divn3[RTL839X_PLL_CTRL1_CMU_DIVN3_SEL(ctrl1)]; + break; + } + div1 = cmu_divn2_selb ? cmu_divn3_sel : cmu_divn2; + div2 = rtcl_xdiv[clk->idx]; + + return (((parent_rate / 16) * cmu_ncode_in) / (div1 * div2)) * + cmu_sel_prediv * cmu_sel_div4 * 16; +} + +static int rtcl_838x_set_rate(int clk_idx, const struct rtcl_reg_set *reg) +{ + unsigned long irqflags; +/* + * Runtime of this function (including locking) + * CPU: up to 14000 cycles / up to 56 us at 250 MHz (half default speed) + */ + spin_lock_irqsave(&rtcl_ccu->lock, irqflags); + rtcl_838x_sram_set_rate(clk_idx, reg->ctrl0, reg->ctrl1); + spin_unlock_irqrestore(&rtcl_ccu->lock, irqflags); + + return 0; +} + +static int rtcl_839x_set_rate(int clk_idx, const struct rtcl_reg_set *reg) +{ + unsigned long vpflags; + unsigned long irqflags; +/* + * Runtime of this function (including locking) + * CPU: up to 31000 cycles / up to 89 us at 350 MHz (half default speed) + */ + spin_lock_irqsave(&rtcl_ccu->lock, irqflags); + vpflags = dvpe(); + rtcl_839x_sram_set_rate(clk_idx, reg->ctrl0, reg->ctrl1); + evpe(vpflags); + spin_unlock_irqrestore(&rtcl_ccu->lock, irqflags); + + return 0; +} + +static int rtcl_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) +{ + int tab_idx; + struct rtcl_clk *clk = rtcl_hw_to_clk(hw); + const struct rtcl_rtab_set *rtab = &rtcl_rtab_set[rtcl_ccu->soc][clk->idx]; + const struct rtcl_round_set *round = &rtcl_round_set[rtcl_ccu->soc][clk->idx]; + + if ((parent_rate != OSC_RATE) || (!rtcl_ccu->sram.vbase)) + return -EINVAL; +/* + * Currently we do not know if SRAM is stable on these devices. Maybe someone changes memory in + * this region and does not care about proper allocation. So check if something might go wrong. + */ + if (unlikely(*rtcl_ccu->sram.pmark != RTL_SRAM_MARKER)) { + dev_err(&rtcl_ccu->pdev->dev, "SRAM code lost\n"); + return -EINVAL; + } + + tab_idx = (rate - round->min) / round->step; + if ((tab_idx < 0) || (tab_idx >= rtab->count) || (rtab->rset[tab_idx].rate != rate)) + return -EINVAL; + + rtcl_ccu->clks[clk->idx].rate = rate; + + switch (rtcl_ccu->soc) { + case SOC_RTL838X: + return rtcl_838x_set_rate(clk->idx, &rtab->rset[tab_idx]); + case SOC_RTL839X: + return rtcl_839x_set_rate(clk->idx, &rtab->rset[tab_idx]); + } + + return -ENXIO; +} + +static long rtcl_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) +{ + struct rtcl_clk *clk = rtcl_hw_to_clk(hw); + unsigned long rrate = max(clk->min, min(clk->max, rate)); + const struct rtcl_round_set *round = &rtcl_round_set[rtcl_ccu->soc][clk->idx]; + + rrate = ((rrate + (round->step >> 1)) / round->step) * round->step; + rrate -= (rrate > clk->max) ? round->step : 0; + rrate += (rrate < clk->min) ? round->step : 0; + + return rrate; +} + +/* + * Initialization functions to register the CCU and its clocks + */ + +#define RTCL_SRAM_FUNC(SOC, PBASE, FN) ({ \ + rtcl_##SOC##_sram_##FN = ((void *)&rtcl_##SOC##_dram_##FN \ + - (void *)&rtcl_##SOC##_dram_start) \ + + (void *)PBASE; }) + +static const struct clk_ops rtcl_clk_ops = { + .set_rate = rtcl_set_rate, + .round_rate = rtcl_round_rate, + .recalc_rate = rtcl_recalc_rate, +}; + +static int rtcl_ccu_create(struct device_node *np) +{ + int soc; + + if (of_device_is_compatible(np, "realtek,rtl8380-clock")) + soc = SOC_RTL838X; + else if (of_device_is_compatible(np, "realtek,rtl8390-clock")) + soc = SOC_RTL839X; + else + return -ENXIO; + + rtcl_ccu = kzalloc(sizeof(*rtcl_ccu), GFP_KERNEL); + if (IS_ERR(rtcl_ccu)) + return -ENOMEM; + + rtcl_ccu->np = np; + rtcl_ccu->soc = soc; + rtcl_ccu->dram.type = RTL_MC_MCR_DRAMTYPE(read_soc(RTL_MC_MCR)); + rtcl_ccu->dram.buswidth = RTL_MC_DCR_BUSWIDTH(read_soc(RTL_MC_DCR)); + spin_lock_init(&rtcl_ccu->lock); + + return 0; +} + +int rtcl_register_clkhw(int clk_idx) +{ + int ret; + struct clk *clk; + struct clk_init_data hw_init = { }; + struct rtcl_clk *rclk = &rtcl_ccu->clks[clk_idx]; + struct clk_parent_data parent_data = { .fw_name = rtcl_clk_info[clk_idx].parent_name }; + + rclk->idx = clk_idx; + rclk->hw.init = &hw_init; + + hw_init.num_parents = 1; + hw_init.ops = &rtcl_clk_ops; + hw_init.parent_data = &parent_data; + hw_init.name = rtcl_clk_info[clk_idx].name; + + ret = of_clk_hw_register(rtcl_ccu->np, &rclk->hw); + if (ret) + return ret; + + clk_hw_register_clkdev(&rclk->hw, rtcl_clk_info[clk_idx].name, NULL); + + clk = clk_get(NULL, rtcl_clk_info[clk_idx].name); + rclk->startup = clk_get_rate(clk); + clk_put(clk); + + switch (clk_idx) { + case CLK_CPU: + rclk->min = rtcl_round_set[rtcl_ccu->soc][clk_idx].min; + rclk->max = rtcl_round_set[rtcl_ccu->soc][clk_idx].max; + break; + default: +/* + * TODO: This driver supports PLL reclocking and nothing else. Additional required steps for non + * CPU PLLs are missing. E.g. if we want to change memory clocks the right way we must adapt a lot + * of other settings like MCR and DTRx timing registers (0xb80001000, 0xb8001008, ...) and initiate + * a DLL reset so that hardware operates in the allowed limits. This is far too complex without + * official support. Avoid this for now. + */ + rclk->min = rclk->max = rclk->startup; + break; + } + + return 0; +} + +static struct clk_hw *rtcl_get_clkhw(struct of_phandle_args *clkspec, void *prv) +{ + unsigned int idx = clkspec->args[0]; + + if (idx >= CLK_COUNT) { + pr_err("%s: Invalid index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } + + return &rtcl_ccu->clks[idx].hw; +} + +static int rtcl_ccu_register_clocks(void) +{ + int clk_idx, ret; + + for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) { + ret = rtcl_register_clkhw(clk_idx); + if (ret) { + pr_err("%s: Couldn't register %s clock\n", + __func__, rtcl_clk_info[clk_idx].display_name); + goto err_hw_unregister; + } + } + + ret = of_clk_add_hw_provider(rtcl_ccu->np, rtcl_get_clkhw, rtcl_ccu); + if (ret) { + pr_err("%s: Couldn't register clock provider of %s\n", + __func__, of_node_full_name(rtcl_ccu->np)); + goto err_hw_unregister; + } + + return 0; + +err_hw_unregister: + for (--clk_idx; clk_idx >= 0; --clk_idx) + clk_hw_unregister(&rtcl_ccu->clks[clk_idx].hw); + + return ret; +} + +int rtcl_init_sram(void) +{ + struct gen_pool *sram_pool; + phys_addr_t sram_pbase; + unsigned long sram_vbase; + struct device_node *node; + struct platform_device *pdev = NULL; + void *dram_start; + int dram_size; + const char *wrn = ", rate setting disabled.\n"; + + switch (rtcl_ccu->soc) { + case SOC_RTL838X: + dram_start = &rtcl_838x_dram_start; + dram_size = rtcl_838x_dram_size; + break; + case SOC_RTL839X: + dram_start = &rtcl_839x_dram_start; + dram_size = rtcl_839x_dram_size; + break; + default: + return -ENXIO; + } + + for_each_compatible_node(node, NULL, "mmio-sram") { + pdev = of_find_device_by_node(node); + if (pdev) { + of_node_put(node); + break; + } + } + + if (!pdev) { + dev_warn(&rtcl_ccu->pdev->dev, "no SRAM device found%s", wrn); + return -ENXIO; + } + + sram_pool = gen_pool_get(&pdev->dev, NULL); + if (!sram_pool) { + dev_warn(&rtcl_ccu->pdev->dev, "SRAM pool unavailable%s", wrn); + goto err_put_device; + } + + sram_vbase = gen_pool_alloc(sram_pool, dram_size); + if (!sram_vbase) { + dev_warn(&rtcl_ccu->pdev->dev, "can not allocate SRAM%s", wrn); + goto err_put_device; + } + + sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_vbase); + memcpy((void *)sram_pbase, dram_start, dram_size); + flush_icache_range((unsigned long)sram_pbase, (unsigned long)(sram_pbase + dram_size)); + + switch (rtcl_ccu->soc) { + case SOC_RTL838X: + RTCL_SRAM_FUNC(838x, sram_pbase, set_rate); + break; + case SOC_RTL839X: + RTCL_SRAM_FUNC(839x, sram_pbase, set_rate); + break; + } + + rtcl_ccu->sram.pmark = (int *)((void *)sram_pbase + (dram_size - 4)); + rtcl_ccu->sram.vbase = sram_vbase; + + return 0; + +err_put_device: + put_device(&pdev->dev); + + return -ENXIO; +} + +void rtcl_ccu_log_early(void) +{ + int clk_idx; + char meminfo[80], clkinfo[255], msg[255] = "rtl83xx-clk: initialized"; + + sprintf(meminfo, " (%d Bit DDR%d)", rtcl_ccu->dram.buswidth, rtcl_ccu->dram.type); + for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) { + sprintf(clkinfo, ", %s %lu MHz", rtcl_clk_info[clk_idx].display_name, + rtcl_ccu->clks[clk_idx].startup / 1000000); + if (clk_idx == CLK_MEM) + strcat(clkinfo, meminfo); + strcat(msg, clkinfo); + } + pr_info("%s\n", msg); +} + +void rtcl_ccu_log_late(void) +{ + int clk_idx; + struct rtcl_clk *rclk; + bool overclock = false; + char clkinfo[80], msg[255] = "rate setting enabled"; + + for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) { + rclk = &rtcl_ccu->clks[clk_idx]; + overclock |= rclk->max > rclk->startup; + sprintf(clkinfo, ", %s %lu-%lu MHz", rtcl_clk_info[clk_idx].display_name, + rclk->min / 1000000, rclk->max / 1000000); + strcat(msg, clkinfo); + } + if (overclock) + strcat(msg, ", OVERCLOCK AT OWN RISK"); + + dev_info(&rtcl_ccu->pdev->dev, "%s\n", msg); +} + +/* + * Early registration: This module provides core startup clocks that are needed for generic SOC + * init and for further builtin devices (e.g. UART). Register asap via clock framework. + */ + +static void __init rtcl_probe_early(struct device_node *np) +{ + if (rtcl_ccu_create(np)) + return; + + if (rtcl_ccu_register_clocks()) + kfree(rtcl_ccu); + else + rtcl_ccu_log_early(); +} + +CLK_OF_DECLARE_DRIVER(rtl838x_clk, "realtek,rtl8380-clock", rtcl_probe_early); +CLK_OF_DECLARE_DRIVER(rtl839x_clk, "realtek,rtl8390-clock", rtcl_probe_early); + +/* + * Late registration: Finally register as normal platform driver. At this point we can make use + * of other modules like SRAM. + */ + +static const struct of_device_id rtcl_dt_ids[] = { + { .compatible = "realtek,rtl8380-clock" }, + { .compatible = "realtek,rtl8390-clock" }, + {} +}; + +static int rtcl_probe_late(struct platform_device *pdev) +{ + int ret; + + if (!rtcl_ccu) { + dev_err(&pdev->dev, "early initialization not run"); + return -ENXIO; + } + rtcl_ccu->pdev = pdev; + ret = rtcl_init_sram(); + if (ret) + return ret; + + rtcl_ccu_log_late(); + + return 0; +} + +static struct platform_driver rtcl_platform_driver = { + .driver = { + .name = "rtl83xx-clk", + .of_match_table = rtcl_dt_ids, + }, + .probe = rtcl_probe_late, +}; + +static int __init rtcl_init_subsys(void) +{ + return platform_driver_register(&rtcl_platform_driver); +} + +/* + * The driver does not know when SRAM module has finally loaded. With an arch_initcall() we might + * overtake SRAM initialization. Be polite and give the system a little more time. + */ + +subsys_initcall(rtcl_init_subsys); diff --git a/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl83xx.h b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl83xx.h new file mode 100644 index 0000000000..a69b16b475 --- /dev/null +++ b/target/linux/realtek/files-5.10/drivers/clk/realtek/clk-rtl83xx.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Realtek RTL83XX clock headers + * Copyright (C) 2022 Markus Stockhausen + */ + +/* + * Switch registers (e.g. PLL) + */ + +#define RTL_SW_CORE_BASE (0xbb000000) + +#define RTL838X_PLL_GLB_CTRL (0x0fc0) +#define RTL838X_PLL_CPU_CTRL0 (0x0fc4) +#define RTL838X_PLL_CPU_CTRL1 (0x0fc8) +#define RTL838X_PLL_LXB_CTRL0 (0x0fd0) +#define RTL838X_PLL_LXB_CTRL1 (0x0fd4) +#define RTL838X_PLL_MEM_CTRL0 (0x0fdc) +#define RTL838X_PLL_MEM_CTRL1 (0x0fe0) + +#define RTL839X_PLL_GLB_CTRL (0x0024) +#define RTL839X_PLL_CPU_CTRL0 (0x0028) +#define RTL839X_PLL_CPU_CTRL1 (0x002c) +#define RTL839X_PLL_LXB_CTRL0 (0x0038) +#define RTL839X_PLL_LXB_CTRL1 (0x003c) +#define RTL839X_PLL_MEM_CTRL0 (0x0048) +#define RTL839X_PLL_MEM_CTRL1 (0x004c) + +#define RTL_PLL_CTRL0_CMU_SEL_PREDIV(v) (((v) >> 0) & 0x3) +#define RTL_PLL_CTRL0_CMU_SEL_DIV4(v) (((v) >> 2) & 0x1) +#define RTL_PLL_CTRL0_CMU_NCODE_IN(v) (((v) >> 4) & 0xff) +#define RTL_PLL_CTRL0_CMU_DIVN2(v) (((v) >> 12) & 0xff) + +#define RTL838X_GLB_CTRL_EN_CPU_PLL_MASK (1 << 0) +#define RTL838X_GLB_CTRL_EN_LXB_PLL_MASK (1 << 1) +#define RTL838X_GLB_CTRL_EN_MEM_PLL_MASK (1 << 2) +#define RTL838X_GLB_CTRL_CPU_PLL_READY_MASK (1 << 8) +#define RTL838X_GLB_CTRL_LXB_PLL_READY_MASK (1 << 9) +#define RTL838X_GLB_CTRL_MEM_PLL_READY_MASK (1 << 10) +#define RTL838X_GLB_CTRL_CPU_PLL_SC_MUX_MASK (1 << 12) + +#define RTL838X_PLL_CTRL1_CMU_DIVN2_SELB(v) (((v) >> 26) & 0x1) +#define RTL838X_PLL_CTRL1_CMU_DIVN3_SEL(v) (((v) >> 27) & 0x3) + +#define RTL839X_GLB_CTRL_CPU_CLKSEL_MASK (1 << 11) +#define RTL839X_GLB_CTRL_MEM_CLKSEL_MASK (1 << 12) +#define RTL839X_GLB_CTRL_LXB_CLKSEL_MASK (1 << 13) + +#define RTL839X_PLL_CTRL1_CMU_DIVN2_SELB(v) (((v) >> 2) & 0x1) +#define RTL839X_PLL_CTRL1_CMU_DIVN3_SEL(v) (((v) >> 0) & 0x3) + +/* + * Core registers (e.g. memory controller) + */ + +#define RTL_SOC_BASE (0xB8000000) + +#define RTL_MC_MCR (0x1000) +#define RTL_MC_DCR (0x1004) +#define RTL_MC_DTR0 (0x1008) +#define RTL_MC_DTR1 (0x100c) +#define RTL_MC_DTR2 (0x1010) +#define RTL_MC_DMCR (0x101c) +#define RTL_MC_DACCR (0x1500) +#define RTL_MC_DCDR (0x1060) + +#define RTL_MC_MCR_DRAMTYPE(v) ((((v) >> 28) & 0xf) + 1) +#define RTL_MC_DCR_BUSWIDTH(v) (8 << (((v) >> 24) & 0xf)) + +/* + * Other stuff + */ + +#define RTL_SRAM_MARKER (0x5eaf00d5) +#define RTL_SRAM_BASE (0x9f000000) diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c index fd6019ec62..2a60f61c95 100644 --- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c @@ -317,6 +317,9 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) phy_interface_t interface; u32 led_set; + if (!of_device_is_available(dn)) + continue; + if (of_property_read_u32(dn, "reg", &pn)) continue; diff --git a/target/linux/realtek/files-5.10/include/dt-bindings/clock/rtl83xx-clk.h b/target/linux/realtek/files-5.10/include/dt-bindings/clock/rtl83xx-clk.h new file mode 100644 index 0000000000..3937052cc5 --- /dev/null +++ b/target/linux/realtek/files-5.10/include/dt-bindings/clock/rtl83xx-clk.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022 Markus Stockhausen + * + * RTL83XX clock indices + */ +#ifndef __DT_BINDINGS_CLOCK_RTL83XX_H +#define __DT_BINDINGS_CLOCK_RTL83XX_H + +#define CLK_CPU 0 +#define CLK_MEM 1 +#define CLK_LXB 2 +#define CLK_COUNT 3 + +#endif /* __DT_BINDINGS_CLOCK_RTL83XX_H */ diff --git a/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch b/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch index 373bcff421..476afba6a8 100644 --- a/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch +++ b/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch @@ -10,7 +10,7 @@ platform-$(CONFIG_SGI_IP28) += sgi-ip22/ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -1037,8 +1037,58 @@ config NLM_XLP_BOARD +@@ -1037,8 +1037,62 @@ config NLM_XLP_BOARD This board is based on Netlogic XLP Processor. Say Y here if you have a XLP based board. @@ -38,14 +38,18 @@ +config RTL838X + bool "Realtek RTL838X based platforms" + depends on RTL83XX ++ select CPU_SUPPORTS_CPUFREQ + select CSRC_R4K + select CEVT_R4K ++ select MIPS_EXTERNAL_TIMER + +config RTL839X + bool "Realtek RTL839X based platforms" + depends on RTL83XX ++ select CPU_SUPPORTS_CPUFREQ + select CSRC_R4K + select CEVT_R4K ++ select MIPS_EXTERNAL_TIMER + select SYS_SUPPORTS_MULTITHREADING + +config RTL930X diff --git a/target/linux/realtek/patches-5.10/318-add-rtl83xx-clk-support.patch b/target/linux/realtek/patches-5.10/318-add-rtl83xx-clk-support.patch new file mode 100644 index 0000000000..5215a75087 --- /dev/null +++ b/target/linux/realtek/patches-5.10/318-add-rtl83xx-clk-support.patch @@ -0,0 +1,26 @@ +diff -rpN x/drivers/clk/Kconfig y/drivers/clk/Kconfig +*** x/drivers/clk/Kconfig 2022-07-29 14:28:59.704481188 +0200 +--- y/drivers/clk/Kconfig 2022-07-29 14:29:56.886053322 +0200 +*************** source "drivers/clk/mediatek/Kconfig" +*** 372,377 **** +--- 372,378 ---- + source "drivers/clk/meson/Kconfig" + source "drivers/clk/mvebu/Kconfig" + source "drivers/clk/qcom/Kconfig" ++ source "drivers/clk/realtek/Kconfig" + source "drivers/clk/renesas/Kconfig" + source "drivers/clk/rockchip/Kconfig" + source "drivers/clk/samsung/Kconfig" +diff -rpN x/drivers/clk/Makefile y/drivers/clk/Makefile +*** x/drivers/clk/Makefile 2022-07-29 13:34:36.638231518 +0200 +--- y/drivers/clk/Makefile 2022-07-29 13:34:19.105060958 +0200 +*************** obj-$(CONFIG_COMMON_CLK_NXP) += nxp/ +*** 100,105 **** +--- 100,106 ---- + obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ + obj-$(CONFIG_COMMON_CLK_PXA) += pxa/ + obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ ++ obj-$(CONFIG_COMMON_CLK_REALTEK) += realtek/ + obj-y += renesas/ + obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ + obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ diff --git a/target/linux/realtek/rtl838x/config-5.10 b/target/linux/realtek/rtl838x/config-5.10 index 6b90b280c9..c45f10dee0 100644 --- a/target/linux/realtek/rtl838x/config-5.10 +++ b/target/linux/realtek/rtl838x/config-5.10 @@ -6,6 +6,7 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BMIPS_CPUFREQ is not set CONFIG_CEVT_R4K=y CONFIG_CEVT_RTL9300=y CONFIG_CLKDEV_LOOKUP=y @@ -13,9 +14,24 @@ CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK_BOSTON=y +CONFIG_COMMON_CLK_REALTEK=y +CONFIG_COMMON_CLK_RTL83XX=y CONFIG_COMPAT_32BIT_TIME=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_GENERIC_DUMP_TLB=y CONFIG_CPU_HAS_DIEI=y CONFIG_CPU_HAS_PREFETCH=y @@ -28,6 +44,7 @@ CONFIG_CPU_MIPSR2=y CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y CONFIG_CPU_R4K_CACHE_TLB=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_CPUFREQ=y CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_CPU_SUPPORTS_MSA=y CONFIG_CRYPTO_BLAKE2S=y @@ -121,6 +138,7 @@ CONFIG_MIPS_CLOCK_VSYSCALL=y # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set CONFIG_MIPS_CMDLINE_FROM_DTB=y # CONFIG_MIPS_ELF_APPENDED_DTB is not set +CONFIG_MIPS_EXTERNAL_TIMER=y CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_MIPS_LD_CAN_LINK_VDSO=y # CONFIG_MIPS_NO_APPENDED_DTB is not set @@ -164,6 +182,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHYLINK=y CONFIG_PINCTRL=y +CONFIG_PM_OPP=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_SYSCON=y @@ -186,6 +205,7 @@ CONFIG_SFP=y CONFIG_SPI=y CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y +CONFIG_SRAM=y CONFIG_SRCU=y CONFIG_SWPHY=y CONFIG_SYSCTL_EXCEPTION_TRACE=y diff --git a/target/linux/realtek/rtl839x/config-5.10 b/target/linux/realtek/rtl839x/config-5.10 index 91594062db..c685a3f24b 100644 --- a/target/linux/realtek/rtl839x/config-5.10 +++ b/target/linux/realtek/rtl839x/config-5.10 @@ -6,6 +6,7 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BMIPS_CPUFREQ is not set CONFIG_CEVT_R4K=y CONFIG_CEVT_RTL9300=y CONFIG_CLKDEV_LOOKUP=y @@ -13,9 +14,24 @@ CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK_BOSTON=y +CONFIG_COMMON_CLK_REALTEK=y +CONFIG_COMMON_CLK_RTL83XX=y CONFIG_COMPAT_32BIT_TIME=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_GENERIC_DUMP_TLB=y CONFIG_CPU_HAS_DIEI=y CONFIG_CPU_HAS_PREFETCH=y @@ -28,6 +44,7 @@ CONFIG_CPU_MIPSR2=y CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y CONFIG_CPU_R4K_CACHE_TLB=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_CPUFREQ=y CONFIG_CPU_SUPPORTS_HIGHMEM=y CONFIG_CPU_SUPPORTS_MSA=y CONFIG_CRYPTO_BLAKE2S=y @@ -118,6 +135,7 @@ CONFIG_MIPS_CLOCK_VSYSCALL=y # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set CONFIG_MIPS_CMDLINE_FROM_DTB=y # CONFIG_MIPS_ELF_APPENDED_DTB is not set +CONFIG_MIPS_EXTERNAL_TIMER=y CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_MIPS_LD_CAN_LINK_VDSO=y # CONFIG_MIPS_NO_APPENDED_DTB is not set @@ -162,6 +180,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHYLINK=y CONFIG_PINCTRL=y +CONFIG_PM_OPP=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_SYSCON=y @@ -184,6 +203,7 @@ CONFIG_SFP=y CONFIG_SPI=y CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y +CONFIG_SRAM=y CONFIG_SRCU=y CONFIG_SWPHY=y CONFIG_SYSCTL_EXCEPTION_TRACE=y diff --git a/toolchain/gcc/Config.version b/toolchain/gcc/Config.version index 1caa51a291..a909979cf6 100644 --- a/toolchain/gcc/Config.version +++ b/toolchain/gcc/Config.version @@ -14,5 +14,5 @@ config GCC_VERSION string default "8.4.0" if GCC_VERSION_8 default "10.3.0" if GCC_VERSION_10 - default "12.1.0" if GCC_VERSION_12 + default "12.2.0" if GCC_VERSION_12 default "11.3.0" diff --git a/toolchain/gcc/common.mk b/toolchain/gcc/common.mk index 926418f4a7..f116af7e1a 100644 --- a/toolchain/gcc/common.mk +++ b/toolchain/gcc/common.mk @@ -40,8 +40,8 @@ ifeq ($(PKG_VERSION),11.3.0) PKG_HASH:=b47cf2818691f5b1e21df2bb38c795fac2cfbd640ede2d0a5e1c89e338a3ac39 endif -ifeq ($(PKG_VERSION),12.1.0) - PKG_HASH:=62fd634889f31c02b64af2c468f064b47ad1ca78411c45abe6ac4b5f8dd19c7b +ifeq ($(PKG_VERSION),12.2.0) + PKG_HASH:=e549cf9cf3594a00e27b6589d4322d70e0720cdd213f39beb4181e06926230ff endif PATCH_DIR=../patches/$(GCC_VERSION) diff --git a/toolchain/gcc/patches/12.1.0/002-case_insensitive.patch b/toolchain/gcc/patches/12.2.0/002-case_insensitive.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/002-case_insensitive.patch rename to toolchain/gcc/patches/12.2.0/002-case_insensitive.patch diff --git a/toolchain/gcc/patches/12.1.0/010-documentation.patch b/toolchain/gcc/patches/12.2.0/010-documentation.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/010-documentation.patch rename to toolchain/gcc/patches/12.2.0/010-documentation.patch diff --git a/toolchain/gcc/patches/12.1.0/110-Fix-MIPS-PR-84790.patch b/toolchain/gcc/patches/12.2.0/110-Fix-MIPS-PR-84790.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/110-Fix-MIPS-PR-84790.patch rename to toolchain/gcc/patches/12.2.0/110-Fix-MIPS-PR-84790.patch diff --git a/toolchain/gcc/patches/12.1.0/230-musl_libssp.patch b/toolchain/gcc/patches/12.2.0/230-musl_libssp.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/230-musl_libssp.patch rename to toolchain/gcc/patches/12.2.0/230-musl_libssp.patch diff --git a/toolchain/gcc/patches/12.1.0/300-mips_Os_cpu_rtx_cost_model.patch b/toolchain/gcc/patches/12.2.0/300-mips_Os_cpu_rtx_cost_model.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/300-mips_Os_cpu_rtx_cost_model.patch rename to toolchain/gcc/patches/12.2.0/300-mips_Os_cpu_rtx_cost_model.patch diff --git a/toolchain/gcc/patches/12.1.0/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches/12.2.0/810-arm-softfloat-libgcc.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/810-arm-softfloat-libgcc.patch rename to toolchain/gcc/patches/12.2.0/810-arm-softfloat-libgcc.patch diff --git a/toolchain/gcc/patches/12.1.0/820-libgcc_pic.patch b/toolchain/gcc/patches/12.2.0/820-libgcc_pic.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/820-libgcc_pic.patch rename to toolchain/gcc/patches/12.2.0/820-libgcc_pic.patch diff --git a/toolchain/gcc/patches/12.1.0/840-armv4_pass_fix-v4bx_to_ld.patch b/toolchain/gcc/patches/12.2.0/840-armv4_pass_fix-v4bx_to_ld.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/840-armv4_pass_fix-v4bx_to_ld.patch rename to toolchain/gcc/patches/12.2.0/840-armv4_pass_fix-v4bx_to_ld.patch diff --git a/toolchain/gcc/patches/12.1.0/850-use_shared_libgcc.patch b/toolchain/gcc/patches/12.2.0/850-use_shared_libgcc.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/850-use_shared_libgcc.patch rename to toolchain/gcc/patches/12.2.0/850-use_shared_libgcc.patch diff --git a/toolchain/gcc/patches/12.1.0/851-libgcc_no_compat.patch b/toolchain/gcc/patches/12.2.0/851-libgcc_no_compat.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/851-libgcc_no_compat.patch rename to toolchain/gcc/patches/12.2.0/851-libgcc_no_compat.patch diff --git a/toolchain/gcc/patches/12.1.0/870-ppc_no_crtsavres.patch b/toolchain/gcc/patches/12.2.0/870-ppc_no_crtsavres.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/870-ppc_no_crtsavres.patch rename to toolchain/gcc/patches/12.2.0/870-ppc_no_crtsavres.patch diff --git a/toolchain/gcc/patches/12.1.0/881-no_tm_section.patch b/toolchain/gcc/patches/12.2.0/881-no_tm_section.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/881-no_tm_section.patch rename to toolchain/gcc/patches/12.2.0/881-no_tm_section.patch diff --git a/toolchain/gcc/patches/12.1.0/900-bad-mips16-crt.patch b/toolchain/gcc/patches/12.2.0/900-bad-mips16-crt.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/900-bad-mips16-crt.patch rename to toolchain/gcc/patches/12.2.0/900-bad-mips16-crt.patch diff --git a/toolchain/gcc/patches/12.1.0/910-mbsd_multi.patch b/toolchain/gcc/patches/12.2.0/910-mbsd_multi.patch similarity index 98% rename from toolchain/gcc/patches/12.1.0/910-mbsd_multi.patch rename to toolchain/gcc/patches/12.2.0/910-mbsd_multi.patch index 37aba93b94..4033c5b23b 100644 --- a/toolchain/gcc/patches/12.1.0/910-mbsd_multi.patch +++ b/toolchain/gcc/patches/12.2.0/910-mbsd_multi.patch @@ -134,7 +134,7 @@ Date: Tue Jul 31 00:52:27 2007 +0000 @opindex Wno-stack-protector --- a/gcc/opts.cc +++ b/gcc/opts.cc -@@ -2658,6 +2658,9 @@ common_handle_option (struct gcc_options +@@ -2692,6 +2692,9 @@ common_handle_option (struct gcc_options add_comma_separated_to_vector (&opts->x_flag_ignored_attributes, arg); break; diff --git a/toolchain/gcc/patches/12.1.0/920-specs_nonfatal_getenv.patch b/toolchain/gcc/patches/12.2.0/920-specs_nonfatal_getenv.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/920-specs_nonfatal_getenv.patch rename to toolchain/gcc/patches/12.2.0/920-specs_nonfatal_getenv.patch diff --git a/toolchain/gcc/patches/12.1.0/960-gotools-fix-compilation-when-making-cross-compiler.patch b/toolchain/gcc/patches/12.2.0/960-gotools-fix-compilation-when-making-cross-compiler.patch similarity index 100% rename from toolchain/gcc/patches/12.1.0/960-gotools-fix-compilation-when-making-cross-compiler.patch rename to toolchain/gcc/patches/12.2.0/960-gotools-fix-compilation-when-making-cross-compiler.patch diff --git a/toolchain/gcc/patches/12.1.0/970-macos_arm64-building-fix.patch b/toolchain/gcc/patches/12.2.0/970-macos_arm64-building-fix.patch similarity index 88% rename from toolchain/gcc/patches/12.1.0/970-macos_arm64-building-fix.patch rename to toolchain/gcc/patches/12.2.0/970-macos_arm64-building-fix.patch index d164d70e88..86fa68e1b1 100644 --- a/toolchain/gcc/patches/12.1.0/970-macos_arm64-building-fix.patch +++ b/toolchain/gcc/patches/12.2.0/970-macos_arm64-building-fix.patch @@ -17,7 +17,7 @@ Date: Mon Aug 16 13:16:21 2021 +0100 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h -@@ -1236,7 +1236,7 @@ extern const char *aarch64_rewrite_mcpu +@@ -1290,7 +1290,7 @@ extern const char *aarch64_rewrite_mcpu #define MCPU_TO_MARCH_SPEC_FUNCTIONS \ { "rewrite_mcpu", aarch64_rewrite_mcpu }, @@ -28,8 +28,8 @@ Date: Mon Aug 16 13:16:21 2021 +0100 # define EXTRA_SPEC_FUNCTIONS \ --- a/gcc/config/host-darwin.cc +++ b/gcc/config/host-darwin.cc -@@ -22,6 +22,8 @@ - #include "coretypes.h" +@@ -23,6 +23,8 @@ + #include "options.h" #include "diagnostic-core.h" #include "config/host-darwin.h" +#include "hosthooks.h" @@ -37,9 +37,9 @@ Date: Mon Aug 16 13:16:21 2021 +0100 #include /* For Darwin (macOS only) platforms, without ASLR (PIE) enabled on the -@@ -79,3 +81,5 @@ darwin_gt_pch_use_address (void *addr, s +@@ -181,3 +183,5 @@ darwin_gt_pch_use_address (void *&addr, - return ret; + return 1; } + +const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; diff --git a/tools/mkimage/patches/020-tools-mtk_image-split-gfh-header-verification-into-a.patch b/tools/mkimage/patches/020-tools-mtk_image-split-gfh-header-verification-into-a.patch new file mode 100644 index 0000000000..62300af266 --- /dev/null +++ b/tools/mkimage/patches/020-tools-mtk_image-split-gfh-header-verification-into-a.patch @@ -0,0 +1,89 @@ +From b6bb61fd3818f4a3025fedbe4d15dbeeaef6ee82 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Tue, 2 Aug 2022 17:21:34 +0800 +Subject: [PATCH 28/31] tools: mtk_image: split gfh header verification into a + new function + +The verification code of gfh header for NAND and non-NAND are identical. +It's better to define a individual function to reduce redundancy. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + tools/mtk_image.c | 51 +++++++++++++++++++---------------------------- + 1 file changed, 21 insertions(+), 30 deletions(-) + +--- a/tools/mtk_image.c ++++ b/tools/mtk_image.c +@@ -432,6 +432,25 @@ static int mtk_image_vrec_header(struct + return SHA256_SUM_LEN; + } + ++static int mtk_image_verify_gfh(struct gfh_header *gfh, uint32_t type, int print) ++{ ++ if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME)) ++ return -1; ++ ++ if (le32_to_cpu(gfh->file_info.flash_type) != type) ++ return -1; ++ ++ if (print) ++ printf("Load Address: %08x\n", ++ le32_to_cpu(gfh->file_info.load_addr) + ++ le32_to_cpu(gfh->file_info.jump_offset)); ++ ++ if (print) ++ printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM"); ++ ++ return 0; ++} ++ + static int mtk_image_verify_gen_header(const uint8_t *ptr, int print) + { + union gen_boot_header *gbh = (union gen_boot_header *)ptr; +@@ -494,21 +513,7 @@ static int mtk_image_verify_gen_header(c + + gfh = (struct gfh_header *)(ptr + gfh_offset); + +- if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME)) +- return -1; +- +- if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN) +- return -1; +- +- if (print) +- printf("Load Address: %08x\n", +- le32_to_cpu(gfh->file_info.load_addr) + +- le32_to_cpu(gfh->file_info.jump_offset)); +- +- if (print) +- printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM"); +- +- return 0; ++ return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print); + } + + static int mtk_image_verify_nand_header(const uint8_t *ptr, int print) +@@ -562,21 +567,7 @@ static int mtk_image_verify_nand_header( + + gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize)); + +- if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME)) +- return -1; +- +- if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND) +- return -1; +- +- if (print) +- printf("Load Address: %08x\n", +- le32_to_cpu(gfh->file_info.load_addr) + +- le32_to_cpu(gfh->file_info.jump_offset)); +- +- if (print) +- printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM"); +- +- return 0; ++ return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print); + } + + static int mtk_image_verify_header(unsigned char *ptr, int image_size, diff --git a/tools/mkimage/patches/021-tools-mtk_image-split-the-code-of-generating-NAND-he.patch b/tools/mkimage/patches/021-tools-mtk_image-split-the-code-of-generating-NAND-he.patch new file mode 100644 index 0000000000..0b4013864e --- /dev/null +++ b/tools/mkimage/patches/021-tools-mtk_image-split-the-code-of-generating-NAND-he.patch @@ -0,0 +1,821 @@ +From 20ebf03eab571b25e9f62b2764ab84932111dcd6 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Tue, 2 Aug 2022 17:23:57 +0800 +Subject: [PATCH 29/31] tools: mtk_image: split the code of generating NAND + header into a new file + +The predefined NAND headers take too much spaces in the mtk_image.c. +Moving them into a new file can significantly improve the readability of +both mtk_image.c and the new mtk_nand_headers.c. + +This is a preparation for adding more NAND headers. + +Reviewed-by: Simon Glass +Signed-off-by: Weijie Gao +--- + tools/Makefile | 1 + + tools/mtk_image.c | 305 ++++++--------------------------------- + tools/mtk_image.h | 25 ---- + tools/mtk_nand_headers.c | 286 ++++++++++++++++++++++++++++++++++++ + tools/mtk_nand_headers.h | 61 ++++++++ + 5 files changed, 389 insertions(+), 289 deletions(-) + create mode 100644 tools/mtk_nand_headers.c + create mode 100644 tools/mtk_nand_headers.h + +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -147,6 +147,7 @@ dumpimage-mkimage-objs := aisimage.o \ + gpimage.o \ + gpimage-common.o \ + mtk_image.o \ ++ mtk_nand_headers.o \ + $(ECDSA_OBJS-y) \ + $(RSA_OBJS-y) \ + $(AES_OBJS-y) +--- a/tools/mtk_image.c ++++ b/tools/mtk_image.c +@@ -10,216 +10,7 @@ + #include + #include "imagetool.h" + #include "mtk_image.h" +- +-/* NAND header for SPI-NAND with 2KB page + 64B spare */ +-static const union nand_boot_header snand_hdr_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D, +- 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7, +- 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8, +- 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00 +- } +-}; +- +-/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */ +-static const union nand_boot_header snand_hdr_2k_128_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13, +- 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3, +- 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7, +- 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00 +- } +-}; +- +-/* NAND header for SPI-NAND with 4KB page + 256B spare */ +-static const union nand_boot_header snand_hdr_4k_256_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3, +- 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57, +- 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F, +- 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */ +-static const union nand_boot_header nand_hdr_1gb_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12, +- 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C, +- 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82, +- 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */ +-static const union nand_boot_header nand_hdr_2gb_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D, +- 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1, +- 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95, +- 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */ +-static const union nand_boot_header nand_hdr_4gb_2k_64_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, +- 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32, +- 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B, +- 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87, +- 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */ +-static const union nand_boot_header nand_hdr_2gb_2k_128_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, +- 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A, +- 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC, +- 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0, +- 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00 +- } +-}; +- +-/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */ +-static const union nand_boot_header nand_hdr_4gb_2k_128_data = { +- .data = { +- 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, +- 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, +- 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, +- 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, +- 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45, +- 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46, +- 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2, +- 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00 +- } +-}; +- +-static const struct nand_header_type { +- const char *name; +- const union nand_boot_header *data; +-} nand_headers[] = { +- { +- .name = "2k+64", +- .data = &snand_hdr_2k_64_data +- }, { +- .name = "2k+120", +- .data = &snand_hdr_2k_128_data +- }, { +- .name = "2k+128", +- .data = &snand_hdr_2k_128_data +- }, { +- .name = "4k+256", +- .data = &snand_hdr_4k_256_data +- }, { +- .name = "1g:2k+64", +- .data = &nand_hdr_1gb_2k_64_data +- }, { +- .name = "2g:2k+64", +- .data = &nand_hdr_2gb_2k_64_data +- }, { +- .name = "4g:2k+64", +- .data = &nand_hdr_4gb_2k_64_data +- }, { +- .name = "2g:2k+128", +- .data = &nand_hdr_2gb_2k_128_data +- }, { +- .name = "4g:2k+128", +- .data = &nand_hdr_4gb_2k_128_data +- } +-}; ++#include "mtk_nand_headers.h" + + static const struct brom_img_type { + const char *name; +@@ -258,6 +49,7 @@ static char lk_name[32] = "U-Boot"; + + /* NAND header selected by user */ + static const union nand_boot_header *hdr_nand; ++static uint32_t hdr_nand_size; + + /* GFH header + 2 * 4KB pages of NAND */ + static char hdr_tmp[sizeof(struct gfh_header) + 0x2000]; +@@ -361,12 +153,7 @@ static int mtk_brom_parse_imagename(cons + } + + /* parse nand header type */ +- for (i = 0; i < ARRAY_SIZE(nand_headers); i++) { +- if (!strcmp(nand_headers[i].name, nandinfo)) { +- hdr_nand = nand_headers[i].data; +- break; +- } +- } ++ hdr_nand = mtk_nand_header_find(nandinfo); + + /* parse device header offset */ + if (hdr_offs && hdr_offs[0]) +@@ -391,6 +178,9 @@ static int mtk_brom_parse_imagename(cons + return -EINVAL; + } + ++ if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) ++ hdr_nand_size = mtk_nand_header_size(hdr_nand); ++ + return 0; + } + +@@ -420,7 +210,7 @@ static int mtk_image_vrec_header(struct + } + + if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) +- tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize); ++ tparams->header_size = hdr_nand_size; + else + tparams->header_size = sizeof(struct gen_device_header); + +@@ -518,16 +308,17 @@ static int mtk_image_verify_gen_header(c + + static int mtk_image_verify_nand_header(const uint8_t *ptr, int print) + { +- union nand_boot_header *nh = (union nand_boot_header *)ptr; + struct brom_layout_header *bh; ++ struct nand_header_info info; + struct gfh_header *gfh; + const char *bootmedia; ++ int ret; + +- if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) || +- strcmp(nh->id, NAND_BOOT_ID)) +- return -1; ++ ret = mtk_nand_header_info(ptr, &info); ++ if (ret < 0) ++ return ret; + +- bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize)); ++ bh = (struct brom_layout_header *)(ptr + info.page_size); + + if (strcmp(bh->name, BRLYT_NAME)) + return -1; +@@ -538,34 +329,23 @@ static int mtk_image_verify_nand_header( + if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) + bootmedia = "Parallel NAND"; + else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND) +- bootmedia = "Serial NAND"; ++ bootmedia = "Serial NAND (SNFI/AP)"; + else + return -1; + } + + if (print) { +- printf("Boot Media: %s\n", bootmedia); +- +- if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) { +- uint64_t capacity = +- (uint64_t)le16_to_cpu(nh->numblocks) * +- (uint64_t)le16_to_cpu(nh->pages_of_block) * +- (uint64_t)le16_to_cpu(nh->pagesize) * 8; +- printf("Capacity: %dGb\n", +- (uint32_t)(capacity >> 30)); +- } ++ printf("Boot Media: %s\n", bootmedia); + +- if (le16_to_cpu(nh->pagesize) >= 1024) +- printf("Page Size: %dKB\n", +- le16_to_cpu(nh->pagesize) >> 10); ++ if (info.page_size >= 1024) ++ printf("Page Size: %dKB\n", info.page_size >> 10); + else +- printf("Page Size: %dB\n", +- le16_to_cpu(nh->pagesize)); ++ printf("Page Size: %dB\n", info.page_size); + +- printf("Spare Size: %dB\n", le16_to_cpu(nh->oobsize)); ++ printf("Spare Size: %dB\n", info.spare_size); + } + +- gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize)); ++ gfh = (struct gfh_header *)(ptr + info.gfh_offset); + + return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print); + } +@@ -581,7 +361,7 @@ static int mtk_image_verify_header(unsig + + img_size = image_size; + +- if (!strcmp((char *)ptr, NAND_BOOT_NAME)) ++ if (is_mtk_nand_header(ptr)) + return mtk_image_verify_nand_header(ptr, 0); + else + return mtk_image_verify_gen_header(ptr, 0); +@@ -601,7 +381,7 @@ static void mtk_image_print_header(const + + printf("Image Type: MediaTek BootROM Loadable Image\n"); + +- if (!strcmp((char *)ptr, NAND_BOOT_NAME)) ++ if (is_mtk_nand_header(ptr)) + mtk_image_verify_nand_header(ptr, 1); + else + mtk_image_verify_gen_header(ptr, 1); +@@ -732,36 +512,33 @@ static void mtk_image_set_gen_header(voi + static void mtk_image_set_nand_header(void *ptr, off_t filesize, + uint32_t loadaddr) + { +- union nand_boot_header *nh = (union nand_boot_header *)ptr; + struct brom_layout_header *brlyt; + struct gfh_header *gfh; +- uint32_t payload_pages; +- int i; ++ uint32_t payload_pages, nand_page_size; + +- /* NAND device header, repeat 4 times */ +- for (i = 0; i < 4; i++) +- memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header)); ++ /* NAND header */ ++ nand_page_size = mtk_nand_header_put(hdr_nand, ptr); + +- /* BRLYT header */ +- payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) / +- le16_to_cpu(hdr_nand->pagesize); +- brlyt = (struct brom_layout_header *) +- (ptr + le16_to_cpu(hdr_nand->pagesize)); +- put_brom_layout_header(brlyt, hdr_media); +- brlyt->header_size = cpu_to_le32(2); +- brlyt->total_size = cpu_to_le32(payload_pages); +- brlyt->header_size_2 = brlyt->header_size; +- brlyt->total_size_2 = brlyt->total_size; +- brlyt->unused = cpu_to_le32(1); ++ if (nand_page_size) { ++ /* BRLYT header */ ++ payload_pages = (filesize + nand_page_size - 1) / ++ nand_page_size; ++ brlyt = (struct brom_layout_header *)(ptr + nand_page_size); ++ put_brom_layout_header(brlyt, hdr_media); ++ brlyt->header_size = cpu_to_le32(2); ++ brlyt->total_size = cpu_to_le32(payload_pages); ++ brlyt->header_size_2 = brlyt->header_size; ++ brlyt->total_size_2 = brlyt->total_size; ++ brlyt->unused = cpu_to_le32(1); ++ } + + /* GFH header */ +- gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize)); +- put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize), +- loadaddr, GFH_FLASH_TYPE_NAND); ++ gfh = (struct gfh_header *)(ptr + hdr_nand_size); ++ put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr, ++ GFH_FLASH_TYPE_NAND); + + /* Generate SHA256 hash */ +- put_hash((uint8_t *)gfh, +- filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN); ++ put_hash((uint8_t *)gfh, filesize - hdr_nand_size - SHA256_SUM_LEN); + } + + static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd, +--- a/tools/mtk_image.h ++++ b/tools/mtk_image.h +@@ -26,31 +26,6 @@ union gen_boot_header { + #define SF_BOOT_NAME "SF_BOOT" + #define SDMMC_BOOT_NAME "SDMMC_BOOT" + +-/* Header for NAND */ +-union nand_boot_header { +- struct { +- char name[12]; +- char version[4]; +- char id[8]; +- uint16_t ioif; +- uint16_t pagesize; +- uint16_t addrcycles; +- uint16_t oobsize; +- uint16_t pages_of_block; +- uint16_t numblocks; +- uint16_t writesize_shift; +- uint16_t erasesize_shift; +- uint8_t dummy[60]; +- uint8_t ecc_parity[28]; +- }; +- +- uint8_t data[0x80]; +-}; +- +-#define NAND_BOOT_NAME "BOOTLOADER!" +-#define NAND_BOOT_VERSION "V006" +-#define NAND_BOOT_ID "NFIINFO" +- + /* BootROM layout header */ + struct brom_layout_header { + char name[8]; +--- /dev/null ++++ b/tools/mtk_nand_headers.c +@@ -0,0 +1,286 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * MediaTek BootROM NAND header definitions ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Weijie Gao ++ */ ++ ++#include ++#include ++#include "imagetool.h" ++#include "mtk_image.h" ++#include "mtk_nand_headers.h" ++ ++/* NAND header for SPI-NAND with 2KB page + 64B spare */ ++static const union nand_boot_header snand_hdr_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D, ++ 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7, ++ 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8, ++ 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */ ++static const union nand_boot_header snand_hdr_2k_128_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13, ++ 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3, ++ 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7, ++ 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for SPI-NAND with 4KB page + 256B spare */ ++static const union nand_boot_header snand_hdr_4k_256_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3, ++ 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57, ++ 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F, ++ 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */ ++static const union nand_boot_header nand_hdr_1gb_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12, ++ 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C, ++ 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82, ++ 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */ ++static const union nand_boot_header nand_hdr_2gb_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D, ++ 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1, ++ 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95, ++ 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */ ++static const union nand_boot_header nand_hdr_4gb_2k_64_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00, ++ 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32, ++ 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B, ++ 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87, ++ 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */ ++static const union nand_boot_header nand_hdr_2gb_2k_128_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, ++ 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A, ++ 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC, ++ 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0, ++ 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00 ++ } ++}; ++ ++/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */ ++static const union nand_boot_header nand_hdr_4gb_2k_128_data = { ++ .data = { ++ 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44, ++ 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36, ++ 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00, ++ 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45, ++ 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46, ++ 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2, ++ 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00 ++ } ++}; ++ ++static const struct nand_header_type { ++ const char *name; ++ const union nand_boot_header *data; ++} nand_headers[] = { ++ { ++ .name = "2k+64", ++ .data = &snand_hdr_2k_64_data ++ }, { ++ .name = "2k+120", ++ .data = &snand_hdr_2k_128_data ++ }, { ++ .name = "2k+128", ++ .data = &snand_hdr_2k_128_data ++ }, { ++ .name = "4k+256", ++ .data = &snand_hdr_4k_256_data ++ }, { ++ .name = "1g:2k+64", ++ .data = &nand_hdr_1gb_2k_64_data ++ }, { ++ .name = "2g:2k+64", ++ .data = &nand_hdr_2gb_2k_64_data ++ }, { ++ .name = "4g:2k+64", ++ .data = &nand_hdr_4gb_2k_64_data ++ }, { ++ .name = "2g:2k+128", ++ .data = &nand_hdr_2gb_2k_128_data ++ }, { ++ .name = "4g:2k+128", ++ .data = &nand_hdr_4gb_2k_128_data ++ } ++}; ++ ++const union nand_boot_header *mtk_nand_header_find(const char *name) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(nand_headers); i++) { ++ if (!strcmp(nand_headers[i].name, name)) ++ return nand_headers[i].data; ++ } ++ ++ return NULL; ++} ++ ++uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand) ++{ ++ return 2 * le16_to_cpu(hdr_nand->pagesize); ++} ++ ++static int mtk_nand_header_ap_info(const void *ptr, ++ struct nand_header_info *info) ++{ ++ union nand_boot_header *nh = (union nand_boot_header *)ptr; ++ ++ if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) || ++ strcmp(nh->id, NAND_BOOT_ID)) ++ return -1; ++ ++ info->page_size = le16_to_cpu(nh->pagesize); ++ info->spare_size = le16_to_cpu(nh->oobsize); ++ info->gfh_offset = 2 * info->page_size; ++ ++ return 0; ++} ++ ++int mtk_nand_header_info(const void *ptr, struct nand_header_info *info) ++{ ++ if (!strcmp((char *)ptr, NAND_BOOT_NAME)) ++ return mtk_nand_header_ap_info(ptr, info); ++ ++ return -1; ++} ++ ++bool is_mtk_nand_header(const void *ptr) ++{ ++ struct nand_header_info info; ++ ++ if (mtk_nand_header_info(ptr, &info) >= 0) ++ return true; ++ ++ return false; ++} ++ ++uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr) ++{ ++ union nand_boot_header *nh = (union nand_boot_header *)ptr; ++ int i; ++ ++ /* NAND device header, repeat 4 times */ ++ for (i = 0; i < 4; i++) ++ memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header)); ++ ++ return le16_to_cpu(hdr_nand->pagesize); ++} +--- /dev/null ++++ b/tools/mtk_nand_headers.h +@@ -0,0 +1,61 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * MediaTek BootROM NAND header definitions ++ * ++ * Copyright (C) 2022 MediaTek Inc. ++ * Author: Weijie Gao ++ */ ++ ++#ifndef _MTK_NAND_HEADERS_H ++#define _MTK_NAND_HEADERS_H ++ ++#include ++#include ++ ++struct nand_header_info { ++ uint32_t page_size; ++ uint32_t spare_size; ++ uint32_t gfh_offset; ++}; ++ ++/* AP BROM Header for NAND */ ++union nand_boot_header { ++ struct { ++ char name[12]; ++ char version[4]; ++ char id[8]; ++ uint16_t ioif; /* I/O interface */ ++ uint16_t pagesize; /* NAND page size */ ++ uint16_t addrcycles; /* Address cycles */ ++ uint16_t oobsize; /* NAND page spare size */ ++ uint16_t pages_of_block; /* Pages of one block */ ++ uint16_t numblocks; /* Total blocks of NAND chip */ ++ uint16_t writesize_shift; ++ uint16_t erasesize_shift; ++ uint8_t dummy[60]; ++ uint8_t ecc_parity[28]; /* ECC parity of this header */ ++ }; ++ ++ uint8_t data[0x80]; ++}; ++ ++#define NAND_BOOT_NAME "BOOTLOADER!" ++#define NAND_BOOT_VERSION "V006" ++#define NAND_BOOT_ID "NFIINFO" ++ ++/* Find nand header data by name */ ++const union nand_boot_header *mtk_nand_header_find(const char *name); ++ ++/* Device header size using this nand header */ ++uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand); ++ ++/* Get nand info from nand header (page size, spare size, ...) */ ++int mtk_nand_header_info(const void *ptr, struct nand_header_info *info); ++ ++/* Whether given header data is valid */ ++bool is_mtk_nand_header(const void *ptr); ++ ++/* Generate Device header using give nand header */ ++uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr); ++ ++#endif /* _MTK_NAND_HEADERS_H */ diff --git a/tools/mkimage/patches/022-tools-mtk_image-add-support-for-nand-headers-used-by.patch b/tools/mkimage/patches/022-tools-mtk_image-add-support-for-nand-headers-used-by.patch new file mode 100644 index 0000000000..12ff7f32de --- /dev/null +++ b/tools/mkimage/patches/022-tools-mtk_image-add-support-for-nand-headers-used-by.patch @@ -0,0 +1,702 @@ +From fbf296f9ed5daab70020686e9ba072efe663bbab Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 3 Aug 2022 11:14:36 +0800 +Subject: [PATCH 30/31] tools: mtk_image: add support for nand headers used by + newer chips + +This patch adds more nand headers in two new types: +1. HSM header, used for spi-nand thru SNFI interface +2. SPIM header, used for spi-nand thru spi-mem interface + +The original nand header is renamed to AP header. + +Signed-off-by: Weijie Gao +--- + tools/mtk_image.c | 23 ++- + tools/mtk_nand_headers.c | 422 +++++++++++++++++++++++++++++++++++++-- + tools/mtk_nand_headers.h | 110 +++++++++- + 3 files changed, 525 insertions(+), 30 deletions(-) + +--- a/tools/mtk_image.c ++++ b/tools/mtk_image.c +@@ -31,6 +31,9 @@ static const struct brom_img_type { + }, { + .name = "snand", + .type = BRLYT_TYPE_SNAND ++ }, { ++ .name = "spim-nand", ++ .type = BRLYT_TYPE_SNAND + } + }; + +@@ -48,7 +51,7 @@ static bool is_arm64_image; + static char lk_name[32] = "U-Boot"; + + /* NAND header selected by user */ +-static const union nand_boot_header *hdr_nand; ++static const struct nand_header_type *hdr_nand; + static uint32_t hdr_nand_size; + + /* GFH header + 2 * 4KB pages of NAND */ +@@ -318,20 +321,26 @@ static int mtk_image_verify_nand_header( + if (ret < 0) + return ret; + +- bh = (struct brom_layout_header *)(ptr + info.page_size); ++ if (!ret) { ++ bh = (struct brom_layout_header *)(ptr + info.page_size); + +- if (strcmp(bh->name, BRLYT_NAME)) +- return -1; ++ if (strcmp(bh->name, BRLYT_NAME)) ++ return -1; ++ ++ if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) ++ return -1; + +- if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) { +- return -1; +- } else { + if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) + bootmedia = "Parallel NAND"; + else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND) + bootmedia = "Serial NAND (SNFI/AP)"; + else + return -1; ++ } else { ++ if (info.snfi) ++ bootmedia = "Serial NAND (SNFI/HSM)"; ++ else ++ bootmedia = "Serial NAND (SPIM)"; + } + + if (print) { +--- a/tools/mtk_nand_headers.c ++++ b/tools/mtk_nand_headers.c +@@ -188,55 +188,346 @@ static const union nand_boot_header nand + } + }; + +-static const struct nand_header_type { ++/* HSM BROM NAND header for SPI NAND with 2KB page + 64B spare */ ++static const union hsm_nand_boot_header hsm_nand_hdr_2k_64_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0xFF, 0x00, 0x00, 0x00, 0x21, 0xD2, 0xEE, 0xF6, ++ 0xAE, 0xDD, 0x5E, 0xC2, 0x82, 0x8E, 0x9A, 0x62, ++ 0x09, 0x8E, 0x80, 0xE2, 0x37, 0x0D, 0xC9, 0xFA, ++ 0xA9, 0xDD, 0xFC, 0x92, 0x34, 0x2A, 0xED, 0x51, ++ 0xA4, 0x1B, 0xF7, 0x63, 0xCC, 0x5A, 0xC7, 0xFB, ++ 0xED, 0x21, 0x02, 0x23, 0x51, 0x31 ++ } ++}; ++ ++/* HSM BROM NAND header for SPI NAND with 2KB page + 128B spare */ ++static const union hsm_nand_boot_header hsm_nand_hdr_2k_128_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0xFF, 0x00, 0x00, 0x00, 0x71, 0x7f, 0x71, 0xAC, ++ 0x42, 0xD0, 0x5B, 0xD2, 0x12, 0x81, 0x15, 0x0A, ++ 0x0C, 0xD4, 0xF6, 0x32, 0x1E, 0x63, 0xE7, 0x81, ++ 0x8A, 0x7F, 0xDE, 0xF9, 0x4B, 0x91, 0xEC, 0xC2, ++ 0x70, 0x00, 0x7F, 0x57, 0xAF, 0xDC, 0xE4, 0x24, ++ 0x57, 0x09, 0xBC, 0xC5, 0x35, 0xDC ++ } ++}; ++ ++/* HSM BROM NAND header for SPI NAND with 4KB page + 256B spare */ ++static const union hsm_nand_boot_header hsm_nand_hdr_4k_256_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ++ 0xFF, 0x00, 0x00, 0x00, 0x62, 0x04, 0xD6, 0x1F, ++ 0x2B, 0x57, 0x7A, 0x2D, 0xFE, 0xBB, 0x4A, 0x50, ++ 0xEC, 0xF8, 0x70, 0x1A, 0x44, 0x15, 0xF6, 0xA2, ++ 0x8E, 0xB0, 0xFD, 0xFA, 0xDC, 0xAA, 0x5A, 0x4E, ++ 0xCB, 0x8E, 0xC9, 0x72, 0x08, 0xDC, 0x20, 0xB9, ++ 0x98, 0xC8, 0x82, 0xD8, 0xBE, 0x44 ++ } ++}; ++ ++/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 64B spare */ ++static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_64_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x5F, 0x4B, 0xB2, 0x5B, 0x8B, 0x1C, 0x35, 0xDA, ++ 0x83, 0xE6, 0x6C, 0xC3, 0xFB, 0x8C, 0x78, 0x23, ++ 0xD0, 0x89, 0x24, 0xD9, 0x6C, 0x35, 0x2C, 0x5D, ++ 0x8F, 0xBB, 0xFC, 0x10, 0xD0, 0xE2, 0x22, 0x7D, ++ 0xC8, 0x97, 0x9A, 0xEF, 0xC6, 0xB5, 0xA7, 0x4E, ++ 0x4E, 0x0E ++ } ++}; ++ ++/* HSM2.0 BROM NAND header for SPI NAND with 2KB page + 128B spare */ ++static const union hsm20_nand_boot_header hsm20_nand_hdr_2k_128_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0xF8, 0x7E, 0xC1, 0x5D, 0x61, 0x54, 0xEA, 0x9F, ++ 0x5E, 0x66, 0x39, 0x66, 0x21, 0xFF, 0x8C, 0x3B, ++ 0xBE, 0xA7, 0x5A, 0x9E, 0xD7, 0xBD, 0x9E, 0x89, ++ 0xEE, 0x7E, 0x10, 0x31, 0x9A, 0x1D, 0x82, 0x49, ++ 0xA3, 0x4E, 0xD8, 0x47, 0xD7, 0x19, 0xF4, 0x2D, ++ 0x8E, 0x53 ++ } ++}; ++ ++/* HSM2.0 BROM NAND header for SPI NAND with 4KB page + 256B spare */ ++static const union hsm20_nand_boot_header hsm20_nand_hdr_4k_256_data = { ++ .data = { ++ 0x4E, 0x41, 0x4E, 0x44, 0x43, 0x46, 0x47, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, ++ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x79, 0x01, 0x1F, 0x86, 0x62, 0x6A, 0x43, 0xAE, ++ 0xE6, 0xF8, 0xDD, 0x5B, 0x29, 0xB7, 0xA2, 0x7F, ++ 0x29, 0x72, 0x54, 0x37, 0xBE, 0x50, 0xD4, 0x24, ++ 0xAB, 0x60, 0xF4, 0x44, 0x97, 0x3B, 0x65, 0x21, ++ 0x73, 0x24, 0x1F, 0x93, 0x0E, 0x9E, 0x96, 0x88, ++ 0x78, 0x6C ++ } ++}; ++ ++/* SPIM-NAND header for SPI NAND with 2KB page + 64B spare */ ++static const union spim_nand_boot_header spim_nand_hdr_2k_64_data = { ++ .data = { ++ 0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30, ++ 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ } ++}; ++ ++/* SPIM-NAND header for SPI NAND with 2KB page + 128B spare */ ++static const union spim_nand_boot_header spim_nand_hdr_2k_128_data = { ++ .data = { ++ 0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x30, ++ 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ } ++}; ++ ++/* SPIM-NAND header for SPI NAND with 4KB page + 256B spare */ ++static const union spim_nand_boot_header spim_nand_hdr_4k_256_data = { ++ .data = { ++ 0x53, 0x50, 0x49, 0x4e, 0x41, 0x4e, 0x44, 0x21, ++ 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x40, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x30, ++ 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ } ++}; ++ ++struct nand_header_type { + const char *name; +- const union nand_boot_header *data; ++ enum nand_boot_header_type type; ++ union { ++ const union nand_boot_header *ap; ++ const union hsm_nand_boot_header *hsm; ++ const union hsm20_nand_boot_header *hsm20; ++ const union spim_nand_boot_header *spim; ++ }; + } nand_headers[] = { + { + .name = "2k+64", +- .data = &snand_hdr_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_2k_64_data, + }, { + .name = "2k+120", +- .data = &snand_hdr_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_2k_128_data, + }, { + .name = "2k+128", +- .data = &snand_hdr_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_2k_128_data, + }, { + .name = "4k+256", +- .data = &snand_hdr_4k_256_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &snand_hdr_4k_256_data, + }, { + .name = "1g:2k+64", +- .data = &nand_hdr_1gb_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_1gb_2k_64_data, + }, { + .name = "2g:2k+64", +- .data = &nand_hdr_2gb_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_2gb_2k_64_data, + }, { + .name = "4g:2k+64", +- .data = &nand_hdr_4gb_2k_64_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_4gb_2k_64_data, + }, { + .name = "2g:2k+128", +- .data = &nand_hdr_2gb_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_2gb_2k_128_data, + }, { + .name = "4g:2k+128", +- .data = &nand_hdr_4gb_2k_128_data ++ .type = NAND_BOOT_AP_HEADER, ++ .ap = &nand_hdr_4gb_2k_128_data, ++ }, { ++ .name = "hsm:2k+64", ++ .type = NAND_BOOT_HSM_HEADER, ++ .hsm = &hsm_nand_hdr_2k_64_data, ++ }, { ++ .name = "hsm:2k+128", ++ .type = NAND_BOOT_HSM_HEADER, ++ .hsm = &hsm_nand_hdr_2k_128_data, ++ }, { ++ .name = "hsm:4k+256", ++ .type = NAND_BOOT_HSM_HEADER, ++ .hsm = &hsm_nand_hdr_4k_256_data, ++ }, { ++ .name = "hsm20:2k+64", ++ .type = NAND_BOOT_HSM20_HEADER, ++ .hsm20 = &hsm20_nand_hdr_2k_64_data, ++ }, { ++ .name = "hsm20:2k+128", ++ .type = NAND_BOOT_HSM20_HEADER, ++ .hsm20 = &hsm20_nand_hdr_2k_128_data, ++ }, { ++ .name = "hsm20:4k+256", ++ .type = NAND_BOOT_HSM20_HEADER, ++ .hsm20 = &hsm20_nand_hdr_4k_256_data, ++ }, { ++ .name = "spim:2k+64", ++ .type = NAND_BOOT_SPIM_HEADER, ++ .spim = &spim_nand_hdr_2k_64_data, ++ }, { ++ .name = "spim:2k+128", ++ .type = NAND_BOOT_SPIM_HEADER, ++ .spim = &spim_nand_hdr_2k_128_data, ++ }, { ++ .name = "spim:4k+256", ++ .type = NAND_BOOT_SPIM_HEADER, ++ .spim = &spim_nand_hdr_4k_256_data, + } + }; + +-const union nand_boot_header *mtk_nand_header_find(const char *name) ++const struct nand_header_type *mtk_nand_header_find(const char *name) + { + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(nand_headers); i++) { + if (!strcmp(nand_headers[i].name, name)) +- return nand_headers[i].data; ++ return &nand_headers[i]; + } + + return NULL; + } + +-uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand) ++uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand) + { +- return 2 * le16_to_cpu(hdr_nand->pagesize); ++ switch (hdr_nand->type) { ++ case NAND_BOOT_HSM_HEADER: ++ return le32_to_cpu(hdr_nand->hsm->page_size); ++ ++ case NAND_BOOT_HSM20_HEADER: ++ return le32_to_cpu(hdr_nand->hsm20->page_size); ++ ++ case NAND_BOOT_SPIM_HEADER: ++ return le32_to_cpu(hdr_nand->spim->page_size); ++ ++ default: ++ return 2 * le16_to_cpu(hdr_nand->ap->pagesize); ++ } + } + + static int mtk_nand_header_ap_info(const void *ptr, +@@ -251,14 +542,45 @@ static int mtk_nand_header_ap_info(const + info->page_size = le16_to_cpu(nh->pagesize); + info->spare_size = le16_to_cpu(nh->oobsize); + info->gfh_offset = 2 * info->page_size; ++ info->snfi = true; + + return 0; + } + ++static int mtk_nand_header_hsm_info(const void *ptr, ++ struct nand_header_info *info) ++{ ++ union hsm_nand_boot_header *nh = (union hsm_nand_boot_header *)ptr; ++ ++ info->page_size = le16_to_cpu(nh->page_size); ++ info->spare_size = le16_to_cpu(nh->spare_size); ++ info->gfh_offset = info->page_size; ++ info->snfi = true; ++ ++ return 1; ++} ++ ++static int mtk_nand_header_spim_info(const void *ptr, ++ struct nand_header_info *info) ++{ ++ union spim_nand_boot_header *nh = (union spim_nand_boot_header *)ptr; ++ ++ info->page_size = le16_to_cpu(nh->page_size); ++ info->spare_size = le16_to_cpu(nh->spare_size); ++ info->gfh_offset = info->page_size; ++ info->snfi = false; ++ ++ return 1; ++} ++ + int mtk_nand_header_info(const void *ptr, struct nand_header_info *info) + { + if (!strcmp((char *)ptr, NAND_BOOT_NAME)) + return mtk_nand_header_ap_info(ptr, info); ++ else if (!strncmp((char *)ptr, HSM_NAND_BOOT_NAME, 8)) ++ return mtk_nand_header_hsm_info(ptr, info); ++ else if (!strncmp((char *)ptr, SPIM_NAND_BOOT_NAME, 8)) ++ return mtk_nand_header_spim_info(ptr, info); + + return -1; + } +@@ -273,14 +595,74 @@ bool is_mtk_nand_header(const void *ptr) + return false; + } + +-uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr) ++static uint16_t crc16(const uint8_t *p, uint32_t len) ++{ ++ uint16_t crc = 0x4f4e; ++ uint32_t i; ++ ++ while (len--) { ++ crc ^= *p++ << 8; ++ for (i = 0; i < 8; i++) ++ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); ++ } ++ ++ return crc; ++} ++ ++static uint32_t mtk_nand_header_put_ap(const struct nand_header_type *hdr_nand, ++ void *ptr) + { +- union nand_boot_header *nh = (union nand_boot_header *)ptr; + int i; + + /* NAND device header, repeat 4 times */ +- for (i = 0; i < 4; i++) +- memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header)); ++ for (i = 0; i < 4; i++) { ++ memcpy(ptr, hdr_nand->ap, sizeof(*hdr_nand->ap)); ++ ptr += sizeof(*hdr_nand->ap); ++ } ++ ++ return le16_to_cpu(hdr_nand->ap->pagesize); ++} + +- return le16_to_cpu(hdr_nand->pagesize); ++static uint32_t mtk_nand_header_put_hsm(const struct nand_header_type *hdr_nand, ++ void *ptr) ++{ ++ memcpy(ptr, hdr_nand->hsm, sizeof(*hdr_nand->hsm)); ++ return 0; ++} ++ ++static uint32_t mtk_nand_header_put_hsm20(const struct nand_header_type *hdr_nand, ++ void *ptr) ++{ ++ memcpy(ptr, hdr_nand->hsm20, sizeof(*hdr_nand->hsm20)); ++ return 0; ++} ++ ++static uint32_t mtk_nand_header_put_spim(const struct nand_header_type *hdr_nand, ++ void *ptr) ++{ ++ uint16_t crc; ++ ++ memcpy(ptr, hdr_nand->spim, sizeof(*hdr_nand->spim)); ++ ++ crc = crc16(ptr, 0x4e); ++ memcpy(ptr + 0x4e, &crc, sizeof(uint16_t)); ++ ++ return 0; ++} ++ ++uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand, void *ptr) ++{ ++ switch (hdr_nand->type) { ++ case NAND_BOOT_HSM_HEADER: ++ return mtk_nand_header_put_hsm(hdr_nand, ptr); ++ ++ case NAND_BOOT_HSM20_HEADER: ++ return mtk_nand_header_put_hsm20(hdr_nand, ptr); ++ ++ case NAND_BOOT_SPIM_HEADER: ++ return mtk_nand_header_put_spim(hdr_nand, ptr); ++ ++ default: ++ return mtk_nand_header_put_ap(hdr_nand, ptr); ++ } + } +--- a/tools/mtk_nand_headers.h ++++ b/tools/mtk_nand_headers.h +@@ -16,6 +16,7 @@ struct nand_header_info { + uint32_t page_size; + uint32_t spare_size; + uint32_t gfh_offset; ++ bool snfi; + }; + + /* AP BROM Header for NAND */ +@@ -39,15 +40,117 @@ union nand_boot_header { + uint8_t data[0x80]; + }; + ++/* HSM BROM Header for NAND */ ++union hsm_nand_boot_header { ++ struct { ++ char id[8]; ++ uint32_t version; /* Header version */ ++ uint32_t config; /* Header config */ ++ uint32_t sector_size; /* ECC step size */ ++ uint32_t fdm_size; /* User OOB size of a step */ ++ uint32_t fdm_ecc_size; /* ECC parity size of a step */ ++ uint32_t lbs; ++ uint32_t page_size; /* NAND page size */ ++ uint32_t spare_size; /* NAND page spare size */ ++ uint32_t page_per_block; /* Pages of one block */ ++ uint32_t blocks; /* Total blocks of NAND chip */ ++ uint32_t plane_sel_position; /* Plane bit position */ ++ uint32_t pll; /* Value of pll reg */ ++ uint32_t acccon; /* Value of access timing reg */ ++ uint32_t strobe_sel; /* Value of DQS selection reg*/ ++ uint32_t acccon1; /* Value of access timing reg */ ++ uint32_t dqs_mux; /* Value of DQS mux reg */ ++ uint32_t dqs_ctrl; /* Value of DQS control reg */ ++ uint32_t delay_ctrl; /* Value of delay ctrl reg */ ++ uint32_t latch_lat; /* Value of latch latency reg */ ++ uint32_t sample_delay; /* Value of sample delay reg */ ++ uint32_t driving; /* Value of driving reg */ ++ uint32_t bl_start; /* Bootloader start addr */ ++ uint32_t bl_end; /* Bootloader end addr */ ++ uint8_t ecc_parity[42]; /* ECC parity of this header */ ++ }; ++ ++ uint8_t data[0x8E]; ++}; ++ ++/* HSM2.0 BROM Header for NAND */ ++union hsm20_nand_boot_header { ++ struct { ++ char id[8]; ++ uint32_t version; /* Header version */ ++ uint32_t config; /* Header config */ ++ uint32_t sector_size; /* ECC step size */ ++ uint32_t fdm_size; /* User OOB size of a step */ ++ uint32_t fdm_ecc_size; /* ECC parity size of a step */ ++ uint32_t lbs; ++ uint32_t page_size; /* NAND page size */ ++ uint32_t spare_size; /* NAND page spare size */ ++ uint32_t page_per_block; /* Pages of one block */ ++ uint32_t blocks; /* Total blocks of NAND chip */ ++ uint32_t plane_sel_position; /* Plane bit position */ ++ uint32_t pll; /* Value of pll reg */ ++ uint32_t acccon; /* Value of access timing reg */ ++ uint32_t strobe_sel; /* Value of DQS selection reg*/ ++ uint32_t acccon1; /* Value of access timing reg */ ++ uint32_t dqs_mux; /* Value of DQS mux reg */ ++ uint32_t dqs_ctrl; /* Value of DQS control reg */ ++ uint32_t delay_ctrl; /* Value of delay ctrl reg */ ++ uint32_t latch_lat; /* Value of latch latency reg */ ++ uint32_t sample_delay; /* Value of sample delay reg */ ++ uint32_t driving; /* Value of driving reg */ ++ uint32_t reserved; ++ uint32_t bl0_start; /* Bootloader start addr */ ++ uint32_t bl0_end; /* Bootloader end addr */ ++ uint32_t bl0_type; /* Bootloader type */ ++ uint8_t bl_reserve[84]; ++ uint8_t ecc_parity[42]; /* ECC parity of this header */ ++ }; ++ ++ uint8_t data[0xEA]; ++}; ++ ++/* SPIM BROM Header for SPI-NAND */ ++union spim_nand_boot_header { ++ struct { ++ char id[8]; ++ uint32_t version; /* Header version */ ++ uint32_t config; /* Header config */ ++ uint32_t page_size; /* NAND page size */ ++ uint32_t spare_size; /* NAND page spare size */ ++ uint16_t page_per_block; /* Pages of one block */ ++ uint16_t plane_sel_position; /* Plane bit position */ ++ uint16_t reserve_reg; ++ uint16_t reserve_val; ++ uint16_t ecc_error; /* ECC error reg addr */ ++ uint16_t ecc_mask; /* ECC error bit mask */ ++ uint32_t bl_start; /* Bootloader start addr */ ++ uint32_t bl_end; /* Bootloader end addr */ ++ uint8_t ecc_parity[32]; /* ECC parity of this header */ ++ uint32_t integrity_crc; /* CRC of this header */ ++ }; ++ ++ uint8_t data[0x50]; ++}; ++ ++enum nand_boot_header_type { ++ NAND_BOOT_AP_HEADER, ++ NAND_BOOT_HSM_HEADER, ++ NAND_BOOT_HSM20_HEADER, ++ NAND_BOOT_SPIM_HEADER ++}; ++ + #define NAND_BOOT_NAME "BOOTLOADER!" + #define NAND_BOOT_VERSION "V006" + #define NAND_BOOT_ID "NFIINFO" + ++#define HSM_NAND_BOOT_NAME "NANDCFG!" ++#define SPIM_NAND_BOOT_NAME "SPINAND!" ++ + /* Find nand header data by name */ +-const union nand_boot_header *mtk_nand_header_find(const char *name); ++const struct nand_header_type *mtk_nand_header_find(const char *name); + + /* Device header size using this nand header */ +-uint32_t mtk_nand_header_size(const union nand_boot_header *hdr_nand); ++uint32_t mtk_nand_header_size(const struct nand_header_type *hdr_nand); + + /* Get nand info from nand header (page size, spare size, ...) */ + int mtk_nand_header_info(const void *ptr, struct nand_header_info *info); +@@ -56,6 +159,7 @@ int mtk_nand_header_info(const void *ptr + bool is_mtk_nand_header(const void *ptr); + + /* Generate Device header using give nand header */ +-uint32_t mtk_nand_header_put(const union nand_boot_header *hdr_nand, void *ptr); ++uint32_t mtk_nand_header_put(const struct nand_header_type *hdr_nand, ++ void *ptr); + + #endif /* _MTK_NAND_HEADERS_H */