diff options
author | John Crispin <john@phrozen.org> | 2018-05-07 12:07:32 +0200 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2018-06-18 21:21:53 +0200 |
commit | da8fc1511fc83f6ba2cf0e1e1feadbe1b9b58f4d (patch) | |
tree | c8093d2f8d65636ed5a6e9b89fb68844b5ffdbc8 | |
parent | 763c0473c8137b236b6d7504b1c6df3d48f90ea4 (diff) | |
download | upstream-da8fc1511fc83f6ba2cf0e1e1feadbe1b9b58f4d.tar.gz upstream-da8fc1511fc83f6ba2cf0e1e1feadbe1b9b58f4d.tar.bz2 upstream-da8fc1511fc83f6ba2cf0e1e1feadbe1b9b58f4d.zip |
mediatek: backport upstream mediatek patches
Signed-off-by: John Crispin <john@phrozen.org>
(cherry picked from commit 050da2107a7eb2a571a8a3d0cee21cc6a44b72b8)
130 files changed, 21978 insertions, 99 deletions
diff --git a/target/linux/mediatek/32/target.mk b/target/linux/mediatek/32/target.mk deleted file mode 100644 index 0a444c2758..0000000000 --- a/target/linux/mediatek/32/target.mk +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright (C) 2009 OpenWrt.org -# - -SUBTARGET:=32 -BOARDNAME:=32bit -CPU_TYPE:=cortex-a7 -CPU_SUBTYPE:=neon-vfpv4 - -define Target/Description - Build firmware images for MediaTek 32bit ARM based boards. -endef - diff --git a/target/linux/mediatek/Makefile b/target/linux/mediatek/Makefile index 6b30f3b19d..7b8742da61 100644 --- a/target/linux/mediatek/Makefile +++ b/target/linux/mediatek/Makefile @@ -5,14 +5,12 @@ include $(TOPDIR)/rules.mk ARCH:=arm BOARD:=mediatek BOARDNAME:=MediaTek Ralink ARM -SUBTARGETS:=32 +SUBTARGETS:=mt7623 FEATURES:=squashfs nand ramdisk fpu MAINTAINER:=John Crispin <john@phrozen.org> KERNEL_PATCHVER:=4.14 -KERNELNAME:=Image dtbs zImage - include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ kmod-mt76 kmod-leds-gpio kmod-gpio-button-hotplug \ diff --git a/target/linux/mediatek/base-files/etc/inittab b/target/linux/mediatek/base-files/etc/inittab index b169c82745..9820e7144b 100644 --- a/target/linux/mediatek/base-files/etc/inittab +++ b/target/linux/mediatek/base-files/etc/inittab @@ -1,3 +1,3 @@ ::sysinit:/etc/init.d/rcS S boot ::shutdown:/etc/init.d/rcS K shutdown -ttyS0::askfirst:/usr/libexec/login.sh +::askconsole:/usr/libexec/login.sh diff --git a/target/linux/mediatek/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/base-files/lib/upgrade/platform.sh index 0429ca8b89..646ce0dc53 100755 --- a/target/linux/mediatek/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/base-files/lib/upgrade/platform.sh @@ -1,49 +1,29 @@ -# -# Copyright (C) 2016 OpenWrt.org -# +platform_do_upgrade() { + default_do_upgrade "$ARGV" +} -platform_do_upgrade() { - local tar_file="$1" - local board="$(board_name)" +PART_NAME=firmware - case "$(board_name)" in - mediatek,mt7623-rfb-nand-ephy |\ - mediatek,mt7623-rfb-nand) - nand_do_upgrade $1 - ;; - *) - echo "flashing kernel" - tar xf $tar_file sysupgrade-$board/kernel -O | mtd write - kernel +platform_check_image() { + local board=$(board_name) + local magic="$(get_magic_long "$1")" - echo "flashing rootfs" - tar xf $tar_file sysupgrade-$board/root -O | mtd write - rootfs + [ "$#" -gt 1 ] && return 1 - return 0 - ;; - esac -} + case "$board" in + bananapi,bpi-r2) + [ "$magic" != "27051956" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; -platform_check_image() { - local tar_file="$1" - local board=$(board_name) - - case "$board" in - bananapi,bpi-r2 |\ - mediatek,mt7623a-rfb-emmc) - local kernel_length=`(tar xf $tar_file sysupgrade-$board/kernel -O | wc -c) 2> /dev/null` - local rootfs_length=`(tar xf $tar_file sysupgrade-$board/root -O | wc -c) 2> /dev/null` - ;; - - *) + *) echo "Sysupgrade is not supported on your board yet." - return 1 - ;; - esac - - [ "$kernel_length" = 0 -o "$rootfs_length" = 0 ] && { - echo "The upgarde image is corrupt." - return 1 - } + return 1 + ;; + esac - return 0 -} + return 0 +} diff --git a/target/linux/mediatek/image/32.mk b/target/linux/mediatek/image/32.mk deleted file mode 100644 index 7b7e303124..0000000000 --- a/target/linux/mediatek/image/32.mk +++ /dev/null @@ -1,32 +0,0 @@ -define Image/BuilduImage - $(CP) $(KDIR)/zImage$(2) $(KDIR)/zImage-$(1)$(2) - cat $(LINUX_DIR)/arch/arm/boot/dts/$1.dtb >> $(KDIR)/zImage-$(1)$(2) - mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 -n 'MIPS OpenWrt Linux-$(LINUX_VERSION)' -d $(KDIR)/zImage-$(1)$(2) $(KDIR)/uImage-$(1)$(2) -endef - -define Image/Build/SysupgradeCombined - $(call Image/BuilduImage,$1) -ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) - $(call Image/BuilduImage,$1,-initramfs) - $(CP) $(KDIR)/uImage-$(1)-initramfs $(BIN_DIR)/$(IMG_PREFIX)-uImage-$(1)-initramfs -endif - mkdir -p "$(KDIR_TMP)/sysupgrade-$(3)/" - echo "BOARD=$(3)" > "$(KDIR_TMP)/sysupgrade-$(3)/CONTROL" - $(CP) "$(KDIR)/root.$(2)" "$(KDIR_TMP)/sysupgrade-$(3)/root" - $(CP) "$(KDIR)/uImage-$(1)" "$(KDIR_TMP)/sysupgrade-$(3)/kernel" - (cd "$(KDIR_TMP)"; $(TAR) cvf \ - "$(BIN_DIR)/$(IMG_PREFIX)-$(3)-sysupgrade.tar" sysupgrade-$(3) \ - $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \ - ) -endef - -COMPAT_BPI-R2:=bananapi,bpi-r2 -COMPAT_EMMC:=mediatek,mt7623a-rfb-emmc - -define Image/Build/squashfs - $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) - $(CP) $(KDIR)/root.squashfs $(BIN_DIR)/$(IMG_PREFIX)-root.squashfs - - $(call Image/Build/SysupgradeCombined,mt7623n-bananapi-bpi-r2,squashfs,$$(COMPAT_BPI-R2)) - $(call Image/Build/SysupgradeCombined,mt7623a-rfb-emmc,squashfs,$$(COMPAT_EMMC)) -endef diff --git a/target/linux/mediatek/image/Makefile b/target/linux/mediatek/image/Makefile index 6721259b20..9e2575b7ee 100644 --- a/target/linux/mediatek/image/Makefile +++ b/target/linux/mediatek/image/Makefile @@ -1,10 +1,42 @@ +# +# Copyright (C) 2012-2015 OpenWrt.org +# Copyright (C) 2016-2017 LEDE project +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk -include $(SUBTARGET).mk +# for arm +KERNEL_LOADADDR := 0x80008000 + +# build dtb +define Build/dtb + $(call Image/BuildDTB,$(DEVICE_DTS_DIR)/$(DEVICE_DTS).dts,$(DEVICE_DTS_DIR)/$(DEVICE_DTS).dtb) + $(CP) $(DEVICE_DTS_DIR)/$(DEVICE_DTS).dtb $(BIN_DIR)/ +endef + +# default all platform image(fit) build +define Device/Default + PROFILES = Default $$(DEVICE_NAME) + KERNEL_NAME := zImage + FILESYSTEMS := squashfs + DEVICE_DTS_DIR := $(DTS_DIR) + IMAGES := sysupgrade.bin + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + KERNEL_NAME := zImage + KERNEL := dtb | kernel-bin | append-dtb | uImage none + KERNEL_INITRAMFS := dtb | kernel-bin | append-dtb | uImage none +endef + +ifeq ($(SUBTARGET),mt7623) +include mt7623.mk +endif define Image/Build $(call Image/Build/$(1),$(1)) endef $(eval $(call BuildImage)) + diff --git a/target/linux/mediatek/image/mt7623.mk b/target/linux/mediatek/image/mt7623.mk new file mode 100644 index 0000000000..ddb4faa480 --- /dev/null +++ b/target/linux/mediatek/image/mt7623.mk @@ -0,0 +1,6 @@ +define Device/7623n-bananapi-bpi-r2 + DEVICE_TITLE := MTK7623n BananaPi R2 + DEVICE_DTS := mt7623n-bananapi-bpi-r2 +endef + +TARGET_DEVICES += 7623n-bananapi-bpi-r2 diff --git a/target/linux/mediatek/config-4.14 b/target/linux/mediatek/mt7623/config-4.14 index 02365ca2c4..4cdd0e76e1 100644 --- a/target/linux/mediatek/config-4.14 +++ b/target/linux/mediatek/mt7623/config-4.14 @@ -1,4 +1,3 @@ -# CONFIG_AHCI_MTK is not set # CONFIG_AIO is not set CONFIG_ALIGNMENT_TRAP=y CONFIG_ARCH_CLOCKSOURCE_DATA=y @@ -63,7 +62,7 @@ CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y CONFIG_CMDLINE="earlyprintk console=ttyS0,115200 rootfstype=squashfs,jffs2" -CONFIG_CMDLINE_FORCE=y +CONFIG_CMDLINE_FROM_BOOTLOADER=y CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK_MEDIATEK=y CONFIG_COMMON_CLK_MT2701=y @@ -73,6 +72,7 @@ CONFIG_COMMON_CLK_MT2701_HIFSYS=y CONFIG_COMMON_CLK_MT2701_IMGSYS=y CONFIG_COMMON_CLK_MT2701_MMSYS=y CONFIG_COMMON_CLK_MT2701_VDECSYS=y +# CONFIG_COMMON_CLK_MT7622 is not set # CONFIG_COMMON_CLK_MT8135 is not set # CONFIG_COMMON_CLK_MT8173 is not set CONFIG_COMPACTION=y @@ -257,7 +257,6 @@ CONFIG_IIO=y # CONFIG_IIO_BUFFER is not set # CONFIG_IIO_TRIGGER is not set CONFIG_INITRAMFS_COMPRESSION="" -# CONFIG_INITRAMFS_FORCE is not set CONFIG_INITRAMFS_ROOT_GID=1000 CONFIG_INITRAMFS_ROOT_UID=1000 CONFIG_INITRAMFS_SOURCE="/openwrt/trunk/build_dir/target-arm_cortex-a7_musl-1.1.14_eabi/root-mediatek /openwrt/trunk/target/linux/generic/image/initramfs-base-files.txt" @@ -276,11 +275,11 @@ CONFIG_LIBFDT=y CONFIG_LOCK_SPIN_ON_OWNER=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y -CONFIG_MACH_MT2701=y +# CONFIG_MACH_MT2701 is not set # CONFIG_MACH_MT6589 is not set # CONFIG_MACH_MT6592 is not set CONFIG_MACH_MT7623=y -CONFIG_MACH_MT8127=y +# CONFIG_MACH_MT8127 is not set # CONFIG_MACH_MT8135 is not set CONFIG_MAGIC_SYSRQ=y CONFIG_MDIO_BITBANG=y @@ -311,6 +310,8 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_ECC=y CONFIG_MTD_NAND_MTK=y CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y CONFIG_MTD_UBI=y CONFIG_MTD_UBI_BEB_LIMIT=20 CONFIG_MTD_UBI_BLOCK=y @@ -318,6 +319,7 @@ CONFIG_MTD_UBI_BLOCK=y # CONFIG_MTD_UBI_GLUEBI is not set CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MTK_EFUSE=y +# CONFIG_MTK_HSDMA is not set CONFIG_MTK_INFRACFG=y # CONFIG_MTK_IOMMU is not set # CONFIG_MTK_IOMMU_V1 is not set @@ -377,7 +379,6 @@ CONFIG_PHY_MTK_TPHY=y CONFIG_PINCTRL=y CONFIG_PINCTRL_MT2701=y CONFIG_PINCTRL_MT6397=y -CONFIG_PINCTRL_MT8127=y CONFIG_PINCTRL_MTK=y CONFIG_PM=y CONFIG_PM_CLK=y @@ -422,6 +423,7 @@ CONFIG_RPS=y CONFIG_RTC_CLASS=y # CONFIG_RTC_DRV_CMOS is not set # CONFIG_RTC_DRV_MT6397 is not set +# CONFIG_RTC_DRV_MT7622 is not set CONFIG_RTC_I2C_AND_SPI=y CONFIG_RWSEM_SPIN_ON_OWNER=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -470,7 +472,6 @@ CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_USB=y CONFIG_USB_COMMON=y # CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_MTU3 is not set CONFIG_USB_SUPPORT=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_MTK=y diff --git a/target/linux/mediatek/32/profiles/default.mk b/target/linux/mediatek/mt7623/profiles/default.mk index 2ef570ba66..2ef570ba66 100644 --- a/target/linux/mediatek/32/profiles/default.mk +++ b/target/linux/mediatek/mt7623/profiles/default.mk diff --git a/target/linux/mediatek/mt7623/target.mk b/target/linux/mediatek/mt7623/target.mk new file mode 100644 index 0000000000..9f995f9951 --- /dev/null +++ b/target/linux/mediatek/mt7623/target.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2009 OpenWrt.org +# + +ARCH:=arm +SUBTARGET:=mt7623 +BOARDNAME:=MT7623 +CPU_TYPE:=cortex-a7 +CPU_SUBTYPE:=neon-vfpv4 + +KERNELNAME:=Image dtbs zImage + +define Target/Description + Build firmware images for MediaTek mt7623 ARM based boards. +endef + diff --git a/target/linux/mediatek/patches-4.14/0101-reset-mediatek-add-reset-controller-dt-bindings-requ.patch b/target/linux/mediatek/patches-4.14/0101-reset-mediatek-add-reset-controller-dt-bindings-requ.patch new file mode 100644 index 0000000000..64f3107162 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0101-reset-mediatek-add-reset-controller-dt-bindings-requ.patch @@ -0,0 +1,120 @@ +From 5d6a82632eb7258c8ca49cc96c18b8b4071b6639 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 20 Sep 2017 17:40:16 +0800 +Subject: [PATCH 101/224] reset: mediatek: add reset controller dt-bindings + required header for MT7622 SoC + +Add the reset controller dt-bindings exported from infracfg, pericfg, +hifsys and ethsys which could be found on MT7622 SoC. So that we can +reference them from within a device-tree file. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> +--- + include/dt-bindings/reset/mt7622-reset.h | 94 ++++++++++++++++++++++++++++++++ + 1 file changed, 94 insertions(+) + create mode 100644 include/dt-bindings/reset/mt7622-reset.h + +diff --git a/include/dt-bindings/reset/mt7622-reset.h b/include/dt-bindings/reset/mt7622-reset.h +new file mode 100644 +index 000000000000..234052f80417 +--- /dev/null ++++ b/include/dt-bindings/reset/mt7622-reset.h +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7622 ++#define _DT_BINDINGS_RESET_CONTROLLER_MT7622 ++ ++/* INFRACFG resets */ ++#define MT7622_INFRA_EMI_REG_RST 0 ++#define MT7622_INFRA_DRAMC0_A0_RST 1 ++#define MT7622_INFRA_APCIRQ_EINT_RST 3 ++#define MT7622_INFRA_APXGPT_RST 4 ++#define MT7622_INFRA_SCPSYS_RST 5 ++#define MT7622_INFRA_PMIC_WRAP_RST 7 ++#define MT7622_INFRA_IRRX_RST 9 ++#define MT7622_INFRA_EMI_RST 16 ++#define MT7622_INFRA_WED0_RST 17 ++#define MT7622_INFRA_DRAMC_RST 18 ++#define MT7622_INFRA_CCI_INTF_RST 19 ++#define MT7622_INFRA_TRNG_RST 21 ++#define MT7622_INFRA_SYSIRQ_RST 22 ++#define MT7622_INFRA_WED1_RST 25 ++ ++/* PERICFG Subsystem resets */ ++#define MT7622_PERI_UART0_SW_RST 0 ++#define MT7622_PERI_UART1_SW_RST 1 ++#define MT7622_PERI_UART2_SW_RST 2 ++#define MT7622_PERI_UART3_SW_RST 3 ++#define MT7622_PERI_UART4_SW_RST 4 ++#define MT7622_PERI_BTIF_SW_RST 6 ++#define MT7622_PERI_PWM_SW_RST 8 ++#define MT7622_PERI_AUXADC_SW_RST 10 ++#define MT7622_PERI_DMA_SW_RST 11 ++#define MT7622_PERI_IRTX_SW_RST 13 ++#define MT7622_PERI_NFI_SW_RST 14 ++#define MT7622_PERI_THERM_SW_RST 16 ++#define MT7622_PERI_MSDC0_SW_RST 19 ++#define MT7622_PERI_MSDC1_SW_RST 20 ++#define MT7622_PERI_I2C0_SW_RST 22 ++#define MT7622_PERI_I2C1_SW_RST 23 ++#define MT7622_PERI_I2C2_SW_RST 24 ++#define MT7622_PERI_SPI0_SW_RST 33 ++#define MT7622_PERI_SPI1_SW_RST 34 ++#define MT7622_PERI_FLASHIF_SW_RST 36 ++ ++/* TOPRGU resets */ ++#define MT7622_TOPRGU_INFRA_RST 0 ++#define MT7622_TOPRGU_ETHDMA_RST 1 ++#define MT7622_TOPRGU_DDRPHY_RST 6 ++#define MT7622_TOPRGU_INFRA_AO_RST 8 ++#define MT7622_TOPRGU_CONN_RST 9 ++#define MT7622_TOPRGU_APMIXED_RST 10 ++#define MT7622_TOPRGU_CONN_MCU_RST 12 ++ ++/* PCIe/SATA Subsystem resets */ ++#define MT7622_SATA_PHY_REG_RST 12 ++#define MT7622_SATA_PHY_SW_RST 13 ++#define MT7622_SATA_AXI_BUS_RST 15 ++#define MT7622_PCIE1_CORE_RST 19 ++#define MT7622_PCIE1_MMIO_RST 20 ++#define MT7622_PCIE1_HRST 21 ++#define MT7622_PCIE1_USER_RST 22 ++#define MT7622_PCIE1_PIPE_RST 23 ++#define MT7622_PCIE0_CORE_RST 27 ++#define MT7622_PCIE0_MMIO_RST 28 ++#define MT7622_PCIE0_HRST 29 ++#define MT7622_PCIE0_USER_RST 30 ++#define MT7622_PCIE0_PIPE_RST 31 ++ ++/* SSUSB Subsystem resets */ ++#define MT7622_SSUSB_PHY_PWR_RST 3 ++#define MT7622_SSUSB_MAC_PWR_RST 4 ++ ++/* ETHSYS Subsystem resets */ ++#define MT7622_ETHSYS_SYS_RST 0 ++#define MT7622_ETHSYS_MCM_RST 2 ++#define MT7622_ETHSYS_HSDMA_RST 5 ++#define MT7622_ETHSYS_FE_RST 6 ++#define MT7622_ETHSYS_GMAC_RST 23 ++#define MT7622_ETHSYS_EPHY_RST 24 ++#define MT7622_ETHSYS_CRYPTO_RST 29 ++#define MT7622_ETHSYS_PPE_RST 31 ++ ++#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7622 */ +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0102-soc-mediatek-pwrap-fixup-warnings-from-coding-style.patch b/target/linux/mediatek/patches-4.14/0102-soc-mediatek-pwrap-fixup-warnings-from-coding-style.patch new file mode 100644 index 0000000000..408de3af9f --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0102-soc-mediatek-pwrap-fixup-warnings-from-coding-style.patch @@ -0,0 +1,76 @@ +From c7cb4b7e750fc9a23cd80ef34ad4ef8a47f895d5 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 21 Sep 2017 16:26:57 +0800 +Subject: [PATCH 102/224] soc: mediatek: pwrap: fixup warnings from coding + style + +fixup those warnings such as lines over 80 words and parenthesis +alignment which would be complained by checkpatch.pl. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/mtk-pmic-wrap.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index c2048382830f..f095faac1e04 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -827,7 +827,8 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) + /* wait for cipher data ready@PMIC */ + ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready); + if (ret) { +- dev_err(wrp->dev, "timeout waiting for cipher data ready@PMIC\n"); ++ dev_err(wrp->dev, ++ "timeout waiting for cipher data ready@PMIC\n"); + return ret; + } + +@@ -1159,23 +1160,27 @@ static int pwrap_probe(struct platform_device *pdev) + if (IS_ERR(wrp->bridge_base)) + return PTR_ERR(wrp->bridge_base); + +- wrp->rstc_bridge = devm_reset_control_get(wrp->dev, "pwrap-bridge"); ++ wrp->rstc_bridge = devm_reset_control_get(wrp->dev, ++ "pwrap-bridge"); + if (IS_ERR(wrp->rstc_bridge)) { + ret = PTR_ERR(wrp->rstc_bridge); +- dev_dbg(wrp->dev, "cannot get pwrap-bridge reset: %d\n", ret); ++ dev_dbg(wrp->dev, ++ "cannot get pwrap-bridge reset: %d\n", ret); + return ret; + } + } + + wrp->clk_spi = devm_clk_get(wrp->dev, "spi"); + if (IS_ERR(wrp->clk_spi)) { +- dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_spi)); ++ dev_dbg(wrp->dev, "failed to get clock: %ld\n", ++ PTR_ERR(wrp->clk_spi)); + return PTR_ERR(wrp->clk_spi); + } + + wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap"); + if (IS_ERR(wrp->clk_wrap)) { +- dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_wrap)); ++ dev_dbg(wrp->dev, "failed to get clock: %ld\n", ++ PTR_ERR(wrp->clk_wrap)); + return PTR_ERR(wrp->clk_wrap); + } + +@@ -1220,8 +1225,9 @@ static int pwrap_probe(struct platform_device *pdev) + pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); + + irq = platform_get_irq(pdev, 0); +- ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH, +- "mt-pmic-pwrap", wrp); ++ ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, ++ IRQF_TRIGGER_HIGH, ++ "mt-pmic-pwrap", wrp); + if (ret) + goto err_out2; + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0104-usb-mtu3-support-option-to-disable-usb3-ports.patch b/target/linux/mediatek/patches-4.14/0104-usb-mtu3-support-option-to-disable-usb3-ports.patch new file mode 100644 index 0000000000..51b5bcffc5 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0104-usb-mtu3-support-option-to-disable-usb3-ports.patch @@ -0,0 +1,117 @@ +From 7a46c3488c48a0fbe313ed25c12af3fb3af48a01 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:38 +0800 +Subject: [PATCH 104/224] usb: mtu3: support option to disable usb3 ports + +Add support to disable specific usb3 ports, it's useful when +usb3 phy is shared with PCIe or SATA, because we should disable +the corresponding usb3 port if the phy is used by PCIe or SATA. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3.h | 3 +++ + drivers/usb/mtu3/mtu3_host.c | 16 +++++++++++++--- + drivers/usb/mtu3/mtu3_plat.c | 8 ++++++-- + 3 files changed, 22 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h +index b26fffc58446..112723d6e7bc 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -210,6 +210,8 @@ struct otg_switch_mtk { + * host only, device only or dual-role mode + * @u2_ports: number of usb2.0 host ports + * @u3_ports: number of usb3.0 host ports ++ * @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to ++ * disable u3port0, bit1==1 to disable u3port1,... etc + * @dbgfs_root: only used when supports manual dual-role switch via debugfs + * @wakeup_en: it's true when supports remote wakeup in host mode + * @wk_deb_p0: port0's wakeup debounce clock +@@ -232,6 +234,7 @@ struct ssusb_mtk { + bool is_host; + int u2_ports; + int u3_ports; ++ int u3p_dis_msk; + struct dentry *dbgfs_root; + /* usb wakeup for host mode */ + bool wakeup_en; +diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c +index e42d308b8dc2..4dd9508a60b5 100644 +--- a/drivers/usb/mtu3/mtu3_host.c ++++ b/drivers/usb/mtu3/mtu3_host.c +@@ -151,6 +151,7 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb) + void __iomem *ibase = ssusb->ippc_base; + int num_u3p = ssusb->u3_ports; + int num_u2p = ssusb->u2_ports; ++ int u3_ports_disabed; + u32 check_clk; + u32 value; + int i; +@@ -158,8 +159,14 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb) + /* power on host ip */ + mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL1, SSUSB_IP_HOST_PDN); + +- /* power on and enable all u3 ports */ ++ /* power on and enable u3 ports except skipped ones */ ++ u3_ports_disabed = 0; + for (i = 0; i < num_u3p; i++) { ++ if ((0x1 << i) & ssusb->u3p_dis_msk) { ++ u3_ports_disabed++; ++ continue; ++ } ++ + value = mtu3_readl(ibase, SSUSB_U3_CTRL(i)); + value &= ~(SSUSB_U3_PORT_PDN | SSUSB_U3_PORT_DIS); + value |= SSUSB_U3_PORT_HOST_SEL; +@@ -175,7 +182,7 @@ int ssusb_host_enable(struct ssusb_mtk *ssusb) + } + + check_clk = SSUSB_XHCI_RST_B_STS; +- if (num_u3p) ++ if (num_u3p > u3_ports_disabed) + check_clk = SSUSB_U3_MAC_RST_B_STS; + + return ssusb_check_clocks(ssusb, check_clk); +@@ -190,8 +197,11 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend) + int ret; + int i; + +- /* power down and disable all u3 ports */ ++ /* power down and disable u3 ports except skipped ones */ + for (i = 0; i < num_u3p; i++) { ++ if ((0x1 << i) & ssusb->u3p_dis_msk) ++ continue; ++ + value = mtu3_readl(ibase, SSUSB_U3_CTRL(i)); + value |= SSUSB_U3_PORT_PDN; + value |= suspend ? 0 : SSUSB_U3_PORT_DIS; +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index 088e3e685c4f..9edad30c8ae5 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -276,6 +276,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + if (ret) + return ret; + ++ /* optional property, ignore the error if it does not exist */ ++ of_property_read_u32(node, "mediatek,u3p-dis-msk", ++ &ssusb->u3p_dis_msk); ++ + if (ssusb->dr_mode != USB_DR_MODE_OTG) + return 0; + +@@ -304,8 +308,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + } + } + +- dev_info(dev, "dr_mode: %d, is_u3_dr: %d\n", +- ssusb->dr_mode, otg_sx->is_u3_drd); ++ dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk:%x\n", ++ ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk); + + return 0; + } +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0105-usb-mtu3-remove-dummy-wakeup-debounce-clocks.patch b/target/linux/mediatek/patches-4.14/0105-usb-mtu3-remove-dummy-wakeup-debounce-clocks.patch new file mode 100644 index 0000000000..adf1cec90b --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0105-usb-mtu3-remove-dummy-wakeup-debounce-clocks.patch @@ -0,0 +1,126 @@ +From 50005796f146351dc9c34bbf8898b305c562e964 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:39 +0800 +Subject: [PATCH 105/224] usb: mtu3: remove dummy wakeup debounce clocks + +The wakeup debounce clocks for each ports in fact are not +needed, so remove them. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3.h | 4 ---- + drivers/usb/mtu3/mtu3_host.c | 57 ++++---------------------------------------- + 2 files changed, 4 insertions(+), 57 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h +index 112723d6e7bc..6d3278e46431 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -214,8 +214,6 @@ struct otg_switch_mtk { + * disable u3port0, bit1==1 to disable u3port1,... etc + * @dbgfs_root: only used when supports manual dual-role switch via debugfs + * @wakeup_en: it's true when supports remote wakeup in host mode +- * @wk_deb_p0: port0's wakeup debounce clock +- * @wk_deb_p1: it's optional, and depends on port1 is supported or not + */ + struct ssusb_mtk { + struct device *dev; +@@ -238,8 +236,6 @@ struct ssusb_mtk { + struct dentry *dbgfs_root; + /* usb wakeup for host mode */ + bool wakeup_en; +- struct clk *wk_deb_p0; +- struct clk *wk_deb_p1; + struct regmap *pericfg; + }; + +diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c +index 4dd9508a60b5..edcc59148171 100644 +--- a/drivers/usb/mtu3/mtu3_host.c ++++ b/drivers/usb/mtu3/mtu3_host.c +@@ -79,20 +79,6 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, + if (!ssusb->wakeup_en) + return 0; + +- ssusb->wk_deb_p0 = devm_clk_get(dev, "wakeup_deb_p0"); +- if (IS_ERR(ssusb->wk_deb_p0)) { +- dev_err(dev, "fail to get wakeup_deb_p0\n"); +- return PTR_ERR(ssusb->wk_deb_p0); +- } +- +- if (of_property_read_bool(dn, "wakeup_deb_p1")) { +- ssusb->wk_deb_p1 = devm_clk_get(dev, "wakeup_deb_p1"); +- if (IS_ERR(ssusb->wk_deb_p1)) { +- dev_err(dev, "fail to get wakeup_deb_p1\n"); +- return PTR_ERR(ssusb->wk_deb_p1); +- } +- } +- + ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn, + "mediatek,syscon-wakeup"); + if (IS_ERR(ssusb->pericfg)) { +@@ -103,36 +89,6 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, + return 0; + } + +-static int ssusb_wakeup_clks_enable(struct ssusb_mtk *ssusb) +-{ +- int ret; +- +- ret = clk_prepare_enable(ssusb->wk_deb_p0); +- if (ret) { +- dev_err(ssusb->dev, "failed to enable wk_deb_p0\n"); +- goto usb_p0_err; +- } +- +- ret = clk_prepare_enable(ssusb->wk_deb_p1); +- if (ret) { +- dev_err(ssusb->dev, "failed to enable wk_deb_p1\n"); +- goto usb_p1_err; +- } +- +- return 0; +- +-usb_p1_err: +- clk_disable_unprepare(ssusb->wk_deb_p0); +-usb_p0_err: +- return -EINVAL; +-} +- +-static void ssusb_wakeup_clks_disable(struct ssusb_mtk *ssusb) +-{ +- clk_disable_unprepare(ssusb->wk_deb_p1); +- clk_disable_unprepare(ssusb->wk_deb_p0); +-} +- + static void host_ports_num_get(struct ssusb_mtk *ssusb) + { + u32 xhci_cap; +@@ -286,19 +242,14 @@ void ssusb_host_exit(struct ssusb_mtk *ssusb) + + int ssusb_wakeup_enable(struct ssusb_mtk *ssusb) + { +- int ret = 0; +- +- if (ssusb->wakeup_en) { +- ret = ssusb_wakeup_clks_enable(ssusb); ++ if (ssusb->wakeup_en) + ssusb_wakeup_ip_sleep_en(ssusb); +- } +- return ret; ++ ++ return 0; + } + + void ssusb_wakeup_disable(struct ssusb_mtk *ssusb) + { +- if (ssusb->wakeup_en) { ++ if (ssusb->wakeup_en) + ssusb_wakeup_ip_sleep_dis(ssusb); +- ssusb_wakeup_clks_disable(ssusb); +- } + } +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0106-usb-mtu3-add-optional-mcu-and-dma-bus-clocks.patch b/target/linux/mediatek/patches-4.14/0106-usb-mtu3-add-optional-mcu-and-dma-bus-clocks.patch new file mode 100644 index 0000000000..93a8c65294 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0106-usb-mtu3-add-optional-mcu-and-dma-bus-clocks.patch @@ -0,0 +1,233 @@ +From 677805f6d83524717b46b3cde74aa455dbf6299f Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:40 +0800 +Subject: [PATCH 106/224] usb: mtu3: add optional mcu and dma bus clocks + +There are mcu_bus and dma_bus clocks needed to be turned on/off by +driver on some SoCs, so add them as optional ones + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3.h | 5 ++ + drivers/usb/mtu3/mtu3_plat.c | 121 +++++++++++++++++++++++++++++-------------- + 2 files changed, 86 insertions(+), 40 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h +index 6d3278e46431..2795294ec92a 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -206,6 +206,9 @@ struct otg_switch_mtk { + * @ippc_base: register base address of IP Power and Clock interface (IPPC) + * @vusb33: usb3.3V shared by device/host IP + * @sys_clk: system clock of mtu3, shared by device/host IP ++ * @ref_clk: reference clock ++ * @mcu_clk: mcu_bus_ck clock for AHB bus etc ++ * @dma_clk: dma_bus_ck clock for AXI bus etc + * @dr_mode: works in which mode: + * host only, device only or dual-role mode + * @u2_ports: number of usb2.0 host ports +@@ -226,6 +229,8 @@ struct ssusb_mtk { + struct regulator *vusb33; + struct clk *sys_clk; + struct clk *ref_clk; ++ struct clk *mcu_clk; ++ struct clk *dma_clk; + /* otg */ + struct otg_switch_mtk otg_switch; + enum usb_dr_mode dr_mode; +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index 9edad30c8ae5..fb8992011bde 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -110,15 +110,9 @@ static void ssusb_phy_power_off(struct ssusb_mtk *ssusb) + phy_power_off(ssusb->phys[i]); + } + +-static int ssusb_rscs_init(struct ssusb_mtk *ssusb) ++static int ssusb_clks_enable(struct ssusb_mtk *ssusb) + { +- int ret = 0; +- +- ret = regulator_enable(ssusb->vusb33); +- if (ret) { +- dev_err(ssusb->dev, "failed to enable vusb33\n"); +- goto vusb33_err; +- } ++ int ret; + + ret = clk_prepare_enable(ssusb->sys_clk); + if (ret) { +@@ -132,6 +126,52 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb) + goto ref_clk_err; + } + ++ ret = clk_prepare_enable(ssusb->mcu_clk); ++ if (ret) { ++ dev_err(ssusb->dev, "failed to enable mcu_clk\n"); ++ goto mcu_clk_err; ++ } ++ ++ ret = clk_prepare_enable(ssusb->dma_clk); ++ if (ret) { ++ dev_err(ssusb->dev, "failed to enable dma_clk\n"); ++ goto dma_clk_err; ++ } ++ ++ return 0; ++ ++dma_clk_err: ++ clk_disable_unprepare(ssusb->mcu_clk); ++mcu_clk_err: ++ clk_disable_unprepare(ssusb->ref_clk); ++ref_clk_err: ++ clk_disable_unprepare(ssusb->sys_clk); ++sys_clk_err: ++ return ret; ++} ++ ++static void ssusb_clks_disable(struct ssusb_mtk *ssusb) ++{ ++ clk_disable_unprepare(ssusb->dma_clk); ++ clk_disable_unprepare(ssusb->mcu_clk); ++ clk_disable_unprepare(ssusb->ref_clk); ++ clk_disable_unprepare(ssusb->sys_clk); ++} ++ ++static int ssusb_rscs_init(struct ssusb_mtk *ssusb) ++{ ++ int ret = 0; ++ ++ ret = regulator_enable(ssusb->vusb33); ++ if (ret) { ++ dev_err(ssusb->dev, "failed to enable vusb33\n"); ++ goto vusb33_err; ++ } ++ ++ ret = ssusb_clks_enable(ssusb); ++ if (ret) ++ goto clks_err; ++ + ret = ssusb_phy_init(ssusb); + if (ret) { + dev_err(ssusb->dev, "failed to init phy\n"); +@@ -149,20 +189,16 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb) + phy_err: + ssusb_phy_exit(ssusb); + phy_init_err: +- clk_disable_unprepare(ssusb->ref_clk); +-ref_clk_err: +- clk_disable_unprepare(ssusb->sys_clk); +-sys_clk_err: ++ ssusb_clks_disable(ssusb); ++clks_err: + regulator_disable(ssusb->vusb33); + vusb33_err: +- + return ret; + } + + static void ssusb_rscs_exit(struct ssusb_mtk *ssusb) + { +- clk_disable_unprepare(ssusb->sys_clk); +- clk_disable_unprepare(ssusb->ref_clk); ++ ssusb_clks_disable(ssusb); + regulator_disable(ssusb->vusb33); + ssusb_phy_power_off(ssusb); + ssusb_phy_exit(ssusb); +@@ -203,6 +239,19 @@ static int get_iddig_pinctrl(struct ssusb_mtk *ssusb) + return 0; + } + ++/* ignore the error if the clock does not exist */ ++static struct clk *get_optional_clk(struct device *dev, const char *id) ++{ ++ struct clk *opt_clk; ++ ++ opt_clk = devm_clk_get(dev, id); ++ /* ignore error number except EPROBE_DEFER */ ++ if (IS_ERR(opt_clk) && (PTR_ERR(opt_clk) != -EPROBE_DEFER)) ++ opt_clk = NULL; ++ ++ return opt_clk; ++} ++ + static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + { + struct device_node *node = pdev->dev.of_node; +@@ -225,18 +274,17 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + return PTR_ERR(ssusb->sys_clk); + } + +- /* +- * reference clock is usually a "fixed-clock", make it optional +- * for backward compatibility and ignore the error if it does +- * not exist. +- */ +- ssusb->ref_clk = devm_clk_get(dev, "ref_ck"); +- if (IS_ERR(ssusb->ref_clk)) { +- if (PTR_ERR(ssusb->ref_clk) == -EPROBE_DEFER) +- return -EPROBE_DEFER; ++ ssusb->ref_clk = get_optional_clk(dev, "ref_ck"); ++ if (IS_ERR(ssusb->ref_clk)) ++ return PTR_ERR(ssusb->ref_clk); + +- ssusb->ref_clk = NULL; +- } ++ ssusb->mcu_clk = get_optional_clk(dev, "mcu_ck"); ++ if (IS_ERR(ssusb->mcu_clk)) ++ return PTR_ERR(ssusb->mcu_clk); ++ ++ ssusb->dma_clk = get_optional_clk(dev, "dma_ck"); ++ if (IS_ERR(ssusb->dma_clk)) ++ return PTR_ERR(ssusb->dma_clk); + + ssusb->num_phys = of_count_phandle_with_args(node, + "phys", "#phy-cells"); +@@ -451,8 +499,7 @@ static int __maybe_unused mtu3_suspend(struct device *dev) + + ssusb_host_disable(ssusb, true); + ssusb_phy_power_off(ssusb); +- clk_disable_unprepare(ssusb->sys_clk); +- clk_disable_unprepare(ssusb->ref_clk); ++ ssusb_clks_disable(ssusb); + ssusb_wakeup_enable(ssusb); + + return 0; +@@ -470,27 +517,21 @@ static int __maybe_unused mtu3_resume(struct device *dev) + return 0; + + ssusb_wakeup_disable(ssusb); +- ret = clk_prepare_enable(ssusb->sys_clk); +- if (ret) +- goto err_sys_clk; +- +- ret = clk_prepare_enable(ssusb->ref_clk); ++ ret = ssusb_clks_enable(ssusb); + if (ret) +- goto err_ref_clk; ++ goto clks_err; + + ret = ssusb_phy_power_on(ssusb); + if (ret) +- goto err_power_on; ++ goto phy_err; + + ssusb_host_enable(ssusb); + + return 0; + +-err_power_on: +- clk_disable_unprepare(ssusb->ref_clk); +-err_ref_clk: +- clk_disable_unprepare(ssusb->sys_clk); +-err_sys_clk: ++phy_err: ++ ssusb_clks_disable(ssusb); ++clks_err: + return ret; + } + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0107-usb-mtu3-support-36-bit-DMA-address.patch b/target/linux/mediatek/patches-4.14/0107-usb-mtu3-support-36-bit-DMA-address.patch new file mode 100644 index 0000000000..652116d0da --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0107-usb-mtu3-support-36-bit-DMA-address.patch @@ -0,0 +1,373 @@ +From d366bf086a61b7a895d8819a3c1349b9c6b8e40f Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:41 +0800 +Subject: [PATCH 107/224] usb: mtu3: support 36-bit DMA address + +add support for 36-bit DMA address + +[ Felipe Balbi: fix printk format for dma_addr_t ] + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3.h | 17 ++++++- + drivers/usb/mtu3/mtu3_core.c | 34 +++++++++++++- + drivers/usb/mtu3/mtu3_hw_regs.h | 10 ++++ + drivers/usb/mtu3/mtu3_qmu.c | 102 +++++++++++++++++++++++++++++++++------- + 4 files changed, 142 insertions(+), 21 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h +index 2795294ec92a..ef2dc92a2109 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -46,6 +46,9 @@ struct mtu3_request; + #define MU3D_EP_RXCR1(epnum) (U3D_RX1CSR1 + (((epnum) - 1) * 0x10)) + #define MU3D_EP_RXCR2(epnum) (U3D_RX1CSR2 + (((epnum) - 1) * 0x10)) + ++#define USB_QMU_TQHIAR(epnum) (U3D_TXQHIAR1 + (((epnum) - 1) * 0x4)) ++#define USB_QMU_RQHIAR(epnum) (U3D_RXQHIAR1 + (((epnum) - 1) * 0x4)) ++ + #define USB_QMU_RQCSR(epnum) (U3D_RXQCSR1 + (((epnum) - 1) * 0x10)) + #define USB_QMU_RQSAR(epnum) (U3D_RXQSAR1 + (((epnum) - 1) * 0x10)) + #define USB_QMU_RQCPR(epnum) (U3D_RXQCPR1 + (((epnum) - 1) * 0x10)) +@@ -138,23 +141,33 @@ struct mtu3_fifo_info { + * Checksum value is calculated over the 16 bytes of the GPD by default; + * @data_buf_len (RX ONLY): This value indicates the length of + * the assigned data buffer ++ * @tx_ext_addr (TX ONLY): [3:0] are 4 extension bits of @buffer, ++ * [7:4] are 4 extension bits of @next_gpd + * @next_gpd: Physical address of the next GPD + * @buffer: Physical address of the data buffer + * @buf_len: + * (TX): This value indicates the length of the assigned data buffer + * (RX): The total length of data received + * @ext_len: reserved ++ * @rx_ext_addr(RX ONLY): [3:0] are 4 extension bits of @buffer, ++ * [7:4] are 4 extension bits of @next_gpd + * @ext_flag: + * bit5 (TX ONLY): Zero Length Packet (ZLP), + */ + struct qmu_gpd { + __u8 flag; + __u8 chksum; +- __le16 data_buf_len; ++ union { ++ __le16 data_buf_len; ++ __le16 tx_ext_addr; ++ }; + __le32 next_gpd; + __le32 buffer; + __le16 buf_len; +- __u8 ext_len; ++ union { ++ __u8 ext_len; ++ __u8 rx_ext_addr; ++ }; + __u8 ext_flag; + } __packed; + +diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c +index 947579842ad7..cd4528f5f337 100644 +--- a/drivers/usb/mtu3/mtu3_core.c ++++ b/drivers/usb/mtu3/mtu3_core.c +@@ -17,6 +17,7 @@ + * + */ + ++#include <linux/dma-mapping.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/of_address.h> +@@ -759,7 +760,31 @@ static void mtu3_hw_exit(struct mtu3 *mtu) + mtu3_mem_free(mtu); + } + +-/*-------------------------------------------------------------------------*/ ++/** ++ * we set 32-bit DMA mask by default, here check whether the controller ++ * supports 36-bit DMA or not, if it does, set 36-bit DMA mask. ++ */ ++static int mtu3_set_dma_mask(struct mtu3 *mtu) ++{ ++ struct device *dev = mtu->dev; ++ bool is_36bit = false; ++ int ret = 0; ++ u32 value; ++ ++ value = mtu3_readl(mtu->mac_base, U3D_MISC_CTRL); ++ if (value & DMA_ADDR_36BIT) { ++ is_36bit = true; ++ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36)); ++ /* If set 36-bit DMA mask fails, fall back to 32-bit DMA mask */ ++ if (ret) { ++ is_36bit = false; ++ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); ++ } ++ } ++ dev_info(dev, "dma mask: %s bits\n", is_36bit ? "36" : "32"); ++ ++ return ret; ++} + + int ssusb_gadget_init(struct ssusb_mtk *ssusb) + { +@@ -820,6 +845,12 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) + return ret; + } + ++ ret = mtu3_set_dma_mask(mtu); ++ if (ret) { ++ dev_err(dev, "mtu3 set dma_mask failed:%d\n", ret); ++ goto dma_mask_err; ++ } ++ + ret = devm_request_irq(dev, mtu->irq, mtu3_irq, 0, dev_name(dev), mtu); + if (ret) { + dev_err(dev, "request irq %d failed!\n", mtu->irq); +@@ -845,6 +876,7 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) + gadget_err: + device_init_wakeup(dev, false); + ++dma_mask_err: + irq_err: + mtu3_hw_exit(mtu); + ssusb->u3d = NULL; +diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h +index 06b29664470f..b6059752dc12 100644 +--- a/drivers/usb/mtu3/mtu3_hw_regs.h ++++ b/drivers/usb/mtu3/mtu3_hw_regs.h +@@ -58,6 +58,8 @@ + #define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404) + #define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408) + #define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C) ++#define U3D_TXQHIAR1 (SSUSB_DEV_BASE + 0x0484) ++#define U3D_RXQHIAR1 (SSUSB_DEV_BASE + 0x04C4) + + #define U3D_TXQCSR1 (SSUSB_DEV_BASE + 0x0510) + #define U3D_TXQSAR1 (SSUSB_DEV_BASE + 0x0514) +@@ -189,6 +191,13 @@ + #define QMU_RX_COZ(x) (BIT(16) << (x)) + #define QMU_RX_ZLP(x) (BIT(0) << (x)) + ++/* U3D_TXQHIAR1 */ ++/* U3D_RXQHIAR1 */ ++#define QMU_LAST_DONE_PTR_HI(x) (((x) >> 16) & 0xf) ++#define QMU_CUR_GPD_ADDR_HI(x) (((x) >> 8) & 0xf) ++#define QMU_START_ADDR_HI_MSK GENMASK(3, 0) ++#define QMU_START_ADDR_HI(x) (((x) & 0xf) << 0) ++ + /* U3D_TXQCSR1 */ + /* U3D_RXQCSR1 */ + #define QMU_Q_ACTIVE BIT(15) +@@ -225,6 +234,7 @@ + #define CAP_TX_EP_NUM(x) ((x) & 0x1f) + + /* U3D_MISC_CTRL */ ++#define DMA_ADDR_36BIT BIT(31) + #define VBUS_ON BIT(1) + #define VBUS_FRC_EN BIT(0) + +diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c +index 7d9ba8a52368..42145a3f1422 100644 +--- a/drivers/usb/mtu3/mtu3_qmu.c ++++ b/drivers/usb/mtu3/mtu3_qmu.c +@@ -40,7 +40,58 @@ + #define GPD_FLAGS_IOC BIT(7) + + #define GPD_EXT_FLAG_ZLP BIT(5) ++#define GPD_EXT_NGP(x) (((x) & 0xf) << 4) ++#define GPD_EXT_BUF(x) (((x) & 0xf) << 0) + ++#define HILO_GEN64(hi, lo) (((u64)(hi) << 32) + (lo)) ++#define HILO_DMA(hi, lo) \ ++ ((dma_addr_t)HILO_GEN64((le32_to_cpu(hi)), (le32_to_cpu(lo)))) ++ ++static dma_addr_t read_txq_cur_addr(void __iomem *mbase, u8 epnum) ++{ ++ u32 txcpr; ++ u32 txhiar; ++ ++ txcpr = mtu3_readl(mbase, USB_QMU_TQCPR(epnum)); ++ txhiar = mtu3_readl(mbase, USB_QMU_TQHIAR(epnum)); ++ ++ return HILO_DMA(QMU_CUR_GPD_ADDR_HI(txhiar), txcpr); ++} ++ ++static dma_addr_t read_rxq_cur_addr(void __iomem *mbase, u8 epnum) ++{ ++ u32 rxcpr; ++ u32 rxhiar; ++ ++ rxcpr = mtu3_readl(mbase, USB_QMU_RQCPR(epnum)); ++ rxhiar = mtu3_readl(mbase, USB_QMU_RQHIAR(epnum)); ++ ++ return HILO_DMA(QMU_CUR_GPD_ADDR_HI(rxhiar), rxcpr); ++} ++ ++static void write_txq_start_addr(void __iomem *mbase, u8 epnum, dma_addr_t dma) ++{ ++ u32 tqhiar; ++ ++ mtu3_writel(mbase, USB_QMU_TQSAR(epnum), ++ cpu_to_le32(lower_32_bits(dma))); ++ tqhiar = mtu3_readl(mbase, USB_QMU_TQHIAR(epnum)); ++ tqhiar &= ~QMU_START_ADDR_HI_MSK; ++ tqhiar |= QMU_START_ADDR_HI(upper_32_bits(dma)); ++ mtu3_writel(mbase, USB_QMU_TQHIAR(epnum), tqhiar); ++} ++ ++static void write_rxq_start_addr(void __iomem *mbase, u8 epnum, dma_addr_t dma) ++{ ++ u32 rqhiar; ++ ++ mtu3_writel(mbase, USB_QMU_RQSAR(epnum), ++ cpu_to_le32(lower_32_bits(dma))); ++ rqhiar = mtu3_readl(mbase, USB_QMU_RQHIAR(epnum)); ++ rqhiar &= ~QMU_START_ADDR_HI_MSK; ++ rqhiar |= QMU_START_ADDR_HI(upper_32_bits(dma)); ++ mtu3_writel(mbase, USB_QMU_RQHIAR(epnum), rqhiar); ++} + + static struct qmu_gpd *gpd_dma_to_virt(struct mtu3_gpd_ring *ring, + dma_addr_t dma_addr) +@@ -193,21 +244,27 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + struct qmu_gpd *gpd = ring->enqueue; + struct usb_request *req = &mreq->request; ++ dma_addr_t enq_dma; ++ u16 ext_addr; + + /* set all fields to zero as default value */ + memset(gpd, 0, sizeof(*gpd)); + +- gpd->buffer = cpu_to_le32((u32)req->dma); ++ gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); ++ ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); + gpd->buf_len = cpu_to_le16(req->length); + gpd->flag |= GPD_FLAGS_IOC; + + /* get the next GPD */ + enq = advance_enq_gpd(ring); +- dev_dbg(mep->mtu->dev, "TX-EP%d queue gpd=%p, enq=%p\n", +- mep->epnum, gpd, enq); ++ enq_dma = gpd_virt_to_dma(ring, enq); ++ dev_dbg(mep->mtu->dev, "TX-EP%d queue gpd=%p, enq=%p, qdma=%pad\n", ++ mep->epnum, gpd, enq, enq_dma); + + enq->flag &= ~GPD_FLAGS_HWO; +- gpd->next_gpd = cpu_to_le32((u32)gpd_virt_to_dma(ring, enq)); ++ gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); ++ ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); ++ gpd->tx_ext_addr = cpu_to_le16(ext_addr); + + if (req->zero) + gpd->ext_flag |= GPD_EXT_FLAG_ZLP; +@@ -226,21 +283,27 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + struct qmu_gpd *gpd = ring->enqueue; + struct usb_request *req = &mreq->request; ++ dma_addr_t enq_dma; ++ u16 ext_addr; + + /* set all fields to zero as default value */ + memset(gpd, 0, sizeof(*gpd)); + +- gpd->buffer = cpu_to_le32((u32)req->dma); ++ gpd->buffer = cpu_to_le32(lower_32_bits(req->dma)); ++ ext_addr = GPD_EXT_BUF(upper_32_bits(req->dma)); + gpd->data_buf_len = cpu_to_le16(req->length); + gpd->flag |= GPD_FLAGS_IOC; + + /* get the next GPD */ + enq = advance_enq_gpd(ring); +- dev_dbg(mep->mtu->dev, "RX-EP%d queue gpd=%p, enq=%p\n", +- mep->epnum, gpd, enq); ++ enq_dma = gpd_virt_to_dma(ring, enq); ++ dev_dbg(mep->mtu->dev, "RX-EP%d queue gpd=%p, enq=%p, qdma=%pad\n", ++ mep->epnum, gpd, enq, enq_dma); + + enq->flag &= ~GPD_FLAGS_HWO; +- gpd->next_gpd = cpu_to_le32((u32)gpd_virt_to_dma(ring, enq)); ++ gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); ++ ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); ++ gpd->rx_ext_addr = cpu_to_le16(ext_addr); + gpd->chksum = qmu_calc_checksum((u8 *)gpd); + gpd->flag |= GPD_FLAGS_HWO; + +@@ -267,8 +330,8 @@ int mtu3_qmu_start(struct mtu3_ep *mep) + + if (mep->is_in) { + /* set QMU start address */ +- mtu3_writel(mbase, USB_QMU_TQSAR(mep->epnum), ring->dma); +- mtu3_setbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN); ++ write_txq_start_addr(mbase, epnum, ring->dma); ++ mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_DMAREQEN); + mtu3_setbits(mbase, U3D_QCR0, QMU_TX_CS_EN(epnum)); + /* send zero length packet according to ZLP flag in GPD */ + mtu3_setbits(mbase, U3D_QCR1, QMU_TX_ZLP(epnum)); +@@ -282,8 +345,8 @@ int mtu3_qmu_start(struct mtu3_ep *mep) + mtu3_writel(mbase, USB_QMU_TQCSR(epnum), QMU_Q_START); + + } else { +- mtu3_writel(mbase, USB_QMU_RQSAR(mep->epnum), ring->dma); +- mtu3_setbits(mbase, MU3D_EP_RXCR0(mep->epnum), RX_DMAREQEN); ++ write_rxq_start_addr(mbase, epnum, ring->dma); ++ mtu3_setbits(mbase, MU3D_EP_RXCR0(epnum), RX_DMAREQEN); + mtu3_setbits(mbase, U3D_QCR0, QMU_RX_CS_EN(epnum)); + /* don't expect ZLP */ + mtu3_clrbits(mbase, U3D_QCR3, QMU_RX_ZLP(epnum)); +@@ -353,9 +416,9 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) + struct mtu3_gpd_ring *ring = &mep->gpd_ring; + void __iomem *mbase = mtu->mac_base; + struct qmu_gpd *gpd_current = NULL; +- dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_TQCPR(epnum)); + struct usb_request *req = NULL; + struct mtu3_request *mreq; ++ dma_addr_t cur_gpd_dma; + u32 txcsr = 0; + int ret; + +@@ -365,7 +428,8 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) + else + return; + +- gpd_current = gpd_dma_to_virt(ring, gpd_dma); ++ cur_gpd_dma = read_txq_cur_addr(mbase, epnum); ++ gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); + + if (le16_to_cpu(gpd_current->buf_len) != 0) { + dev_err(mtu->dev, "TX EP%d buffer length error(!=0)\n", epnum); +@@ -408,12 +472,13 @@ static void qmu_done_tx(struct mtu3 *mtu, u8 epnum) + void __iomem *mbase = mtu->mac_base; + struct qmu_gpd *gpd = ring->dequeue; + struct qmu_gpd *gpd_current = NULL; +- dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_TQCPR(epnum)); + struct usb_request *request = NULL; + struct mtu3_request *mreq; ++ dma_addr_t cur_gpd_dma; + + /*transfer phy address got from QMU register to virtual address */ +- gpd_current = gpd_dma_to_virt(ring, gpd_dma); ++ cur_gpd_dma = read_txq_cur_addr(mbase, epnum); ++ gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); + + dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n", + __func__, epnum, gpd, gpd_current, ring->enqueue); +@@ -446,11 +511,12 @@ static void qmu_done_rx(struct mtu3 *mtu, u8 epnum) + void __iomem *mbase = mtu->mac_base; + struct qmu_gpd *gpd = ring->dequeue; + struct qmu_gpd *gpd_current = NULL; +- dma_addr_t gpd_dma = mtu3_readl(mbase, USB_QMU_RQCPR(epnum)); + struct usb_request *req = NULL; + struct mtu3_request *mreq; ++ dma_addr_t cur_gpd_dma; + +- gpd_current = gpd_dma_to_virt(ring, gpd_dma); ++ cur_gpd_dma = read_rxq_cur_addr(mbase, epnum); ++ gpd_current = gpd_dma_to_virt(ring, cur_gpd_dma); + + dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n", + __func__, epnum, gpd, gpd_current, ring->enqueue); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0108-usb-mtu3-use-FORCE-RG_IDDIG-to-implement-manual-DRD-.patch b/target/linux/mediatek/patches-4.14/0108-usb-mtu3-use-FORCE-RG_IDDIG-to-implement-manual-DRD-.patch new file mode 100644 index 0000000000..ce454feb23 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0108-usb-mtu3-use-FORCE-RG_IDDIG-to-implement-manual-DRD-.patch @@ -0,0 +1,290 @@ +From 6c4995c9a8ba8841ba640201636954c84f494587 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:42 +0800 +Subject: [PATCH 108/224] usb: mtu3: use FORCE/RG_IDDIG to implement manual DRD + switch + +In order to keep manual DRD switch independent on IDDIG interrupt, +make use of FORCE/RG_IDDIG instead of IDDIG EINT interrupt to +implement manual DRD switch function. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3.h | 18 ++++++++---- + drivers/usb/mtu3/mtu3_dr.c | 61 ++++++++++++++++++++++++++++++----------- + drivers/usb/mtu3/mtu3_dr.h | 6 ++++ + drivers/usb/mtu3/mtu3_host.c | 5 ++++ + drivers/usb/mtu3/mtu3_hw_regs.h | 2 ++ + drivers/usb/mtu3/mtu3_plat.c | 38 ++----------------------- + 6 files changed, 74 insertions(+), 56 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h +index ef2dc92a2109..b0c2b5dca045 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -115,6 +115,19 @@ enum mtu3_g_ep0_state { + }; + + /** ++ * MTU3_DR_FORCE_NONE: automatically switch host and periperal mode ++ * by IDPIN signal. ++ * MTU3_DR_FORCE_HOST: force to enter host mode and override OTG ++ * IDPIN signal. ++ * MTU3_DR_FORCE_DEVICE: force to enter peripheral mode. ++ */ ++enum mtu3_dr_force_mode { ++ MTU3_DR_FORCE_NONE = 0, ++ MTU3_DR_FORCE_HOST, ++ MTU3_DR_FORCE_DEVICE, ++}; ++ ++/** + * @base: the base address of fifo + * @limit: the bitmap size in bits + * @bitmap: fifo bitmap in unit of @MTU3_EP_FIFO_UNIT +@@ -196,7 +209,6 @@ struct mtu3_gpd_ring { + * xHCI driver initialization, it's necessary for system bootup + * as device. + * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not +-* @id_*: used to maually switch between host and device modes by idpin + * @manual_drd_enabled: it's true when supports dual-role device by debugfs + * to switch host/device modes depending on user input. + */ +@@ -207,10 +219,6 @@ struct otg_switch_mtk { + struct notifier_block id_nb; + struct delayed_work extcon_reg_dwork; + bool is_u3_drd; +- /* dual-role switch by debugfs */ +- struct pinctrl *id_pinctrl; +- struct pinctrl_state *id_float; +- struct pinctrl_state *id_ground; + bool manual_drd_enabled; + }; + +diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c +index 560256115b23..ec442cd5a1ad 100644 +--- a/drivers/usb/mtu3/mtu3_dr.c ++++ b/drivers/usb/mtu3/mtu3_dr.c +@@ -261,21 +261,22 @@ static void extcon_register_dwork(struct work_struct *work) + * depending on user input. + * This is useful in special cases, such as uses TYPE-A receptacle but also + * wants to support dual-role mode. +- * It generates cable state changes by pulling up/down IDPIN and +- * notifies driver to switch mode by "extcon-usb-gpio". +- * NOTE: when use MICRO receptacle, should not enable this interface. + */ + static void ssusb_mode_manual_switch(struct ssusb_mtk *ssusb, int to_host) + { + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + +- if (to_host) +- pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_ground); +- else +- pinctrl_select_state(otg_sx->id_pinctrl, otg_sx->id_float); ++ if (to_host) { ++ ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); ++ ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF); ++ ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND); ++ } else { ++ ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_DEVICE); ++ ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); ++ ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); ++ } + } + +- + static int ssusb_mode_show(struct seq_file *sf, void *unused) + { + struct ssusb_mtk *ssusb = sf->private; +@@ -388,17 +389,45 @@ static void ssusb_debugfs_exit(struct ssusb_mtk *ssusb) + debugfs_remove_recursive(ssusb->dbgfs_root); + } + ++void ssusb_set_force_mode(struct ssusb_mtk *ssusb, ++ enum mtu3_dr_force_mode mode) ++{ ++ u32 value; ++ ++ value = mtu3_readl(ssusb->ippc_base, SSUSB_U2_CTRL(0)); ++ switch (mode) { ++ case MTU3_DR_FORCE_DEVICE: ++ value |= SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG; ++ break; ++ case MTU3_DR_FORCE_HOST: ++ value |= SSUSB_U2_PORT_FORCE_IDDIG; ++ value &= ~SSUSB_U2_PORT_RG_IDDIG; ++ break; ++ case MTU3_DR_FORCE_NONE: ++ value &= ~(SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG); ++ break; ++ default: ++ return; ++ } ++ mtu3_writel(ssusb->ippc_base, SSUSB_U2_CTRL(0), value); ++} ++ + int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) + { + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + +- INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, extcon_register_dwork); +- +- if (otg_sx->manual_drd_enabled) ++ if (otg_sx->manual_drd_enabled) { + ssusb_debugfs_init(ssusb); +- +- /* It is enough to delay 1s for waiting for host initialization */ +- schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ); ++ } else { ++ INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, ++ extcon_register_dwork); ++ ++ /* ++ * It is enough to delay 1s for waiting for ++ * host initialization ++ */ ++ schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ); ++ } + + return 0; + } +@@ -407,8 +436,8 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) + { + struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; + +- cancel_delayed_work(&otg_sx->extcon_reg_dwork); +- + if (otg_sx->manual_drd_enabled) + ssusb_debugfs_exit(ssusb); ++ else ++ cancel_delayed_work(&otg_sx->extcon_reg_dwork); + } +diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h +index 9b228b5811b0..0f0cbac00192 100644 +--- a/drivers/usb/mtu3/mtu3_dr.h ++++ b/drivers/usb/mtu3/mtu3_dr.h +@@ -87,6 +87,8 @@ static inline void ssusb_gadget_exit(struct ssusb_mtk *ssusb) + int ssusb_otg_switch_init(struct ssusb_mtk *ssusb); + void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb); + int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on); ++void ssusb_set_force_mode(struct ssusb_mtk *ssusb, ++ enum mtu3_dr_force_mode mode); + + #else + +@@ -103,6 +105,10 @@ static inline int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) + return 0; + } + ++static inline void ++ssusb_set_force_mode(struct ssusb_mtk *ssusb, enum mtu3_dr_force_mode mode) ++{} ++ + #endif + + #endif /* _MTU3_DR_H_ */ +diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c +index edcc59148171..ec76b86dd887 100644 +--- a/drivers/usb/mtu3/mtu3_host.c ++++ b/drivers/usb/mtu3/mtu3_host.c +@@ -189,6 +189,8 @@ int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend) + + static void ssusb_host_setup(struct ssusb_mtk *ssusb) + { ++ struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; ++ + host_ports_num_get(ssusb); + + /* +@@ -197,6 +199,9 @@ static void ssusb_host_setup(struct ssusb_mtk *ssusb) + */ + ssusb_host_enable(ssusb); + ++ if (otg_sx->manual_drd_enabled) ++ ssusb_set_force_mode(ssusb, MTU3_DR_FORCE_HOST); ++ + /* if port0 supports dual-role, works as host mode by default */ + ssusb_set_vbus(&ssusb->otg_switch, 1); + } +diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h +index b6059752dc12..a7e35f6ad90a 100644 +--- a/drivers/usb/mtu3/mtu3_hw_regs.h ++++ b/drivers/usb/mtu3/mtu3_hw_regs.h +@@ -472,6 +472,8 @@ + #define SSUSB_U3_PORT_DIS BIT(0) + + /* U3D_SSUSB_U2_CTRL_0P */ ++#define SSUSB_U2_PORT_RG_IDDIG BIT(12) ++#define SSUSB_U2_PORT_FORCE_IDDIG BIT(11) + #define SSUSB_U2_PORT_VBUSVALID BIT(9) + #define SSUSB_U2_PORT_OTG_SEL BIT(7) + #define SSUSB_U2_PORT_HOST BIT(2) +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index fb8992011bde..1e473b068650 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -21,7 +21,6 @@ + #include <linux/module.h> + #include <linux/of_address.h> + #include <linux/of_irq.h> +-#include <linux/pinctrl/consumer.h> + #include <linux/platform_device.h> + + #include "mtu3.h" +@@ -212,33 +211,6 @@ static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb) + mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); + } + +-static int get_iddig_pinctrl(struct ssusb_mtk *ssusb) +-{ +- struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; +- +- otg_sx->id_pinctrl = devm_pinctrl_get(ssusb->dev); +- if (IS_ERR(otg_sx->id_pinctrl)) { +- dev_err(ssusb->dev, "Cannot find id pinctrl!\n"); +- return PTR_ERR(otg_sx->id_pinctrl); +- } +- +- otg_sx->id_float = +- pinctrl_lookup_state(otg_sx->id_pinctrl, "id_float"); +- if (IS_ERR(otg_sx->id_float)) { +- dev_err(ssusb->dev, "Cannot find pinctrl id_float!\n"); +- return PTR_ERR(otg_sx->id_float); +- } +- +- otg_sx->id_ground = +- pinctrl_lookup_state(otg_sx->id_pinctrl, "id_ground"); +- if (IS_ERR(otg_sx->id_ground)) { +- dev_err(ssusb->dev, "Cannot find pinctrl id_ground!\n"); +- return PTR_ERR(otg_sx->id_ground); +- } +- +- return 0; +-} +- + /* ignore the error if the clock does not exist */ + static struct clk *get_optional_clk(struct device *dev, const char *id) + { +@@ -349,15 +321,11 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + dev_err(ssusb->dev, "couldn't get extcon device\n"); + return -EPROBE_DEFER; + } +- if (otg_sx->manual_drd_enabled) { +- ret = get_iddig_pinctrl(ssusb); +- if (ret) +- return ret; +- } + } + +- dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk:%x\n", +- ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk); ++ dev_info(dev, "dr_mode: %d, is_u3_dr: %d, u3p_dis_msk: %x, drd: %s\n", ++ ssusb->dr_mode, otg_sx->is_u3_drd, ssusb->u3p_dis_msk, ++ otg_sx->manual_drd_enabled ? "manual" : "auto"); + + return 0; + } +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0109-usb-mtu3-add-support-for-usb3.1-IP.patch b/target/linux/mediatek/patches-4.14/0109-usb-mtu3-add-support-for-usb3.1-IP.patch new file mode 100644 index 0000000000..020dabf782 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0109-usb-mtu3-add-support-for-usb3.1-IP.patch @@ -0,0 +1,165 @@ +From 8f444887e23b9f0ea31aaae74fbc18171714d8d2 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:43 +0800 +Subject: [PATCH 109/224] usb: mtu3: add support for usb3.1 IP + +Support SuperSpeedPlus for usb3.1 device IP + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3.h | 1 + + drivers/usb/mtu3/mtu3_core.c | 14 +++++++++++--- + drivers/usb/mtu3/mtu3_gadget.c | 3 ++- + drivers/usb/mtu3/mtu3_gadget_ep0.c | 16 ++++++++-------- + drivers/usb/mtu3/mtu3_hw_regs.h | 1 + + 5 files changed, 23 insertions(+), 12 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h +index b0c2b5dca045..d80e4e813248 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -94,6 +94,7 @@ enum mtu3_speed { + MTU3_SPEED_FULL = 1, + MTU3_SPEED_HIGH = 3, + MTU3_SPEED_SUPER = 4, ++ MTU3_SPEED_SUPER_PLUS = 5, + }; + + /** +diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c +index cd4528f5f337..67f7a309aba7 100644 +--- a/drivers/usb/mtu3/mtu3_core.c ++++ b/drivers/usb/mtu3/mtu3_core.c +@@ -237,7 +237,7 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set) + + void mtu3_dev_on_off(struct mtu3 *mtu, int is_on) + { +- if (mtu->is_u3_ip && (mtu->max_speed == USB_SPEED_SUPER)) ++ if (mtu->is_u3_ip && mtu->max_speed >= USB_SPEED_SUPER) + mtu3_ss_func_set(mtu, is_on); + else + mtu3_hs_softconn_set(mtu, is_on); +@@ -547,6 +547,9 @@ static void mtu3_set_speed(struct mtu3 *mtu) + mtu3_clrbits(mbase, U3D_USB3_CONFIG, USB3_EN); + /* HS/FS detected by HW */ + mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, HS_ENABLE); ++ } else if (mtu->max_speed == USB_SPEED_SUPER) { ++ mtu3_clrbits(mtu->ippc_base, SSUSB_U3_CTRL(0), ++ SSUSB_U3_PORT_SSP_SPEED); + } + + dev_info(mtu->dev, "max_speed: %s\n", +@@ -624,6 +627,10 @@ static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) + udev_speed = USB_SPEED_SUPER; + maxpkt = 512; + break; ++ case MTU3_SPEED_SUPER_PLUS: ++ udev_speed = USB_SPEED_SUPER_PLUS; ++ maxpkt = 512; ++ break; + default: + udev_speed = USB_SPEED_UNKNOWN; + break; +@@ -825,14 +832,15 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + case USB_SPEED_SUPER: ++ case USB_SPEED_SUPER_PLUS: + break; + default: + dev_err(dev, "invalid max_speed: %s\n", + usb_speed_string(mtu->max_speed)); + /* fall through */ + case USB_SPEED_UNKNOWN: +- /* default as SS */ +- mtu->max_speed = USB_SPEED_SUPER; ++ /* default as SSP */ ++ mtu->max_speed = USB_SPEED_SUPER_PLUS; + break; + } + +diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c +index 434fca58143c..b495471f689f 100644 +--- a/drivers/usb/mtu3/mtu3_gadget.c ++++ b/drivers/usb/mtu3/mtu3_gadget.c +@@ -89,6 +89,7 @@ static int mtu3_ep_enable(struct mtu3_ep *mep) + + switch (mtu->g.speed) { + case USB_SPEED_SUPER: ++ case USB_SPEED_SUPER_PLUS: + if (usb_endpoint_xfer_int(desc) || + usb_endpoint_xfer_isoc(desc)) { + interval = desc->bInterval; +@@ -456,7 +457,7 @@ static int mtu3_gadget_wakeup(struct usb_gadget *gadget) + return -EOPNOTSUPP; + + spin_lock_irqsave(&mtu->lock, flags); +- if (mtu->g.speed == USB_SPEED_SUPER) { ++ if (mtu->g.speed >= USB_SPEED_SUPER) { + mtu3_setbits(mtu->mac_base, U3D_LINK_POWER_CONTROL, UX_EXIT); + } else { + mtu3_setbits(mtu->mac_base, U3D_POWER_MANAGEMENT, RESUME); +diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c +index 958d74dd2b78..020b25314a68 100644 +--- a/drivers/usb/mtu3/mtu3_gadget_ep0.c ++++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c +@@ -212,8 +212,8 @@ ep0_get_status(struct mtu3 *mtu, const struct usb_ctrlrequest *setup) + case USB_RECIP_DEVICE: + result[0] = mtu->is_self_powered << USB_DEVICE_SELF_POWERED; + result[0] |= mtu->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; +- /* superspeed only */ +- if (mtu->g.speed == USB_SPEED_SUPER) { ++ ++ if (mtu->g.speed >= USB_SPEED_SUPER) { + result[0] |= mtu->u1_enable << USB_DEV_STAT_U1_ENABLED; + result[0] |= mtu->u2_enable << USB_DEV_STAT_U2_ENABLED; + } +@@ -329,8 +329,8 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu, + handled = handle_test_mode(mtu, setup); + break; + case USB_DEVICE_U1_ENABLE: +- if (mtu->g.speed != USB_SPEED_SUPER || +- mtu->g.state != USB_STATE_CONFIGURED) ++ if (mtu->g.speed < USB_SPEED_SUPER || ++ mtu->g.state != USB_STATE_CONFIGURED) + break; + + lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); +@@ -344,8 +344,8 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu, + handled = 1; + break; + case USB_DEVICE_U2_ENABLE: +- if (mtu->g.speed != USB_SPEED_SUPER || +- mtu->g.state != USB_STATE_CONFIGURED) ++ if (mtu->g.speed < USB_SPEED_SUPER || ++ mtu->g.state != USB_STATE_CONFIGURED) + break; + + lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); +@@ -384,8 +384,8 @@ static int ep0_handle_feature(struct mtu3 *mtu, + break; + case USB_RECIP_INTERFACE: + /* superspeed only */ +- if ((value == USB_INTRF_FUNC_SUSPEND) +- && (mtu->g.speed == USB_SPEED_SUPER)) { ++ if (value == USB_INTRF_FUNC_SUSPEND && ++ mtu->g.speed >= USB_SPEED_SUPER) { + /* + * forward the request because function drivers + * should handle it +diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h +index a7e35f6ad90a..6953436a1688 100644 +--- a/drivers/usb/mtu3/mtu3_hw_regs.h ++++ b/drivers/usb/mtu3/mtu3_hw_regs.h +@@ -467,6 +467,7 @@ + #define SSUSB_VBUS_CHG_INT_B_EN BIT(6) + + /* U3D_SSUSB_U3_CTRL_0P */ ++#define SSUSB_U3_PORT_SSP_SPEED BIT(9) + #define SSUSB_U3_PORT_HOST_SEL BIT(2) + #define SSUSB_U3_PORT_PDN BIT(1) + #define SSUSB_U3_PORT_DIS BIT(0) +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0110-usb-mtu3-get-optional-vbus-for-host-only-mode.patch b/target/linux/mediatek/patches-4.14/0110-usb-mtu3-get-optional-vbus-for-host-only-mode.patch new file mode 100644 index 0000000000..d55fe7dbe2 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0110-usb-mtu3-get-optional-vbus-for-host-only-mode.patch @@ -0,0 +1,45 @@ +From b6712b72d1273e792ee8a533048ba731a3709163 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:44 +0800 +Subject: [PATCH 110/224] usb: mtu3: get optional vbus for host only mode + +When dr_mode is set as USB_DR_MODE_HOST, it's better to try to +get optional vbus, this can increase flexibility, although we +can set vbus as always on for regulator or put it in host driver +to turn it on. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3_plat.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index 1e473b068650..7ca81f4e78a3 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -300,10 +300,6 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + of_property_read_u32(node, "mediatek,u3p-dis-msk", + &ssusb->u3p_dis_msk); + +- if (ssusb->dr_mode != USB_DR_MODE_OTG) +- return 0; +- +- /* if dual-role mode is supported */ + vbus = devm_regulator_get(&pdev->dev, "vbus"); + if (IS_ERR(vbus)) { + dev_err(dev, "failed to get vbus\n"); +@@ -311,6 +307,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + } + otg_sx->vbus = vbus; + ++ if (ssusb->dr_mode == USB_DR_MODE_HOST) ++ return 0; ++ ++ /* if dual-role mode is supported */ + otg_sx->is_u3_drd = of_property_read_bool(node, "mediatek,usb3-drd"); + otg_sx->manual_drd_enabled = + of_property_read_bool(node, "enable-manual-drd"); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0111-usb-mtu3-set-invalid-dr_mode-as-dual-role-mode.patch b/target/linux/mediatek/patches-4.14/0111-usb-mtu3-set-invalid-dr_mode-as-dual-role-mode.patch new file mode 100644 index 0000000000..1c23d15eca --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0111-usb-mtu3-set-invalid-dr_mode-as-dual-role-mode.patch @@ -0,0 +1,34 @@ +From e315036cdbf8dad7cff4df9dfe8bcff2eddf2277 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:45 +0800 +Subject: [PATCH 111/224] usb: mtu3: set invalid dr_mode as dual-role mode + +Treat dr_mode of USB_DR_MODE_UNKNOWN as USB_DR_MODE_OTG to +enhance functional robustness. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3_plat.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index 7ca81f4e78a3..9ff33579b42e 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -283,10 +283,8 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + return PTR_ERR(ssusb->ippc_base); + + ssusb->dr_mode = usb_get_dr_mode(dev); +- if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN) { +- dev_err(dev, "dr_mode is error\n"); +- return -EINVAL; +- } ++ if (ssusb->dr_mode == USB_DR_MODE_UNKNOWN) ++ ssusb->dr_mode = USB_DR_MODE_OTG; + + if (ssusb->dr_mode == USB_DR_MODE_PERIPHERAL) + return 0; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0112-usb-mtu3-set-otg_sel-for-u2port-only-if-works-as-dua.patch b/target/linux/mediatek/patches-4.14/0112-usb-mtu3-set-otg_sel-for-u2port-only-if-works-as-dua.patch new file mode 100644 index 0000000000..3a74fe534f --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0112-usb-mtu3-set-otg_sel-for-u2port-only-if-works-as-dua.patch @@ -0,0 +1,49 @@ +From 36f70702b66cd3453b65d46b5c26ea87d8897363 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:46 +0800 +Subject: [PATCH 112/224] usb: mtu3: set otg_sel for u2port only if works as + dual-role mode + +When set otg_sel(SSUSB_U2_PORT_OTG_SEL) for u2port which supports +dual-role mode, the controller will automatically switch mode +between host and device according to IDDIG signal. But if the +u2port only supports device mode, and no IDDIG pin is provided, +setting otg_sel may cause failure of detection by host. +So set it only for dual-role mode. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + drivers/usb/mtu3/mtu3_core.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c +index 67f7a309aba7..7c149a7da14e 100644 +--- a/drivers/usb/mtu3/mtu3_core.c ++++ b/drivers/usb/mtu3/mtu3_core.c +@@ -115,7 +115,9 @@ static int mtu3_device_enable(struct mtu3 *mtu) + mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), + (SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN | + SSUSB_U2_PORT_HOST_SEL)); +- mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); ++ ++ if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) ++ mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); + + return ssusb_check_clocks(mtu->ssusb, check_clk); + } +@@ -130,7 +132,10 @@ static void mtu3_device_disable(struct mtu3 *mtu) + + mtu3_setbits(ibase, SSUSB_U2_CTRL(0), + SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN); +- mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); ++ ++ if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) ++ mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); ++ + mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); + } + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0113-dt-bindings-usb-mtu3-add-a-optional-property-to-disa.patch b/target/linux/mediatek/patches-4.14/0113-dt-bindings-usb-mtu3-add-a-optional-property-to-disa.patch new file mode 100644 index 0000000000..c45f7d2e1c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0113-dt-bindings-usb-mtu3-add-a-optional-property-to-disa.patch @@ -0,0 +1,30 @@ +From 6b6f2c178ee2cd57713993e3cf0afbe4effb2578 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:47 +0800 +Subject: [PATCH 113/224] dt-bindings: usb: mtu3: add a optional property to + disable u3ports + +Add a new optional property to disable u3ports + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +index 49f54767cd21..7c611d14a0a0 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +@@ -44,6 +44,8 @@ Optional properties: + - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode + - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup + control register, it depends on "mediatek,enable-wakeup". ++ - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, ++ bit1 for u3port1, ... etc; + + Sub-nodes: + The xhci should be added as subnode to mtu3 as shown in the following example +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0114-dt-bindings-usb-mtu3-remove-dummy-clocks-and-add-opt.patch b/target/linux/mediatek/patches-4.14/0114-dt-bindings-usb-mtu3-remove-dummy-clocks-and-add-opt.patch new file mode 100644 index 0000000000..71e44b31f6 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0114-dt-bindings-usb-mtu3-remove-dummy-clocks-and-add-opt.patch @@ -0,0 +1,46 @@ +From 2c90367440a0dbf9962e7a7f701b0e7a320d325a Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:48 +0800 +Subject: [PATCH 114/224] dt-bindings: usb: mtu3: remove dummy clocks and add + optional ones + +Remove dummy clocks for usb wakeup and add optional ones for +mcu_bus and dma_bus bus. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +index 7c611d14a0a0..49c982bb5bfc 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +@@ -14,9 +14,9 @@ Required properties: + - vusb33-supply : regulator of USB avdd3.3v + - clocks : a list of phandle + clock-specifier pairs, one for each + entry in clock-names +- - clock-names : must contain "sys_ck" and "ref_ck" for clock of controller; +- "wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are +- depends on "mediatek,enable-wakeup" ++ - clock-names : must contain "sys_ck" for clock of controller, ++ the following clocks are optional: ++ "ref_ck", "mcu_ck" and "dam_ck"; + - phys : a list of phandle + phy specifier pairs + - dr_mode : should be one of "host", "peripheral" or "otg", + refer to usb/generic.txt +@@ -65,9 +65,7 @@ ssusb: usb@11271000 { + clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>, + <&pericfg CLK_PERI_USB0>, + <&pericfg CLK_PERI_USB1>; +- clock-names = "sys_ck", "ref_ck", +- "wakeup_deb_p0", +- "wakeup_deb_p1"; ++ clock-names = "sys_ck", "ref_ck"; + vusb33-supply = <&mt6397_vusb_reg>; + vbus-supply = <&usb_p0_vbus>; + extcon = <&extcon_usb>; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0115-dt-bindings-usb-mtu3-remove-optional-pinctrls.patch b/target/linux/mediatek/patches-4.14/0115-dt-bindings-usb-mtu3-remove-optional-pinctrls.patch new file mode 100644 index 0000000000..ea5cf5f8af --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0115-dt-bindings-usb-mtu3-remove-optional-pinctrls.patch @@ -0,0 +1,35 @@ +From df2f0d10213798a806c90bc06db6bed501e7bf7d Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 17:10:49 +0800 +Subject: [PATCH 115/224] dt-bindings: usb: mtu3: remove optional pinctrls + +Remove optional pinctrls due to using FORCE/RG_IDDIG to implement +manual switch function. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +--- + Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +index 49c982bb5bfc..b2271d8e6b50 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +@@ -30,9 +30,10 @@ Optional properties: + when supports dual-role mode. + - vbus-supply : reference to the VBUS regulator, needed when supports + dual-role mode. +- - pinctl-names : a pinctrl state named "default" must be defined, +- "id_float" and "id_ground" are optinal which depends on +- "mediatek,enable-manual-drd" ++ - pinctrl-names : a pinctrl state named "default" is optional, and need be ++ defined if auto drd switch is enabled, that means the property dr_mode ++ is set as "otg", and meanwhile the property "mediatek,enable-manual-drd" ++ is not set. + - pinctrl-0 : pin control group + See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0116-dt-bindings-arm-mediatek-add-MT7622-string-to-the-PM.patch b/target/linux/mediatek/patches-4.14/0116-dt-bindings-arm-mediatek-add-MT7622-string-to-the-PM.patch new file mode 100644 index 0000000000..540c1273a4 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0116-dt-bindings-arm-mediatek-add-MT7622-string-to-the-PM.patch @@ -0,0 +1,43 @@ +From 1567cde49a0f2304e18c08e2ccd830e0686fc0a7 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 18 Oct 2017 16:28:42 +0800 +Subject: [PATCH 116/224] dt-bindings: arm: mediatek: add MT7622 string to the + PMIC wrapper doc + +Signed-off-by: Chenglin Xu <chenglin.xu@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + Documentation/devicetree/bindings/soc/mediatek/pwrap.txt | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt +index 107700d00df4..bf80e3f96f8c 100644 +--- a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt ++++ b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt +@@ -19,6 +19,7 @@ IP Pairing + Required properties in pwrap device node. + - compatible: + "mediatek,mt2701-pwrap" for MT2701/7623 SoCs ++ "mediatek,mt7622-pwrap" for MT7622 SoCs + "mediatek,mt8135-pwrap" for MT8135 SoCs + "mediatek,mt8173-pwrap" for MT8173 SoCs + - interrupts: IRQ for pwrap in SOC +@@ -36,9 +37,12 @@ Required properties in pwrap device node. + - clocks: Must contain an entry for each entry in clock-names. + + Optional properities: +-- pmic: Mediatek PMIC MFD is the child device of pwrap ++- pmic: Using either MediaTek PMIC MFD as the child device of pwrap + See the following for child node definitions: + Documentation/devicetree/bindings/mfd/mt6397.txt ++ or the regulator-only device as the child device of pwrap, such as MT6380. ++ See the following definitions for such kinds of devices. ++ Documentation/devicetree/bindings/regulator/mt6380-regulator.txt + + Example: + pwrap: pwrap@1000f000 { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0117-soc-mediatek-pwrap-add-pwrap_read32-for-reading-in-3.patch b/target/linux/mediatek/patches-4.14/0117-soc-mediatek-pwrap-add-pwrap_read32-for-reading-in-3.patch new file mode 100644 index 0000000000..c178ddca7a --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0117-soc-mediatek-pwrap-add-pwrap_read32-for-reading-in-3.patch @@ -0,0 +1,139 @@ +From 9c37953bd08daa3ca227098d763e980d1898add3 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 18 Oct 2017 16:28:43 +0800 +Subject: [PATCH 117/224] soc: mediatek: pwrap: add pwrap_read32 for reading in + 32-bit mode + +Some regulators such as MediaTek MT6380 has to be read in 32-bit mode. +So the patch adds pwrap_read32, rename old pwrap_read into pwrap_read16 +and one function pointer is introduced for increasing flexibility allowing +the determination which mode is used by the pwrap slave detection through +device tree. + +Signed-off-by: Chenglin Xu <chenglin.xu@mediatek.com> +Signed-off-by: Chen Zhong <chen.zhong@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/mtk-pmic-wrap.c | 55 +++++++++++++++++++++++++++++++++++- + 1 file changed, 54 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index f095faac1e04..06930e2ebe4c 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -487,6 +487,7 @@ static int mt8135_regs[] = { + + enum pmic_type { + PMIC_MT6323, ++ PMIC_MT6380, + PMIC_MT6397, + }; + +@@ -496,9 +497,16 @@ enum pwrap_type { + PWRAP_MT8173, + }; + ++struct pmic_wrapper; + struct pwrap_slv_type { + const u32 *dew_regs; + enum pmic_type type; ++ /* ++ * pwrap operations are highly associated with the PMIC types, ++ * so the pointers added increases flexibility allowing determination ++ * which type is used by the detection through device tree. ++ */ ++ int (*pwrap_read)(struct pmic_wrapper *wrp, u32 adr, u32 *rdata); + }; + + struct pmic_wrapper { +@@ -609,7 +617,7 @@ static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata) + return 0; + } + +-static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) ++static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) + { + int ret; + +@@ -632,6 +640,39 @@ static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) + return 0; + } + ++static int pwrap_read32(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) ++{ ++ int ret, msb; ++ ++ *rdata = 0; ++ for (msb = 0; msb < 2; msb++) { ++ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); ++ if (ret) { ++ pwrap_leave_fsm_vldclr(wrp); ++ return ret; ++ } ++ ++ pwrap_writel(wrp, ((msb << 30) | (adr << 16)), ++ PWRAP_WACS2_CMD); ++ ++ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr); ++ if (ret) ++ return ret; ++ ++ *rdata += (PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, ++ PWRAP_WACS2_RDATA)) << (16 * msb)); ++ ++ pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); ++ } ++ ++ return 0; ++} ++ ++static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) ++{ ++ return wrp->slave->pwrap_read(wrp, adr, rdata); ++} ++ + static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata) + { + return pwrap_read(context, adr, rdata); +@@ -752,6 +793,8 @@ static int pwrap_mt2701_init_reg_clock(struct pmic_wrapper *wrp) + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); + pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); + break; ++ default: ++ break; + } + + return 0; +@@ -815,6 +858,8 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN], + 0x1); + break; ++ default: ++ break; + } + + /* wait for cipher data ready@AP */ +@@ -1036,11 +1081,19 @@ static const struct regmap_config pwrap_regmap_config = { + static const struct pwrap_slv_type pmic_mt6323 = { + .dew_regs = mt6323_regs, + .type = PMIC_MT6323, ++ .pwrap_read = pwrap_read16, ++}; ++ ++static const struct pwrap_slv_type pmic_mt6380 = { ++ .dew_regs = NULL, ++ .type = PMIC_MT6380, ++ .pwrap_read = pwrap_read32, + }; + + static const struct pwrap_slv_type pmic_mt6397 = { + .dew_regs = mt6397_regs, + .type = PMIC_MT6397, ++ .pwrap_read = pwrap_read16, + }; + + static const struct of_device_id of_slave_match_tbl[] = { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0118-soc-mediatek-pwrap-add-pwrap_write32-for-writing-in-.patch b/target/linux/mediatek/patches-4.14/0118-soc-mediatek-pwrap-add-pwrap_write32-for-writing-in-.patch new file mode 100644 index 0000000000..6048d6e40b --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0118-soc-mediatek-pwrap-add-pwrap_write32-for-writing-in-.patch @@ -0,0 +1,137 @@ +From 635f800995e4ea2a18ce7520d816dab018ce091f Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 18 Oct 2017 16:28:44 +0800 +Subject: [PATCH 118/224] soc: mediatek: pwrap: add pwrap_write32 for writing + in 32-bit mode + +Some regulators such as MediaTek MT6380 also has to be written in +32-bit mode. So the patch adds pwrap_write32, rename old pwrap_write +into pwrap_write16 and one additional function pointer is introduced +for increasing flexibility allowing the determination which mode is +used by the pwrap slave detection through device tree. + +Signed-off-by: Chenglin Xu <chenglin.xu@mediatek.com> +Signed-off-by: Chen Zhong <chen.zhong@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/mtk-pmic-wrap.c | 70 +++++++++++++++++++++++++++--------- + 1 file changed, 54 insertions(+), 16 deletions(-) + +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index 06930e2ebe4c..2d3a8faae124 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -507,6 +507,7 @@ struct pwrap_slv_type { + * which type is used by the detection through device tree. + */ + int (*pwrap_read)(struct pmic_wrapper *wrp, u32 adr, u32 *rdata); ++ int (*pwrap_write)(struct pmic_wrapper *wrp, u32 adr, u32 wdata); + }; + + struct pmic_wrapper { +@@ -601,22 +602,6 @@ static int pwrap_wait_for_state(struct pmic_wrapper *wrp, + } while (1); + } + +-static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata) +-{ +- int ret; +- +- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); +- if (ret) { +- pwrap_leave_fsm_vldclr(wrp); +- return ret; +- } +- +- pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata, +- PWRAP_WACS2_CMD); +- +- return 0; +-} +- + static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) + { + int ret; +@@ -673,6 +658,56 @@ static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) + return wrp->slave->pwrap_read(wrp, adr, rdata); + } + ++static int pwrap_write16(struct pmic_wrapper *wrp, u32 adr, u32 wdata) ++{ ++ int ret; ++ ++ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); ++ if (ret) { ++ pwrap_leave_fsm_vldclr(wrp); ++ return ret; ++ } ++ ++ pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata, ++ PWRAP_WACS2_CMD); ++ ++ return 0; ++} ++ ++static int pwrap_write32(struct pmic_wrapper *wrp, u32 adr, u32 wdata) ++{ ++ int ret, msb, rdata; ++ ++ for (msb = 0; msb < 2; msb++) { ++ ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); ++ if (ret) { ++ pwrap_leave_fsm_vldclr(wrp); ++ return ret; ++ } ++ ++ pwrap_writel(wrp, (1 << 31) | (msb << 30) | (adr << 16) | ++ ((wdata >> (msb * 16)) & 0xffff), ++ PWRAP_WACS2_CMD); ++ ++ /* ++ * The pwrap_read operation is the requirement of hardware used ++ * for the synchronization between two successive 16-bit ++ * pwrap_writel operations composing one 32-bit bus writing. ++ * Otherwise, we'll find the result fails on the lower 16-bit ++ * pwrap writing. ++ */ ++ if (!msb) ++ pwrap_read(wrp, adr, &rdata); ++ } ++ ++ return 0; ++} ++ ++static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata) ++{ ++ return wrp->slave->pwrap_write(wrp, adr, wdata); ++} ++ + static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata) + { + return pwrap_read(context, adr, rdata); +@@ -1082,18 +1117,21 @@ static const struct pwrap_slv_type pmic_mt6323 = { + .dew_regs = mt6323_regs, + .type = PMIC_MT6323, + .pwrap_read = pwrap_read16, ++ .pwrap_write = pwrap_write16, + }; + + static const struct pwrap_slv_type pmic_mt6380 = { + .dew_regs = NULL, + .type = PMIC_MT6380, + .pwrap_read = pwrap_read32, ++ .pwrap_write = pwrap_write32, + }; + + static const struct pwrap_slv_type pmic_mt6397 = { + .dew_regs = mt6397_regs, + .type = PMIC_MT6397, + .pwrap_read = pwrap_read16, ++ .pwrap_write = pwrap_write16, + }; + + static const struct of_device_id of_slave_match_tbl[] = { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0119-soc-mediatek-pwrap-refactor-pwrap_init-for-the-vario.patch b/target/linux/mediatek/patches-4.14/0119-soc-mediatek-pwrap-refactor-pwrap_init-for-the-vario.patch new file mode 100644 index 0000000000..c730fb1eec --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0119-soc-mediatek-pwrap-refactor-pwrap_init-for-the-vario.patch @@ -0,0 +1,232 @@ +From 16bebe4ad52083316907fb7149c797cd331f5948 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 18 Oct 2017 16:28:45 +0800 +Subject: [PATCH 119/224] soc: mediatek: pwrap: refactor pwrap_init for the + various PMIC types + +pwrap initialization is highly associated with the base SoC and the +target PMICs, so slight refactorization is made here for allowing +pwrap_init to run on those PMICs with different capability from the +previous MediaTek PMICs and the determination for the enablement of the +pwrap capability depending on PMIC type. Apart from this, the patch +makes the driver more extensible especially when more PMICs join into +the pwrap driver. + +Signed-off-by: Chenglin Xu <chenglin.xu@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/mtk-pmic-wrap.c | 130 ++++++++++++++++++++++++----------- + 1 file changed, 90 insertions(+), 40 deletions(-) + +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index 2d3a8faae124..e3398e37a7a6 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -70,6 +70,12 @@ + PWRAP_WDT_SRC_EN_HARB_STAUPD_DLE | \ + PWRAP_WDT_SRC_EN_HARB_STAUPD_ALE) + ++/* Group of bits used for shown slave capability */ ++#define PWRAP_SLV_CAP_SPI BIT(0) ++#define PWRAP_SLV_CAP_DUALIO BIT(1) ++#define PWRAP_SLV_CAP_SECURITY BIT(2) ++#define HAS_CAP(_c, _x) (((_c) & (_x)) == (_x)) ++ + /* defines for slave device wrapper registers */ + enum dew_regs { + PWRAP_DEW_BASE, +@@ -501,6 +507,8 @@ struct pmic_wrapper; + struct pwrap_slv_type { + const u32 *dew_regs; + enum pmic_type type; ++ /* Flags indicating the capability for the target slave */ ++ u32 caps; + /* + * pwrap operations are highly associated with the PMIC types, + * so the pointers added increases flexibility allowing determination +@@ -787,6 +795,37 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp) + return 0; + } + ++static int pwrap_init_dual_io(struct pmic_wrapper *wrp) ++{ ++ int ret; ++ u32 rdata; ++ ++ /* Enable dual IO mode */ ++ pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); ++ ++ /* Check IDLE & INIT_DONE in advance */ ++ ret = pwrap_wait_for_state(wrp, ++ pwrap_is_fsm_idle_and_sync_idle); ++ if (ret) { ++ dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); ++ return ret; ++ } ++ ++ pwrap_writel(wrp, 1, PWRAP_DIO_EN); ++ ++ /* Read Test */ ++ pwrap_read(wrp, ++ wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata); ++ if (rdata != PWRAP_DEW_READ_TEST_VAL) { ++ dev_err(wrp->dev, ++ "Read failed on DIO mode: 0x%04x!=0x%04x\n", ++ PWRAP_DEW_READ_TEST_VAL, rdata); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ + static int pwrap_mt8135_init_reg_clock(struct pmic_wrapper *wrp) + { + pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); +@@ -935,6 +974,30 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) + return 0; + } + ++static int pwrap_init_security(struct pmic_wrapper *wrp) ++{ ++ int ret; ++ ++ /* Enable encryption */ ++ ret = pwrap_init_cipher(wrp); ++ if (ret) ++ return ret; ++ ++ /* Signature checking - using CRC */ ++ if (pwrap_write(wrp, ++ wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1)) ++ return -EFAULT; ++ ++ pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); ++ pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); ++ pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL], ++ PWRAP_SIG_ADR); ++ pwrap_writel(wrp, ++ wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); ++ ++ return 0; ++} ++ + static int pwrap_mt8135_init_soc_specific(struct pmic_wrapper *wrp) + { + /* enable pwrap events and pwrap bridge in AP side */ +@@ -995,7 +1058,6 @@ static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp) + static int pwrap_init(struct pmic_wrapper *wrp) + { + int ret; +- u32 rdata; + + reset_control_reset(wrp->rstc); + if (wrp->rstc_bridge) +@@ -1007,10 +1069,12 @@ static int pwrap_init(struct pmic_wrapper *wrp) + pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); + } + +- /* Reset SPI slave */ +- ret = pwrap_reset_spislave(wrp); +- if (ret) +- return ret; ++ if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) { ++ /* Reset SPI slave */ ++ ret = pwrap_reset_spislave(wrp); ++ if (ret) ++ return ret; ++ } + + pwrap_writel(wrp, 1, PWRAP_WRAP_EN); + +@@ -1022,45 +1086,26 @@ static int pwrap_init(struct pmic_wrapper *wrp) + if (ret) + return ret; + +- /* Setup serial input delay */ +- ret = pwrap_init_sidly(wrp); +- if (ret) +- return ret; +- +- /* Enable dual IO mode */ +- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_DIO_EN], 1); +- +- /* Check IDLE & INIT_DONE in advance */ +- ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle); +- if (ret) { +- dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret); +- return ret; ++ if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SPI)) { ++ /* Setup serial input delay */ ++ ret = pwrap_init_sidly(wrp); ++ if (ret) ++ return ret; + } + +- pwrap_writel(wrp, 1, PWRAP_DIO_EN); +- +- /* Read Test */ +- pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_READ_TEST], &rdata); +- if (rdata != PWRAP_DEW_READ_TEST_VAL) { +- dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n", +- PWRAP_DEW_READ_TEST_VAL, rdata); +- return -EFAULT; ++ if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_DUALIO)) { ++ /* Enable dual I/O mode */ ++ ret = pwrap_init_dual_io(wrp); ++ if (ret) ++ return ret; + } + +- /* Enable encryption */ +- ret = pwrap_init_cipher(wrp); +- if (ret) +- return ret; +- +- /* Signature checking - using CRC */ +- if (pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1)) +- return -EFAULT; +- +- pwrap_writel(wrp, 0x1, PWRAP_CRC_EN); +- pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE); +- pwrap_writel(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_VAL], +- PWRAP_SIG_ADR); +- pwrap_writel(wrp, wrp->master->arb_en_all, PWRAP_HIPRIO_ARB_EN); ++ if (HAS_CAP(wrp->slave->caps, PWRAP_SLV_CAP_SECURITY)) { ++ /* Enable security on bus */ ++ ret = pwrap_init_security(wrp); ++ if (ret) ++ return ret; ++ } + + if (wrp->master->type == PWRAP_MT8135) + pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN); +@@ -1116,6 +1161,8 @@ static const struct regmap_config pwrap_regmap_config = { + static const struct pwrap_slv_type pmic_mt6323 = { + .dew_regs = mt6323_regs, + .type = PMIC_MT6323, ++ .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | ++ PWRAP_SLV_CAP_SECURITY, + .pwrap_read = pwrap_read16, + .pwrap_write = pwrap_write16, + }; +@@ -1123,6 +1170,7 @@ static const struct pwrap_slv_type pmic_mt6323 = { + static const struct pwrap_slv_type pmic_mt6380 = { + .dew_regs = NULL, + .type = PMIC_MT6380, ++ .caps = 0, + .pwrap_read = pwrap_read32, + .pwrap_write = pwrap_write32, + }; +@@ -1130,6 +1178,8 @@ static const struct pwrap_slv_type pmic_mt6380 = { + static const struct pwrap_slv_type pmic_mt6397 = { + .dew_regs = mt6397_regs, + .type = PMIC_MT6397, ++ .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | ++ PWRAP_SLV_CAP_SECURITY, + .pwrap_read = pwrap_read16, + .pwrap_write = pwrap_write16, + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0120-soc-mediatek-pwrap-add-MediaTek-MT6380-as-one-slave-.patch b/target/linux/mediatek/patches-4.14/0120-soc-mediatek-pwrap-add-MediaTek-MT6380-as-one-slave-.patch new file mode 100644 index 0000000000..532c42c40c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0120-soc-mediatek-pwrap-add-MediaTek-MT6380-as-one-slave-.patch @@ -0,0 +1,103 @@ +From 81c54afc5bc918ea3ed65cc356236b302b1f21ca Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 18 Oct 2017 16:28:46 +0800 +Subject: [PATCH 120/224] soc: mediatek: pwrap: add MediaTek MT6380 as one + slave of pwrap + +Add MediaTek MT6380 regulator becoming one of PMIC wrapper slave +and also add extra new regmap_config of 32-bit mode for MT6380 +since old regmap_config of 16-bit mode can't be fit into the need. + +Signed-off-by: Chenglin Xu <chenglin.xu@mediatek.com> +Signed-off-by: Chen Zhong <chen.zhong@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/mtk-pmic-wrap.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index e3398e37a7a6..45c3e44d8f40 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -507,6 +507,7 @@ struct pmic_wrapper; + struct pwrap_slv_type { + const u32 *dew_regs; + enum pmic_type type; ++ const struct regmap_config *regmap; + /* Flags indicating the capability for the target slave */ + u32 caps; + /* +@@ -1149,7 +1150,7 @@ static irqreturn_t pwrap_interrupt(int irqno, void *dev_id) + return IRQ_HANDLED; + } + +-static const struct regmap_config pwrap_regmap_config = { ++static const struct regmap_config pwrap_regmap_config16 = { + .reg_bits = 16, + .val_bits = 16, + .reg_stride = 2, +@@ -1158,9 +1159,19 @@ static const struct regmap_config pwrap_regmap_config = { + .max_register = 0xffff, + }; + ++static const struct regmap_config pwrap_regmap_config32 = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .reg_read = pwrap_regmap_read, ++ .reg_write = pwrap_regmap_write, ++ .max_register = 0xffff, ++}; ++ + static const struct pwrap_slv_type pmic_mt6323 = { + .dew_regs = mt6323_regs, + .type = PMIC_MT6323, ++ .regmap = &pwrap_regmap_config16, + .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | + PWRAP_SLV_CAP_SECURITY, + .pwrap_read = pwrap_read16, +@@ -1170,6 +1181,7 @@ static const struct pwrap_slv_type pmic_mt6323 = { + static const struct pwrap_slv_type pmic_mt6380 = { + .dew_regs = NULL, + .type = PMIC_MT6380, ++ .regmap = &pwrap_regmap_config32, + .caps = 0, + .pwrap_read = pwrap_read32, + .pwrap_write = pwrap_write32, +@@ -1178,6 +1190,7 @@ static const struct pwrap_slv_type pmic_mt6380 = { + static const struct pwrap_slv_type pmic_mt6397 = { + .dew_regs = mt6397_regs, + .type = PMIC_MT6397, ++ .regmap = &pwrap_regmap_config16, + .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO | + PWRAP_SLV_CAP_SECURITY, + .pwrap_read = pwrap_read16, +@@ -1189,9 +1202,14 @@ static const struct of_device_id of_slave_match_tbl[] = { + .compatible = "mediatek,mt6323", + .data = &pmic_mt6323, + }, { ++ /* The MT6380 PMIC only implements a regulator, so we bind it ++ * directly instead of using a MFD. ++ */ ++ .compatible = "mediatek,mt6380-regulator", ++ .data = &pmic_mt6380, ++ }, { + .compatible = "mediatek,mt6397", + .data = &pmic_mt6397, +- }, { + /* sentinel */ + } + }; +@@ -1372,7 +1390,7 @@ static int pwrap_probe(struct platform_device *pdev) + if (ret) + goto err_out2; + +- wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, &pwrap_regmap_config); ++ wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, wrp->slave->regmap); + if (IS_ERR(wrp->regmap)) { + ret = PTR_ERR(wrp->regmap); + goto err_out2; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0121-soc-mediatek-pwrap-add-common-way-for-setup-CS-timin.patch b/target/linux/mediatek/patches-4.14/0121-soc-mediatek-pwrap-add-common-way-for-setup-CS-timin.patch new file mode 100644 index 0000000000..cab2178e2b --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0121-soc-mediatek-pwrap-add-common-way-for-setup-CS-timin.patch @@ -0,0 +1,124 @@ +From 442c890727e0f585154662b0908fbe3a7986052a Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 18 Oct 2017 16:28:47 +0800 +Subject: [PATCH 121/224] soc: mediatek: pwrap: add common way for setup CS + timing extenstion + +Multiple platforms would always use their own way handling CS timing +extension on the bus which leads to a little bit code duplication. +Therefore, the patch groups the similar logic to handle CS timing +extension into the common function which allows the following SoCs +have more reusability for configing CS timing. + +Signed-off-by: Chenglin Xu <chenglin.xu@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/mtk-pmic-wrap.c | 59 ++++++++++++++++++++++-------------- + 1 file changed, 37 insertions(+), 22 deletions(-) + +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index 45c3e44d8f40..cbc3f0e82337 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -827,23 +827,44 @@ static int pwrap_init_dual_io(struct pmic_wrapper *wrp) + return 0; + } + +-static int pwrap_mt8135_init_reg_clock(struct pmic_wrapper *wrp) ++/* ++ * pwrap_init_chip_select_ext is used to configure CS extension time for each ++ * phase during data transactions on the pwrap bus. ++ */ ++static void pwrap_init_chip_select_ext(struct pmic_wrapper *wrp, u8 hext_write, ++ u8 hext_read, u8 lext_start, ++ u8 lext_end) + { +- pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); +- pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); +- pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); +- pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START); +- pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END); ++ /* ++ * After finishing a write and read transaction, extends CS high time ++ * to be at least xT of BUS CLK as hext_write and hext_read specifies ++ * respectively. ++ */ ++ pwrap_writel(wrp, hext_write, PWRAP_CSHEXT_WRITE); ++ pwrap_writel(wrp, hext_read, PWRAP_CSHEXT_READ); + +- return 0; ++ /* ++ * Extends CS low time after CSL and before CSH command to be at ++ * least xT of BUS CLK as lext_start and lext_end specifies ++ * respectively. ++ */ ++ pwrap_writel(wrp, lext_start, PWRAP_CSLEXT_START); ++ pwrap_writel(wrp, lext_end, PWRAP_CSLEXT_END); + } + +-static int pwrap_mt8173_init_reg_clock(struct pmic_wrapper *wrp) ++static int pwrap_common_init_reg_clock(struct pmic_wrapper *wrp) + { +- pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE); +- pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ); +- pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); +- pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); ++ switch (wrp->master->type) { ++ case PWRAP_MT8173: ++ pwrap_init_chip_select_ext(wrp, 0, 4, 2, 2); ++ break; ++ case PWRAP_MT8135: ++ pwrap_writel(wrp, 0x4, PWRAP_CSHEXT); ++ pwrap_init_chip_select_ext(wrp, 0, 4, 0, 0); ++ break; ++ default: ++ break; ++ } + + return 0; + } +@@ -853,20 +874,14 @@ static int pwrap_mt2701_init_reg_clock(struct pmic_wrapper *wrp) + switch (wrp->slave->type) { + case PMIC_MT6397: + pwrap_writel(wrp, 0xc, PWRAP_RDDMY); +- pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE); +- pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ); +- pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); +- pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); ++ pwrap_init_chip_select_ext(wrp, 4, 0, 2, 2); + break; + + case PMIC_MT6323: + pwrap_writel(wrp, 0x8, PWRAP_RDDMY); + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_RDDMY_NO], + 0x8); +- pwrap_writel(wrp, 0x5, PWRAP_CSHEXT_WRITE); +- pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_READ); +- pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_START); +- pwrap_writel(wrp, 0x2, PWRAP_CSLEXT_END); ++ pwrap_init_chip_select_ext(wrp, 5, 0, 2, 2); + break; + default: + break; +@@ -1235,7 +1250,7 @@ static const struct pmic_wrapper_type pwrap_mt8135 = { + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .has_bridge = 1, +- .init_reg_clock = pwrap_mt8135_init_reg_clock, ++ .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = pwrap_mt8135_init_soc_specific, + }; + +@@ -1247,7 +1262,7 @@ static const struct pmic_wrapper_type pwrap_mt8173 = { + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, + .has_bridge = 0, +- .init_reg_clock = pwrap_mt8173_init_reg_clock, ++ .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = pwrap_mt8173_init_soc_specific, + }; + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0122-soc-mediatek-pwrap-add-support-for-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0122-soc-mediatek-pwrap-add-support-for-MT7622-SoC.patch new file mode 100644 index 0000000000..6556444108 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0122-soc-mediatek-pwrap-add-support-for-MT7622-SoC.patch @@ -0,0 +1,242 @@ +From 87996dabef0d83bbd2ed5264b83b01224bc42968 Mon Sep 17 00:00:00 2001 +From: Chenglin Xu <chenglin.xu@mediatek.com> +Date: Wed, 18 Oct 2017 16:28:48 +0800 +Subject: [PATCH 122/224] soc: mediatek: pwrap: add support for MT7622 SoC + +Add the registers, callbacks and data structures required to make the +PMIC wrapper work on MT7622. + +Signed-off-by: Chenglin Xu <chenglin.xu@mediatek.com> +Signed-off-by: Chen Zhong <chen.zhong@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/mtk-pmic-wrap.c | 170 +++++++++++++++++++++++++++++++++++ + 1 file changed, 170 insertions(+) + +diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c +index cbc3f0e82337..5d61d127e1d7 100644 +--- a/drivers/soc/mediatek/mtk-pmic-wrap.c ++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c +@@ -214,6 +214,36 @@ enum pwrap_regs { + PWRAP_ADC_RDATA_ADDR1, + PWRAP_ADC_RDATA_ADDR2, + ++ /* MT7622 only regs */ ++ PWRAP_EINT_STA0_ADR, ++ PWRAP_EINT_STA1_ADR, ++ PWRAP_STA, ++ PWRAP_CLR, ++ PWRAP_DVFS_ADR8, ++ PWRAP_DVFS_WDATA8, ++ PWRAP_DVFS_ADR9, ++ PWRAP_DVFS_WDATA9, ++ PWRAP_DVFS_ADR10, ++ PWRAP_DVFS_WDATA10, ++ PWRAP_DVFS_ADR11, ++ PWRAP_DVFS_WDATA11, ++ PWRAP_DVFS_ADR12, ++ PWRAP_DVFS_WDATA12, ++ PWRAP_DVFS_ADR13, ++ PWRAP_DVFS_WDATA13, ++ PWRAP_DVFS_ADR14, ++ PWRAP_DVFS_WDATA14, ++ PWRAP_DVFS_ADR15, ++ PWRAP_DVFS_WDATA15, ++ PWRAP_EXT_CK, ++ PWRAP_ADC_RDATA_ADDR, ++ PWRAP_GPS_STA, ++ PWRAP_SW_RST, ++ PWRAP_DVFS_STEP_CTRL0, ++ PWRAP_DVFS_STEP_CTRL1, ++ PWRAP_DVFS_STEP_CTRL2, ++ PWRAP_SPI2_CTRL, ++ + /* MT8135 only regs */ + PWRAP_CSHEXT, + PWRAP_EVENT_IN_EN, +@@ -336,6 +366,118 @@ static int mt2701_regs[] = { + [PWRAP_ADC_RDATA_ADDR2] = 0x154, + }; + ++static int mt7622_regs[] = { ++ [PWRAP_MUX_SEL] = 0x0, ++ [PWRAP_WRAP_EN] = 0x4, ++ [PWRAP_DIO_EN] = 0x8, ++ [PWRAP_SIDLY] = 0xC, ++ [PWRAP_RDDMY] = 0x10, ++ [PWRAP_SI_CK_CON] = 0x14, ++ [PWRAP_CSHEXT_WRITE] = 0x18, ++ [PWRAP_CSHEXT_READ] = 0x1C, ++ [PWRAP_CSLEXT_START] = 0x20, ++ [PWRAP_CSLEXT_END] = 0x24, ++ [PWRAP_STAUPD_PRD] = 0x28, ++ [PWRAP_STAUPD_GRPEN] = 0x2C, ++ [PWRAP_EINT_STA0_ADR] = 0x30, ++ [PWRAP_EINT_STA1_ADR] = 0x34, ++ [PWRAP_STA] = 0x38, ++ [PWRAP_CLR] = 0x3C, ++ [PWRAP_STAUPD_MAN_TRIG] = 0x40, ++ [PWRAP_STAUPD_STA] = 0x44, ++ [PWRAP_WRAP_STA] = 0x48, ++ [PWRAP_HARB_INIT] = 0x4C, ++ [PWRAP_HARB_HPRIO] = 0x50, ++ [PWRAP_HIPRIO_ARB_EN] = 0x54, ++ [PWRAP_HARB_STA0] = 0x58, ++ [PWRAP_HARB_STA1] = 0x5C, ++ [PWRAP_MAN_EN] = 0x60, ++ [PWRAP_MAN_CMD] = 0x64, ++ [PWRAP_MAN_RDATA] = 0x68, ++ [PWRAP_MAN_VLDCLR] = 0x6C, ++ [PWRAP_WACS0_EN] = 0x70, ++ [PWRAP_INIT_DONE0] = 0x74, ++ [PWRAP_WACS0_CMD] = 0x78, ++ [PWRAP_WACS0_RDATA] = 0x7C, ++ [PWRAP_WACS0_VLDCLR] = 0x80, ++ [PWRAP_WACS1_EN] = 0x84, ++ [PWRAP_INIT_DONE1] = 0x88, ++ [PWRAP_WACS1_CMD] = 0x8C, ++ [PWRAP_WACS1_RDATA] = 0x90, ++ [PWRAP_WACS1_VLDCLR] = 0x94, ++ [PWRAP_WACS2_EN] = 0x98, ++ [PWRAP_INIT_DONE2] = 0x9C, ++ [PWRAP_WACS2_CMD] = 0xA0, ++ [PWRAP_WACS2_RDATA] = 0xA4, ++ [PWRAP_WACS2_VLDCLR] = 0xA8, ++ [PWRAP_INT_EN] = 0xAC, ++ [PWRAP_INT_FLG_RAW] = 0xB0, ++ [PWRAP_INT_FLG] = 0xB4, ++ [PWRAP_INT_CLR] = 0xB8, ++ [PWRAP_SIG_ADR] = 0xBC, ++ [PWRAP_SIG_MODE] = 0xC0, ++ [PWRAP_SIG_VALUE] = 0xC4, ++ [PWRAP_SIG_ERRVAL] = 0xC8, ++ [PWRAP_CRC_EN] = 0xCC, ++ [PWRAP_TIMER_EN] = 0xD0, ++ [PWRAP_TIMER_STA] = 0xD4, ++ [PWRAP_WDT_UNIT] = 0xD8, ++ [PWRAP_WDT_SRC_EN] = 0xDC, ++ [PWRAP_WDT_FLG] = 0xE0, ++ [PWRAP_DEBUG_INT_SEL] = 0xE4, ++ [PWRAP_DVFS_ADR0] = 0xE8, ++ [PWRAP_DVFS_WDATA0] = 0xEC, ++ [PWRAP_DVFS_ADR1] = 0xF0, ++ [PWRAP_DVFS_WDATA1] = 0xF4, ++ [PWRAP_DVFS_ADR2] = 0xF8, ++ [PWRAP_DVFS_WDATA2] = 0xFC, ++ [PWRAP_DVFS_ADR3] = 0x100, ++ [PWRAP_DVFS_WDATA3] = 0x104, ++ [PWRAP_DVFS_ADR4] = 0x108, ++ [PWRAP_DVFS_WDATA4] = 0x10C, ++ [PWRAP_DVFS_ADR5] = 0x110, ++ [PWRAP_DVFS_WDATA5] = 0x114, ++ [PWRAP_DVFS_ADR6] = 0x118, ++ [PWRAP_DVFS_WDATA6] = 0x11C, ++ [PWRAP_DVFS_ADR7] = 0x120, ++ [PWRAP_DVFS_WDATA7] = 0x124, ++ [PWRAP_DVFS_ADR8] = 0x128, ++ [PWRAP_DVFS_WDATA8] = 0x12C, ++ [PWRAP_DVFS_ADR9] = 0x130, ++ [PWRAP_DVFS_WDATA9] = 0x134, ++ [PWRAP_DVFS_ADR10] = 0x138, ++ [PWRAP_DVFS_WDATA10] = 0x13C, ++ [PWRAP_DVFS_ADR11] = 0x140, ++ [PWRAP_DVFS_WDATA11] = 0x144, ++ [PWRAP_DVFS_ADR12] = 0x148, ++ [PWRAP_DVFS_WDATA12] = 0x14C, ++ [PWRAP_DVFS_ADR13] = 0x150, ++ [PWRAP_DVFS_WDATA13] = 0x154, ++ [PWRAP_DVFS_ADR14] = 0x158, ++ [PWRAP_DVFS_WDATA14] = 0x15C, ++ [PWRAP_DVFS_ADR15] = 0x160, ++ [PWRAP_DVFS_WDATA15] = 0x164, ++ [PWRAP_SPMINF_STA] = 0x168, ++ [PWRAP_CIPHER_KEY_SEL] = 0x16C, ++ [PWRAP_CIPHER_IV_SEL] = 0x170, ++ [PWRAP_CIPHER_EN] = 0x174, ++ [PWRAP_CIPHER_RDY] = 0x178, ++ [PWRAP_CIPHER_MODE] = 0x17C, ++ [PWRAP_CIPHER_SWRST] = 0x180, ++ [PWRAP_DCM_EN] = 0x184, ++ [PWRAP_DCM_DBC_PRD] = 0x188, ++ [PWRAP_EXT_CK] = 0x18C, ++ [PWRAP_ADC_CMD_ADDR] = 0x190, ++ [PWRAP_PWRAP_ADC_CMD] = 0x194, ++ [PWRAP_ADC_RDATA_ADDR] = 0x198, ++ [PWRAP_GPS_STA] = 0x19C, ++ [PWRAP_SW_RST] = 0x1A0, ++ [PWRAP_DVFS_STEP_CTRL0] = 0x238, ++ [PWRAP_DVFS_STEP_CTRL1] = 0x23C, ++ [PWRAP_DVFS_STEP_CTRL2] = 0x240, ++ [PWRAP_SPI2_CTRL] = 0x244, ++}; ++ + static int mt8173_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, +@@ -499,6 +641,7 @@ enum pmic_type { + + enum pwrap_type { + PWRAP_MT2701, ++ PWRAP_MT7622, + PWRAP_MT8135, + PWRAP_MT8173, + }; +@@ -927,6 +1070,9 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) + case PWRAP_MT8173: + pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); + break; ++ case PWRAP_MT7622: ++ pwrap_writel(wrp, 0, PWRAP_CIPHER_EN); ++ break; + } + + /* Config cipher mode @PMIC */ +@@ -1071,6 +1217,15 @@ static int pwrap_mt2701_init_soc_specific(struct pmic_wrapper *wrp) + return 0; + } + ++static int pwrap_mt7622_init_soc_specific(struct pmic_wrapper *wrp) ++{ ++ pwrap_writel(wrp, 0, PWRAP_STAUPD_PRD); ++ /* enable 2wire SPI master */ ++ pwrap_writel(wrp, 0x8000000, PWRAP_SPI2_CTRL); ++ ++ return 0; ++} ++ + static int pwrap_init(struct pmic_wrapper *wrp) + { + int ret; +@@ -1242,6 +1397,18 @@ static const struct pmic_wrapper_type pwrap_mt2701 = { + .init_soc_specific = pwrap_mt2701_init_soc_specific, + }; + ++static const struct pmic_wrapper_type pwrap_mt7622 = { ++ .regs = mt7622_regs, ++ .type = PWRAP_MT7622, ++ .arb_en_all = 0xff, ++ .int_en_all = ~(u32)BIT(31), ++ .spi_w = PWRAP_MAN_CMD_SPI_WRITE, ++ .wdt_src = PWRAP_WDT_SRC_MASK_ALL, ++ .has_bridge = 0, ++ .init_reg_clock = pwrap_common_init_reg_clock, ++ .init_soc_specific = pwrap_mt7622_init_soc_specific, ++}; ++ + static const struct pmic_wrapper_type pwrap_mt8135 = { + .regs = mt8135_regs, + .type = PWRAP_MT8135, +@@ -1271,6 +1438,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = { + .compatible = "mediatek,mt2701-pwrap", + .data = &pwrap_mt2701, + }, { ++ .compatible = "mediatek,mt7622-pwrap", ++ .data = &pwrap_mt7622, ++ }, { + .compatible = "mediatek,mt8135-pwrap", + .data = &pwrap_mt8135, + }, { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0123-soc-mediatek-place-Kconfig-for-all-SoC-drivers-under.patch b/target/linux/mediatek/patches-4.14/0123-soc-mediatek-place-Kconfig-for-all-SoC-drivers-under.patch new file mode 100644 index 0000000000..4735f845be --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0123-soc-mediatek-place-Kconfig-for-all-SoC-drivers-under.patch @@ -0,0 +1,62 @@ +From 21501b17e017cb10f1a64a73e62e3e2e91a52efa Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 5 Oct 2017 11:17:49 +0800 +Subject: [PATCH 123/224] soc: mediatek: place Kconfig for all SoC drivers + under menu + +Add cleanup for placing all Kconfig for all MediaTek SoC drivers under +the independent menu as other SoCs vendor usually did. Since the menu +would be shown depending on "ARCH_MEDIATEK || COMPILE_TEST" selected and +MTK_PMIC_WRAP is still safe compiling with the case of "COMPILE_TEST" +only, the superfluous dependency for those items under the menu also is +also being removed for the sake of simplicity. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Jean Delvare <jdelvare@suse.de> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/soc/mediatek/Kconfig | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig +index 609bb3424c14..a7d0667338f2 100644 +--- a/drivers/soc/mediatek/Kconfig ++++ b/drivers/soc/mediatek/Kconfig +@@ -1,9 +1,11 @@ + # + # MediaTek SoC drivers + # ++menu "MediaTek SoC drivers" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ + config MTK_INFRACFG + bool "MediaTek INFRACFG Support" +- depends on ARCH_MEDIATEK || COMPILE_TEST + select REGMAP + help + Say yes here to add support for the MediaTek INFRACFG controller. The +@@ -12,7 +14,6 @@ config MTK_INFRACFG + + config MTK_PMIC_WRAP + tristate "MediaTek PMIC Wrapper Support" +- depends on ARCH_MEDIATEK + depends on RESET_CONTROLLER + select REGMAP + help +@@ -22,7 +23,6 @@ config MTK_PMIC_WRAP + + config MTK_SCPSYS + bool "MediaTek SCPSYS Support" +- depends on ARCH_MEDIATEK || COMPILE_TEST + default ARCH_MEDIATEK + select REGMAP + select MTK_INFRACFG +@@ -30,3 +30,5 @@ config MTK_SCPSYS + help + Say yes here to add support for the MediaTek SCPSYS power domain + driver. ++ ++endmenu +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0124-arm64-mediatek-cleanup-message-for-platform-selectio.patch b/target/linux/mediatek/patches-4.14/0124-arm64-mediatek-cleanup-message-for-platform-selectio.patch new file mode 100644 index 0000000000..0e7fa9c1d3 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0124-arm64-mediatek-cleanup-message-for-platform-selectio.patch @@ -0,0 +1,39 @@ +From f9bea440dd8dbf1eda8644e4b1d76503053f17b6 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 19 Oct 2017 17:52:54 +0800 +Subject: [PATCH 124/224] arm64: mediatek: cleanup message for platform + selection + +The latest kernel tree already can support more MediaTek platforms such as +MT2712 and MT7622, so additional descriptions for those platforms are added +and certain cleanups are also being made here. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + arch/arm64/Kconfig.platforms | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 6b54ee8c1262..ab69f5fce261 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -91,12 +91,13 @@ config ARCH_HISI + This enables support for Hisilicon ARMv8 SoC family + + config ARCH_MEDIATEK +- bool "Mediatek MT65xx & MT81xx ARMv8 SoC" ++ bool "MediaTek SoC Family" + select ARM_GIC + select PINCTRL + select MTK_TIMER + help +- Support for Mediatek MT65xx & MT81xx ARMv8 SoCs ++ This enables support for MediaTek MT27xx, MT65xx, MT76xx ++ & MT81xx ARMv8 SoCs + + config ARCH_MESON + bool "Amlogic Platforms" +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0125-phy-phy-mtk-tphy-add-set_mode-callback.patch b/target/linux/mediatek/patches-4.14/0125-phy-phy-mtk-tphy-add-set_mode-callback.patch new file mode 100644 index 0000000000..75b3908c8d --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0125-phy-phy-mtk-tphy-add-set_mode-callback.patch @@ -0,0 +1,91 @@ +From d42ebed1aa669c5a897ec0aa5e1ede8d9069894a Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Thu, 21 Sep 2017 18:31:49 +0800 +Subject: [PATCH 125/224] phy: phy-mtk-tphy: add set_mode callback + +This is used to force PHY with USB OTG function to enter a specific +mode, and override OTG IDPIN(or IDDIG) signal. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + drivers/phy/mediatek/phy-mtk-tphy.c | 39 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c +index 721a2a1c97ef..402385f2562a 100644 +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -96,9 +96,11 @@ + + #define U3P_U2PHYDTM1 0x06C + #define P2C_RG_UART_EN BIT(16) ++#define P2C_FORCE_IDDIG BIT(9) + #define P2C_RG_VBUSVALID BIT(5) + #define P2C_RG_SESSEND BIT(4) + #define P2C_RG_AVALID BIT(2) ++#define P2C_RG_IDDIG BIT(1) + + #define U3P_U3_CHIP_GPIO_CTLD 0x0c + #define P3C_REG_IP_SW_RST BIT(31) +@@ -585,6 +587,31 @@ static void u2_phy_instance_exit(struct mtk_tphy *tphy, + } + } + ++static void u2_phy_instance_set_mode(struct mtk_tphy *tphy, ++ struct mtk_phy_instance *instance, ++ enum phy_mode mode) ++{ ++ struct u2phy_banks *u2_banks = &instance->u2_banks; ++ u32 tmp; ++ ++ tmp = readl(u2_banks->com + U3P_U2PHYDTM1); ++ switch (mode) { ++ case PHY_MODE_USB_DEVICE: ++ tmp |= P2C_FORCE_IDDIG | P2C_RG_IDDIG; ++ break; ++ case PHY_MODE_USB_HOST: ++ tmp |= P2C_FORCE_IDDIG; ++ tmp &= ~P2C_RG_IDDIG; ++ break; ++ case PHY_MODE_USB_OTG: ++ tmp &= ~(P2C_FORCE_IDDIG | P2C_RG_IDDIG); ++ break; ++ default: ++ return; ++ } ++ writel(tmp, u2_banks->com + U3P_U2PHYDTM1); ++} ++ + static void pcie_phy_instance_init(struct mtk_tphy *tphy, + struct mtk_phy_instance *instance) + { +@@ -881,6 +908,17 @@ static int mtk_phy_exit(struct phy *phy) + return 0; + } + ++static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) ++{ ++ struct mtk_phy_instance *instance = phy_get_drvdata(phy); ++ struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); ++ ++ if (instance->type == PHY_TYPE_USB2) ++ u2_phy_instance_set_mode(tphy, instance, mode); ++ ++ return 0; ++} ++ + static struct phy *mtk_phy_xlate(struct device *dev, + struct of_phandle_args *args) + { +@@ -931,6 +969,7 @@ static const struct phy_ops mtk_tphy_ops = { + .exit = mtk_phy_exit, + .power_on = mtk_phy_power_on, + .power_off = mtk_phy_power_off, ++ .set_mode = mtk_phy_set_mode, + .owner = THIS_MODULE, + }; + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0126-usb-xhci-mtk-use-dma_set_mask_and_coherent-in-probe-.patch b/target/linux/mediatek/patches-4.14/0126-usb-xhci-mtk-use-dma_set_mask_and_coherent-in-probe-.patch new file mode 100644 index 0000000000..70ed474d05 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0126-usb-xhci-mtk-use-dma_set_mask_and_coherent-in-probe-.patch @@ -0,0 +1,40 @@ +From 9f617ce19c5dab429a539d411204ae220b5b8cd6 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:33 +0800 +Subject: [PATCH 126/224] usb: xhci-mtk: use dma_set_mask_and_coherent() in + probe function + +This patch uses the simpler dma_set_mask_and_coherent() instead of +doing these as separate steps + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/xhci-mtk.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index 8fb60657ed4f..c197a6d9e157 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -606,15 +606,10 @@ static int xhci_mtk_probe(struct platform_device *pdev) + } + + /* Initialize dma_mask and coherent_dma_mask to 32-bits */ +- ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); ++ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) + goto disable_clk; + +- if (!dev->dma_mask) +- dev->dma_mask = &dev->coherent_dma_mask; +- else +- dma_set_mask(dev, DMA_BIT_MASK(32)); +- + hcd = usb_create_hcd(driver, dev, dev_name(dev)); + if (!hcd) { + ret = -ENOMEM; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0127-usb-xhci-mtk-use-ports-count-from-xhci-in-xhci_mtk_s.patch b/target/linux/mediatek/patches-4.14/0127-usb-xhci-mtk-use-ports-count-from-xhci-in-xhci_mtk_s.patch new file mode 100644 index 0000000000..67fc84ed3d --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0127-usb-xhci-mtk-use-ports-count-from-xhci-in-xhci_mtk_s.patch @@ -0,0 +1,60 @@ +From f97aa71fe34135e7fc8da6231e61ee06f79d739d Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:34 +0800 +Subject: [PATCH 127/224] usb: xhci-mtk: use ports count from xhci in + xhci_mtk_sch_init() + +Make use of ports count from xhci but not from ippc in +xhci_mtk_sch_init() + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/xhci-mtk-sch.c | 3 ++- + drivers/usb/host/xhci-mtk.c | 3 --- + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c +index 6e7ddf6cafae..bfc51bc902b8 100644 +--- a/drivers/usb/host/xhci-mtk-sch.c ++++ b/drivers/usb/host/xhci-mtk-sch.c +@@ -287,12 +287,13 @@ static bool need_bw_sch(struct usb_host_endpoint *ep, + + int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk) + { ++ struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); + struct mu3h_sch_bw_info *sch_array; + int num_usb_bus; + int i; + + /* ss IN and OUT are separated */ +- num_usb_bus = mtk->num_u3_ports * 2 + mtk->num_u2_ports; ++ num_usb_bus = xhci->num_usb3_ports * 2 + xhci->num_usb2_ports; + + sch_array = kcalloc(num_usb_bus, sizeof(*sch_array), GFP_KERNEL); + if (sch_array == NULL) +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index c197a6d9e157..9502ca408f01 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -492,7 +492,6 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) + /* called during probe() after chip reset completes */ + static int xhci_mtk_setup(struct usb_hcd *hcd) + { +- struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); + int ret; + +@@ -507,8 +506,6 @@ static int xhci_mtk_setup(struct usb_hcd *hcd) + return ret; + + if (usb_hcd_is_primary_hcd(hcd)) { +- mtk->num_u3_ports = xhci->num_usb3_ports; +- mtk->num_u2_ports = xhci->num_usb2_ports; + ret = xhci_mtk_sch_init(mtk); + if (ret) + return ret; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0128-usb-xhci-mtk-check-clock-stability-of-U3_MAC.patch b/target/linux/mediatek/patches-4.14/0128-usb-xhci-mtk-check-clock-stability-of-U3_MAC.patch new file mode 100644 index 0000000000..d046574216 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0128-usb-xhci-mtk-check-clock-stability-of-U3_MAC.patch @@ -0,0 +1,41 @@ +From 4422c4efeed2a8b9fa745c6e529623d89c0be75e Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:35 +0800 +Subject: [PATCH 128/224] usb: xhci-mtk: check clock stability of U3_MAC + +This is useful to find out the root cause when the Super Speed doesn't +work. Such as when the T-PHY is switched to PCIe or SATA, and affects +Super Speed function, the check will fail. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/xhci-mtk.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index 9502ca408f01..7a92bb782e5c 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -43,6 +43,7 @@ + + /* ip_pw_sts1 register */ + #define STS1_IP_SLEEP_STS BIT(30) ++#define STS1_U3_MAC_RST BIT(16) + #define STS1_XHCI_RST BIT(11) + #define STS1_SYS125_RST BIT(10) + #define STS1_REF_RST BIT(8) +@@ -125,6 +126,9 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) + check_val = STS1_SYSPLL_STABLE | STS1_REF_RST | + STS1_SYS125_RST | STS1_XHCI_RST; + ++ if (mtk->num_u3_ports) ++ check_val |= STS1_U3_MAC_RST; ++ + ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, + (check_val == (value & check_val)), 100, 20000); + if (ret) { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0129-usb-xhci-mtk-support-option-to-disable-usb3-ports.patch b/target/linux/mediatek/patches-4.14/0129-usb-xhci-mtk-support-option-to-disable-usb3-ports.patch new file mode 100644 index 0000000000..90e2aed441 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0129-usb-xhci-mtk-support-option-to-disable-usb3-ports.patch @@ -0,0 +1,92 @@ +From 13a1b2e927893cbb046a1ec5a55ec3516873a3f6 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:36 +0800 +Subject: [PATCH 129/224] usb: xhci-mtk: support option to disable usb3 ports + +Add support to disable specific usb3 ports, it's useful when +usb3 phy is shared with PCIe or SATA, because we should disable +the corresponding usb3 port if the phy is used by PCIe or SATA. +Sometimes it's helpful to analyse and solve problems. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/xhci-mtk.c | 18 +++++++++++++++--- + drivers/usb/host/xhci-mtk.h | 1 + + 2 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index 7a92bb782e5c..97ba51e4e149 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -92,6 +92,7 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) + { + struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; + u32 value, check_val; ++ int u3_ports_disabed = 0; + int ret; + int i; + +@@ -103,8 +104,13 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) + value &= ~CTRL1_IP_HOST_PDN; + writel(value, &ippc->ip_pw_ctr1); + +- /* power on and enable all u3 ports */ ++ /* power on and enable u3 ports except skipped ones */ + for (i = 0; i < mtk->num_u3_ports; i++) { ++ if ((0x1 << i) & mtk->u3p_dis_msk) { ++ u3_ports_disabed++; ++ continue; ++ } ++ + value = readl(&ippc->u3_ctrl_p[i]); + value &= ~(CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS); + value |= CTRL_U3_PORT_HOST_SEL; +@@ -126,7 +132,7 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) + check_val = STS1_SYSPLL_STABLE | STS1_REF_RST | + STS1_SYS125_RST | STS1_XHCI_RST; + +- if (mtk->num_u3_ports) ++ if (mtk->num_u3_ports > u3_ports_disabed) + check_val |= STS1_U3_MAC_RST; + + ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, +@@ -149,8 +155,11 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk) + if (!mtk->has_ippc) + return 0; + +- /* power down all u3 ports */ ++ /* power down u3 ports except skipped ones */ + for (i = 0; i < mtk->num_u3_ports; i++) { ++ if ((0x1 << i) & mtk->u3p_dis_msk) ++ continue; ++ + value = readl(&ippc->u3_ctrl_p[i]); + value |= CTRL_U3_PORT_PDN; + writel(value, &ippc->u3_ctrl_p[i]); +@@ -573,6 +582,9 @@ static int xhci_mtk_probe(struct platform_device *pdev) + } + + mtk->lpm_support = of_property_read_bool(node, "usb3-lpm-capable"); ++ /* optional property, ignore the error if it does not exist */ ++ of_property_read_u32(node, "mediatek,u3p-dis-msk", ++ &mtk->u3p_dis_msk); + + ret = usb_wakeup_of_property_parse(mtk, node); + if (ret) +diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h +index 3aa5e1d25064..db55a12f1585 100644 +--- a/drivers/usb/host/xhci-mtk.h ++++ b/drivers/usb/host/xhci-mtk.h +@@ -121,6 +121,7 @@ struct xhci_hcd_mtk { + bool has_ippc; + int num_u2_ports; + int num_u3_ports; ++ int u3p_dis_msk; + struct regulator *vusb33; + struct regulator *vbus; + struct clk *sys_clk; /* sys and mac clock */ +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0130-usb-xhci-mtk-remove-dummy-wakeup-debounce-clocks.patch b/target/linux/mediatek/patches-4.14/0130-usb-xhci-mtk-remove-dummy-wakeup-debounce-clocks.patch new file mode 100644 index 0000000000..cb595ff7de --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0130-usb-xhci-mtk-remove-dummy-wakeup-debounce-clocks.patch @@ -0,0 +1,93 @@ +From 25adaf94e0fcbf6c1b47cb610edb7f5c23c53139 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:37 +0800 +Subject: [PATCH 130/224] usb: xhci-mtk: remove dummy wakeup debounce clocks + +The wakeup debounce clocks for each ports in fact are not +needed, so remove them. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/xhci-mtk.c | 33 --------------------------------- + drivers/usb/host/xhci-mtk.h | 2 -- + 2 files changed, 35 deletions(-) + +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index 97ba51e4e149..d60463c07c54 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -237,25 +237,8 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) + goto sys_clk_err; + } + +- if (mtk->wakeup_src) { +- ret = clk_prepare_enable(mtk->wk_deb_p0); +- if (ret) { +- dev_err(mtk->dev, "failed to enable wk_deb_p0\n"); +- goto usb_p0_err; +- } +- +- ret = clk_prepare_enable(mtk->wk_deb_p1); +- if (ret) { +- dev_err(mtk->dev, "failed to enable wk_deb_p1\n"); +- goto usb_p1_err; +- } +- } + return 0; + +-usb_p1_err: +- clk_disable_unprepare(mtk->wk_deb_p0); +-usb_p0_err: +- clk_disable_unprepare(mtk->sys_clk); + sys_clk_err: + clk_disable_unprepare(mtk->ref_clk); + ref_clk_err: +@@ -264,10 +247,6 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) + + static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) + { +- if (mtk->wakeup_src) { +- clk_disable_unprepare(mtk->wk_deb_p1); +- clk_disable_unprepare(mtk->wk_deb_p0); +- } + clk_disable_unprepare(mtk->sys_clk); + clk_disable_unprepare(mtk->ref_clk); + } +@@ -371,18 +350,6 @@ static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk, + if (!mtk->wakeup_src) + return 0; + +- mtk->wk_deb_p0 = devm_clk_get(dev, "wakeup_deb_p0"); +- if (IS_ERR(mtk->wk_deb_p0)) { +- dev_err(dev, "fail to get wakeup_deb_p0\n"); +- return PTR_ERR(mtk->wk_deb_p0); +- } +- +- mtk->wk_deb_p1 = devm_clk_get(dev, "wakeup_deb_p1"); +- if (IS_ERR(mtk->wk_deb_p1)) { +- dev_err(dev, "fail to get wakeup_deb_p1\n"); +- return PTR_ERR(mtk->wk_deb_p1); +- } +- + mtk->pericfg = syscon_regmap_lookup_by_phandle(dn, + "mediatek,syscon-wakeup"); + if (IS_ERR(mtk->pericfg)) { +diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h +index db55a12f1585..67783a7af509 100644 +--- a/drivers/usb/host/xhci-mtk.h ++++ b/drivers/usb/host/xhci-mtk.h +@@ -126,8 +126,6 @@ struct xhci_hcd_mtk { + struct regulator *vbus; + struct clk *sys_clk; /* sys and mac clock */ + struct clk *ref_clk; +- struct clk *wk_deb_p0; /* port0's wakeup debounce clock */ +- struct clk *wk_deb_p1; + struct regmap *pericfg; + struct phy **phys; + int num_phys; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0131-usb-xhci-mtk-add-optional-mcu-and-dma-bus-clocks.patch b/target/linux/mediatek/patches-4.14/0131-usb-xhci-mtk-add-optional-mcu-and-dma-bus-clocks.patch new file mode 100644 index 0000000000..a533826937 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0131-usb-xhci-mtk-add-optional-mcu-and-dma-bus-clocks.patch @@ -0,0 +1,146 @@ +From 9dce908d64ffb8b0ab71cb3a4b79db398d2e6dc3 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:38 +0800 +Subject: [PATCH 131/224] usb: xhci-mtk: add optional mcu and dma bus clocks + +There are mcu_bus and dma_bus clocks needed to be controlled by +driver on some SoCs, so add them as optional ones + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/xhci-mtk.c | 79 ++++++++++++++++++++++++++++++++++----------- + drivers/usb/host/xhci-mtk.h | 2 ++ + 2 files changed, 62 insertions(+), 19 deletions(-) + +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index d60463c07c54..e5caabe7eebe 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -221,6 +221,44 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk) + return xhci_mtk_host_enable(mtk); + } + ++/* ignore the error if the clock does not exist */ ++static struct clk *optional_clk_get(struct device *dev, const char *id) ++{ ++ struct clk *opt_clk; ++ ++ opt_clk = devm_clk_get(dev, id); ++ /* ignore error number except EPROBE_DEFER */ ++ if (IS_ERR(opt_clk) && (PTR_ERR(opt_clk) != -EPROBE_DEFER)) ++ opt_clk = NULL; ++ ++ return opt_clk; ++} ++ ++static int xhci_mtk_clks_get(struct xhci_hcd_mtk *mtk) ++{ ++ struct device *dev = mtk->dev; ++ ++ mtk->sys_clk = devm_clk_get(dev, "sys_ck"); ++ if (IS_ERR(mtk->sys_clk)) { ++ dev_err(dev, "fail to get sys_ck\n"); ++ return PTR_ERR(mtk->sys_clk); ++ } ++ ++ mtk->ref_clk = optional_clk_get(dev, "ref_ck"); ++ if (IS_ERR(mtk->ref_clk)) ++ return PTR_ERR(mtk->ref_clk); ++ ++ mtk->mcu_clk = optional_clk_get(dev, "mcu_ck"); ++ if (IS_ERR(mtk->mcu_clk)) ++ return PTR_ERR(mtk->mcu_clk); ++ ++ mtk->dma_clk = optional_clk_get(dev, "dma_ck"); ++ if (IS_ERR(mtk->dma_clk)) ++ return PTR_ERR(mtk->dma_clk); ++ ++ return 0; ++} ++ + static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) + { + int ret; +@@ -237,16 +275,34 @@ static int xhci_mtk_clks_enable(struct xhci_hcd_mtk *mtk) + goto sys_clk_err; + } + ++ ret = clk_prepare_enable(mtk->mcu_clk); ++ if (ret) { ++ dev_err(mtk->dev, "failed to enable mcu_clk\n"); ++ goto mcu_clk_err; ++ } ++ ++ ret = clk_prepare_enable(mtk->dma_clk); ++ if (ret) { ++ dev_err(mtk->dev, "failed to enable dma_clk\n"); ++ goto dma_clk_err; ++ } ++ + return 0; + ++dma_clk_err: ++ clk_disable_unprepare(mtk->mcu_clk); ++mcu_clk_err: ++ clk_disable_unprepare(mtk->sys_clk); + sys_clk_err: + clk_disable_unprepare(mtk->ref_clk); + ref_clk_err: +- return -EINVAL; ++ return ret; + } + + static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) + { ++ clk_disable_unprepare(mtk->dma_clk); ++ clk_disable_unprepare(mtk->mcu_clk); + clk_disable_unprepare(mtk->sys_clk); + clk_disable_unprepare(mtk->ref_clk); + } +@@ -529,24 +585,9 @@ static int xhci_mtk_probe(struct platform_device *pdev) + return PTR_ERR(mtk->vusb33); + } + +- mtk->sys_clk = devm_clk_get(dev, "sys_ck"); +- if (IS_ERR(mtk->sys_clk)) { +- dev_err(dev, "fail to get sys_ck\n"); +- return PTR_ERR(mtk->sys_clk); +- } +- +- /* +- * reference clock is usually a "fixed-clock", make it optional +- * for backward compatibility and ignore the error if it does +- * not exist. +- */ +- mtk->ref_clk = devm_clk_get(dev, "ref_ck"); +- if (IS_ERR(mtk->ref_clk)) { +- if (PTR_ERR(mtk->ref_clk) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- +- mtk->ref_clk = NULL; +- } ++ ret = xhci_mtk_clks_get(mtk); ++ if (ret) ++ return ret; + + mtk->lpm_support = of_property_read_bool(node, "usb3-lpm-capable"); + /* optional property, ignore the error if it does not exist */ +diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h +index 67783a7af509..45ff5c67efb5 100644 +--- a/drivers/usb/host/xhci-mtk.h ++++ b/drivers/usb/host/xhci-mtk.h +@@ -126,6 +126,8 @@ struct xhci_hcd_mtk { + struct regulator *vbus; + struct clk *sys_clk; /* sys and mac clock */ + struct clk *ref_clk; ++ struct clk *mcu_clk; ++ struct clk *dma_clk; + struct regmap *pericfg; + struct phy **phys; + int num_phys; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0132-usb-host-modify-description-for-MTK-xHCI-config.patch b/target/linux/mediatek/patches-4.14/0132-usb-host-modify-description-for-MTK-xHCI-config.patch new file mode 100644 index 0000000000..87e1b3daa9 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0132-usb-host-modify-description-for-MTK-xHCI-config.patch @@ -0,0 +1,37 @@ +From d975bd8976c4d19fbfbaafe269dd466e281a2e3e Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:39 +0800 +Subject: [PATCH 132/224] usb: host: modify description for MTK xHCI config + +Due to all MediaTek SoCs with xHCI host controller use this +driver, remove limitation for specific SoCs + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index fa5692dec832..bc09a2e4faeb 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -45,12 +45,12 @@ config USB_XHCI_PLATFORM + If unsure, say N. + + config USB_XHCI_MTK +- tristate "xHCI support for Mediatek MT65xx/MT7621" ++ tristate "xHCI support for MediaTek SoCs" + select MFD_SYSCON + depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST + ---help--- + Say 'Y' to enable the support for the xHCI host controller +- found in Mediatek MT65xx SoCs. ++ found in MediaTek SoCs. + If unsure, say N. + + config USB_XHCI_MVEBU +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0133-dt-bindings-usb-mtk-xhci-add-a-optional-property-to-.patch b/target/linux/mediatek/patches-4.14/0133-dt-bindings-usb-mtk-xhci-add-a-optional-property-to-.patch new file mode 100644 index 0000000000..e59f46a1fe --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0133-dt-bindings-usb-mtk-xhci-add-a-optional-property-to-.patch @@ -0,0 +1,30 @@ +From 3a2dce7d84793ec60cff173e17e3669acaade8c9 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:40 +0800 +Subject: [PATCH 133/224] dt-bindings: usb: mtk-xhci: add a optional property + to disable u3ports + +Add a new optional property to disable u3ports + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +index 5611a2e4ddf0..2d9b459bd890 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +@@ -38,6 +38,8 @@ Optional properties: + mode; + - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup + control register, it depends on "mediatek,wakeup-src". ++ - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, ++ bit1 for u3port1, ... etc; + - vbus-supply : reference to the VBUS regulator; + - usb3-lpm-capable : supports USB3.0 LPM + - pinctrl-names : a pinctrl state named "default" must be defined +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0134-dt-bindings-usb-mtk-xhci-remove-dummy-clocks-and-add.patch b/target/linux/mediatek/patches-4.14/0134-dt-bindings-usb-mtk-xhci-remove-dummy-clocks-and-add.patch new file mode 100644 index 0000000000..9d196ab498 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0134-dt-bindings-usb-mtk-xhci-remove-dummy-clocks-and-add.patch @@ -0,0 +1,63 @@ +From a96468412cac8abd66667c322fbcda756cc3abc9 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 13 Oct 2017 16:26:41 +0800 +Subject: [PATCH 134/224] dt-bindings: usb: mtk-xhci: remove dummy clocks and + add optional ones + +Remove dummy clocks for usb wakeup and add optional ones for +MCU_BUS_CK and DMA_BUS_CK. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + .../devicetree/bindings/usb/mediatek,mtk-xhci.txt | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +index 2d9b459bd890..30595964876a 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +@@ -26,10 +26,11 @@ Required properties: + - clocks : a list of phandle + clock-specifier pairs, one for each + entry in clock-names + - clock-names : must contain +- "sys_ck": for clock of xHCI MAC +- "ref_ck": for reference clock of xHCI MAC +- "wakeup_deb_p0": for USB wakeup debounce clock of port0 +- "wakeup_deb_p1": for USB wakeup debounce clock of port1 ++ "sys_ck": controller clock used by normal mode, ++ the following ones are optional: ++ "ref_ck": reference clock used by low power mode etc, ++ "mcu_ck": mcu_bus clock for register access, ++ "dma_ck": dma_bus clock for data transfer by DMA + + - phys : a list of phandle + phy specifier pairs + +@@ -57,9 +58,7 @@ usb30: usb@11270000 { + clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>, + <&pericfg CLK_PERI_USB0>, + <&pericfg CLK_PERI_USB1>; +- clock-names = "sys_ck", "ref_ck", +- "wakeup_deb_p0", +- "wakeup_deb_p1"; ++ clock-names = "sys_ck", "ref_ck"; + phys = <&phy_port0 PHY_TYPE_USB3>, + <&phy_port1 PHY_TYPE_USB2>; + vusb33-supply = <&mt6397_vusb_reg>; +@@ -91,9 +90,8 @@ Required properties: + + - clocks : a list of phandle + clock-specifier pairs, one for each + entry in clock-names +- - clock-names : must be +- "sys_ck": for clock of xHCI MAC +- "ref_ck": for reference clock of xHCI MAC ++ - clock-names : must contain "sys_ck", and the following ones are optional: ++ "ref_ck", "mcu_ck" and "dma_ck" + + Optional properties: + - vbus-supply : reference to the VBUS regulator; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0135-dt-bindings-mtd-add-new-compatible-strings-and-impro.patch b/target/linux/mediatek/patches-4.14/0135-dt-bindings-mtd-add-new-compatible-strings-and-impro.patch new file mode 100644 index 0000000000..4c699860c8 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0135-dt-bindings-mtd-add-new-compatible-strings-and-impro.patch @@ -0,0 +1,47 @@ +From 2af9a8582cb28e786a8cbd913f41e6db9adcf3dc Mon Sep 17 00:00:00 2001 +From: Guochun Mao <guochun.mao@mediatek.com> +Date: Thu, 21 Sep 2017 20:45:05 +0800 +Subject: [PATCH 135/224] dt-bindings: mtd: add new compatible strings and + improve description + +Add "mediatak,mt2712-nor" and "mediatek,mt7622-nor" +for nor flash node's compatible strings. +Explicate the fallback compatible. + +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Guochun Mao <guochun.mao@mediatek.com> +Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr> +--- + Documentation/devicetree/bindings/mtd/mtk-quadspi.txt | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt b/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt +index 840f9405dcf0..56d3668e2c50 100644 +--- a/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt ++++ b/Documentation/devicetree/bindings/mtd/mtk-quadspi.txt +@@ -1,13 +1,16 @@ + * Serial NOR flash controller for MTK MT81xx (and similar) + + Required properties: +-- compatible: The possible values are: +- "mediatek,mt2701-nor" +- "mediatek,mt7623-nor" ++- compatible: For mt8173, compatible should be "mediatek,mt8173-nor", ++ and it's the fallback compatible for other Soc. ++ For every other SoC, should contain both the SoC-specific compatible ++ string and "mediatek,mt8173-nor". ++ The possible values are: ++ "mediatek,mt2701-nor", "mediatek,mt8173-nor" ++ "mediatek,mt2712-nor", "mediatek,mt8173-nor" ++ "mediatek,mt7622-nor", "mediatek,mt8173-nor" ++ "mediatek,mt7623-nor", "mediatek,mt8173-nor" + "mediatek,mt8173-nor" +- For mt8173, compatible should be "mediatek,mt8173-nor". +- For every other SoC, should contain both the SoC-specific compatible string +- and "mediatek,mt8173-nor". + - reg: physical base address and length of the controller's register + - clocks: the phandle of the clocks needed by the nor controller + - clock-names: the names of the clocks +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0136-mtd-mtk-nor-add-suspend-resume-support.patch b/target/linux/mediatek/patches-4.14/0136-mtd-mtk-nor-add-suspend-resume-support.patch new file mode 100644 index 0000000000..248e195f45 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0136-mtd-mtk-nor-add-suspend-resume-support.patch @@ -0,0 +1,133 @@ +From 8947f8cd407a55db816cd03fc03b59096210978e Mon Sep 17 00:00:00 2001 +From: Guochun Mao <guochun.mao@mediatek.com> +Date: Thu, 21 Sep 2017 20:45:06 +0800 +Subject: [PATCH 136/224] mtd: mtk-nor: add suspend/resume support + +Abstract functions of clock setting, to avoid duplicated code, +these functions been used in new feature. +Implement suspend/resume functions. + +Signed-off-by: Guochun Mao <guochun.mao@mediatek.com> +Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr> +--- + drivers/mtd/spi-nor/mtk-quadspi.c | 70 ++++++++++++++++++++++++++++++++------- + 1 file changed, 58 insertions(+), 12 deletions(-) + +diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c +index c258c7adf1c5..abe455ccd68b 100644 +--- a/drivers/mtd/spi-nor/mtk-quadspi.c ++++ b/drivers/mtd/spi-nor/mtk-quadspi.c +@@ -404,6 +404,29 @@ static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, + return ret; + } + ++static void mt8173_nor_disable_clk(struct mt8173_nor *mt8173_nor) ++{ ++ clk_disable_unprepare(mt8173_nor->spi_clk); ++ clk_disable_unprepare(mt8173_nor->nor_clk); ++} ++ ++static int mt8173_nor_enable_clk(struct mt8173_nor *mt8173_nor) ++{ ++ int ret; ++ ++ ret = clk_prepare_enable(mt8173_nor->spi_clk); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(mt8173_nor->nor_clk); ++ if (ret) { ++ clk_disable_unprepare(mt8173_nor->spi_clk); ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int mtk_nor_init(struct mt8173_nor *mt8173_nor, + struct device_node *flash_node) + { +@@ -468,15 +491,11 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) + return PTR_ERR(mt8173_nor->nor_clk); + + mt8173_nor->dev = &pdev->dev; +- ret = clk_prepare_enable(mt8173_nor->spi_clk); ++ ++ ret = mt8173_nor_enable_clk(mt8173_nor); + if (ret) + return ret; + +- ret = clk_prepare_enable(mt8173_nor->nor_clk); +- if (ret) { +- clk_disable_unprepare(mt8173_nor->spi_clk); +- return ret; +- } + /* only support one attached flash */ + flash_np = of_get_next_available_child(pdev->dev.of_node, NULL); + if (!flash_np) { +@@ -487,10 +506,9 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) + ret = mtk_nor_init(mt8173_nor, flash_np); + + nor_free: +- if (ret) { +- clk_disable_unprepare(mt8173_nor->spi_clk); +- clk_disable_unprepare(mt8173_nor->nor_clk); +- } ++ if (ret) ++ mt8173_nor_disable_clk(mt8173_nor); ++ + return ret; + } + +@@ -498,11 +516,38 @@ static int mtk_nor_drv_remove(struct platform_device *pdev) + { + struct mt8173_nor *mt8173_nor = platform_get_drvdata(pdev); + +- clk_disable_unprepare(mt8173_nor->spi_clk); +- clk_disable_unprepare(mt8173_nor->nor_clk); ++ mt8173_nor_disable_clk(mt8173_nor); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int mtk_nor_suspend(struct device *dev) ++{ ++ struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); ++ ++ mt8173_nor_disable_clk(mt8173_nor); ++ + return 0; + } + ++static int mtk_nor_resume(struct device *dev) ++{ ++ struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); ++ ++ return mt8173_nor_enable_clk(mt8173_nor); ++} ++ ++static const struct dev_pm_ops mtk_nor_dev_pm_ops = { ++ .suspend = mtk_nor_suspend, ++ .resume = mtk_nor_resume, ++}; ++ ++#define MTK_NOR_DEV_PM_OPS (&mtk_nor_dev_pm_ops) ++#else ++#define MTK_NOR_DEV_PM_OPS NULL ++#endif ++ + static const struct of_device_id mtk_nor_of_ids[] = { + { .compatible = "mediatek,mt8173-nor"}, + { /* sentinel */ } +@@ -514,6 +559,7 @@ static struct platform_driver mtk_nor_driver = { + .remove = mtk_nor_drv_remove, + .driver = { + .name = "mtk-nor", ++ .pm = MTK_NOR_DEV_PM_OPS, + .of_match_table = mtk_nor_of_ids, + }, + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0137-dt-bindings-rtc-mediatek-add-bindings-for-MediaTek-S.patch b/target/linux/mediatek/patches-4.14/0137-dt-bindings-rtc-mediatek-add-bindings-for-MediaTek-S.patch new file mode 100644 index 0000000000..2488276b69 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0137-dt-bindings-rtc-mediatek-add-bindings-for-MediaTek-S.patch @@ -0,0 +1,47 @@ +From 3254edde244fcbcce3bf4da1ade9db2db558ae28 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 23 Oct 2017 15:16:44 +0800 +Subject: [PATCH 137/224] dt-bindings: rtc: mediatek: add bindings for MediaTek + SoC based RTC + +Add device-tree binding for MediaTek SoC based RTC + +Cc: devicetree@vger.kernel.org +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> +--- + .../devicetree/bindings/rtc/rtc-mt7622.txt | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + create mode 100644 Documentation/devicetree/bindings/rtc/rtc-mt7622.txt + +diff --git a/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt b/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt +new file mode 100644 +index 000000000000..09fe8f51476f +--- /dev/null ++++ b/Documentation/devicetree/bindings/rtc/rtc-mt7622.txt +@@ -0,0 +1,21 @@ ++Device-Tree bindings for MediaTek SoC based RTC ++ ++Required properties: ++- compatible : Should be ++ "mediatek,mt7622-rtc", "mediatek,soc-rtc" : for MT7622 SoC ++- reg : Specifies base physical address and size of the registers; ++- interrupts : Should contain the interrupt for RTC alarm; ++- clocks : Specifies list of clock specifiers, corresponding to ++ entries in clock-names property; ++- clock-names : Should contain "rtc" entries ++ ++Example: ++ ++rtc: rtc@10212800 { ++ compatible = "mediatek,mt7622-rtc", ++ "mediatek,soc-rtc"; ++ reg = <0 0x10212800 0 0x200>; ++ interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_RTC>; ++ clock-names = "rtc"; ++}; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0138-rtc-mediatek-add-driver-for-RTC-on-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0138-rtc-mediatek-add-driver-for-RTC-on-MT7622-SoC.patch new file mode 100644 index 0000000000..6be78ac4ca --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0138-rtc-mediatek-add-driver-for-RTC-on-MT7622-SoC.patch @@ -0,0 +1,481 @@ +From 4cf0b74c175cb5cb751e449223c0baafc2f98499 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 23 Oct 2017 15:16:45 +0800 +Subject: [PATCH 138/224] rtc: mediatek: add driver for RTC on MT7622 SoC + +This patch introduces the driver for the RTC on MT7622 SoC. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Yingjoe Chen <yingjoe.chen@mediatek.com> +Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> +--- + drivers/rtc/Kconfig | 10 ++ + drivers/rtc/Makefile | 1 + + drivers/rtc/rtc-mt7622.c | 422 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 433 insertions(+) + create mode 100644 drivers/rtc/rtc-mt7622.c + +diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig +index e0e58f3b1420..322752ebc5a7 100644 +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -1715,6 +1715,16 @@ config RTC_DRV_MT6397 + + If you want to use Mediatek(R) RTC interface, select Y or M here. + ++config RTC_DRV_MT7622 ++ tristate "MediaTek SoC based RTC" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ help ++ This enables support for the real time clock built in the MediaTek ++ SoCs. ++ ++ This drive can also be built as a module. If so, the module ++ will be called rtc-mt7622. ++ + config RTC_DRV_XGENE + tristate "APM X-Gene RTC" + depends on HAS_IOMEM +diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile +index 7230014c92af..5ec891a81f4f 100644 +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -102,6 +102,7 @@ obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o + obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o + obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o + obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o ++obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o + obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o + obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o + obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o +diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c +new file mode 100644 +index 000000000000..d79b9ae4d237 +--- /dev/null ++++ b/drivers/rtc/rtc-mt7622.c +@@ -0,0 +1,422 @@ ++/* ++ * Driver for MediaTek SoC based RTC ++ * ++ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/interrupt.h> ++#include <linux/module.h> ++#include <linux/of_address.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++#include <linux/rtc.h> ++ ++#define MTK_RTC_DEV KBUILD_MODNAME ++ ++#define MTK_RTC_PWRCHK1 0x4 ++#define RTC_PWRCHK1_MAGIC 0xc6 ++ ++#define MTK_RTC_PWRCHK2 0x8 ++#define RTC_PWRCHK2_MAGIC 0x9a ++ ++#define MTK_RTC_KEY 0xc ++#define RTC_KEY_MAGIC 0x59 ++ ++#define MTK_RTC_PROT1 0x10 ++#define RTC_PROT1_MAGIC 0xa3 ++ ++#define MTK_RTC_PROT2 0x14 ++#define RTC_PROT2_MAGIC 0x57 ++ ++#define MTK_RTC_PROT3 0x18 ++#define RTC_PROT3_MAGIC 0x67 ++ ++#define MTK_RTC_PROT4 0x1c ++#define RTC_PROT4_MAGIC 0xd2 ++ ++#define MTK_RTC_CTL 0x20 ++#define RTC_RC_STOP BIT(0) ++ ++#define MTK_RTC_DEBNCE 0x2c ++#define RTC_DEBNCE_MASK GENMASK(2, 0) ++ ++#define MTK_RTC_INT 0x30 ++#define RTC_INT_AL_STA BIT(4) ++ ++/* ++ * Ranges from 0x40 to 0x78 provide RTC time setup for year, month, ++ * day of month, day of week, hour, minute and second. ++ */ ++#define MTK_RTC_TREG(_t, _f) (0x40 + (0x4 * (_f)) + ((_t) * 0x20)) ++ ++#define MTK_RTC_AL_CTL 0x7c ++#define RTC_AL_EN BIT(0) ++#define RTC_AL_ALL GENMASK(7, 0) ++ ++/* ++ * The offset is used in the translation for the year between in struct ++ * rtc_time and in hardware register MTK_RTC_TREG(x,MTK_YEA) ++ */ ++#define MTK_RTC_TM_YR_OFFSET 100 ++ ++/* ++ * The lowest value for the valid tm_year. RTC hardware would take incorrectly ++ * tm_year 100 as not a leap year and thus it is also required being excluded ++ * from the valid options. ++ */ ++#define MTK_RTC_TM_YR_L (MTK_RTC_TM_YR_OFFSET + 1) ++ ++/* ++ * The most year the RTC can hold is 99 and the next to 99 in year register ++ * would be wraparound to 0, for MT7622. ++ */ ++#define MTK_RTC_HW_YR_LIMIT 99 ++ ++/* The highest value for the valid tm_year */ ++#define MTK_RTC_TM_YR_H (MTK_RTC_TM_YR_OFFSET + MTK_RTC_HW_YR_LIMIT) ++ ++/* Simple macro helps to check whether the hardware supports the tm_year */ ++#define MTK_RTC_TM_YR_VALID(_y) ((_y) >= MTK_RTC_TM_YR_L && \ ++ (_y) <= MTK_RTC_TM_YR_H) ++ ++/* Types of the function the RTC provides are time counter and alarm. */ ++enum { ++ MTK_TC, ++ MTK_AL, ++}; ++ ++/* Indexes are used for the pointer to relevant registers in MTK_RTC_TREG */ ++enum { ++ MTK_YEA, ++ MTK_MON, ++ MTK_DOM, ++ MTK_DOW, ++ MTK_HOU, ++ MTK_MIN, ++ MTK_SEC ++}; ++ ++struct mtk_rtc { ++ struct rtc_device *rtc; ++ void __iomem *base; ++ int irq; ++ struct clk *clk; ++}; ++ ++static void mtk_w32(struct mtk_rtc *rtc, u32 reg, u32 val) ++{ ++ writel_relaxed(val, rtc->base + reg); ++} ++ ++static u32 mtk_r32(struct mtk_rtc *rtc, u32 reg) ++{ ++ return readl_relaxed(rtc->base + reg); ++} ++ ++static void mtk_rmw(struct mtk_rtc *rtc, u32 reg, u32 mask, u32 set) ++{ ++ u32 val; ++ ++ val = mtk_r32(rtc, reg); ++ val &= ~mask; ++ val |= set; ++ mtk_w32(rtc, reg, val); ++} ++ ++static void mtk_set(struct mtk_rtc *rtc, u32 reg, u32 val) ++{ ++ mtk_rmw(rtc, reg, 0, val); ++} ++ ++static void mtk_clr(struct mtk_rtc *rtc, u32 reg, u32 val) ++{ ++ mtk_rmw(rtc, reg, val, 0); ++} ++ ++static void mtk_rtc_hw_init(struct mtk_rtc *hw) ++{ ++ /* The setup of the init sequence is for allowing RTC got to work */ ++ mtk_w32(hw, MTK_RTC_PWRCHK1, RTC_PWRCHK1_MAGIC); ++ mtk_w32(hw, MTK_RTC_PWRCHK2, RTC_PWRCHK2_MAGIC); ++ mtk_w32(hw, MTK_RTC_KEY, RTC_KEY_MAGIC); ++ mtk_w32(hw, MTK_RTC_PROT1, RTC_PROT1_MAGIC); ++ mtk_w32(hw, MTK_RTC_PROT2, RTC_PROT2_MAGIC); ++ mtk_w32(hw, MTK_RTC_PROT3, RTC_PROT3_MAGIC); ++ mtk_w32(hw, MTK_RTC_PROT4, RTC_PROT4_MAGIC); ++ mtk_rmw(hw, MTK_RTC_DEBNCE, RTC_DEBNCE_MASK, 0); ++ mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP); ++} ++ ++static void mtk_rtc_get_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm, ++ int time_alarm) ++{ ++ u32 year, mon, mday, wday, hour, min, sec; ++ ++ /* ++ * Read again until the field of the second is not changed which ++ * ensures all fields in the consistent state. Note that MTK_SEC must ++ * be read first. In this way, it guarantees the others remain not ++ * changed when the results for two MTK_SEC consecutive reads are same. ++ */ ++ do { ++ sec = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC)); ++ min = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN)); ++ hour = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU)); ++ wday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW)); ++ mday = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM)); ++ mon = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_MON)); ++ year = mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA)); ++ } while (sec != mtk_r32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC))); ++ ++ tm->tm_sec = sec; ++ tm->tm_min = min; ++ tm->tm_hour = hour; ++ tm->tm_wday = wday; ++ tm->tm_mday = mday; ++ tm->tm_mon = mon - 1; ++ ++ /* Rebase to the absolute year which userspace queries */ ++ tm->tm_year = year + MTK_RTC_TM_YR_OFFSET; ++} ++ ++static void mtk_rtc_set_alarm_or_time(struct mtk_rtc *hw, struct rtc_time *tm, ++ int time_alarm) ++{ ++ u32 year; ++ ++ /* Rebase to the relative year which RTC hardware requires */ ++ year = tm->tm_year - MTK_RTC_TM_YR_OFFSET; ++ ++ mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_YEA), year); ++ mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MON), tm->tm_mon + 1); ++ mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOW), tm->tm_wday); ++ mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_DOM), tm->tm_mday); ++ mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_HOU), tm->tm_hour); ++ mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_MIN), tm->tm_min); ++ mtk_w32(hw, MTK_RTC_TREG(time_alarm, MTK_SEC), tm->tm_sec); ++} ++ ++static irqreturn_t mtk_rtc_alarmirq(int irq, void *id) ++{ ++ struct mtk_rtc *hw = (struct mtk_rtc *)id; ++ u32 irq_sta; ++ ++ irq_sta = mtk_r32(hw, MTK_RTC_INT); ++ if (irq_sta & RTC_INT_AL_STA) { ++ /* Stop alarm also implicitly disables the alarm interrupt */ ++ mtk_w32(hw, MTK_RTC_AL_CTL, 0); ++ rtc_update_irq(hw->rtc, 1, RTC_IRQF | RTC_AF); ++ ++ /* Ack alarm interrupt status */ ++ mtk_w32(hw, MTK_RTC_INT, RTC_INT_AL_STA); ++ return IRQ_HANDLED; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static int mtk_rtc_gettime(struct device *dev, struct rtc_time *tm) ++{ ++ struct mtk_rtc *hw = dev_get_drvdata(dev); ++ ++ mtk_rtc_get_alarm_or_time(hw, tm, MTK_TC); ++ ++ return rtc_valid_tm(tm); ++} ++ ++static int mtk_rtc_settime(struct device *dev, struct rtc_time *tm) ++{ ++ struct mtk_rtc *hw = dev_get_drvdata(dev); ++ ++ if (!MTK_RTC_TM_YR_VALID(tm->tm_year)) ++ return -EINVAL; ++ ++ /* Stop time counter before setting a new one*/ ++ mtk_set(hw, MTK_RTC_CTL, RTC_RC_STOP); ++ ++ mtk_rtc_set_alarm_or_time(hw, tm, MTK_TC); ++ ++ /* Restart the time counter */ ++ mtk_clr(hw, MTK_RTC_CTL, RTC_RC_STOP); ++ ++ return 0; ++} ++ ++static int mtk_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) ++{ ++ struct mtk_rtc *hw = dev_get_drvdata(dev); ++ struct rtc_time *alrm_tm = &wkalrm->time; ++ ++ mtk_rtc_get_alarm_or_time(hw, alrm_tm, MTK_AL); ++ ++ wkalrm->enabled = !!(mtk_r32(hw, MTK_RTC_AL_CTL) & RTC_AL_EN); ++ wkalrm->pending = !!(mtk_r32(hw, MTK_RTC_INT) & RTC_INT_AL_STA); ++ ++ return 0; ++} ++ ++static int mtk_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) ++{ ++ struct mtk_rtc *hw = dev_get_drvdata(dev); ++ struct rtc_time *alrm_tm = &wkalrm->time; ++ ++ if (!MTK_RTC_TM_YR_VALID(alrm_tm->tm_year)) ++ return -EINVAL; ++ ++ /* ++ * Stop the alarm also implicitly including disables interrupt before ++ * setting a new one. ++ */ ++ mtk_clr(hw, MTK_RTC_AL_CTL, RTC_AL_EN); ++ ++ /* ++ * Avoid contention between mtk_rtc_setalarm and IRQ handler so that ++ * disabling the interrupt and awaiting for pending IRQ handler to ++ * complete. ++ */ ++ synchronize_irq(hw->irq); ++ ++ mtk_rtc_set_alarm_or_time(hw, alrm_tm, MTK_AL); ++ ++ /* Restart the alarm with the new setup */ ++ mtk_w32(hw, MTK_RTC_AL_CTL, RTC_AL_ALL); ++ ++ return 0; ++} ++ ++static const struct rtc_class_ops mtk_rtc_ops = { ++ .read_time = mtk_rtc_gettime, ++ .set_time = mtk_rtc_settime, ++ .read_alarm = mtk_rtc_getalarm, ++ .set_alarm = mtk_rtc_setalarm, ++}; ++ ++static const struct of_device_id mtk_rtc_match[] = { ++ { .compatible = "mediatek,mt7622-rtc" }, ++ { .compatible = "mediatek,soc-rtc" }, ++ {}, ++}; ++ ++static int mtk_rtc_probe(struct platform_device *pdev) ++{ ++ struct mtk_rtc *hw; ++ struct resource *res; ++ int ret; ++ ++ hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL); ++ if (!hw) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, hw); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ hw->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(hw->base)) ++ return PTR_ERR(hw->base); ++ ++ hw->clk = devm_clk_get(&pdev->dev, "rtc"); ++ if (IS_ERR(hw->clk)) { ++ dev_err(&pdev->dev, "No clock\n"); ++ return PTR_ERR(hw->clk); ++ } ++ ++ ret = clk_prepare_enable(hw->clk); ++ if (ret) ++ return ret; ++ ++ hw->irq = platform_get_irq(pdev, 0); ++ if (hw->irq < 0) { ++ dev_err(&pdev->dev, "No IRQ resource\n"); ++ ret = hw->irq; ++ goto err; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, hw->irq, mtk_rtc_alarmirq, ++ 0, dev_name(&pdev->dev), hw); ++ if (ret) { ++ dev_err(&pdev->dev, "Can't request IRQ\n"); ++ goto err; ++ } ++ ++ mtk_rtc_hw_init(hw); ++ ++ device_init_wakeup(&pdev->dev, true); ++ ++ hw->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, ++ &mtk_rtc_ops, THIS_MODULE); ++ if (IS_ERR(hw->rtc)) { ++ ret = PTR_ERR(hw->rtc); ++ dev_err(&pdev->dev, "Unable to register device\n"); ++ goto err; ++ } ++ ++ return 0; ++err: ++ clk_disable_unprepare(hw->clk); ++ ++ return ret; ++} ++ ++static int mtk_rtc_remove(struct platform_device *pdev) ++{ ++ struct mtk_rtc *hw = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(hw->clk); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int mtk_rtc_suspend(struct device *dev) ++{ ++ struct mtk_rtc *hw = dev_get_drvdata(dev); ++ ++ if (device_may_wakeup(dev)) ++ enable_irq_wake(hw->irq); ++ ++ return 0; ++} ++ ++static int mtk_rtc_resume(struct device *dev) ++{ ++ struct mtk_rtc *hw = dev_get_drvdata(dev); ++ ++ if (device_may_wakeup(dev)) ++ disable_irq_wake(hw->irq); ++ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(mtk_rtc_pm_ops, mtk_rtc_suspend, mtk_rtc_resume); ++ ++#define MTK_RTC_PM_OPS (&mtk_rtc_pm_ops) ++#else /* CONFIG_PM */ ++#define MTK_RTC_PM_OPS NULL ++#endif /* CONFIG_PM */ ++ ++static struct platform_driver mtk_rtc_driver = { ++ .probe = mtk_rtc_probe, ++ .remove = mtk_rtc_remove, ++ .driver = { ++ .name = MTK_RTC_DEV, ++ .of_match_table = mtk_rtc_match, ++ .pm = MTK_RTC_PM_OPS, ++ }, ++}; ++ ++module_platform_driver(mtk_rtc_driver); ++ ++MODULE_DESCRIPTION("MediaTek SoC based RTC Driver"); ++MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); ++MODULE_LICENSE("GPL"); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0139-rtc-mediatek-enhance-the-description-for-MediaTek-PM.patch b/target/linux/mediatek/patches-4.14/0139-rtc-mediatek-enhance-the-description-for-MediaTek-PM.patch new file mode 100644 index 0000000000..d492731669 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0139-rtc-mediatek-enhance-the-description-for-MediaTek-PM.patch @@ -0,0 +1,44 @@ +From ff4f8c2c894f1e6b5b5551571e22b2f947545bff Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 23 Oct 2017 15:16:46 +0800 +Subject: [PATCH 139/224] rtc: mediatek: enhance the description for MediaTek + PMIC based RTC + +Give a better description for original MediaTek RTC driver as PMIC based +RTC in order to distinguish SoC based RTC. Also turning all words with +Mediatek to MediaTek here. + +Cc: Eddie Huang <eddie.huang@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Acked-by: Eddie Huang <eddie.huang@mediatek.com> +Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> +--- + drivers/rtc/Kconfig | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig +index 322752ebc5a7..616fe53c788e 100644 +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -1706,14 +1706,14 @@ config RTC_DRV_MOXART + will be called rtc-moxart + + config RTC_DRV_MT6397 +- tristate "Mediatek Real Time Clock driver" ++ tristate "MediaTek PMIC based RTC" + depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN) + help +- This selects the Mediatek(R) RTC driver. RTC is part of Mediatek ++ This selects the MediaTek(R) RTC driver. RTC is part of MediaTek + MT6397 PMIC. You should enable MT6397 PMIC MFD before select +- Mediatek(R) RTC driver. ++ MediaTek(R) RTC driver. + +- If you want to use Mediatek(R) RTC interface, select Y or M here. ++ If you want to use MediaTek(R) RTC interface, select Y or M here. + + config RTC_DRV_MT7622 + tristate "MediaTek SoC based RTC" +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0140-mtd-nand-mtk-change-the-compile-sequence-of-mtk_nand.patch b/target/linux/mediatek/patches-4.14/0140-mtd-nand-mtk-change-the-compile-sequence-of-mtk_nand.patch new file mode 100644 index 0000000000..6a31a60b28 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0140-mtd-nand-mtk-change-the-compile-sequence-of-mtk_nand.patch @@ -0,0 +1,36 @@ +From 71f568692a6d0a746d72c32d46a1bc09486b9dbb Mon Sep 17 00:00:00 2001 +From: Xiaolei Li <xiaolei.li@mediatek.com> +Date: Sat, 28 Oct 2017 14:52:23 +0800 +Subject: [PATCH 140/224] mtd: nand: mtk: change the compile sequence of + mtk_nand.o and mtk_ecc.o + +There will get mtk ecc handler during mtk nand probe now. +If mtk ecc module is not initialized, then mtk nand probe will return +-EPROBE_DEFER, and retry later. + +Change the compile sequence of mtk_nand.o and mtk_ecc.o, initialize mtk +ecc module before mtk nand module. This makes mtk nand module initialized +as soon as possible. + +Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com> +Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> +--- + drivers/mtd/nand/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index ade5fc4c3819..57f4cdedf137 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -58,7 +58,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o + obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o + obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ + obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o +-obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o ++obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o + + nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_amd.o +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0142-mmc-dt-bindings-Add-reg-source_cg-latch-ck-for-Media.patch b/target/linux/mediatek/patches-4.14/0142-mmc-dt-bindings-Add-reg-source_cg-latch-ck-for-Media.patch new file mode 100644 index 0000000000..77190abd76 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0142-mmc-dt-bindings-Add-reg-source_cg-latch-ck-for-Media.patch @@ -0,0 +1,65 @@ +From 9ff279fef1a47a152993bf23f8d75fd233c27015 Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:28 +0800 +Subject: [PATCH 142/224] mmc: dt-bindings: Add reg/source_cg/latch-ck for + Mediatek MMC bindings + +Change the comptiable for support of multi-platform +Make compatible explicit, as MMC host of mt8173 has difference with +mt8135(mt8173 supports hs400 and hs400_tune),so that need separate +mt8173/mt8135 compatible name. +Add description for reg +Add description for source_cg +Add description for mediatek,latch-ck +Note that source_cg and mediatek,latch-ck are optional for some projects, +eg, MT2701 do not have source_cg, and MT2712 do not need +mediatek,latch-ck + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + Documentation/devicetree/bindings/mmc/mtk-sd.txt | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt +index 4182ea36ca5b..72d2a734ab85 100644 +--- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt ++++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt +@@ -7,10 +7,18 @@ This file documents differences between the core properties in mmc.txt + and the properties used by the msdc driver. + + Required properties: +-- compatible: Should be "mediatek,mt8173-mmc","mediatek,mt8135-mmc" ++- compatible: value should be either of the following. ++ "mediatek,mt8135-mmc": for mmc host ip compatible with mt8135 ++ "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 ++ "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 ++ "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 ++- reg: physical base address of the controller and length + - interrupts: Should contain MSDC interrupt number +-- clocks: MSDC source clock, HCLK +-- clock-names: "source", "hclk" ++- clocks: Should contain phandle for the clock feeding the MMC controller ++- clock-names: Should contain the following: ++ "source" - source clock (required) ++ "hclk" - HCLK which used for host (required) ++ "source_cg" - independent source clock gate (required for MT2712) + - pinctrl-names: should be "default", "state_uhs" + - pinctrl-0: should contain default/high speed pin ctrl + - pinctrl-1: should contain uhs mode pin ctrl +@@ -30,6 +38,10 @@ Optional properties: + - mediatek,hs400-cmd-resp-sel-rising: HS400 command response sample selection + If present,HS400 command responses are sampled on rising edges. + If not present,HS400 command responses are sampled on falling edges. ++- mediatek,latch-ck: Some SoCs do not support enhance_rx, need set correct latch-ck to avoid data crc ++ error caused by stop clock(fifo full) ++ Valid range = [0:0x7]. if not present, default value is 0. ++ applied to compatible "mediatek,mt2701-mmc". + + Examples: + mmc0: mmc@11230000 { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0143-mmc-mediatek-add-support-of-mt2701-mt2712.patch b/target/linux/mediatek/patches-4.14/0143-mmc-mediatek-add-support-of-mt2701-mt2712.patch new file mode 100644 index 0000000000..d315eda865 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0143-mmc-mediatek-add-support-of-mt2701-mt2712.patch @@ -0,0 +1,192 @@ +From 8119f3e147deaf97a66e953fecf3d2b0edbb07fd Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:29 +0800 +Subject: [PATCH 143/224] mmc: mediatek: add support of mt2701/mt2712 + +mt2701/mt2712 has 12bit clock div, which is not compatible with +mt8135/mt8173. and, some additional features will be added in +mt2701/mt2712, so that need distinguish it by comatibale name. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 82 +++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 69 insertions(+), 13 deletions(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index 267f7ab08420..643c795f1bdd 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -95,6 +95,9 @@ + #define MSDC_CFG_CKDIV (0xff << 8) /* RW */ + #define MSDC_CFG_CKMOD (0x3 << 16) /* RW */ + #define MSDC_CFG_HS400_CK_MODE (0x1 << 18) /* RW */ ++#define MSDC_CFG_HS400_CK_MODE_EXTRA (0x1 << 22) /* RW */ ++#define MSDC_CFG_CKDIV_EXTRA (0xfff << 8) /* RW */ ++#define MSDC_CFG_CKMOD_EXTRA (0x3 << 20) /* RW */ + + /* MSDC_IOCON mask */ + #define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */ +@@ -295,6 +298,10 @@ struct msdc_save_para { + u32 emmc50_cfg0; + }; + ++struct mtk_mmc_compatible { ++ u8 clk_div_bits; ++}; ++ + struct msdc_tune_para { + u32 iocon; + u32 pad_tune; +@@ -309,6 +316,7 @@ struct msdc_delay_phase { + + struct msdc_host { + struct device *dev; ++ const struct mtk_mmc_compatible *dev_comp; + struct mmc_host *mmc; /* mmc structure */ + int cmd_rsp; + +@@ -350,6 +358,31 @@ struct msdc_host { + struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */ + }; + ++static const struct mtk_mmc_compatible mt8135_compat = { ++ .clk_div_bits = 8, ++}; ++ ++static const struct mtk_mmc_compatible mt8173_compat = { ++ .clk_div_bits = 8, ++}; ++ ++static const struct mtk_mmc_compatible mt2701_compat = { ++ .clk_div_bits = 12, ++}; ++ ++static const struct mtk_mmc_compatible mt2712_compat = { ++ .clk_div_bits = 12, ++}; ++ ++static const struct of_device_id msdc_of_ids[] = { ++ { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, ++ { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, ++ { .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat}, ++ { .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat}, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, msdc_of_ids); ++ + static void sdr_set_bits(void __iomem *reg, u32 bs) + { + u32 val = readl(reg); +@@ -509,7 +542,12 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) + timeout = (ns + clk_ns - 1) / clk_ns + clks; + /* in 1048576 sclk cycle unit */ + timeout = (timeout + (0x1 << 20) - 1) >> 20; +- sdr_get_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD, &mode); ++ if (host->dev_comp->clk_div_bits == 8) ++ sdr_get_field(host->base + MSDC_CFG, ++ MSDC_CFG_CKMOD, &mode); ++ else ++ sdr_get_field(host->base + MSDC_CFG, ++ MSDC_CFG_CKMOD_EXTRA, &mode); + /*DDR mode will double the clk cycles for data timeout */ + timeout = mode >= 2 ? timeout * 2 : timeout; + timeout = timeout > 1 ? timeout - 1 : 0; +@@ -548,7 +586,11 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + + flags = readl(host->base + MSDC_INTEN); + sdr_clr_bits(host->base + MSDC_INTEN, flags); +- sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_HS400_CK_MODE); ++ if (host->dev_comp->clk_div_bits == 8) ++ sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_HS400_CK_MODE); ++ else ++ sdr_clr_bits(host->base + MSDC_CFG, ++ MSDC_CFG_HS400_CK_MODE_EXTRA); + if (timing == MMC_TIMING_UHS_DDR50 || + timing == MMC_TIMING_MMC_DDR52 || + timing == MMC_TIMING_MMC_HS400) { +@@ -568,8 +610,12 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + + if (timing == MMC_TIMING_MMC_HS400 && + hz >= (host->src_clk_freq >> 1)) { +- sdr_set_bits(host->base + MSDC_CFG, +- MSDC_CFG_HS400_CK_MODE); ++ if (host->dev_comp->clk_div_bits == 8) ++ sdr_set_bits(host->base + MSDC_CFG, ++ MSDC_CFG_HS400_CK_MODE); ++ else ++ sdr_set_bits(host->base + MSDC_CFG, ++ MSDC_CFG_HS400_CK_MODE_EXTRA); + sclk = host->src_clk_freq >> 1; + div = 0; /* div is ignore when bit18 is set */ + } +@@ -587,8 +633,15 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + sclk = (host->src_clk_freq >> 2) / div; + } + } +- sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD | MSDC_CFG_CKDIV, +- (mode << 8) | div); ++ if (host->dev_comp->clk_div_bits == 8) ++ sdr_set_field(host->base + MSDC_CFG, ++ MSDC_CFG_CKMOD | MSDC_CFG_CKDIV, ++ (mode << 8) | div); ++ else ++ sdr_set_field(host->base + MSDC_CFG, ++ MSDC_CFG_CKMOD_EXTRA | MSDC_CFG_CKDIV_EXTRA, ++ (mode << 12) | div); ++ + sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN); + while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) + cpu_relax(); +@@ -1617,12 +1670,17 @@ static int msdc_drv_probe(struct platform_device *pdev) + struct mmc_host *mmc; + struct msdc_host *host; + struct resource *res; ++ const struct of_device_id *of_id; + int ret; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } ++ ++ of_id = of_match_node(msdc_of_ids, pdev->dev.of_node); ++ if (!of_id) ++ return -EINVAL; + /* Allocate MMC host for this device */ + mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); + if (!mmc) +@@ -1686,11 +1744,15 @@ static int msdc_drv_probe(struct platform_device *pdev) + msdc_of_property_parse(pdev, host); + + host->dev = &pdev->dev; ++ host->dev_comp = of_id->data; + host->mmc = mmc; + host->src_clk_freq = clk_get_rate(host->src_clk); + /* Set host parameters to mmc */ + mmc->ops = &mt_msdc_ops; +- mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 255); ++ if (host->dev_comp->clk_div_bits == 8) ++ mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 255); ++ else ++ mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 4095); + + mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23; + /* MMC core transfer sizes tunable parameters */ +@@ -1839,12 +1901,6 @@ static const struct dev_pm_ops msdc_dev_pm_ops = { + SET_RUNTIME_PM_OPS(msdc_runtime_suspend, msdc_runtime_resume, NULL) + }; + +-static const struct of_device_id msdc_of_ids[] = { +- { .compatible = "mediatek,mt8135-mmc", }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, msdc_of_ids); +- + static struct platform_driver mt_msdc_driver = { + .probe = msdc_drv_probe, + .remove = msdc_drv_remove, +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0144-dt-bindings-ARM-Mediatek-Document-bindings-for-MT271.patch b/target/linux/mediatek/patches-4.14/0144-dt-bindings-ARM-Mediatek-Document-bindings-for-MT271.patch new file mode 100644 index 0000000000..901e6757ae --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0144-dt-bindings-ARM-Mediatek-Document-bindings-for-MT271.patch @@ -0,0 +1,226 @@ +From 815d90faddd22e05f05623086a9c42187fbfb1d8 Mon Sep 17 00:00:00 2001 +From: "weiyi.lu@mediatek.com" <weiyi.lu@mediatek.com> +Date: Mon, 23 Oct 2017 12:10:32 +0800 +Subject: [PATCH 144/224] dt-bindings: ARM: Mediatek: Document bindings for + MT2712 + +This patch adds the binding documentation for apmixedsys, bdpsys, +imgsys, imgsys, infracfg, mcucfg, mfgcfg, mmsys, pericfg, topckgen, +vdecsys and vencsys for Mediatek MT2712. + +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,bdpsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,imgsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,infracfg.txt | 1 + + .../bindings/arm/mediatek/mediatek,jpgdecsys.txt | 22 ++++++++++++++++++++++ + .../bindings/arm/mediatek/mediatek,mcucfg.txt | 22 ++++++++++++++++++++++ + .../bindings/arm/mediatek/mediatek,mfgcfg.txt | 22 ++++++++++++++++++++++ + .../bindings/arm/mediatek/mediatek,mmsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,pericfg.txt | 1 + + .../bindings/arm/mediatek/mediatek,topckgen.txt | 1 + + .../bindings/arm/mediatek/mediatek,vdecsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,vencsys.txt | 1 + + 12 files changed, 75 insertions(+) + create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt + create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt + create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt + +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt +index cd977db7630c..19fc116346d6 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt +@@ -7,6 +7,7 @@ Required Properties: + + - compatible: Should be one of: + - "mediatek,mt2701-apmixedsys" ++ - "mediatek,mt2712-apmixedsys", "syscon" + - "mediatek,mt6797-apmixedsys" + - "mediatek,mt8135-apmixedsys" + - "mediatek,mt8173-apmixedsys" +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt +index 4137196dd686..4010e37c53a0 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt +@@ -7,6 +7,7 @@ Required Properties: + + - compatible: Should be: + - "mediatek,mt2701-bdpsys", "syscon" ++ - "mediatek,mt2712-bdpsys", "syscon" + - #clock-cells: Must be 1 + + The bdpsys controller uses the common clk binding from +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt +index 047b11ae5f45..868bd51a98be 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt +@@ -7,6 +7,7 @@ Required Properties: + + - compatible: Should be one of: + - "mediatek,mt2701-imgsys", "syscon" ++ - "mediatek,mt2712-imgsys", "syscon" + - "mediatek,mt6797-imgsys", "syscon" + - "mediatek,mt8173-imgsys", "syscon" + - #clock-cells: Must be 1 +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt +index 58d58e2006b8..a3430cd96d0f 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt +@@ -8,6 +8,7 @@ Required Properties: + + - compatible: Should be one of: + - "mediatek,mt2701-infracfg", "syscon" ++ - "mediatek,mt2712-infracfg", "syscon" + - "mediatek,mt6797-infracfg", "syscon" + - "mediatek,mt8135-infracfg", "syscon" + - "mediatek,mt8173-infracfg", "syscon" +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt +new file mode 100644 +index 000000000000..2df799cd06a7 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,jpgdecsys.txt +@@ -0,0 +1,22 @@ ++Mediatek jpgdecsys controller ++============================ ++ ++The Mediatek jpgdecsys controller provides various clocks to the system. ++ ++Required Properties: ++ ++- compatible: Should be: ++ - "mediatek,mt2712-jpgdecsys", "syscon" ++- #clock-cells: Must be 1 ++ ++The jpgdecsys controller uses the common clk binding from ++Documentation/devicetree/bindings/clock/clock-bindings.txt ++The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++Example: ++ ++jpgdecsys: syscon@19000000 { ++ compatible = "mediatek,mt2712-jpgdecsys", "syscon"; ++ reg = <0 0x19000000 0 0x1000>; ++ #clock-cells = <1>; ++}; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt +new file mode 100644 +index 000000000000..b8fb03f3613e +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mcucfg.txt +@@ -0,0 +1,22 @@ ++Mediatek mcucfg controller ++============================ ++ ++The Mediatek mcucfg controller provides various clocks to the system. ++ ++Required Properties: ++ ++- compatible: Should be one of: ++ - "mediatek,mt2712-mcucfg", "syscon" ++- #clock-cells: Must be 1 ++ ++The mcucfg controller uses the common clk binding from ++Documentation/devicetree/bindings/clock/clock-bindings.txt ++The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++Example: ++ ++mcucfg: syscon@10220000 { ++ compatible = "mediatek,mt2712-mcucfg", "syscon"; ++ reg = <0 0x10220000 0 0x1000>; ++ #clock-cells = <1>; ++}; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt +new file mode 100644 +index 000000000000..859e67b416d5 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt +@@ -0,0 +1,22 @@ ++Mediatek mfgcfg controller ++============================ ++ ++The Mediatek mfgcfg controller provides various clocks to the system. ++ ++Required Properties: ++ ++- compatible: Should be one of: ++ - "mediatek,mt2712-mfgcfg", "syscon" ++- #clock-cells: Must be 1 ++ ++The mfgcfg controller uses the common clk binding from ++Documentation/devicetree/bindings/clock/clock-bindings.txt ++The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++Example: ++ ++mfgcfg: syscon@13000000 { ++ compatible = "mediatek,mt2712-mfgcfg", "syscon"; ++ reg = <0 0x13000000 0 0x1000>; ++ #clock-cells = <1>; ++}; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt +index 70529e0b58e9..4eb8bbe15c01 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt +@@ -7,6 +7,7 @@ Required Properties: + + - compatible: Should be one of: + - "mediatek,mt2701-mmsys", "syscon" ++ - "mediatek,mt2712-mmsys", "syscon" + - "mediatek,mt6797-mmsys", "syscon" + - "mediatek,mt8173-mmsys", "syscon" + - #clock-cells: Must be 1 +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt +index e494366782aa..d9f092eb3550 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt +@@ -8,6 +8,7 @@ Required Properties: + + - compatible: Should be one of: + - "mediatek,mt2701-pericfg", "syscon" ++ - "mediatek,mt2712-pericfg", "syscon" + - "mediatek,mt8135-pericfg", "syscon" + - "mediatek,mt8173-pericfg", "syscon" + - #clock-cells: Must be 1 +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt +index ec93ecbb9f3c..2024fc909d69 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt +@@ -7,6 +7,7 @@ Required Properties: + + - compatible: Should be one of: + - "mediatek,mt2701-topckgen" ++ - "mediatek,mt2712-topckgen", "syscon" + - "mediatek,mt6797-topckgen" + - "mediatek,mt8135-topckgen" + - "mediatek,mt8173-topckgen" +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt +index d150104f928a..ea40d05089f8 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt +@@ -7,6 +7,7 @@ Required Properties: + + - compatible: Should be one of: + - "mediatek,mt2701-vdecsys", "syscon" ++ - "mediatek,mt2712-vdecsys", "syscon" + - "mediatek,mt6797-vdecsys", "syscon" + - "mediatek,mt8173-vdecsys", "syscon" + - #clock-cells: Must be 1 +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt +index 8a93be643647..851545357e94 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt +@@ -6,6 +6,7 @@ The Mediatek vencsys controller provides various clocks to the system. + Required Properties: + + - compatible: Should be one of: ++ - "mediatek,mt2712-vencsys", "syscon" + - "mediatek,mt6797-vencsys", "syscon" + - "mediatek,mt8173-vencsys", "syscon" + - #clock-cells: Must be 1 +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0145-clk-mediatek-Add-dt-bindings-for-MT2712-clocks.patch b/target/linux/mediatek/patches-4.14/0145-clk-mediatek-Add-dt-bindings-for-MT2712-clocks.patch new file mode 100644 index 0000000000..9405732563 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0145-clk-mediatek-Add-dt-bindings-for-MT2712-clocks.patch @@ -0,0 +1,452 @@ +From 8a64bf0c04a4b7670cf56be5b0ae63fe9d6ecd56 Mon Sep 17 00:00:00 2001 +From: "weiyi.lu@mediatek.com" <weiyi.lu@mediatek.com> +Date: Mon, 23 Oct 2017 12:10:33 +0800 +Subject: [PATCH 145/224] clk: mediatek: Add dt-bindings for MT2712 clocks + +Add MT2712 clock dt-bindings, include topckgen, apmixedsys, +infracfg, pericfg, mcucfg and subsystem clocks. + +Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + include/dt-bindings/clock/mt2712-clk.h | 427 +++++++++++++++++++++++++++++++++ + 1 file changed, 427 insertions(+) + create mode 100644 include/dt-bindings/clock/mt2712-clk.h + +diff --git a/include/dt-bindings/clock/mt2712-clk.h b/include/dt-bindings/clock/mt2712-clk.h +new file mode 100644 +index 000000000000..48a8e797a617 +--- /dev/null ++++ b/include/dt-bindings/clock/mt2712-clk.h +@@ -0,0 +1,427 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _DT_BINDINGS_CLK_MT2712_H ++#define _DT_BINDINGS_CLK_MT2712_H ++ ++/* APMIXEDSYS */ ++ ++#define CLK_APMIXED_MAINPLL 0 ++#define CLK_APMIXED_UNIVPLL 1 ++#define CLK_APMIXED_VCODECPLL 2 ++#define CLK_APMIXED_VENCPLL 3 ++#define CLK_APMIXED_APLL1 4 ++#define CLK_APMIXED_APLL2 5 ++#define CLK_APMIXED_LVDSPLL 6 ++#define CLK_APMIXED_LVDSPLL2 7 ++#define CLK_APMIXED_MSDCPLL 8 ++#define CLK_APMIXED_MSDCPLL2 9 ++#define CLK_APMIXED_TVDPLL 10 ++#define CLK_APMIXED_MMPLL 11 ++#define CLK_APMIXED_ARMCA35PLL 12 ++#define CLK_APMIXED_ARMCA72PLL 13 ++#define CLK_APMIXED_ETHERPLL 14 ++#define CLK_APMIXED_NR_CLK 15 ++ ++/* TOPCKGEN */ ++ ++#define CLK_TOP_ARMCA35PLL 0 ++#define CLK_TOP_ARMCA35PLL_600M 1 ++#define CLK_TOP_ARMCA35PLL_400M 2 ++#define CLK_TOP_ARMCA72PLL 3 ++#define CLK_TOP_SYSPLL 4 ++#define CLK_TOP_SYSPLL_D2 5 ++#define CLK_TOP_SYSPLL1_D2 6 ++#define CLK_TOP_SYSPLL1_D4 7 ++#define CLK_TOP_SYSPLL1_D8 8 ++#define CLK_TOP_SYSPLL1_D16 9 ++#define CLK_TOP_SYSPLL_D3 10 ++#define CLK_TOP_SYSPLL2_D2 11 ++#define CLK_TOP_SYSPLL2_D4 12 ++#define CLK_TOP_SYSPLL_D5 13 ++#define CLK_TOP_SYSPLL3_D2 14 ++#define CLK_TOP_SYSPLL3_D4 15 ++#define CLK_TOP_SYSPLL_D7 16 ++#define CLK_TOP_SYSPLL4_D2 17 ++#define CLK_TOP_SYSPLL4_D4 18 ++#define CLK_TOP_UNIVPLL 19 ++#define CLK_TOP_UNIVPLL_D7 20 ++#define CLK_TOP_UNIVPLL_D26 21 ++#define CLK_TOP_UNIVPLL_D52 22 ++#define CLK_TOP_UNIVPLL_D104 23 ++#define CLK_TOP_UNIVPLL_D208 24 ++#define CLK_TOP_UNIVPLL_D2 25 ++#define CLK_TOP_UNIVPLL1_D2 26 ++#define CLK_TOP_UNIVPLL1_D4 27 ++#define CLK_TOP_UNIVPLL1_D8 28 ++#define CLK_TOP_UNIVPLL_D3 29 ++#define CLK_TOP_UNIVPLL2_D2 30 ++#define CLK_TOP_UNIVPLL2_D4 31 ++#define CLK_TOP_UNIVPLL2_D8 32 ++#define CLK_TOP_UNIVPLL_D5 33 ++#define CLK_TOP_UNIVPLL3_D2 34 ++#define CLK_TOP_UNIVPLL3_D4 35 ++#define CLK_TOP_UNIVPLL3_D8 36 ++#define CLK_TOP_F_MP0_PLL1 37 ++#define CLK_TOP_F_MP0_PLL2 38 ++#define CLK_TOP_F_BIG_PLL1 39 ++#define CLK_TOP_F_BIG_PLL2 40 ++#define CLK_TOP_F_BUS_PLL1 41 ++#define CLK_TOP_F_BUS_PLL2 42 ++#define CLK_TOP_APLL1 43 ++#define CLK_TOP_APLL1_D2 44 ++#define CLK_TOP_APLL1_D4 45 ++#define CLK_TOP_APLL1_D8 46 ++#define CLK_TOP_APLL1_D16 47 ++#define CLK_TOP_APLL2 48 ++#define CLK_TOP_APLL2_D2 49 ++#define CLK_TOP_APLL2_D4 50 ++#define CLK_TOP_APLL2_D8 51 ++#define CLK_TOP_APLL2_D16 52 ++#define CLK_TOP_LVDSPLL 53 ++#define CLK_TOP_LVDSPLL_D2 54 ++#define CLK_TOP_LVDSPLL_D4 55 ++#define CLK_TOP_LVDSPLL_D8 56 ++#define CLK_TOP_LVDSPLL2 57 ++#define CLK_TOP_LVDSPLL2_D2 58 ++#define CLK_TOP_LVDSPLL2_D4 59 ++#define CLK_TOP_LVDSPLL2_D8 60 ++#define CLK_TOP_ETHERPLL_125M 61 ++#define CLK_TOP_ETHERPLL_50M 62 ++#define CLK_TOP_CVBS 63 ++#define CLK_TOP_CVBS_D2 64 ++#define CLK_TOP_SYS_26M 65 ++#define CLK_TOP_MMPLL 66 ++#define CLK_TOP_MMPLL_D2 67 ++#define CLK_TOP_VENCPLL 68 ++#define CLK_TOP_VENCPLL_D2 69 ++#define CLK_TOP_VCODECPLL 70 ++#define CLK_TOP_VCODECPLL_D2 71 ++#define CLK_TOP_TVDPLL 72 ++#define CLK_TOP_TVDPLL_D2 73 ++#define CLK_TOP_TVDPLL_D4 74 ++#define CLK_TOP_TVDPLL_D8 75 ++#define CLK_TOP_TVDPLL_429M 76 ++#define CLK_TOP_TVDPLL_429M_D2 77 ++#define CLK_TOP_TVDPLL_429M_D4 78 ++#define CLK_TOP_MSDCPLL 79 ++#define CLK_TOP_MSDCPLL_D2 80 ++#define CLK_TOP_MSDCPLL_D4 81 ++#define CLK_TOP_MSDCPLL2 82 ++#define CLK_TOP_MSDCPLL2_D2 83 ++#define CLK_TOP_MSDCPLL2_D4 84 ++#define CLK_TOP_CLK26M_D2 85 ++#define CLK_TOP_D2A_ULCLK_6P5M 86 ++#define CLK_TOP_VPLL3_DPIX 87 ++#define CLK_TOP_VPLL_DPIX 88 ++#define CLK_TOP_LTEPLL_FS26M 89 ++#define CLK_TOP_DMPLL 90 ++#define CLK_TOP_DSI0_LNTC 91 ++#define CLK_TOP_DSI1_LNTC 92 ++#define CLK_TOP_LVDSTX3_CLKDIG_CTS 93 ++#define CLK_TOP_LVDSTX_CLKDIG_CTS 94 ++#define CLK_TOP_CLKRTC_EXT 95 ++#define CLK_TOP_CLKRTC_INT 96 ++#define CLK_TOP_CSI0 97 ++#define CLK_TOP_CVBSPLL 98 ++#define CLK_TOP_AXI_SEL 99 ++#define CLK_TOP_MEM_SEL 100 ++#define CLK_TOP_MM_SEL 101 ++#define CLK_TOP_PWM_SEL 102 ++#define CLK_TOP_VDEC_SEL 103 ++#define CLK_TOP_VENC_SEL 104 ++#define CLK_TOP_MFG_SEL 105 ++#define CLK_TOP_CAMTG_SEL 106 ++#define CLK_TOP_UART_SEL 107 ++#define CLK_TOP_SPI_SEL 108 ++#define CLK_TOP_USB20_SEL 109 ++#define CLK_TOP_USB30_SEL 110 ++#define CLK_TOP_MSDC50_0_HCLK_SEL 111 ++#define CLK_TOP_MSDC50_0_SEL 112 ++#define CLK_TOP_MSDC30_1_SEL 113 ++#define CLK_TOP_MSDC30_2_SEL 114 ++#define CLK_TOP_MSDC30_3_SEL 115 ++#define CLK_TOP_AUDIO_SEL 116 ++#define CLK_TOP_AUD_INTBUS_SEL 117 ++#define CLK_TOP_PMICSPI_SEL 118 ++#define CLK_TOP_DPILVDS1_SEL 119 ++#define CLK_TOP_ATB_SEL 120 ++#define CLK_TOP_NR_SEL 121 ++#define CLK_TOP_NFI2X_SEL 122 ++#define CLK_TOP_IRDA_SEL 123 ++#define CLK_TOP_CCI400_SEL 124 ++#define CLK_TOP_AUD_1_SEL 125 ++#define CLK_TOP_AUD_2_SEL 126 ++#define CLK_TOP_MEM_MFG_IN_AS_SEL 127 ++#define CLK_TOP_AXI_MFG_IN_AS_SEL 128 ++#define CLK_TOP_SCAM_SEL 129 ++#define CLK_TOP_NFIECC_SEL 130 ++#define CLK_TOP_PE2_MAC_P0_SEL 131 ++#define CLK_TOP_PE2_MAC_P1_SEL 132 ++#define CLK_TOP_DPILVDS_SEL 133 ++#define CLK_TOP_MSDC50_3_HCLK_SEL 134 ++#define CLK_TOP_HDCP_SEL 135 ++#define CLK_TOP_HDCP_24M_SEL 136 ++#define CLK_TOP_RTC_SEL 137 ++#define CLK_TOP_SPINOR_SEL 138 ++#define CLK_TOP_APLL_SEL 139 ++#define CLK_TOP_APLL2_SEL 140 ++#define CLK_TOP_A1SYS_HP_SEL 141 ++#define CLK_TOP_A2SYS_HP_SEL 142 ++#define CLK_TOP_ASM_L_SEL 143 ++#define CLK_TOP_ASM_M_SEL 144 ++#define CLK_TOP_ASM_H_SEL 145 ++#define CLK_TOP_I2SO1_SEL 146 ++#define CLK_TOP_I2SO2_SEL 147 ++#define CLK_TOP_I2SO3_SEL 148 ++#define CLK_TOP_TDMO0_SEL 149 ++#define CLK_TOP_TDMO1_SEL 150 ++#define CLK_TOP_I2SI1_SEL 151 ++#define CLK_TOP_I2SI2_SEL 152 ++#define CLK_TOP_I2SI3_SEL 153 ++#define CLK_TOP_ETHER_125M_SEL 154 ++#define CLK_TOP_ETHER_50M_SEL 155 ++#define CLK_TOP_JPGDEC_SEL 156 ++#define CLK_TOP_SPISLV_SEL 157 ++#define CLK_TOP_ETHER_50M_RMII_SEL 158 ++#define CLK_TOP_CAM2TG_SEL 159 ++#define CLK_TOP_DI_SEL 160 ++#define CLK_TOP_TVD_SEL 161 ++#define CLK_TOP_I2C_SEL 162 ++#define CLK_TOP_PWM_INFRA_SEL 163 ++#define CLK_TOP_MSDC0P_AES_SEL 164 ++#define CLK_TOP_CMSYS_SEL 165 ++#define CLK_TOP_GCPU_SEL 166 ++#define CLK_TOP_AUD_APLL1_SEL 167 ++#define CLK_TOP_AUD_APLL2_SEL 168 ++#define CLK_TOP_DA_AUDULL_VTX_6P5M_SEL 169 ++#define CLK_TOP_APLL_DIV0 170 ++#define CLK_TOP_APLL_DIV1 171 ++#define CLK_TOP_APLL_DIV2 172 ++#define CLK_TOP_APLL_DIV3 173 ++#define CLK_TOP_APLL_DIV4 174 ++#define CLK_TOP_APLL_DIV5 175 ++#define CLK_TOP_APLL_DIV6 176 ++#define CLK_TOP_APLL_DIV7 177 ++#define CLK_TOP_APLL_DIV_PDN0 178 ++#define CLK_TOP_APLL_DIV_PDN1 179 ++#define CLK_TOP_APLL_DIV_PDN2 180 ++#define CLK_TOP_APLL_DIV_PDN3 181 ++#define CLK_TOP_APLL_DIV_PDN4 182 ++#define CLK_TOP_APLL_DIV_PDN5 183 ++#define CLK_TOP_APLL_DIV_PDN6 184 ++#define CLK_TOP_APLL_DIV_PDN7 185 ++#define CLK_TOP_NR_CLK 186 ++ ++/* INFRACFG */ ++ ++#define CLK_INFRA_DBGCLK 0 ++#define CLK_INFRA_GCE 1 ++#define CLK_INFRA_M4U 2 ++#define CLK_INFRA_KP 3 ++#define CLK_INFRA_AO_SPI0 4 ++#define CLK_INFRA_AO_SPI1 5 ++#define CLK_INFRA_AO_UART5 6 ++#define CLK_INFRA_NR_CLK 7 ++ ++/* PERICFG */ ++ ++#define CLK_PERI_NFI 0 ++#define CLK_PERI_THERM 1 ++#define CLK_PERI_PWM0 2 ++#define CLK_PERI_PWM1 3 ++#define CLK_PERI_PWM2 4 ++#define CLK_PERI_PWM3 5 ++#define CLK_PERI_PWM4 6 ++#define CLK_PERI_PWM5 7 ++#define CLK_PERI_PWM6 8 ++#define CLK_PERI_PWM7 9 ++#define CLK_PERI_PWM 10 ++#define CLK_PERI_AP_DMA 11 ++#define CLK_PERI_MSDC30_0 12 ++#define CLK_PERI_MSDC30_1 13 ++#define CLK_PERI_MSDC30_2 14 ++#define CLK_PERI_MSDC30_3 15 ++#define CLK_PERI_UART0 16 ++#define CLK_PERI_UART1 17 ++#define CLK_PERI_UART2 18 ++#define CLK_PERI_UART3 19 ++#define CLK_PERI_I2C0 20 ++#define CLK_PERI_I2C1 21 ++#define CLK_PERI_I2C2 22 ++#define CLK_PERI_I2C3 23 ++#define CLK_PERI_I2C4 24 ++#define CLK_PERI_AUXADC 25 ++#define CLK_PERI_SPI0 26 ++#define CLK_PERI_SPI 27 ++#define CLK_PERI_I2C5 28 ++#define CLK_PERI_SPI2 29 ++#define CLK_PERI_SPI3 30 ++#define CLK_PERI_SPI5 31 ++#define CLK_PERI_UART4 32 ++#define CLK_PERI_SFLASH 33 ++#define CLK_PERI_GMAC 34 ++#define CLK_PERI_PCIE0 35 ++#define CLK_PERI_PCIE1 36 ++#define CLK_PERI_GMAC_PCLK 37 ++#define CLK_PERI_MSDC50_0_EN 38 ++#define CLK_PERI_MSDC30_1_EN 39 ++#define CLK_PERI_MSDC30_2_EN 40 ++#define CLK_PERI_MSDC30_3_EN 41 ++#define CLK_PERI_MSDC50_0_HCLK_EN 42 ++#define CLK_PERI_MSDC50_3_HCLK_EN 43 ++#define CLK_PERI_NR_CLK 44 ++ ++/* MCUCFG */ ++ ++#define CLK_MCU_MP0_SEL 0 ++#define CLK_MCU_MP2_SEL 1 ++#define CLK_MCU_BUS_SEL 2 ++#define CLK_MCU_NR_CLK 3 ++ ++/* MFGCFG */ ++ ++#define CLK_MFG_BG3D 0 ++#define CLK_MFG_NR_CLK 1 ++ ++/* MMSYS */ ++ ++#define CLK_MM_SMI_COMMON 0 ++#define CLK_MM_SMI_LARB0 1 ++#define CLK_MM_CAM_MDP 2 ++#define CLK_MM_MDP_RDMA0 3 ++#define CLK_MM_MDP_RDMA1 4 ++#define CLK_MM_MDP_RSZ0 5 ++#define CLK_MM_MDP_RSZ1 6 ++#define CLK_MM_MDP_RSZ2 7 ++#define CLK_MM_MDP_TDSHP0 8 ++#define CLK_MM_MDP_TDSHP1 9 ++#define CLK_MM_MDP_CROP 10 ++#define CLK_MM_MDP_WDMA 11 ++#define CLK_MM_MDP_WROT0 12 ++#define CLK_MM_MDP_WROT1 13 ++#define CLK_MM_FAKE_ENG 14 ++#define CLK_MM_MUTEX_32K 15 ++#define CLK_MM_DISP_OVL0 16 ++#define CLK_MM_DISP_OVL1 17 ++#define CLK_MM_DISP_RDMA0 18 ++#define CLK_MM_DISP_RDMA1 19 ++#define CLK_MM_DISP_RDMA2 20 ++#define CLK_MM_DISP_WDMA0 21 ++#define CLK_MM_DISP_WDMA1 22 ++#define CLK_MM_DISP_COLOR0 23 ++#define CLK_MM_DISP_COLOR1 24 ++#define CLK_MM_DISP_AAL 25 ++#define CLK_MM_DISP_GAMMA 26 ++#define CLK_MM_DISP_UFOE 27 ++#define CLK_MM_DISP_SPLIT0 28 ++#define CLK_MM_DISP_OD 29 ++#define CLK_MM_DISP_PWM0_MM 30 ++#define CLK_MM_DISP_PWM0_26M 31 ++#define CLK_MM_DISP_PWM1_MM 32 ++#define CLK_MM_DISP_PWM1_26M 33 ++#define CLK_MM_DSI0_ENGINE 34 ++#define CLK_MM_DSI0_DIGITAL 35 ++#define CLK_MM_DSI1_ENGINE 36 ++#define CLK_MM_DSI1_DIGITAL 37 ++#define CLK_MM_DPI_PIXEL 38 ++#define CLK_MM_DPI_ENGINE 39 ++#define CLK_MM_DPI1_PIXEL 40 ++#define CLK_MM_DPI1_ENGINE 41 ++#define CLK_MM_LVDS_PIXEL 42 ++#define CLK_MM_LVDS_CTS 43 ++#define CLK_MM_SMI_LARB4 44 ++#define CLK_MM_SMI_COMMON1 45 ++#define CLK_MM_SMI_LARB5 46 ++#define CLK_MM_MDP_RDMA2 47 ++#define CLK_MM_MDP_TDSHP2 48 ++#define CLK_MM_DISP_OVL2 49 ++#define CLK_MM_DISP_WDMA2 50 ++#define CLK_MM_DISP_COLOR2 51 ++#define CLK_MM_DISP_AAL1 52 ++#define CLK_MM_DISP_OD1 53 ++#define CLK_MM_LVDS1_PIXEL 54 ++#define CLK_MM_LVDS1_CTS 55 ++#define CLK_MM_SMI_LARB7 56 ++#define CLK_MM_MDP_RDMA3 57 ++#define CLK_MM_MDP_WROT2 58 ++#define CLK_MM_DSI2 59 ++#define CLK_MM_DSI2_DIGITAL 60 ++#define CLK_MM_DSI3 61 ++#define CLK_MM_DSI3_DIGITAL 62 ++#define CLK_MM_NR_CLK 63 ++ ++/* IMGSYS */ ++ ++#define CLK_IMG_SMI_LARB2 0 ++#define CLK_IMG_SENINF_SCAM_EN 1 ++#define CLK_IMG_SENINF_CAM_EN 2 ++#define CLK_IMG_CAM_SV_EN 3 ++#define CLK_IMG_CAM_SV1_EN 4 ++#define CLK_IMG_CAM_SV2_EN 5 ++#define CLK_IMG_NR_CLK 6 ++ ++/* BDPSYS */ ++ ++#define CLK_BDP_BRIDGE_B 0 ++#define CLK_BDP_BRIDGE_DRAM 1 ++#define CLK_BDP_LARB_DRAM 2 ++#define CLK_BDP_WR_CHANNEL_VDI_PXL 3 ++#define CLK_BDP_WR_CHANNEL_VDI_DRAM 4 ++#define CLK_BDP_WR_CHANNEL_VDI_B 5 ++#define CLK_BDP_MT_B 6 ++#define CLK_BDP_DISPFMT_27M 7 ++#define CLK_BDP_DISPFMT_27M_VDOUT 8 ++#define CLK_BDP_DISPFMT_27_74_74 9 ++#define CLK_BDP_DISPFMT_2FS 10 ++#define CLK_BDP_DISPFMT_2FS_2FS74_148 11 ++#define CLK_BDP_DISPFMT_B 12 ++#define CLK_BDP_VDO_DRAM 13 ++#define CLK_BDP_VDO_2FS 14 ++#define CLK_BDP_VDO_B 15 ++#define CLK_BDP_WR_CHANNEL_DI_PXL 16 ++#define CLK_BDP_WR_CHANNEL_DI_DRAM 17 ++#define CLK_BDP_WR_CHANNEL_DI_B 18 ++#define CLK_BDP_NR_AGENT 19 ++#define CLK_BDP_NR_DRAM 20 ++#define CLK_BDP_NR_B 21 ++#define CLK_BDP_BRIDGE_RT_B 22 ++#define CLK_BDP_BRIDGE_RT_DRAM 23 ++#define CLK_BDP_LARB_RT_DRAM 24 ++#define CLK_BDP_TVD_TDC 25 ++#define CLK_BDP_TVD_54 26 ++#define CLK_BDP_TVD_CBUS 27 ++#define CLK_BDP_NR_CLK 28 ++ ++/* VDECSYS */ ++ ++#define CLK_VDEC_CKEN 0 ++#define CLK_VDEC_LARB1_CKEN 1 ++#define CLK_VDEC_IMGRZ_CKEN 2 ++#define CLK_VDEC_NR_CLK 3 ++ ++/* VENCSYS */ ++ ++#define CLK_VENC_SMI_COMMON_CON 0 ++#define CLK_VENC_VENC 1 ++#define CLK_VENC_SMI_LARB6 2 ++#define CLK_VENC_NR_CLK 3 ++ ++/* JPGDECSYS */ ++ ++#define CLK_JPGDEC_JPGDEC1 0 ++#define CLK_JPGDEC_JPGDEC 1 ++#define CLK_JPGDEC_NR_CLK 2 ++ ++#endif /* _DT_BINDINGS_CLK_MT2712_H */ +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0146-clk-mediatek-Add-MT2712-clock-support.patch b/target/linux/mediatek/patches-4.14/0146-clk-mediatek-Add-MT2712-clock-support.patch new file mode 100644 index 0000000000..5876541d8b --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0146-clk-mediatek-Add-MT2712-clock-support.patch @@ -0,0 +1,2331 @@ +From ec5192303a3938d0972fde3b1f2526d8d6dd02d7 Mon Sep 17 00:00:00 2001 +From: "weiyi.lu@mediatek.com" <weiyi.lu@mediatek.com> +Date: Mon, 23 Oct 2017 12:10:34 +0800 +Subject: [PATCH 146/224] clk: mediatek: Add MT2712 clock support + +Add MT2712 clock support, include topckgen, apmixedsys, +infracfg, pericfg, mcucfg and subsystem clocks. + +Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com> +[sboyd@codeaurora.org: Static on top_clk_data] +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/mediatek/Kconfig | 50 ++ + drivers/clk/mediatek/Makefile | 8 + + drivers/clk/mediatek/clk-mt2712-bdp.c | 102 +++ + drivers/clk/mediatek/clk-mt2712-img.c | 80 ++ + drivers/clk/mediatek/clk-mt2712-jpgdec.c | 76 ++ + drivers/clk/mediatek/clk-mt2712-mfg.c | 75 ++ + drivers/clk/mediatek/clk-mt2712-mm.c | 170 ++++ + drivers/clk/mediatek/clk-mt2712-vdec.c | 94 ++ + drivers/clk/mediatek/clk-mt2712-venc.c | 77 ++ + drivers/clk/mediatek/clk-mt2712.c | 1435 ++++++++++++++++++++++++++++++ + drivers/clk/mediatek/clk-mtk.h | 2 + + drivers/clk/mediatek/clk-pll.c | 13 +- + 12 files changed, 2180 insertions(+), 2 deletions(-) + create mode 100644 drivers/clk/mediatek/clk-mt2712-bdp.c + create mode 100644 drivers/clk/mediatek/clk-mt2712-img.c + create mode 100644 drivers/clk/mediatek/clk-mt2712-jpgdec.c + create mode 100644 drivers/clk/mediatek/clk-mt2712-mfg.c + create mode 100644 drivers/clk/mediatek/clk-mt2712-mm.c + create mode 100644 drivers/clk/mediatek/clk-mt2712-vdec.c + create mode 100644 drivers/clk/mediatek/clk-mt2712-venc.c + create mode 100644 drivers/clk/mediatek/clk-mt2712.c + +diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig +index 28739a9a6e37..300dbb551bf7 100644 +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -50,6 +50,56 @@ config COMMON_CLK_MT2701_BDPSYS + ---help--- + This driver supports Mediatek MT2701 bdpsys clocks. + ++config COMMON_CLK_MT2712 ++ bool "Clock driver for Mediatek MT2712" ++ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST ++ select COMMON_CLK_MEDIATEK ++ default ARCH_MEDIATEK && ARM64 ++ ---help--- ++ This driver supports Mediatek MT2712 basic clocks. ++ ++config COMMON_CLK_MT2712_BDPSYS ++ bool "Clock driver for Mediatek MT2712 bdpsys" ++ depends on COMMON_CLK_MT2712 ++ ---help--- ++ This driver supports Mediatek MT2712 bdpsys clocks. ++ ++config COMMON_CLK_MT2712_IMGSYS ++ bool "Clock driver for Mediatek MT2712 imgsys" ++ depends on COMMON_CLK_MT2712 ++ ---help--- ++ This driver supports Mediatek MT2712 imgsys clocks. ++ ++config COMMON_CLK_MT2712_JPGDECSYS ++ bool "Clock driver for Mediatek MT2712 jpgdecsys" ++ depends on COMMON_CLK_MT2712 ++ ---help--- ++ This driver supports Mediatek MT2712 jpgdecsys clocks. ++ ++config COMMON_CLK_MT2712_MFGCFG ++ bool "Clock driver for Mediatek MT2712 mfgcfg" ++ depends on COMMON_CLK_MT2712 ++ ---help--- ++ This driver supports Mediatek MT2712 mfgcfg clocks. ++ ++config COMMON_CLK_MT2712_MMSYS ++ bool "Clock driver for Mediatek MT2712 mmsys" ++ depends on COMMON_CLK_MT2712 ++ ---help--- ++ This driver supports Mediatek MT2712 mmsys clocks. ++ ++config COMMON_CLK_MT2712_VDECSYS ++ bool "Clock driver for Mediatek MT2712 vdecsys" ++ depends on COMMON_CLK_MT2712 ++ ---help--- ++ This driver supports Mediatek MT2712 vdecsys clocks. ++ ++config COMMON_CLK_MT2712_VENCSYS ++ bool "Clock driver for Mediatek MT2712 vencsys" ++ depends on COMMON_CLK_MT2712 ++ ---help--- ++ This driver supports Mediatek MT2712 vencsys clocks. ++ + config COMMON_CLK_MT6797 + bool "Clock driver for Mediatek MT6797" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST +diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile +index 2a755b5fb51b..a4e5c47c73a4 100644 +--- a/drivers/clk/mediatek/Makefile ++++ b/drivers/clk/mediatek/Makefile +@@ -12,5 +12,13 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o + obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o + obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o + obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o ++obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o ++obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o ++obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o ++obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o ++obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o ++obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o ++obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o ++obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o + obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o + obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o +diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c +new file mode 100644 +index 000000000000..5fe4728c076e +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712-bdp.c +@@ -0,0 +1,102 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static const struct mtk_gate_regs bdp_cg_regs = { ++ .set_ofs = 0x100, ++ .clr_ofs = 0x100, ++ .sta_ofs = 0x100, ++}; ++ ++#define GATE_BDP(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &bdp_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++static const struct mtk_gate bdp_clks[] = { ++ GATE_BDP(CLK_BDP_BRIDGE_B, "bdp_bridge_b", "mm_sel", 0), ++ GATE_BDP(CLK_BDP_BRIDGE_DRAM, "bdp_bridge_d", "mm_sel", 1), ++ GATE_BDP(CLK_BDP_LARB_DRAM, "bdp_larb_d", "mm_sel", 2), ++ GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_PXL, "bdp_vdi_pxl", "tvd_sel", 3), ++ GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_DRAM, "bdp_vdi_d", "mm_sel", 4), ++ GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_B, "bdp_vdi_b", "mm_sel", 5), ++ GATE_BDP(CLK_BDP_MT_B, "bdp_fmt_b", "mm_sel", 9), ++ GATE_BDP(CLK_BDP_DISPFMT_27M, "bdp_27m", "di_sel", 10), ++ GATE_BDP(CLK_BDP_DISPFMT_27M_VDOUT, "bdp_27m_vdout", "di_sel", 11), ++ GATE_BDP(CLK_BDP_DISPFMT_27_74_74, "bdp_27_74_74", "di_sel", 12), ++ GATE_BDP(CLK_BDP_DISPFMT_2FS, "bdp_2fs", "di_sel", 13), ++ GATE_BDP(CLK_BDP_DISPFMT_2FS_2FS74_148, "bdp_2fs74_148", "di_sel", 14), ++ GATE_BDP(CLK_BDP_DISPFMT_B, "bdp_b", "mm_sel", 15), ++ GATE_BDP(CLK_BDP_VDO_DRAM, "bdp_vdo_d", "mm_sel", 16), ++ GATE_BDP(CLK_BDP_VDO_2FS, "bdp_vdo_2fs", "di_sel", 17), ++ GATE_BDP(CLK_BDP_VDO_B, "bdp_vdo_b", "mm_sel", 18), ++ GATE_BDP(CLK_BDP_WR_CHANNEL_DI_PXL, "bdp_di_pxl", "di_sel", 19), ++ GATE_BDP(CLK_BDP_WR_CHANNEL_DI_DRAM, "bdp_di_d", "mm_sel", 20), ++ GATE_BDP(CLK_BDP_WR_CHANNEL_DI_B, "bdp_di_b", "mm_sel", 21), ++ GATE_BDP(CLK_BDP_NR_AGENT, "bdp_nr_agent", "nr_sel", 22), ++ GATE_BDP(CLK_BDP_NR_DRAM, "bdp_nr_d", "mm_sel", 23), ++ GATE_BDP(CLK_BDP_NR_B, "bdp_nr_b", "mm_sel", 24), ++ GATE_BDP(CLK_BDP_BRIDGE_RT_B, "bdp_bridge_rt_b", "mm_sel", 25), ++ GATE_BDP(CLK_BDP_BRIDGE_RT_DRAM, "bdp_bridge_rt_d", "mm_sel", 26), ++ GATE_BDP(CLK_BDP_LARB_RT_DRAM, "bdp_larb_rt_d", "mm_sel", 27), ++ GATE_BDP(CLK_BDP_TVD_TDC, "bdp_tvd_tdc", "mm_sel", 28), ++ GATE_BDP(CLK_BDP_TVD_54, "bdp_tvd_clk_54", "tvd_sel", 29), ++ GATE_BDP(CLK_BDP_TVD_CBUS, "bdp_tvd_cbus", "mm_sel", 30), ++}; ++ ++static int clk_mt2712_bdp_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_BDP_NR_CLK); ++ ++ mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712_bdp[] = { ++ { .compatible = "mediatek,mt2712-bdpsys", }, ++ {} ++}; ++ ++static struct platform_driver clk_mt2712_bdp_drv = { ++ .probe = clk_mt2712_bdp_probe, ++ .driver = { ++ .name = "clk-mt2712-bdp", ++ .of_match_table = of_match_clk_mt2712_bdp, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt2712_bdp_drv); +diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c +new file mode 100644 +index 000000000000..139ff55d495e +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712-img.c +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static const struct mtk_gate_regs img_cg_regs = { ++ .set_ofs = 0x0, ++ .clr_ofs = 0x0, ++ .sta_ofs = 0x0, ++}; ++ ++#define GATE_IMG(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &img_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++static const struct mtk_gate img_clks[] = { ++ GATE_IMG(CLK_IMG_SMI_LARB2, "img_smi_larb2", "mm_sel", 0), ++ GATE_IMG(CLK_IMG_SENINF_SCAM_EN, "img_scam_en", "csi0", 3), ++ GATE_IMG(CLK_IMG_SENINF_CAM_EN, "img_cam_en", "mm_sel", 8), ++ GATE_IMG(CLK_IMG_CAM_SV_EN, "img_cam_sv_en", "mm_sel", 9), ++ GATE_IMG(CLK_IMG_CAM_SV1_EN, "img_cam_sv1_en", "mm_sel", 10), ++ GATE_IMG(CLK_IMG_CAM_SV2_EN, "img_cam_sv2_en", "mm_sel", 11), ++}; ++ ++static int clk_mt2712_img_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); ++ ++ mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712_img[] = { ++ { .compatible = "mediatek,mt2712-imgsys", }, ++ {} ++}; ++ ++static struct platform_driver clk_mt2712_img_drv = { ++ .probe = clk_mt2712_img_probe, ++ .driver = { ++ .name = "clk-mt2712-img", ++ .of_match_table = of_match_clk_mt2712_img, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt2712_img_drv); +diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c +new file mode 100644 +index 000000000000..c7d4aada4892 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c +@@ -0,0 +1,76 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static const struct mtk_gate_regs jpgdec_cg_regs = { ++ .set_ofs = 0x4, ++ .clr_ofs = 0x8, ++ .sta_ofs = 0x0, ++}; ++ ++#define GATE_JPGDEC(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &jpgdec_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr_inv, \ ++ } ++ ++static const struct mtk_gate jpgdec_clks[] = { ++ GATE_JPGDEC(CLK_JPGDEC_JPGDEC1, "jpgdec_jpgdec1", "jpgdec_sel", 0), ++ GATE_JPGDEC(CLK_JPGDEC_JPGDEC, "jpgdec_jpgdec", "jpgdec_sel", 4), ++}; ++ ++static int clk_mt2712_jpgdec_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_JPGDEC_NR_CLK); ++ ++ mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712_jpgdec[] = { ++ { .compatible = "mediatek,mt2712-jpgdecsys", }, ++ {} ++}; ++ ++static struct platform_driver clk_mt2712_jpgdec_drv = { ++ .probe = clk_mt2712_jpgdec_probe, ++ .driver = { ++ .name = "clk-mt2712-jpgdec", ++ .of_match_table = of_match_clk_mt2712_jpgdec, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt2712_jpgdec_drv); +diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c +new file mode 100644 +index 000000000000..570f72d48d4d +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712-mfg.c +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static const struct mtk_gate_regs mfg_cg_regs = { ++ .set_ofs = 0x4, ++ .clr_ofs = 0x8, ++ .sta_ofs = 0x0, ++}; ++ ++#define GATE_MFG(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &mfg_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++static const struct mtk_gate mfg_clks[] = { ++ GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0), ++}; ++ ++static int clk_mt2712_mfg_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK); ++ ++ mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712_mfg[] = { ++ { .compatible = "mediatek,mt2712-mfgcfg", }, ++ {} ++}; ++ ++static struct platform_driver clk_mt2712_mfg_drv = { ++ .probe = clk_mt2712_mfg_probe, ++ .driver = { ++ .name = "clk-mt2712-mfg", ++ .of_match_table = of_match_clk_mt2712_mfg, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt2712_mfg_drv); +diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c +new file mode 100644 +index 000000000000..a8b4b6d42488 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712-mm.c +@@ -0,0 +1,170 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static const struct mtk_gate_regs mm0_cg_regs = { ++ .set_ofs = 0x104, ++ .clr_ofs = 0x108, ++ .sta_ofs = 0x100, ++}; ++ ++static const struct mtk_gate_regs mm1_cg_regs = { ++ .set_ofs = 0x114, ++ .clr_ofs = 0x118, ++ .sta_ofs = 0x110, ++}; ++ ++static const struct mtk_gate_regs mm2_cg_regs = { ++ .set_ofs = 0x224, ++ .clr_ofs = 0x228, ++ .sta_ofs = 0x220, ++}; ++ ++#define GATE_MM0(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &mm0_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_MM1(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &mm1_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_MM2(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &mm2_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++static const struct mtk_gate mm_clks[] = { ++ /* MM0 */ ++ GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), ++ GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), ++ GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2), ++ GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3), ++ GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4), ++ GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5), ++ GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6), ++ GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7), ++ GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8), ++ GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9), ++ GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10), ++ GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), ++ GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12), ++ GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13), ++ GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14), ++ GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15), ++ GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16), ++ GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17), ++ GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18), ++ GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), ++ GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20), ++ GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21), ++ GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22), ++ GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23), ++ GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24), ++ GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25), ++ GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26), ++ GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27), ++ GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28), ++ GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31), ++ /* MM1 */ ++ GATE_MM1(CLK_MM_DISP_PWM0_MM, "mm_pwm0_mm", "mm_sel", 0), ++ GATE_MM1(CLK_MM_DISP_PWM0_26M, "mm_pwm0_26m", "pwm_sel", 1), ++ GATE_MM1(CLK_MM_DISP_PWM1_MM, "mm_pwm1_mm", "mm_sel", 2), ++ GATE_MM1(CLK_MM_DISP_PWM1_26M, "mm_pwm1_26m", "pwm_sel", 3), ++ GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4), ++ GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_lntc", 5), ++ GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6), ++ GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_lntc", 7), ++ GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "vpll_dpix", 8), ++ GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9), ++ GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "vpll3_dpix", 10), ++ GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11), ++ GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "vpll_dpix", 16), ++ GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx", 17), ++ GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18), ++ GATE_MM1(CLK_MM_SMI_COMMON1, "mm_smi_common1", "mm_sel", 21), ++ GATE_MM1(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 22), ++ GATE_MM1(CLK_MM_MDP_RDMA2, "mm_mdp_rdma2", "mm_sel", 23), ++ GATE_MM1(CLK_MM_MDP_TDSHP2, "mm_mdp_tdshp2", "mm_sel", 24), ++ GATE_MM1(CLK_MM_DISP_OVL2, "mm_disp_ovl2", "mm_sel", 25), ++ GATE_MM1(CLK_MM_DISP_WDMA2, "mm_disp_wdma2", "mm_sel", 26), ++ GATE_MM1(CLK_MM_DISP_COLOR2, "mm_disp_color2", "mm_sel", 27), ++ GATE_MM1(CLK_MM_DISP_AAL1, "mm_disp_aal1", "mm_sel", 28), ++ GATE_MM1(CLK_MM_DISP_OD1, "mm_disp_od1", "mm_sel", 29), ++ GATE_MM1(CLK_MM_LVDS1_PIXEL, "mm_lvds1_pixel", "vpll3_dpix", 30), ++ GATE_MM1(CLK_MM_LVDS1_CTS, "mm_lvds1_cts", "lvdstx3", 31), ++ /* MM2 */ ++ GATE_MM2(CLK_MM_SMI_LARB7, "mm_smi_larb7", "mm_sel", 0), ++ GATE_MM2(CLK_MM_MDP_RDMA3, "mm_mdp_rdma3", "mm_sel", 1), ++ GATE_MM2(CLK_MM_MDP_WROT2, "mm_mdp_wrot2", "mm_sel", 2), ++ GATE_MM2(CLK_MM_DSI2, "mm_dsi2", "mm_sel", 3), ++ GATE_MM2(CLK_MM_DSI2_DIGITAL, "mm_dsi2_digital", "dsi0_lntc", 4), ++ GATE_MM2(CLK_MM_DSI3, "mm_dsi3", "mm_sel", 5), ++ GATE_MM2(CLK_MM_DSI3_DIGITAL, "mm_dsi3_digital", "dsi1_lntc", 6), ++}; ++ ++static int clk_mt2712_mm_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); ++ ++ mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712_mm[] = { ++ { .compatible = "mediatek,mt2712-mmsys", }, ++ {} ++}; ++ ++static struct platform_driver clk_mt2712_mm_drv = { ++ .probe = clk_mt2712_mm_probe, ++ .driver = { ++ .name = "clk-mt2712-mm", ++ .of_match_table = of_match_clk_mt2712_mm, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt2712_mm_drv); +diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c +new file mode 100644 +index 000000000000..55c64ee8cc91 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712-vdec.c +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static const struct mtk_gate_regs vdec0_cg_regs = { ++ .set_ofs = 0x0, ++ .clr_ofs = 0x4, ++ .sta_ofs = 0x0, ++}; ++ ++static const struct mtk_gate_regs vdec1_cg_regs = { ++ .set_ofs = 0x8, ++ .clr_ofs = 0xc, ++ .sta_ofs = 0x8, ++}; ++ ++#define GATE_VDEC0(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &vdec0_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr_inv, \ ++ } ++ ++#define GATE_VDEC1(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &vdec1_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr_inv, \ ++ } ++ ++static const struct mtk_gate vdec_clks[] = { ++ /* VDEC0 */ ++ GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0), ++ /* VDEC1 */ ++ GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "vdec_sel", 0), ++ GATE_VDEC1(CLK_VDEC_IMGRZ_CKEN, "vdec_imgrz_cken", "vdec_sel", 1), ++}; ++ ++static int clk_mt2712_vdec_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); ++ ++ mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712_vdec[] = { ++ { .compatible = "mediatek,mt2712-vdecsys", }, ++ {} ++}; ++ ++static struct platform_driver clk_mt2712_vdec_drv = { ++ .probe = clk_mt2712_vdec_probe, ++ .driver = { ++ .name = "clk-mt2712-vdec", ++ .of_match_table = of_match_clk_mt2712_vdec, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt2712_vdec_drv); +diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c +new file mode 100644 +index 000000000000..ccbfe98777c8 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712-venc.c +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static const struct mtk_gate_regs venc_cg_regs = { ++ .set_ofs = 0x4, ++ .clr_ofs = 0x8, ++ .sta_ofs = 0x0, ++}; ++ ++#define GATE_VENC(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &venc_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr_inv, \ ++ } ++ ++static const struct mtk_gate venc_clks[] = { ++ GATE_VENC(CLK_VENC_SMI_COMMON_CON, "venc_smi", "mm_sel", 0), ++ GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4), ++ GATE_VENC(CLK_VENC_SMI_LARB6, "venc_smi_larb6", "jpgdec_sel", 12), ++}; ++ ++static int clk_mt2712_venc_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK); ++ ++ mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712_venc[] = { ++ { .compatible = "mediatek,mt2712-vencsys", }, ++ {} ++}; ++ ++static struct platform_driver clk_mt2712_venc_drv = { ++ .probe = clk_mt2712_venc_probe, ++ .driver = { ++ .name = "clk-mt2712-venc", ++ .of_match_table = of_match_clk_mt2712_venc, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt2712_venc_drv); +diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c +new file mode 100644 +index 000000000000..498d13799388 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt2712.c +@@ -0,0 +1,1435 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Weiyi Lu <weiyi.lu@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/mfd/syscon.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt2712-clk.h> ++ ++static DEFINE_SPINLOCK(mt2712_clk_lock); ++ ++static const struct mtk_fixed_clk top_fixed_clks[] = { ++ FIXED_CLK(CLK_TOP_VPLL3_DPIX, "vpll3_dpix", NULL, 200000000), ++ FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", NULL, 200000000), ++ FIXED_CLK(CLK_TOP_LTEPLL_FS26M, "ltepll_fs26m", NULL, 26000000), ++ FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 350000000), ++ FIXED_CLK(CLK_TOP_DSI0_LNTC, "dsi0_lntc", NULL, 143000000), ++ FIXED_CLK(CLK_TOP_DSI1_LNTC, "dsi1_lntc", NULL, 143000000), ++ FIXED_CLK(CLK_TOP_LVDSTX3_CLKDIG_CTS, "lvdstx3", NULL, 140000000), ++ FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx", NULL, 140000000), ++ FIXED_CLK(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", NULL, 32768), ++ FIXED_CLK(CLK_TOP_CLKRTC_INT, "clkrtc_int", NULL, 32747), ++ FIXED_CLK(CLK_TOP_CSI0, "csi0", NULL, 26000000), ++ FIXED_CLK(CLK_TOP_CVBSPLL, "cvbspll", NULL, 108000000), ++}; ++ ++static const struct mtk_fixed_factor top_early_divs[] = { ++ FACTOR(CLK_TOP_SYS_26M, "sys_26m", "clk26m", 1, ++ 1), ++ FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "sys_26m", 1, ++ 2), ++}; ++ ++static const struct mtk_fixed_factor top_divs[] = { ++ FACTOR(CLK_TOP_ARMCA35PLL, "armca35pll_ck", "armca35pll", 1, ++ 1), ++ FACTOR(CLK_TOP_ARMCA35PLL_600M, "armca35pll_600m", "armca35pll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_ARMCA35PLL_400M, "armca35pll_400m", "armca35pll_ck", 1, ++ 3), ++ FACTOR(CLK_TOP_ARMCA72PLL, "armca72pll_ck", "armca72pll", 1, ++ 1), ++ FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, ++ 1), ++ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, ++ 2), ++ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, ++ 4), ++ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, ++ 8), ++ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, ++ 16), ++ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "syspll_ck", 1, ++ 3), ++ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, ++ 2), ++ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, ++ 4), ++ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "syspll_ck", 1, ++ 5), ++ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, ++ 2), ++ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, ++ 4), ++ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "syspll_ck", 1, ++ 7), ++ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, ++ 2), ++ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, ++ 4), ++ FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, ++ 1), ++ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_ck", 1, ++ 7), ++ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_ck", 1, ++ 26), ++ FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll_ck", 1, ++ 52), ++ FACTOR(CLK_TOP_UNIVPLL_D104, "univpll_d104", "univpll_ck", 1, ++ 104), ++ FACTOR(CLK_TOP_UNIVPLL_D208, "univpll_d208", "univpll_ck", 1, ++ 208), ++ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, ++ 2), ++ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, ++ 4), ++ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, ++ 8), ++ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_ck", 1, ++ 3), ++ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, ++ 2), ++ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, ++ 4), ++ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, ++ 8), ++ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_ck", 1, ++ 5), ++ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, ++ 2), ++ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, ++ 4), ++ FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, ++ 8), ++ FACTOR(CLK_TOP_F_MP0_PLL1, "f_mp0_pll1_ck", "univpll_d2", 1, ++ 1), ++ FACTOR(CLK_TOP_F_MP0_PLL2, "f_mp0_pll2_ck", "univpll1_d2", 1, ++ 1), ++ FACTOR(CLK_TOP_F_BIG_PLL1, "f_big_pll1_ck", "univpll_d2", 1, ++ 1), ++ FACTOR(CLK_TOP_F_BIG_PLL2, "f_big_pll2_ck", "univpll1_d2", 1, ++ 1), ++ FACTOR(CLK_TOP_F_BUS_PLL1, "f_bus_pll1_ck", "univpll_d2", 1, ++ 1), ++ FACTOR(CLK_TOP_F_BUS_PLL2, "f_bus_pll2_ck", "univpll1_d2", 1, ++ 1), ++ FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, ++ 1), ++ FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1, ++ 4), ++ FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1, ++ 8), ++ FACTOR(CLK_TOP_APLL1_D16, "apll1_d16", "apll1_ck", 1, ++ 16), ++ FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, ++ 1), ++ FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2_ck", 1, ++ 4), ++ FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2_ck", 1, ++ 8), ++ FACTOR(CLK_TOP_APLL2_D16, "apll2_d16", "apll2_ck", 1, ++ 16), ++ FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1, ++ 1), ++ FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll_ck", 1, ++ 4), ++ FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll_ck", 1, ++ 8), ++ FACTOR(CLK_TOP_LVDSPLL2, "lvdspll2_ck", "lvdspll2", 1, ++ 1), ++ FACTOR(CLK_TOP_LVDSPLL2_D2, "lvdspll2_d2", "lvdspll2_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_LVDSPLL2_D4, "lvdspll2_d4", "lvdspll2_ck", 1, ++ 4), ++ FACTOR(CLK_TOP_LVDSPLL2_D8, "lvdspll2_d8", "lvdspll2_ck", 1, ++ 8), ++ FACTOR(CLK_TOP_ETHERPLL_125M, "etherpll_125m", "etherpll", 1, ++ 1), ++ FACTOR(CLK_TOP_ETHERPLL_50M, "etherpll_50m", "etherpll", 1, ++ 1), ++ FACTOR(CLK_TOP_CVBS, "cvbs", "cvbspll", 1, ++ 1), ++ FACTOR(CLK_TOP_CVBS_D2, "cvbs_d2", "cvbs", 1, ++ 2), ++ FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, ++ 1), ++ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, ++ 1), ++ FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, ++ 1), ++ FACTOR(CLK_TOP_VCODECPLL_D2, "vcodecpll_d2", "vcodecpll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, ++ 1), ++ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, ++ 4), ++ FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, ++ 8), ++ FACTOR(CLK_TOP_TVDPLL_429M, "tvdpll_429m", "tvdpll", 1, ++ 1), ++ FACTOR(CLK_TOP_TVDPLL_429M_D2, "tvdpll_429m_d2", "tvdpll_429m", 1, ++ 2), ++ FACTOR(CLK_TOP_TVDPLL_429M_D4, "tvdpll_429m_d4", "tvdpll_429m", 1, ++ 4), ++ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, ++ 1), ++ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, ++ 4), ++ FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, ++ 1), ++ FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2_ck", 1, ++ 2), ++ FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2_ck", 1, ++ 4), ++ FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1, ++ 4), ++}; ++ ++static const char * const axi_parents[] = { ++ "clk26m", ++ "syspll1_d2", ++ "syspll_d5", ++ "syspll1_d4", ++ "univpll_d5", ++ "univpll2_d2", ++ "msdcpll2_ck" ++}; ++ ++static const char * const mem_parents[] = { ++ "clk26m", ++ "dmpll_ck" ++}; ++ ++static const char * const mm_parents[] = { ++ "clk26m", ++ "vencpll_ck", ++ "syspll_d3", ++ "syspll1_d2", ++ "syspll_d5", ++ "syspll1_d4", ++ "univpll1_d2", ++ "univpll2_d2" ++}; ++ ++static const char * const pwm_parents[] = { ++ "clk26m", ++ "univpll2_d4", ++ "univpll3_d2", ++ "univpll1_d4" ++}; ++ ++static const char * const vdec_parents[] = { ++ "clk26m", ++ "vcodecpll_ck", ++ "tvdpll_429m", ++ "univpll_d3", ++ "vencpll_ck", ++ "syspll_d3", ++ "univpll1_d2", ++ "mmpll_d2", ++ "syspll3_d2", ++ "tvdpll_ck" ++}; ++ ++static const char * const venc_parents[] = { ++ "clk26m", ++ "univpll1_d2", ++ "mmpll_d2", ++ "tvdpll_d2", ++ "syspll1_d2", ++ "univpll_d5", ++ "vcodecpll_d2", ++ "univpll2_d2", ++ "syspll3_d2" ++}; ++ ++static const char * const mfg_parents[] = { ++ "clk26m", ++ "mmpll_ck", ++ "univpll_d3", ++ "clk26m", ++ "clk26m", ++ "clk26m", ++ "clk26m", ++ "clk26m", ++ "clk26m", ++ "syspll_d3", ++ "syspll1_d2", ++ "syspll_d5", ++ "univpll_d3", ++ "univpll1_d2", ++ "univpll_d5", ++ "univpll2_d2" ++}; ++ ++static const char * const camtg_parents[] = { ++ "clk26m", ++ "univpll_d52", ++ "univpll_d208", ++ "univpll_d104", ++ "clk26m_d2", ++ "univpll_d26", ++ "univpll2_d8", ++ "syspll3_d4", ++ "syspll3_d2", ++ "univpll1_d4", ++ "univpll2_d2" ++}; ++ ++static const char * const uart_parents[] = { ++ "clk26m", ++ "univpll2_d8" ++}; ++ ++static const char * const spi_parents[] = { ++ "clk26m", ++ "univpll2_d4", ++ "univpll1_d4", ++ "univpll2_d2", ++ "univpll3_d2", ++ "univpll1_d8" ++}; ++ ++static const char * const usb20_parents[] = { ++ "clk26m", ++ "univpll1_d8", ++ "univpll3_d4" ++}; ++ ++static const char * const usb30_parents[] = { ++ "clk26m", ++ "univpll3_d2", ++ "univpll3_d4", ++ "univpll2_d4" ++}; ++ ++static const char * const msdc50_0_h_parents[] = { ++ "clk26m", ++ "syspll1_d2", ++ "syspll2_d2", ++ "syspll4_d2", ++ "univpll_d5", ++ "univpll1_d4" ++}; ++ ++static const char * const msdc50_0_parents[] = { ++ "clk26m", ++ "msdcpll_ck", ++ "msdcpll_d2", ++ "univpll1_d4", ++ "syspll2_d2", ++ "msdcpll_d4", ++ "vencpll_d2", ++ "univpll1_d2", ++ "msdcpll2_ck", ++ "msdcpll2_d2", ++ "msdcpll2_d4" ++}; ++ ++static const char * const msdc30_1_parents[] = { ++ "clk26m", ++ "univpll2_d2", ++ "msdcpll_d2", ++ "univpll1_d4", ++ "syspll2_d2", ++ "univpll_d7", ++ "vencpll_d2" ++}; ++ ++static const char * const msdc30_3_parents[] = { ++ "clk26m", ++ "msdcpll2_ck", ++ "msdcpll2_d2", ++ "univpll2_d2", ++ "msdcpll2_d4", ++ "univpll1_d4", ++ "syspll2_d2", ++ "syspll_d7", ++ "univpll_d7", ++ "vencpll_d2", ++ "msdcpll_ck", ++ "msdcpll_d2", ++ "msdcpll_d4" ++}; ++ ++static const char * const audio_parents[] = { ++ "clk26m", ++ "syspll3_d4", ++ "syspll4_d4", ++ "syspll1_d16" ++}; ++ ++static const char * const aud_intbus_parents[] = { ++ "clk26m", ++ "syspll1_d4", ++ "syspll4_d2", ++ "univpll3_d2", ++ "univpll2_d8", ++ "syspll3_d2", ++ "syspll3_d4" ++}; ++ ++static const char * const pmicspi_parents[] = { ++ "clk26m", ++ "syspll1_d8", ++ "syspll3_d4", ++ "syspll1_d16", ++ "univpll3_d4", ++ "univpll_d26", ++ "syspll3_d4" ++}; ++ ++static const char * const dpilvds1_parents[] = { ++ "clk26m", ++ "lvdspll2_ck", ++ "lvdspll2_d2", ++ "lvdspll2_d4", ++ "lvdspll2_d8", ++ "clkfpc" ++}; ++ ++static const char * const atb_parents[] = { ++ "clk26m", ++ "syspll1_d2", ++ "univpll_d5", ++ "syspll_d5" ++}; ++ ++static const char * const nr_parents[] = { ++ "clk26m", ++ "univpll1_d4", ++ "syspll2_d2", ++ "syspll1_d4", ++ "univpll1_d8", ++ "univpll3_d2", ++ "univpll2_d2", ++ "syspll_d5" ++}; ++ ++static const char * const nfi2x_parents[] = { ++ "clk26m", ++ "syspll4_d4", ++ "univpll3_d4", ++ "univpll1_d8", ++ "syspll2_d4", ++ "univpll3_d2", ++ "syspll_d7", ++ "syspll2_d2", ++ "univpll2_d2", ++ "syspll_d5", ++ "syspll1_d2" ++}; ++ ++static const char * const irda_parents[] = { ++ "clk26m", ++ "univpll2_d4", ++ "syspll2_d4", ++ "univpll2_d8" ++}; ++ ++static const char * const cci400_parents[] = { ++ "clk26m", ++ "vencpll_ck", ++ "armca35pll_600m", ++ "armca35pll_400m", ++ "univpll_d2", ++ "syspll_d2", ++ "msdcpll_ck", ++ "univpll_d3" ++}; ++ ++static const char * const aud_1_parents[] = { ++ "clk26m", ++ "apll1_ck", ++ "univpll2_d4", ++ "univpll2_d8" ++}; ++ ++static const char * const aud_2_parents[] = { ++ "clk26m", ++ "apll2_ck", ++ "univpll2_d4", ++ "univpll2_d8" ++}; ++ ++static const char * const mem_mfg_parents[] = { ++ "clk26m", ++ "mmpll_ck", ++ "univpll_d3" ++}; ++ ++static const char * const axi_mfg_parents[] = { ++ "clk26m", ++ "axi_sel", ++ "univpll_d5" ++}; ++ ++static const char * const scam_parents[] = { ++ "clk26m", ++ "syspll3_d2", ++ "univpll2_d4", ++ "syspll2_d4" ++}; ++ ++static const char * const nfiecc_parents[] = { ++ "clk26m", ++ "nfi2x_sel", ++ "syspll_d7", ++ "syspll2_d2", ++ "univpll2_d2", ++ "univpll_d5", ++ "syspll1_d2" ++}; ++ ++static const char * const pe2_mac_p0_parents[] = { ++ "clk26m", ++ "syspll1_d8", ++ "syspll4_d2", ++ "syspll2_d4", ++ "univpll2_d4", ++ "syspll3_d2" ++}; ++ ++static const char * const dpilvds_parents[] = { ++ "clk26m", ++ "lvdspll_ck", ++ "lvdspll_d2", ++ "lvdspll_d4", ++ "lvdspll_d8", ++ "clkfpc" ++}; ++ ++static const char * const hdcp_parents[] = { ++ "clk26m", ++ "syspll4_d2", ++ "syspll3_d4", ++ "univpll2_d4" ++}; ++ ++static const char * const hdcp_24m_parents[] = { ++ "clk26m", ++ "univpll_d26", ++ "univpll_d52", ++ "univpll2_d8" ++}; ++ ++static const char * const rtc_parents[] = { ++ "clkrtc_int", ++ "clkrtc_ext", ++ "clk26m", ++ "univpll3_d8" ++}; ++ ++static const char * const spinor_parents[] = { ++ "clk26m", ++ "clk26m_d2", ++ "syspll4_d4", ++ "univpll2_d8", ++ "univpll3_d4", ++ "syspll4_d2", ++ "syspll2_d4", ++ "univpll2_d4", ++ "etherpll_125m", ++ "syspll1_d4" ++}; ++ ++static const char * const apll_parents[] = { ++ "clk26m", ++ "apll1_ck", ++ "apll1_d2", ++ "apll1_d4", ++ "apll1_d8", ++ "apll1_d16", ++ "apll2_ck", ++ "apll2_d2", ++ "apll2_d4", ++ "apll2_d8", ++ "apll2_d16", ++ "clk26m", ++ "clk26m" ++}; ++ ++static const char * const a1sys_hp_parents[] = { ++ "clk26m", ++ "apll1_ck", ++ "apll1_d2", ++ "apll1_d4", ++ "apll1_d8" ++}; ++ ++static const char * const a2sys_hp_parents[] = { ++ "clk26m", ++ "apll2_ck", ++ "apll2_d2", ++ "apll2_d4", ++ "apll2_d8" ++}; ++ ++static const char * const asm_l_parents[] = { ++ "clk26m", ++ "univpll2_d4", ++ "univpll2_d2", ++ "syspll_d5" ++}; ++ ++static const char * const i2so1_parents[] = { ++ "clk26m", ++ "apll1_ck", ++ "apll2_ck" ++}; ++ ++static const char * const ether_125m_parents[] = { ++ "clk26m", ++ "etherpll_125m", ++ "univpll3_d2" ++}; ++ ++static const char * const ether_50m_parents[] = { ++ "clk26m", ++ "etherpll_50m", ++ "univpll_d26", ++ "univpll3_d4" ++}; ++ ++static const char * const jpgdec_parents[] = { ++ "clk26m", ++ "univpll_d3", ++ "tvdpll_429m", ++ "vencpll_ck", ++ "syspll_d3", ++ "vcodecpll_ck", ++ "univpll1_d2", ++ "armca35pll_400m", ++ "tvdpll_429m_d2", ++ "tvdpll_429m_d4" ++}; ++ ++static const char * const spislv_parents[] = { ++ "clk26m", ++ "univpll2_d4", ++ "univpll1_d4", ++ "univpll2_d2", ++ "univpll3_d2", ++ "univpll1_d8", ++ "univpll1_d2", ++ "univpll_d5" ++}; ++ ++static const char * const ether_parents[] = { ++ "clk26m", ++ "etherpll_50m", ++ "univpll_d26" ++}; ++ ++static const char * const di_parents[] = { ++ "clk26m", ++ "tvdpll_d2", ++ "tvdpll_d4", ++ "tvdpll_d8", ++ "vencpll_ck", ++ "vencpll_d2", ++ "cvbs", ++ "cvbs_d2" ++}; ++ ++static const char * const tvd_parents[] = { ++ "clk26m", ++ "cvbs_d2", ++ "univpll2_d8" ++}; ++ ++static const char * const i2c_parents[] = { ++ "clk26m", ++ "univpll_d26", ++ "univpll2_d4", ++ "univpll3_d2", ++ "univpll1_d4" ++}; ++ ++static const char * const msdc0p_aes_parents[] = { ++ "clk26m", ++ "msdcpll_ck", ++ "univpll_d3", ++ "vcodecpll_ck" ++}; ++ ++static const char * const cmsys_parents[] = { ++ "clk26m", ++ "univpll_d3", ++ "syspll_d3", ++ "syspll1_d2", ++ "syspll2_d2" ++}; ++ ++static const char * const gcpu_parents[] = { ++ "clk26m", ++ "syspll_d3", ++ "syspll1_d2", ++ "univpll1_d2", ++ "univpll_d5", ++ "univpll3_d2", ++ "univpll_d3" ++}; ++ ++static const char * const aud_apll1_parents[] = { ++ "apll1", ++ "clkaud_ext_i_1" ++}; ++ ++static const char * const aud_apll2_parents[] = { ++ "apll2", ++ "clkaud_ext_i_2" ++}; ++ ++static const char * const audull_vtx_parents[] = { ++ "d2a_ulclk_6p5m", ++ "clkaud_ext_i_0" ++}; ++ ++static struct mtk_composite top_muxes[] = { ++ /* CLK_CFG_0 */ ++ MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x040, 0, 3, ++ 7, CLK_IS_CRITICAL), ++ MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, 8, 1, ++ 15, CLK_IS_CRITICAL), ++ MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", ++ mm_parents, 0x040, 24, 3, 31), ++ /* CLK_CFG_1 */ ++ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", ++ pwm_parents, 0x050, 0, 2, 7), ++ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", ++ vdec_parents, 0x050, 8, 4, 15), ++ MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", ++ venc_parents, 0x050, 16, 4, 23), ++ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", ++ mfg_parents, 0x050, 24, 4, 31), ++ /* CLK_CFG_2 */ ++ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", ++ camtg_parents, 0x060, 0, 4, 7), ++ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", ++ uart_parents, 0x060, 8, 1, 15), ++ MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", ++ spi_parents, 0x060, 16, 3, 23), ++ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", ++ usb20_parents, 0x060, 24, 2, 31), ++ /* CLK_CFG_3 */ ++ MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", ++ usb30_parents, 0x070, 0, 2, 7), ++ MUX_GATE(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc50_0_h_sel", ++ msdc50_0_h_parents, 0x070, 8, 3, 15), ++ MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", ++ msdc50_0_parents, 0x070, 16, 4, 23), ++ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", ++ msdc30_1_parents, 0x070, 24, 3, 31), ++ /* CLK_CFG_4 */ ++ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", ++ msdc30_1_parents, 0x080, 0, 3, 7), ++ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", ++ msdc30_3_parents, 0x080, 8, 4, 15), ++ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", ++ audio_parents, 0x080, 16, 2, 23), ++ MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", ++ aud_intbus_parents, 0x080, 24, 3, 31), ++ /* CLK_CFG_5 */ ++ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", ++ pmicspi_parents, 0x090, 0, 3, 7), ++ MUX_GATE(CLK_TOP_DPILVDS1_SEL, "dpilvds1_sel", ++ dpilvds1_parents, 0x090, 8, 3, 15), ++ MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", ++ atb_parents, 0x090, 16, 2, 23), ++ MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", ++ nr_parents, 0x090, 24, 3, 31), ++ /* CLK_CFG_6 */ ++ MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", ++ nfi2x_parents, 0x0a0, 0, 4, 7), ++ MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", ++ irda_parents, 0x0a0, 8, 2, 15), ++ MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", ++ cci400_parents, 0x0a0, 16, 3, 23), ++ MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", ++ aud_1_parents, 0x0a0, 24, 2, 31), ++ /* CLK_CFG_7 */ ++ MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", ++ aud_2_parents, 0x0b0, 0, 2, 7), ++ MUX_GATE(CLK_TOP_MEM_MFG_IN_AS_SEL, "mem_mfg_sel", ++ mem_mfg_parents, 0x0b0, 8, 2, 15), ++ MUX_GATE(CLK_TOP_AXI_MFG_IN_AS_SEL, "axi_mfg_sel", ++ axi_mfg_parents, 0x0b0, 16, 2, 23), ++ MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", ++ scam_parents, 0x0b0, 24, 2, 31), ++ /* CLK_CFG_8 */ ++ MUX_GATE(CLK_TOP_NFIECC_SEL, "nfiecc_sel", ++ nfiecc_parents, 0x0c0, 0, 3, 7), ++ MUX_GATE(CLK_TOP_PE2_MAC_P0_SEL, "pe2_mac_p0_sel", ++ pe2_mac_p0_parents, 0x0c0, 8, 3, 15), ++ MUX_GATE(CLK_TOP_PE2_MAC_P1_SEL, "pe2_mac_p1_sel", ++ pe2_mac_p0_parents, 0x0c0, 16, 3, 23), ++ MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", ++ dpilvds_parents, 0x0c0, 24, 3, 31), ++ /* CLK_CFG_9 */ ++ MUX_GATE(CLK_TOP_MSDC50_3_HCLK_SEL, "msdc50_3_h_sel", ++ msdc50_0_h_parents, 0x0d0, 0, 3, 7), ++ MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", ++ hdcp_parents, 0x0d0, 8, 2, 15), ++ MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", ++ hdcp_24m_parents, 0x0d0, 16, 2, 23), ++ MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x0d0, 24, 2, ++ 31, CLK_IS_CRITICAL), ++ /* CLK_CFG_10 */ ++ MUX_GATE(CLK_TOP_SPINOR_SEL, "spinor_sel", ++ spinor_parents, 0x500, 0, 4, 7), ++ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", ++ apll_parents, 0x500, 8, 4, 15), ++ MUX_GATE(CLK_TOP_APLL2_SEL, "apll2_sel", ++ apll_parents, 0x500, 16, 4, 23), ++ MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", ++ a1sys_hp_parents, 0x500, 24, 3, 31), ++ /* CLK_CFG_11 */ ++ MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", ++ a2sys_hp_parents, 0x510, 0, 3, 7), ++ MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", ++ asm_l_parents, 0x510, 8, 2, 15), ++ MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", ++ asm_l_parents, 0x510, 16, 2, 23), ++ MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", ++ asm_l_parents, 0x510, 24, 2, 31), ++ /* CLK_CFG_12 */ ++ MUX_GATE(CLK_TOP_I2SO1_SEL, "i2so1_sel", ++ i2so1_parents, 0x520, 0, 2, 7), ++ MUX_GATE(CLK_TOP_I2SO2_SEL, "i2so2_sel", ++ i2so1_parents, 0x520, 8, 2, 15), ++ MUX_GATE(CLK_TOP_I2SO3_SEL, "i2so3_sel", ++ i2so1_parents, 0x520, 16, 2, 23), ++ MUX_GATE(CLK_TOP_TDMO0_SEL, "tdmo0_sel", ++ i2so1_parents, 0x520, 24, 2, 31), ++ /* CLK_CFG_13 */ ++ MUX_GATE(CLK_TOP_TDMO1_SEL, "tdmo1_sel", ++ i2so1_parents, 0x530, 0, 2, 7), ++ MUX_GATE(CLK_TOP_I2SI1_SEL, "i2si1_sel", ++ i2so1_parents, 0x530, 8, 2, 15), ++ MUX_GATE(CLK_TOP_I2SI2_SEL, "i2si2_sel", ++ i2so1_parents, 0x530, 16, 2, 23), ++ MUX_GATE(CLK_TOP_I2SI3_SEL, "i2si3_sel", ++ i2so1_parents, 0x530, 24, 2, 31), ++ /* CLK_CFG_14 */ ++ MUX_GATE(CLK_TOP_ETHER_125M_SEL, "ether_125m_sel", ++ ether_125m_parents, 0x540, 0, 2, 7), ++ MUX_GATE(CLK_TOP_ETHER_50M_SEL, "ether_50m_sel", ++ ether_50m_parents, 0x540, 8, 2, 15), ++ MUX_GATE(CLK_TOP_JPGDEC_SEL, "jpgdec_sel", ++ jpgdec_parents, 0x540, 16, 4, 23), ++ MUX_GATE(CLK_TOP_SPISLV_SEL, "spislv_sel", ++ spislv_parents, 0x540, 24, 3, 31), ++ /* CLK_CFG_15 */ ++ MUX_GATE(CLK_TOP_ETHER_50M_RMII_SEL, "ether_sel", ++ ether_parents, 0x550, 0, 2, 7), ++ MUX_GATE(CLK_TOP_CAM2TG_SEL, "cam2tg_sel", ++ camtg_parents, 0x550, 8, 4, 15), ++ MUX_GATE(CLK_TOP_DI_SEL, "di_sel", ++ di_parents, 0x550, 16, 3, 23), ++ MUX_GATE(CLK_TOP_TVD_SEL, "tvd_sel", ++ tvd_parents, 0x550, 24, 2, 31), ++ /* CLK_CFG_16 */ ++ MUX_GATE(CLK_TOP_I2C_SEL, "i2c_sel", ++ i2c_parents, 0x560, 0, 3, 7), ++ MUX_GATE(CLK_TOP_PWM_INFRA_SEL, "pwm_infra_sel", ++ pwm_parents, 0x560, 8, 2, 15), ++ MUX_GATE(CLK_TOP_MSDC0P_AES_SEL, "msdc0p_aes_sel", ++ msdc0p_aes_parents, 0x560, 16, 2, 23), ++ MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", ++ cmsys_parents, 0x560, 24, 3, 31), ++ /* CLK_CFG_17 */ ++ MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", ++ gcpu_parents, 0x570, 0, 3, 7), ++ /* CLK_AUDDIV_4 */ ++ MUX(CLK_TOP_AUD_APLL1_SEL, "aud_apll1_sel", ++ aud_apll1_parents, 0x134, 0, 1), ++ MUX(CLK_TOP_AUD_APLL2_SEL, "aud_apll2_sel", ++ aud_apll2_parents, 0x134, 1, 1), ++ MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel", ++ audull_vtx_parents, 0x134, 31, 1), ++}; ++ ++static const char * const mcu_mp0_parents[] = { ++ "clk26m", ++ "armca35pll_ck", ++ "f_mp0_pll1_ck", ++ "f_mp0_pll2_ck" ++}; ++ ++static const char * const mcu_mp2_parents[] = { ++ "clk26m", ++ "armca72pll_ck", ++ "f_big_pll1_ck", ++ "f_big_pll2_ck" ++}; ++ ++static const char * const mcu_bus_parents[] = { ++ "clk26m", ++ "cci400_sel", ++ "f_bus_pll1_ck", ++ "f_bus_pll2_ck" ++}; ++ ++static struct mtk_composite mcu_muxes[] = { ++ /* mp0_pll_divider_cfg */ ++ MUX_GATE_FLAGS(CLK_MCU_MP0_SEL, "mcu_mp0_sel", mcu_mp0_parents, 0x7A0, ++ 9, 2, -1, CLK_IS_CRITICAL), ++ /* mp2_pll_divider_cfg */ ++ MUX_GATE_FLAGS(CLK_MCU_MP2_SEL, "mcu_mp2_sel", mcu_mp2_parents, 0x7A8, ++ 9, 2, -1, CLK_IS_CRITICAL), ++ /* bus_pll_divider_cfg */ ++ MUX_GATE_FLAGS(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0, ++ 9, 2, -1, CLK_IS_CRITICAL), ++}; ++ ++static const struct mtk_clk_divider top_adj_divs[] = { ++ DIV_ADJ(CLK_TOP_APLL_DIV0, "apll_div0", "i2so1_sel", 0x124, 0, 8), ++ DIV_ADJ(CLK_TOP_APLL_DIV1, "apll_div1", "i2so2_sel", 0x124, 8, 8), ++ DIV_ADJ(CLK_TOP_APLL_DIV2, "apll_div2", "i2so3_sel", 0x124, 16, 8), ++ DIV_ADJ(CLK_TOP_APLL_DIV3, "apll_div3", "tdmo0_sel", 0x124, 24, 8), ++ DIV_ADJ(CLK_TOP_APLL_DIV4, "apll_div4", "tdmo1_sel", 0x128, 0, 8), ++ DIV_ADJ(CLK_TOP_APLL_DIV5, "apll_div5", "i2si1_sel", 0x128, 8, 8), ++ DIV_ADJ(CLK_TOP_APLL_DIV6, "apll_div6", "i2si2_sel", 0x128, 16, 8), ++ DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8), ++}; ++ ++static const struct mtk_gate_regs top_cg_regs = { ++ .set_ofs = 0x120, ++ .clr_ofs = 0x120, ++ .sta_ofs = 0x120, ++}; ++ ++#define GATE_TOP(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &top_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++static const struct mtk_gate top_clks[] = { ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0), ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1), ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2), ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3), ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4), ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5), ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6), ++ GATE_TOP(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7), ++}; ++ ++static const struct mtk_gate_regs infra_cg_regs = { ++ .set_ofs = 0x40, ++ .clr_ofs = 0x44, ++ .sta_ofs = 0x40, ++}; ++ ++#define GATE_INFRA(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &infra_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++static const struct mtk_gate infra_clks[] = { ++ GATE_INFRA(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), ++ GATE_INFRA(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6), ++ GATE_INFRA(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8), ++ GATE_INFRA(CLK_INFRA_KP, "infra_kp", "axi_sel", 16), ++ GATE_INFRA(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "spi_sel", 24), ++ GATE_INFRA(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "spislv_sel", 25), ++ GATE_INFRA(CLK_INFRA_AO_UART5, "infra_ao_uart5", "axi_sel", 26), ++}; ++ ++static const struct mtk_gate_regs peri0_cg_regs = { ++ .set_ofs = 0x8, ++ .clr_ofs = 0x10, ++ .sta_ofs = 0x18, ++}; ++ ++static const struct mtk_gate_regs peri1_cg_regs = { ++ .set_ofs = 0xc, ++ .clr_ofs = 0x14, ++ .sta_ofs = 0x1c, ++}; ++ ++static const struct mtk_gate_regs peri2_cg_regs = { ++ .set_ofs = 0x42c, ++ .clr_ofs = 0x42c, ++ .sta_ofs = 0x42c, ++}; ++ ++#define GATE_PERI0(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &peri0_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_PERI1(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &peri1_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_PERI2(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &peri2_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++static const struct mtk_gate peri_clks[] = { ++ /* PERI0 */ ++ GATE_PERI0(CLK_PERI_NFI, "per_nfi", ++ "axi_sel", 0), ++ GATE_PERI0(CLK_PERI_THERM, "per_therm", ++ "axi_sel", 1), ++ GATE_PERI0(CLK_PERI_PWM0, "per_pwm0", ++ "pwm_sel", 2), ++ GATE_PERI0(CLK_PERI_PWM1, "per_pwm1", ++ "pwm_sel", 3), ++ GATE_PERI0(CLK_PERI_PWM2, "per_pwm2", ++ "pwm_sel", 4), ++ GATE_PERI0(CLK_PERI_PWM3, "per_pwm3", ++ "pwm_sel", 5), ++ GATE_PERI0(CLK_PERI_PWM4, "per_pwm4", ++ "pwm_sel", 6), ++ GATE_PERI0(CLK_PERI_PWM5, "per_pwm5", ++ "pwm_sel", 7), ++ GATE_PERI0(CLK_PERI_PWM6, "per_pwm6", ++ "pwm_sel", 8), ++ GATE_PERI0(CLK_PERI_PWM7, "per_pwm7", ++ "pwm_sel", 9), ++ GATE_PERI0(CLK_PERI_PWM, "per_pwm", ++ "pwm_sel", 10), ++ GATE_PERI0(CLK_PERI_AP_DMA, "per_ap_dma", ++ "axi_sel", 13), ++ GATE_PERI0(CLK_PERI_MSDC30_0, "per_msdc30_0", ++ "msdc50_0_sel", 14), ++ GATE_PERI0(CLK_PERI_MSDC30_1, "per_msdc30_1", ++ "msdc30_1_sel", 15), ++ GATE_PERI0(CLK_PERI_MSDC30_2, "per_msdc30_2", ++ "msdc30_2_sel", 16), ++ GATE_PERI0(CLK_PERI_MSDC30_3, "per_msdc30_3", ++ "msdc30_3_sel", 17), ++ GATE_PERI0(CLK_PERI_UART0, "per_uart0", ++ "uart_sel", 20), ++ GATE_PERI0(CLK_PERI_UART1, "per_uart1", ++ "uart_sel", 21), ++ GATE_PERI0(CLK_PERI_UART2, "per_uart2", ++ "uart_sel", 22), ++ GATE_PERI0(CLK_PERI_UART3, "per_uart3", ++ "uart_sel", 23), ++ GATE_PERI0(CLK_PERI_I2C0, "per_i2c0", ++ "axi_sel", 24), ++ GATE_PERI0(CLK_PERI_I2C1, "per_i2c1", ++ "axi_sel", 25), ++ GATE_PERI0(CLK_PERI_I2C2, "per_i2c2", ++ "axi_sel", 26), ++ GATE_PERI0(CLK_PERI_I2C3, "per_i2c3", ++ "axi_sel", 27), ++ GATE_PERI0(CLK_PERI_I2C4, "per_i2c4", ++ "axi_sel", 28), ++ GATE_PERI0(CLK_PERI_AUXADC, "per_auxadc", ++ "ltepll_fs26m", 29), ++ GATE_PERI0(CLK_PERI_SPI0, "per_spi0", ++ "spi_sel", 30), ++ /* PERI1 */ ++ GATE_PERI1(CLK_PERI_SPI, "per_spi", ++ "spinor_sel", 1), ++ GATE_PERI1(CLK_PERI_I2C5, "per_i2c5", ++ "axi_sel", 3), ++ GATE_PERI1(CLK_PERI_SPI2, "per_spi2", ++ "spi_sel", 5), ++ GATE_PERI1(CLK_PERI_SPI3, "per_spi3", ++ "spi_sel", 6), ++ GATE_PERI1(CLK_PERI_SPI5, "per_spi5", ++ "spi_sel", 8), ++ GATE_PERI1(CLK_PERI_UART4, "per_uart4", ++ "uart_sel", 9), ++ GATE_PERI1(CLK_PERI_SFLASH, "per_sflash", ++ "uart_sel", 11), ++ GATE_PERI1(CLK_PERI_GMAC, "per_gmac", ++ "uart_sel", 12), ++ GATE_PERI1(CLK_PERI_PCIE0, "per_pcie0", ++ "uart_sel", 14), ++ GATE_PERI1(CLK_PERI_PCIE1, "per_pcie1", ++ "uart_sel", 15), ++ GATE_PERI1(CLK_PERI_GMAC_PCLK, "per_gmac_pclk", ++ "uart_sel", 16), ++ /* PERI2 */ ++ GATE_PERI2(CLK_PERI_MSDC50_0_EN, "per_msdc50_0_en", ++ "msdc50_0_sel", 0), ++ GATE_PERI2(CLK_PERI_MSDC30_1_EN, "per_msdc30_1_en", ++ "msdc30_1_sel", 1), ++ GATE_PERI2(CLK_PERI_MSDC30_2_EN, "per_msdc30_2_en", ++ "msdc30_2_sel", 2), ++ GATE_PERI2(CLK_PERI_MSDC30_3_EN, "per_msdc30_3_en", ++ "msdc30_3_sel", 3), ++ GATE_PERI2(CLK_PERI_MSDC50_0_HCLK_EN, "per_msdc50_0_h", ++ "msdc50_0_h_sel", 4), ++ GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h", ++ "msdc50_3_h_sel", 5), ++}; ++ ++#define MT2712_PLL_FMAX (3000UL * MHZ) ++ ++#define CON0_MT2712_RST_BAR BIT(24) ++ ++#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ ++ _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ ++ _tuner_en_bit, _pcw_reg, _pcw_shift, \ ++ _div_table) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .reg = _reg, \ ++ .pwr_reg = _pwr_reg, \ ++ .en_mask = _en_mask, \ ++ .flags = _flags, \ ++ .rst_bar_mask = CON0_MT2712_RST_BAR, \ ++ .fmax = MT2712_PLL_FMAX, \ ++ .pcwbits = _pcwbits, \ ++ .pd_reg = _pd_reg, \ ++ .pd_shift = _pd_shift, \ ++ .tuner_reg = _tuner_reg, \ ++ .tuner_en_reg = _tuner_en_reg, \ ++ .tuner_en_bit = _tuner_en_bit, \ ++ .pcw_reg = _pcw_reg, \ ++ .pcw_shift = _pcw_shift, \ ++ .div_table = _div_table, \ ++ } ++ ++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ ++ _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ ++ _tuner_en_bit, _pcw_reg, _pcw_shift) \ ++ PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ ++ _pcwbits, _pd_reg, _pd_shift, _tuner_reg, \ ++ _tuner_en_reg, _tuner_en_bit, _pcw_reg, \ ++ _pcw_shift, NULL) ++ ++static const struct mtk_pll_div_table armca35pll_div_table[] = { ++ { .div = 0, .freq = MT2712_PLL_FMAX }, ++ { .div = 1, .freq = 1202500000 }, ++ { .div = 2, .freq = 500500000 }, ++ { .div = 3, .freq = 315250000 }, ++ { .div = 4, .freq = 157625000 }, ++ { } /* sentinel */ ++}; ++ ++static const struct mtk_pll_div_table armca72pll_div_table[] = { ++ { .div = 0, .freq = MT2712_PLL_FMAX }, ++ { .div = 1, .freq = 994500000 }, ++ { .div = 2, .freq = 520000000 }, ++ { .div = 3, .freq = 315250000 }, ++ { .div = 4, .freq = 157625000 }, ++ { } /* sentinel */ ++}; ++ ++static const struct mtk_pll_div_table mmpll_div_table[] = { ++ { .div = 0, .freq = MT2712_PLL_FMAX }, ++ { .div = 1, .freq = 1001000000 }, ++ { .div = 2, .freq = 601250000 }, ++ { .div = 3, .freq = 250250000 }, ++ { .div = 4, .freq = 125125000 }, ++ { } /* sentinel */ ++}; ++ ++static const struct mtk_pll_data plls[] = { ++ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000101, ++ HAVE_RST_BAR, 31, 0x0230, 4, 0, 0, 0, 0x0234, 0), ++ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000101, ++ HAVE_RST_BAR, 31, 0x0240, 4, 0, 0, 0, 0x0244, 0), ++ PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000101, ++ 0, 31, 0x0320, 4, 0, 0, 0, 0x0324, 0), ++ PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000101, ++ 0, 31, 0x0280, 4, 0, 0, 0, 0x0284, 0), ++ PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000101, ++ 0, 31, 0x0330, 4, 0x0338, 0x0014, 0, 0x0334, 0), ++ PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000101, ++ 0, 31, 0x0350, 4, 0x0358, 0x0014, 1, 0x0354, 0), ++ PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000101, ++ 0, 31, 0x0370, 4, 0, 0, 0, 0x0374, 0), ++ PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000101, ++ 0, 31, 0x0390, 4, 0, 0, 0, 0x0394, 0), ++ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000101, ++ 0, 31, 0x0270, 4, 0, 0, 0, 0x0274, 0), ++ PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000101, ++ 0, 31, 0x0410, 4, 0, 0, 0, 0x0414, 0), ++ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000101, ++ 0, 31, 0x0290, 4, 0, 0, 0, 0x0294, 0), ++ PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000101, ++ 0, 31, 0x0250, 4, 0, 0, 0, 0x0254, 0, ++ mmpll_div_table), ++ PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000101, ++ HAVE_RST_BAR, 31, 0x0100, 4, 0, 0, 0, 0x0104, 0, ++ armca35pll_div_table), ++ PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000101, ++ 0, 31, 0x0210, 4, 0, 0, 0, 0x0214, 0, ++ armca72pll_div_table), ++ PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000101, ++ 0, 31, 0x0300, 4, 0, 0, 0, 0x0304, 0), ++}; ++ ++static int clk_mt2712_apmixed_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); ++ ++ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static struct clk_onecell_data *top_clk_data; ++ ++static void clk_mt2712_top_init_early(struct device_node *node) ++{ ++ int r, i; ++ ++ if (!top_clk_data) { ++ top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); ++ ++ for (i = 0; i < CLK_TOP_NR_CLK; i++) ++ top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); ++ } ++ ++ mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), ++ top_clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); ++ if (r) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++} ++ ++CLK_OF_DECLARE_DRIVER(mt2712_topckgen, "mediatek,mt2712-topckgen", ++ clk_mt2712_top_init_early); ++ ++static int clk_mt2712_top_probe(struct platform_device *pdev) ++{ ++ int r, i; ++ struct device_node *node = pdev->dev.of_node; ++ void __iomem *base; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) { ++ pr_err("%s(): ioremap failed\n", __func__); ++ return PTR_ERR(base); ++ } ++ ++ if (!top_clk_data) { ++ top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); ++ } else { ++ for (i = 0; i < CLK_TOP_NR_CLK; i++) { ++ if (top_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) ++ top_clk_data->clks[i] = ERR_PTR(-ENOENT); ++ } ++ } ++ ++ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), ++ top_clk_data); ++ mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), ++ top_clk_data); ++ mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); ++ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, ++ &mt2712_clk_lock, top_clk_data); ++ mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, ++ &mt2712_clk_lock, top_clk_data); ++ mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), ++ top_clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static int clk_mt2712_infra_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); ++ ++ 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 != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ mtk_register_reset_controller(node, 2, 0x30); ++ ++ return r; ++} ++ ++static int clk_mt2712_peri_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); ++ ++ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ mtk_register_reset_controller(node, 2, 0); ++ ++ return r; ++} ++ ++static int clk_mt2712_mcu_probe(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ void __iomem *base; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) { ++ pr_err("%s(): ioremap failed\n", __func__); ++ return PTR_ERR(base); ++ } ++ ++ clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); ++ ++ mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, ++ &mt2712_clk_lock, clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ if (r != 0) ++ pr_err("%s(): could not register clock provider: %d\n", ++ __func__, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt2712[] = { ++ { ++ .compatible = "mediatek,mt2712-apmixedsys", ++ .data = clk_mt2712_apmixed_probe, ++ }, { ++ .compatible = "mediatek,mt2712-topckgen", ++ .data = clk_mt2712_top_probe, ++ }, { ++ .compatible = "mediatek,mt2712-infracfg", ++ .data = clk_mt2712_infra_probe, ++ }, { ++ .compatible = "mediatek,mt2712-pericfg", ++ .data = clk_mt2712_peri_probe, ++ }, { ++ .compatible = "mediatek,mt2712-mcucfg", ++ .data = clk_mt2712_mcu_probe, ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static int clk_mt2712_probe(struct platform_device *pdev) ++{ ++ int (*clk_probe)(struct platform_device *); ++ int r; ++ ++ clk_probe = of_device_get_match_data(&pdev->dev); ++ if (!clk_probe) ++ return -EINVAL; ++ ++ r = clk_probe(pdev); ++ if (r != 0) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ return r; ++} ++ ++static struct platform_driver clk_mt2712_drv = { ++ .probe = clk_mt2712_probe, ++ .driver = { ++ .name = "clk-mt2712", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_clk_mt2712, ++ }, ++}; ++ ++static int __init clk_mt2712_init(void) ++{ ++ return platform_driver_register(&clk_mt2712_drv); ++} ++ ++arch_initcall(clk_mt2712_init); +diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h +index f5d6b70ce189..f48df75cc901 100644 +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -207,6 +207,8 @@ struct mtk_pll_data { + uint32_t en_mask; + uint32_t pd_reg; + uint32_t tuner_reg; ++ uint32_t tuner_en_reg; ++ uint8_t tuner_en_bit; + int pd_shift; + unsigned int flags; + const struct clk_ops *ops; +diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c +index a409142e9346..3c546bae6955 100644 +--- a/drivers/clk/mediatek/clk-pll.c ++++ b/drivers/clk/mediatek/clk-pll.c +@@ -47,6 +47,7 @@ struct mtk_clk_pll { + void __iomem *pd_addr; + void __iomem *pwr_addr; + void __iomem *tuner_addr; ++ void __iomem *tuner_en_addr; + void __iomem *pcw_addr; + const struct mtk_pll_data *data; + }; +@@ -227,7 +228,10 @@ static int mtk_pll_prepare(struct clk_hw *hw) + r |= pll->data->en_mask; + writel(r, pll->base_addr + REG_CON0); + +- if (pll->tuner_addr) { ++ if (pll->tuner_en_addr) { ++ r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit); ++ writel(r, pll->tuner_en_addr); ++ } else if (pll->tuner_addr) { + r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } +@@ -254,7 +258,10 @@ static void mtk_pll_unprepare(struct clk_hw *hw) + writel(r, pll->base_addr + REG_CON0); + } + +- if (pll->tuner_addr) { ++ if (pll->tuner_en_addr) { ++ r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit); ++ writel(r, pll->tuner_en_addr); ++ } else if (pll->tuner_addr) { + r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } +@@ -297,6 +304,8 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, + pll->pcw_addr = base + data->pcw_reg; + if (data->tuner_reg) + pll->tuner_addr = base + data->tuner_reg; ++ if (data->tuner_en_reg) ++ pll->tuner_en_addr = base + data->tuner_en_reg; + pll->hw.init = &init; + pll->data = data; + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0147-dt-bindings-clock-mediatek-document-clk-bindings-for.patch b/target/linux/mediatek/patches-4.14/0147-dt-bindings-clock-mediatek-document-clk-bindings-for.patch new file mode 100644 index 0000000000..7cdb4168bd --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0147-dt-bindings-clock-mediatek-document-clk-bindings-for.patch @@ -0,0 +1,217 @@ +From acfa4eba7a4391d443b33a3d90a07eae0ef2ebca Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 5 Oct 2017 11:50:22 +0800 +Subject: [PATCH 147/224] dt-bindings: clock: mediatek: document clk bindings + for MediaTek MT7622 SoC + +This patch adds the binding documentation for apmixedsys, ethsys, hifsys, +infracfg, pericfg, topckgen and audsys for MT7622. + +Signed-off-by: Chen Zhong <chen.zhong@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,audsys.txt | 22 ++++++++++++++++++++++ + .../bindings/arm/mediatek/mediatek,ethsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,hifsys.txt | 1 + + .../bindings/arm/mediatek/mediatek,infracfg.txt | 1 + + .../bindings/arm/mediatek/mediatek,pciesys.txt | 22 ++++++++++++++++++++++ + .../bindings/arm/mediatek/mediatek,pericfg.txt | 1 + + .../bindings/arm/mediatek/mediatek,sgmiisys.txt | 22 ++++++++++++++++++++++ + .../bindings/arm/mediatek/mediatek,ssusbsys.txt | 22 ++++++++++++++++++++++ + .../bindings/arm/mediatek/mediatek,topckgen.txt | 1 + + 10 files changed, 94 insertions(+) + create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt + create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt + create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt + create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt + +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt +index 19fc116346d6..b404d592ce58 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt +@@ -9,6 +9,7 @@ Required Properties: + - "mediatek,mt2701-apmixedsys" + - "mediatek,mt2712-apmixedsys", "syscon" + - "mediatek,mt6797-apmixedsys" ++ - "mediatek,mt7622-apmixedsys" + - "mediatek,mt8135-apmixedsys" + - "mediatek,mt8173-apmixedsys" + - #clock-cells: Must be 1 +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt +new file mode 100644 +index 000000000000..9b8f578d5e19 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt +@@ -0,0 +1,22 @@ ++MediaTek AUDSYS controller ++============================ ++ ++The MediaTek AUDSYS controller provides various clocks to the system. ++ ++Required Properties: ++ ++- compatible: Should be one of: ++ - "mediatek,mt7622-audsys", "syscon" ++- #clock-cells: Must be 1 ++ ++The AUDSYS controller uses the common clk binding from ++Documentation/devicetree/bindings/clock/clock-bindings.txt ++The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++Example: ++ ++audsys: audsys@11220000 { ++ compatible = "mediatek,mt7622-audsys", "syscon"; ++ reg = <0 0x11220000 0 0x1000>; ++ #clock-cells = <1>; ++}; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt +index 768f3a5bc055..7aa3fa167668 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt +@@ -7,6 +7,7 @@ Required Properties: + + - compatible: Should be: + - "mediatek,mt2701-ethsys", "syscon" ++ - "mediatek,mt7622-ethsys", "syscon" + - #clock-cells: Must be 1 + + The ethsys controller uses the common clk binding from +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt +index beed7b594cea..f5629d64cef2 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt +@@ -8,6 +8,7 @@ Required Properties: + + - compatible: Should be: + - "mediatek,mt2701-hifsys", "syscon" ++ - "mediatek,mt7622-hifsys", "syscon" + - #clock-cells: Must be 1 + + The hifsys controller uses the common clk binding from +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt +index a3430cd96d0f..566f153f9f83 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt +@@ -10,6 +10,7 @@ Required Properties: + - "mediatek,mt2701-infracfg", "syscon" + - "mediatek,mt2712-infracfg", "syscon" + - "mediatek,mt6797-infracfg", "syscon" ++ - "mediatek,mt7622-infracfg", "syscon" + - "mediatek,mt8135-infracfg", "syscon" + - "mediatek,mt8173-infracfg", "syscon" + - #clock-cells: Must be 1 +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt +new file mode 100644 +index 000000000000..d5d5f1227665 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt +@@ -0,0 +1,22 @@ ++MediaTek PCIESYS controller ++============================ ++ ++The MediaTek PCIESYS controller provides various clocks to the system. ++ ++Required Properties: ++ ++- compatible: Should be: ++ - "mediatek,mt7622-pciesys", "syscon" ++- #clock-cells: Must be 1 ++ ++The PCIESYS controller uses the common clk binding from ++Documentation/devicetree/bindings/clock/clock-bindings.txt ++The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++Example: ++ ++pciesys: pciesys@1a100800 { ++ compatible = "mediatek,mt7622-pciesys", "syscon"; ++ reg = <0 0x1a100800 0 0x1000>; ++ #clock-cells = <1>; ++}; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt +index d9f092eb3550..fb58ca8c2770 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt +@@ -9,6 +9,7 @@ Required Properties: + - compatible: Should be one of: + - "mediatek,mt2701-pericfg", "syscon" + - "mediatek,mt2712-pericfg", "syscon" ++ - "mediatek,mt7622-pericfg", "syscon" + - "mediatek,mt8135-pericfg", "syscon" + - "mediatek,mt8173-pericfg", "syscon" + - #clock-cells: Must be 1 +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt +new file mode 100644 +index 000000000000..d113b8e741f3 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,sgmiisys.txt +@@ -0,0 +1,22 @@ ++MediaTek SGMIISYS controller ++============================ ++ ++The MediaTek SGMIISYS controller provides various clocks to the system. ++ ++Required Properties: ++ ++- compatible: Should be: ++ - "mediatek,mt7622-sgmiisys", "syscon" ++- #clock-cells: Must be 1 ++ ++The SGMIISYS controller uses the common clk binding from ++Documentation/devicetree/bindings/clock/clock-bindings.txt ++The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++Example: ++ ++sgmiisys: sgmiisys@1b128000 { ++ compatible = "mediatek,mt7622-sgmiisys", "syscon"; ++ reg = <0 0x1b128000 0 0x1000>; ++ #clock-cells = <1>; ++}; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt +new file mode 100644 +index 000000000000..00760019da00 +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt +@@ -0,0 +1,22 @@ ++MediaTek SSUSBSYS controller ++============================ ++ ++The MediaTek SSUSBSYS controller provides various clocks to the system. ++ ++Required Properties: ++ ++- compatible: Should be: ++ - "mediatek,mt7622-ssusbsys", "syscon" ++- #clock-cells: Must be 1 ++ ++The SSUSBSYS controller uses the common clk binding from ++Documentation/devicetree/bindings/clock/clock-bindings.txt ++The available clocks are defined in dt-bindings/clock/mt*-clk.h. ++ ++Example: ++ ++ssusbsys: ssusbsys@1a000000 { ++ compatible = "mediatek,mt7622-ssusbsys", "syscon"; ++ reg = <0 0x1a000000 0 0x1000>; ++ #clock-cells = <1>; ++}; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt +index 2024fc909d69..24014a7e2332 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt +@@ -9,6 +9,7 @@ Required Properties: + - "mediatek,mt2701-topckgen" + - "mediatek,mt2712-topckgen", "syscon" + - "mediatek,mt6797-topckgen" ++ - "mediatek,mt7622-topckgen" + - "mediatek,mt8135-topckgen" + - "mediatek,mt8173-topckgen" + - #clock-cells: Must be 1 +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0149-clk-mediatek-add-clocks-dt-bindings-required-header-.patch b/target/linux/mediatek/patches-4.14/0149-clk-mediatek-add-clocks-dt-bindings-required-header-.patch new file mode 100644 index 0000000000..fea00f32b0 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0149-clk-mediatek-add-clocks-dt-bindings-required-header-.patch @@ -0,0 +1,316 @@ +From ea009d063f7a3d70831788046c7285a4af4ab82d Mon Sep 17 00:00:00 2001 +From: Chen Zhong <chen.zhong@mediatek.com> +Date: Thu, 5 Oct 2017 11:50:25 +0800 +Subject: [PATCH 149/224] clk: mediatek: add clocks dt-bindings required header + for MT7622 SoC + +Add the required header for the entire clocks dt-bindings exported +from topckgen, apmixedsys, infracfg, pericfg, ethsys, pciesys, ssusbsys +and audsys which could be found on MT7622 SoC. + +Signed-off-by: Chen Zhong <chen.zhong@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + include/dt-bindings/clock/mt7622-clk.h | 289 +++++++++++++++++++++++++++++++++ + 1 file changed, 289 insertions(+) + create mode 100644 include/dt-bindings/clock/mt7622-clk.h + +diff --git a/include/dt-bindings/clock/mt7622-clk.h b/include/dt-bindings/clock/mt7622-clk.h +new file mode 100644 +index 000000000000..3e514ed51d15 +--- /dev/null ++++ b/include/dt-bindings/clock/mt7622-clk.h +@@ -0,0 +1,289 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Chen Zhong <chen.zhong@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef _DT_BINDINGS_CLK_MT7622_H ++#define _DT_BINDINGS_CLK_MT7622_H ++ ++/* TOPCKGEN */ ++ ++#define CLK_TOP_TO_U2_PHY 0 ++#define CLK_TOP_TO_U2_PHY_1P 1 ++#define CLK_TOP_PCIE0_PIPE_EN 2 ++#define CLK_TOP_PCIE1_PIPE_EN 3 ++#define CLK_TOP_SSUSB_TX250M 4 ++#define CLK_TOP_SSUSB_EQ_RX250M 5 ++#define CLK_TOP_SSUSB_CDR_REF 6 ++#define CLK_TOP_SSUSB_CDR_FB 7 ++#define CLK_TOP_SATA_ASIC 8 ++#define CLK_TOP_SATA_RBC 9 ++#define CLK_TOP_TO_USB3_SYS 10 ++#define CLK_TOP_P1_1MHZ 11 ++#define CLK_TOP_4MHZ 12 ++#define CLK_TOP_P0_1MHZ 13 ++#define CLK_TOP_TXCLK_SRC_PRE 14 ++#define CLK_TOP_RTC 15 ++#define CLK_TOP_MEMPLL 16 ++#define CLK_TOP_DMPLL 17 ++#define CLK_TOP_SYSPLL_D2 18 ++#define CLK_TOP_SYSPLL1_D2 19 ++#define CLK_TOP_SYSPLL1_D4 20 ++#define CLK_TOP_SYSPLL1_D8 21 ++#define CLK_TOP_SYSPLL2_D4 22 ++#define CLK_TOP_SYSPLL2_D8 23 ++#define CLK_TOP_SYSPLL_D5 24 ++#define CLK_TOP_SYSPLL3_D2 25 ++#define CLK_TOP_SYSPLL3_D4 26 ++#define CLK_TOP_SYSPLL4_D2 27 ++#define CLK_TOP_SYSPLL4_D4 28 ++#define CLK_TOP_SYSPLL4_D16 29 ++#define CLK_TOP_UNIVPLL 30 ++#define CLK_TOP_UNIVPLL_D2 31 ++#define CLK_TOP_UNIVPLL1_D2 32 ++#define CLK_TOP_UNIVPLL1_D4 33 ++#define CLK_TOP_UNIVPLL1_D8 34 ++#define CLK_TOP_UNIVPLL1_D16 35 ++#define CLK_TOP_UNIVPLL2_D2 36 ++#define CLK_TOP_UNIVPLL2_D4 37 ++#define CLK_TOP_UNIVPLL2_D8 38 ++#define CLK_TOP_UNIVPLL2_D16 39 ++#define CLK_TOP_UNIVPLL_D5 40 ++#define CLK_TOP_UNIVPLL3_D2 41 ++#define CLK_TOP_UNIVPLL3_D4 42 ++#define CLK_TOP_UNIVPLL3_D16 43 ++#define CLK_TOP_UNIVPLL_D7 44 ++#define CLK_TOP_UNIVPLL_D80_D4 45 ++#define CLK_TOP_UNIV48M 46 ++#define CLK_TOP_SGMIIPLL 47 ++#define CLK_TOP_SGMIIPLL_D2 48 ++#define CLK_TOP_AUD1PLL 49 ++#define CLK_TOP_AUD2PLL 50 ++#define CLK_TOP_AUD_I2S2_MCK 51 ++#define CLK_TOP_TO_USB3_REF 52 ++#define CLK_TOP_PCIE1_MAC_EN 53 ++#define CLK_TOP_PCIE0_MAC_EN 54 ++#define CLK_TOP_ETH_500M 55 ++#define CLK_TOP_AXI_SEL 56 ++#define CLK_TOP_MEM_SEL 57 ++#define CLK_TOP_DDRPHYCFG_SEL 58 ++#define CLK_TOP_ETH_SEL 59 ++#define CLK_TOP_PWM_SEL 60 ++#define CLK_TOP_F10M_REF_SEL 61 ++#define CLK_TOP_NFI_INFRA_SEL 62 ++#define CLK_TOP_FLASH_SEL 63 ++#define CLK_TOP_UART_SEL 64 ++#define CLK_TOP_SPI0_SEL 65 ++#define CLK_TOP_SPI1_SEL 66 ++#define CLK_TOP_MSDC50_0_SEL 67 ++#define CLK_TOP_MSDC30_0_SEL 68 ++#define CLK_TOP_MSDC30_1_SEL 69 ++#define CLK_TOP_A1SYS_HP_SEL 70 ++#define CLK_TOP_A2SYS_HP_SEL 71 ++#define CLK_TOP_INTDIR_SEL 72 ++#define CLK_TOP_AUD_INTBUS_SEL 73 ++#define CLK_TOP_PMICSPI_SEL 74 ++#define CLK_TOP_SCP_SEL 75 ++#define CLK_TOP_ATB_SEL 76 ++#define CLK_TOP_HIF_SEL 77 ++#define CLK_TOP_AUDIO_SEL 78 ++#define CLK_TOP_U2_SEL 79 ++#define CLK_TOP_AUD1_SEL 80 ++#define CLK_TOP_AUD2_SEL 81 ++#define CLK_TOP_IRRX_SEL 82 ++#define CLK_TOP_IRTX_SEL 83 ++#define CLK_TOP_ASM_L_SEL 84 ++#define CLK_TOP_ASM_M_SEL 85 ++#define CLK_TOP_ASM_H_SEL 86 ++#define CLK_TOP_APLL1_SEL 87 ++#define CLK_TOP_APLL2_SEL 88 ++#define CLK_TOP_I2S0_MCK_SEL 89 ++#define CLK_TOP_I2S1_MCK_SEL 90 ++#define CLK_TOP_I2S2_MCK_SEL 91 ++#define CLK_TOP_I2S3_MCK_SEL 92 ++#define CLK_TOP_APLL1_DIV 93 ++#define CLK_TOP_APLL2_DIV 94 ++#define CLK_TOP_I2S0_MCK_DIV 95 ++#define CLK_TOP_I2S1_MCK_DIV 96 ++#define CLK_TOP_I2S2_MCK_DIV 97 ++#define CLK_TOP_I2S3_MCK_DIV 98 ++#define CLK_TOP_A1SYS_HP_DIV 99 ++#define CLK_TOP_A2SYS_HP_DIV 100 ++#define CLK_TOP_APLL1_DIV_PD 101 ++#define CLK_TOP_APLL2_DIV_PD 102 ++#define CLK_TOP_I2S0_MCK_DIV_PD 103 ++#define CLK_TOP_I2S1_MCK_DIV_PD 104 ++#define CLK_TOP_I2S2_MCK_DIV_PD 105 ++#define CLK_TOP_I2S3_MCK_DIV_PD 106 ++#define CLK_TOP_A1SYS_HP_DIV_PD 107 ++#define CLK_TOP_A2SYS_HP_DIV_PD 108 ++#define CLK_TOP_NR_CLK 109 ++ ++/* INFRACFG */ ++ ++#define CLK_INFRA_MUX1_SEL 0 ++#define CLK_INFRA_DBGCLK_PD 1 ++#define CLK_INFRA_AUDIO_PD 2 ++#define CLK_INFRA_IRRX_PD 3 ++#define CLK_INFRA_APXGPT_PD 4 ++#define CLK_INFRA_PMIC_PD 5 ++#define CLK_INFRA_TRNG 6 ++#define CLK_INFRA_NR_CLK 7 ++ ++/* PERICFG */ ++ ++#define CLK_PERIBUS_SEL 0 ++#define CLK_PERI_THERM_PD 1 ++#define CLK_PERI_PWM1_PD 2 ++#define CLK_PERI_PWM2_PD 3 ++#define CLK_PERI_PWM3_PD 4 ++#define CLK_PERI_PWM4_PD 5 ++#define CLK_PERI_PWM5_PD 6 ++#define CLK_PERI_PWM6_PD 7 ++#define CLK_PERI_PWM7_PD 8 ++#define CLK_PERI_PWM_PD 9 ++#define CLK_PERI_AP_DMA_PD 10 ++#define CLK_PERI_MSDC30_0_PD 11 ++#define CLK_PERI_MSDC30_1_PD 12 ++#define CLK_PERI_UART0_PD 13 ++#define CLK_PERI_UART1_PD 14 ++#define CLK_PERI_UART2_PD 15 ++#define CLK_PERI_UART3_PD 16 ++#define CLK_PERI_UART4_PD 17 ++#define CLK_PERI_BTIF_PD 18 ++#define CLK_PERI_I2C0_PD 19 ++#define CLK_PERI_I2C1_PD 20 ++#define CLK_PERI_I2C2_PD 21 ++#define CLK_PERI_SPI1_PD 22 ++#define CLK_PERI_AUXADC_PD 23 ++#define CLK_PERI_SPI0_PD 24 ++#define CLK_PERI_SNFI_PD 25 ++#define CLK_PERI_NFI_PD 26 ++#define CLK_PERI_NFIECC_PD 27 ++#define CLK_PERI_FLASH_PD 28 ++#define CLK_PERI_IRTX_PD 29 ++#define CLK_PERI_NR_CLK 30 ++ ++/* APMIXEDSYS */ ++ ++#define CLK_APMIXED_ARMPLL 0 ++#define CLK_APMIXED_MAINPLL 1 ++#define CLK_APMIXED_UNIV2PLL 2 ++#define CLK_APMIXED_ETH1PLL 3 ++#define CLK_APMIXED_ETH2PLL 4 ++#define CLK_APMIXED_AUD1PLL 5 ++#define CLK_APMIXED_AUD2PLL 6 ++#define CLK_APMIXED_TRGPLL 7 ++#define CLK_APMIXED_SGMIPLL 8 ++#define CLK_APMIXED_MAIN_CORE_EN 9 ++#define CLK_APMIXED_NR_CLK 10 ++ ++/* AUDIOSYS */ ++ ++#define CLK_AUDIO_AFE 0 ++#define CLK_AUDIO_HDMI 1 ++#define CLK_AUDIO_SPDF 2 ++#define CLK_AUDIO_APLL 3 ++#define CLK_AUDIO_I2SIN1 4 ++#define CLK_AUDIO_I2SIN2 5 ++#define CLK_AUDIO_I2SIN3 6 ++#define CLK_AUDIO_I2SIN4 7 ++#define CLK_AUDIO_I2SO1 8 ++#define CLK_AUDIO_I2SO2 9 ++#define CLK_AUDIO_I2SO3 10 ++#define CLK_AUDIO_I2SO4 11 ++#define CLK_AUDIO_ASRCI1 12 ++#define CLK_AUDIO_ASRCI2 13 ++#define CLK_AUDIO_ASRCO1 14 ++#define CLK_AUDIO_ASRCO2 15 ++#define CLK_AUDIO_INTDIR 16 ++#define CLK_AUDIO_A1SYS 17 ++#define CLK_AUDIO_A2SYS 18 ++#define CLK_AUDIO_UL1 19 ++#define CLK_AUDIO_UL2 20 ++#define CLK_AUDIO_UL3 21 ++#define CLK_AUDIO_UL4 22 ++#define CLK_AUDIO_UL5 23 ++#define CLK_AUDIO_UL6 24 ++#define CLK_AUDIO_DL1 25 ++#define CLK_AUDIO_DL2 26 ++#define CLK_AUDIO_DL3 27 ++#define CLK_AUDIO_DL4 28 ++#define CLK_AUDIO_DL5 29 ++#define CLK_AUDIO_DL6 30 ++#define CLK_AUDIO_DLMCH 31 ++#define CLK_AUDIO_ARB1 32 ++#define CLK_AUDIO_AWB 33 ++#define CLK_AUDIO_AWB2 34 ++#define CLK_AUDIO_DAI 35 ++#define CLK_AUDIO_MOD 36 ++#define CLK_AUDIO_ASRCI3 37 ++#define CLK_AUDIO_ASRCI4 38 ++#define CLK_AUDIO_ASRCO3 39 ++#define CLK_AUDIO_ASRCO4 40 ++#define CLK_AUDIO_MEM_ASRC1 41 ++#define CLK_AUDIO_MEM_ASRC2 42 ++#define CLK_AUDIO_MEM_ASRC3 43 ++#define CLK_AUDIO_MEM_ASRC4 44 ++#define CLK_AUDIO_MEM_ASRC5 45 ++#define CLK_AUDIO_NR_CLK 46 ++ ++/* SSUSBSYS */ ++ ++#define CLK_SSUSB_U2_PHY_1P_EN 0 ++#define CLK_SSUSB_U2_PHY_EN 1 ++#define CLK_SSUSB_REF_EN 2 ++#define CLK_SSUSB_SYS_EN 3 ++#define CLK_SSUSB_MCU_EN 4 ++#define CLK_SSUSB_DMA_EN 5 ++#define CLK_SSUSB_NR_CLK 6 ++ ++/* PCIESYS */ ++ ++#define CLK_PCIE_P1_AUX_EN 0 ++#define CLK_PCIE_P1_OBFF_EN 1 ++#define CLK_PCIE_P1_AHB_EN 2 ++#define CLK_PCIE_P1_AXI_EN 3 ++#define CLK_PCIE_P1_MAC_EN 4 ++#define CLK_PCIE_P1_PIPE_EN 5 ++#define CLK_PCIE_P0_AUX_EN 6 ++#define CLK_PCIE_P0_OBFF_EN 7 ++#define CLK_PCIE_P0_AHB_EN 8 ++#define CLK_PCIE_P0_AXI_EN 9 ++#define CLK_PCIE_P0_MAC_EN 10 ++#define CLK_PCIE_P0_PIPE_EN 11 ++#define CLK_SATA_AHB_EN 12 ++#define CLK_SATA_AXI_EN 13 ++#define CLK_SATA_ASIC_EN 14 ++#define CLK_SATA_RBC_EN 15 ++#define CLK_SATA_PM_EN 16 ++#define CLK_PCIE_NR_CLK 17 ++ ++/* ETHSYS */ ++ ++#define CLK_ETH_HSDMA_EN 0 ++#define CLK_ETH_ESW_EN 1 ++#define CLK_ETH_GP2_EN 2 ++#define CLK_ETH_GP1_EN 3 ++#define CLK_ETH_GP0_EN 4 ++#define CLK_ETH_NR_CLK 5 ++ ++/* SGMIISYS */ ++ ++#define CLK_SGMII_TX250M_EN 0 ++#define CLK_SGMII_RX250M_EN 1 ++#define CLK_SGMII_CDR_REF 2 ++#define CLK_SGMII_CDR_FB 3 ++#define CLK_SGMII_NR_CLK 4 ++ ++#endif /* _DT_BINDINGS_CLK_MT7622_H */ ++ +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0150-clk-mediatek-add-clock-support-for-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0150-clk-mediatek-add-clock-support-for-MT7622-SoC.patch new file mode 100644 index 0000000000..ea015e8d6a --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0150-clk-mediatek-add-clock-support-for-MT7622-SoC.patch @@ -0,0 +1,1407 @@ +From b24e830d69f1fa637284c093410645a059b60028 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 5 Oct 2017 11:50:24 +0800 +Subject: [PATCH 150/224] clk: mediatek: add clock support for MT7622 SoC + +Add all supported clocks exported from every susbystem found on MT7622 SoC +such as topckgen, apmixedsys, infracfg, pericfg , pciessys, ssusbsys, +ethsys and audsys. + +Signed-off-by: Chen Zhong <chen.zhong@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/mediatek/Kconfig | 30 ++ + drivers/clk/mediatek/Makefile | 4 + + drivers/clk/mediatek/clk-mt7622-aud.c | 195 +++++++++ + drivers/clk/mediatek/clk-mt7622-eth.c | 156 +++++++ + drivers/clk/mediatek/clk-mt7622-hif.c | 169 ++++++++ + drivers/clk/mediatek/clk-mt7622.c | 780 ++++++++++++++++++++++++++++++++++ + 6 files changed, 1334 insertions(+) + create mode 100644 drivers/clk/mediatek/clk-mt7622-aud.c + create mode 100644 drivers/clk/mediatek/clk-mt7622-eth.c + create mode 100644 drivers/clk/mediatek/clk-mt7622-hif.c + create mode 100644 drivers/clk/mediatek/clk-mt7622.c + +diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig +index 300dbb551bf7..59dc0aad553c 100644 +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -132,6 +132,36 @@ config COMMON_CLK_MT6797_VENCSYS + ---help--- + This driver supports Mediatek MT6797 vencsys clocks. + ++config COMMON_CLK_MT7622 ++ bool "Clock driver for MediaTek MT7622" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ select COMMON_CLK_MEDIATEK ++ default ARCH_MEDIATEK ++ ---help--- ++ This driver supports MediaTek MT7622 basic clocks and clocks ++ required for various periperals found on MediaTek. ++ ++config COMMON_CLK_MT7622_ETHSYS ++ bool "Clock driver for MediaTek MT7622 ETHSYS" ++ depends on COMMON_CLK_MT7622 ++ ---help--- ++ This driver add support for clocks for Ethernet and SGMII ++ required on MediaTek MT7622 SoC. ++ ++config COMMON_CLK_MT7622_HIFSYS ++ bool "Clock driver for MediaTek MT7622 HIFSYS" ++ depends on COMMON_CLK_MT7622 ++ ---help--- ++ This driver supports MediaTek MT7622 HIFSYS clocks providing ++ to PCI-E and USB. ++ ++config COMMON_CLK_MT7622_AUDSYS ++ bool "Clock driver for MediaTek MT7622 AUDSYS" ++ depends on COMMON_CLK_MT7622 ++ ---help--- ++ This driver supports MediaTek MT7622 AUDSYS clocks providing ++ to audio consumers such as I2S and TDM. ++ + config COMMON_CLK_MT8135 + bool "Clock driver for Mediatek MT8135" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST +diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile +index a4e5c47c73a4..de8c3d0bb4ca 100644 +--- a/drivers/clk/mediatek/Makefile ++++ b/drivers/clk/mediatek/Makefile +@@ -20,5 +20,9 @@ obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o + obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o + obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o + obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o ++obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o ++obj-$(CONFIG_COMMON_CLK_MT7622_ETHSYS) += clk-mt7622-eth.o ++obj-$(CONFIG_COMMON_CLK_MT7622_HIFSYS) += clk-mt7622-hif.o ++obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o + obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o + obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o +diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c +new file mode 100644 +index 000000000000..fad7d9fc53ba +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7622-aud.c +@@ -0,0 +1,195 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Chen Zhong <chen.zhong@mediatek.com> ++ * Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt7622-clk.h> ++ ++#define GATE_AUDIO0(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &audio0_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++#define GATE_AUDIO1(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &audio1_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++#define GATE_AUDIO2(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &audio2_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++#define GATE_AUDIO3(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &audio3_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++static const struct mtk_gate_regs audio0_cg_regs = { ++ .set_ofs = 0x0, ++ .clr_ofs = 0x0, ++ .sta_ofs = 0x0, ++}; ++ ++static const struct mtk_gate_regs audio1_cg_regs = { ++ .set_ofs = 0x10, ++ .clr_ofs = 0x10, ++ .sta_ofs = 0x10, ++}; ++ ++static const struct mtk_gate_regs audio2_cg_regs = { ++ .set_ofs = 0x14, ++ .clr_ofs = 0x14, ++ .sta_ofs = 0x14, ++}; ++ ++static const struct mtk_gate_regs audio3_cg_regs = { ++ .set_ofs = 0x634, ++ .clr_ofs = 0x634, ++ .sta_ofs = 0x634, ++}; ++ ++static const struct mtk_gate audio_clks[] = { ++ /* AUDIO0 */ ++ GATE_AUDIO0(CLK_AUDIO_AFE, "audio_afe", "rtc", 2), ++ GATE_AUDIO0(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 20), ++ GATE_AUDIO0(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 21), ++ GATE_AUDIO0(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 23), ++ /* AUDIO1 */ ++ GATE_AUDIO1(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0), ++ GATE_AUDIO1(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 1), ++ GATE_AUDIO1(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 2), ++ GATE_AUDIO1(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 3), ++ GATE_AUDIO1(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 6), ++ GATE_AUDIO1(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 7), ++ GATE_AUDIO1(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 8), ++ GATE_AUDIO1(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 9), ++ GATE_AUDIO1(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 12), ++ GATE_AUDIO1(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 13), ++ GATE_AUDIO1(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 14), ++ GATE_AUDIO1(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 15), ++ GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20), ++ GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21), ++ GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22), ++ /* AUDIO2 */ ++ GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0), ++ GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1), ++ GATE_AUDIO2(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 2), ++ GATE_AUDIO2(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 3), ++ GATE_AUDIO2(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 4), ++ GATE_AUDIO2(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 5), ++ GATE_AUDIO2(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 6), ++ GATE_AUDIO2(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 7), ++ GATE_AUDIO2(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 8), ++ GATE_AUDIO2(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 9), ++ GATE_AUDIO2(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 10), ++ GATE_AUDIO2(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 11), ++ GATE_AUDIO2(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 12), ++ GATE_AUDIO2(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 13), ++ GATE_AUDIO2(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 14), ++ GATE_AUDIO2(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 15), ++ GATE_AUDIO2(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 16), ++ GATE_AUDIO2(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 17), ++ /* AUDIO3 */ ++ GATE_AUDIO3(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 2), ++ GATE_AUDIO3(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 3), ++ GATE_AUDIO3(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 6), ++ GATE_AUDIO3(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 7), ++ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10), ++ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11), ++ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12), ++ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13), ++ GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), ++}; ++ ++static int clk_mt7622_audiosys_init(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(CLK_AUDIO_NR_CLK); ++ ++ mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt7622_aud[] = { ++ { ++ .compatible = "mediatek,mt7622-audsys", ++ .data = clk_mt7622_audiosys_init, ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static int clk_mt7622_aud_probe(struct platform_device *pdev) ++{ ++ int (*clk_init)(struct platform_device *); ++ int r; ++ ++ clk_init = of_device_get_match_data(&pdev->dev); ++ if (!clk_init) ++ return -EINVAL; ++ ++ r = clk_init(pdev); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ return r; ++} ++ ++static struct platform_driver clk_mt7622_aud_drv = { ++ .probe = clk_mt7622_aud_probe, ++ .driver = { ++ .name = "clk-mt7622-aud", ++ .of_match_table = of_match_clk_mt7622_aud, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt7622_aud_drv); +diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c +new file mode 100644 +index 000000000000..6328127bbb3c +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7622-eth.c +@@ -0,0 +1,156 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Chen Zhong <chen.zhong@mediatek.com> ++ * Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt7622-clk.h> ++ ++#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_regs eth_cg_regs = { ++ .set_ofs = 0x30, ++ .clr_ofs = 0x30, ++ .sta_ofs = 0x30, ++}; ++ ++static const struct mtk_gate eth_clks[] = { ++ GATE_ETH(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 5), ++ GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 6), ++ GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7), ++ GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8), ++ GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9), ++}; ++ ++static const struct mtk_gate_regs sgmii_cg_regs = { ++ .set_ofs = 0xE4, ++ .clr_ofs = 0xE4, ++ .sta_ofs = 0xE4, ++}; ++ ++#define GATE_SGMII(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &sgmii_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++static const struct mtk_gate sgmii_clks[] = { ++ GATE_SGMII(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en", ++ "ssusb_tx250m", 2), ++ GATE_SGMII(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en", ++ "ssusb_eq_rx250m", 3), ++ GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref", ++ "ssusb_cdr_ref", 4), ++ GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb", ++ "ssusb_cdr_fb", 5), ++}; ++ ++static int clk_mt7622_ethsys_init(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(CLK_ETH_NR_CLK); ++ ++ 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) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ mtk_register_reset_controller(node, 1, 0x34); ++ ++ return r; ++} ++ ++static int clk_mt7622_sgmiisys_init(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(CLK_SGMII_NR_CLK); ++ ++ mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt7622_eth[] = { ++ { ++ .compatible = "mediatek,mt7622-ethsys", ++ .data = clk_mt7622_ethsys_init, ++ }, { ++ .compatible = "mediatek,mt7622-sgmiisys", ++ .data = clk_mt7622_sgmiisys_init, ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static int clk_mt7622_eth_probe(struct platform_device *pdev) ++{ ++ int (*clk_init)(struct platform_device *); ++ int r; ++ ++ clk_init = of_device_get_match_data(&pdev->dev); ++ if (!clk_init) ++ return -EINVAL; ++ ++ r = clk_init(pdev); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ return r; ++} ++ ++static struct platform_driver clk_mt7622_eth_drv = { ++ .probe = clk_mt7622_eth_probe, ++ .driver = { ++ .name = "clk-mt7622-eth", ++ .of_match_table = of_match_clk_mt7622_eth, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt7622_eth_drv); +diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c +new file mode 100644 +index 000000000000..a6e8534276c6 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7622-hif.c +@@ -0,0 +1,169 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Chen Zhong <chen.zhong@mediatek.com> ++ * Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++ ++#include <dt-bindings/clock/mt7622-clk.h> ++ ++#define GATE_PCIE(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &pcie_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++#define GATE_SSUSB(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &ssusb_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++static const struct mtk_gate_regs pcie_cg_regs = { ++ .set_ofs = 0x30, ++ .clr_ofs = 0x30, ++ .sta_ofs = 0x30, ++}; ++ ++static const struct mtk_gate_regs ssusb_cg_regs = { ++ .set_ofs = 0x30, ++ .clr_ofs = 0x30, ++ .sta_ofs = 0x30, ++}; ++ ++static const struct mtk_gate ssusb_clks[] = { ++ GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p", ++ "to_u2_phy_1p", 0), ++ GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1), ++ GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5), ++ GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6), ++ GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 7), ++ GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 8), ++}; ++ ++static const struct mtk_gate pcie_clks[] = { ++ GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12), ++ GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13), ++ GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 14), ++ GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 15), ++ GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16), ++ GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17), ++ GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18), ++ GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19), ++ GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 20), ++ GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 21), ++ GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22), ++ GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23), ++ GATE_PCIE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 26), ++ GATE_PCIE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 27), ++ GATE_PCIE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 28), ++ GATE_PCIE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 29), ++ GATE_PCIE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 30), ++}; ++ ++static int clk_mt7622_ssusbsys_init(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(CLK_SSUSB_NR_CLK); ++ ++ mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ mtk_register_reset_controller(node, 1, 0x34); ++ ++ return r; ++} ++ ++static int clk_mt7622_pciesys_init(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(CLK_PCIE_NR_CLK); ++ ++ mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ mtk_register_reset_controller(node, 1, 0x34); ++ ++ return r; ++} ++ ++static const struct of_device_id of_match_clk_mt7622_hif[] = { ++ { ++ .compatible = "mediatek,mt7622-pciesys", ++ .data = clk_mt7622_pciesys_init, ++ }, { ++ .compatible = "mediatek,mt7622-ssusbsys", ++ .data = clk_mt7622_ssusbsys_init, ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static int clk_mt7622_hif_probe(struct platform_device *pdev) ++{ ++ int (*clk_init)(struct platform_device *); ++ int r; ++ ++ clk_init = of_device_get_match_data(&pdev->dev); ++ if (!clk_init) ++ return -EINVAL; ++ ++ r = clk_init(pdev); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ return r; ++} ++ ++static struct platform_driver clk_mt7622_hif_drv = { ++ .probe = clk_mt7622_hif_probe, ++ .driver = { ++ .name = "clk-mt7622-hif", ++ .of_match_table = of_match_clk_mt7622_hif, ++ }, ++}; ++ ++builtin_platform_driver(clk_mt7622_hif_drv); +diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c +new file mode 100644 +index 000000000000..92f7e32770c6 +--- /dev/null ++++ b/drivers/clk/mediatek/clk-mt7622.c +@@ -0,0 +1,780 @@ ++/* ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Chen Zhong <chen.zhong@mediatek.com> ++ * Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/clk-provider.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++ ++#include "clk-mtk.h" ++#include "clk-gate.h" ++#include "clk-cpumux.h" ++ ++#include <dt-bindings/clock/mt7622-clk.h> ++#include <linux/clk.h> /* for consumer */ ++ ++#define MT7622_PLL_FMAX (2500UL * MHZ) ++#define CON0_MT7622_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_MT7622_RST_BAR, \ ++ .fmax = MT7622_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") ++ ++#define GATE_APMIXED(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &apmixed_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ ++ } ++ ++#define GATE_INFRA(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &infra_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_TOP0(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &top0_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++#define GATE_TOP1(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &top1_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_no_setclr, \ ++ } ++ ++#define GATE_PERI0(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &peri0_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++#define GATE_PERI1(_id, _name, _parent, _shift) { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _parent, \ ++ .regs = &peri1_cg_regs, \ ++ .shift = _shift, \ ++ .ops = &mtk_clk_gate_ops_setclr, \ ++ } ++ ++static DEFINE_SPINLOCK(mt7622_clk_lock); ++ ++static const char * const infra_mux1_parents[] = { ++ "clkxtal", ++ "armpll", ++ "main_core_en", ++ "armpll" ++}; ++ ++static const char * const axi_parents[] = { ++ "clkxtal", ++ "syspll1_d2", ++ "syspll_d5", ++ "syspll1_d4", ++ "univpll_d5", ++ "univpll2_d2", ++ "univpll_d7" ++}; ++ ++static const char * const mem_parents[] = { ++ "clkxtal", ++ "dmpll_ck" ++}; ++ ++static const char * const ddrphycfg_parents[] = { ++ "clkxtal", ++ "syspll1_d8" ++}; ++ ++static const char * const eth_parents[] = { ++ "clkxtal", ++ "syspll1_d2", ++ "univpll1_d2", ++ "syspll1_d4", ++ "univpll_d5", ++ "clk_null", ++ "univpll_d7" ++}; ++ ++static const char * const pwm_parents[] = { ++ "clkxtal", ++ "univpll2_d4" ++}; ++ ++static const char * const f10m_ref_parents[] = { ++ "clkxtal", ++ "syspll4_d16" ++}; ++ ++static const char * const nfi_infra_parents[] = { ++ "clkxtal", ++ "clkxtal", ++ "clkxtal", ++ "clkxtal", ++ "clkxtal", ++ "clkxtal", ++ "clkxtal", ++ "clkxtal", ++ "univpll2_d8", ++ "syspll1_d8", ++ "univpll1_d8", ++ "syspll4_d2", ++ "univpll2_d4", ++ "univpll3_d2", ++ "syspll1_d4" ++}; ++ ++static const char * const flash_parents[] = { ++ "clkxtal", ++ "univpll_d80_d4", ++ "syspll2_d8", ++ "syspll3_d4", ++ "univpll3_d4", ++ "univpll1_d8", ++ "syspll2_d4", ++ "univpll2_d4" ++}; ++ ++static const char * const uart_parents[] = { ++ "clkxtal", ++ "univpll2_d8" ++}; ++ ++static const char * const spi0_parents[] = { ++ "clkxtal", ++ "syspll3_d2", ++ "clkxtal", ++ "syspll2_d4", ++ "syspll4_d2", ++ "univpll2_d4", ++ "univpll1_d8", ++ "clkxtal" ++}; ++ ++static const char * const spi1_parents[] = { ++ "clkxtal", ++ "syspll3_d2", ++ "clkxtal", ++ "syspll4_d4", ++ "syspll4_d2", ++ "univpll2_d4", ++ "univpll1_d8", ++ "clkxtal" ++}; ++ ++static const char * const msdc30_0_parents[] = { ++ "clkxtal", ++ "univpll2_d16", ++ "univ48m" ++}; ++ ++static const char * const a1sys_hp_parents[] = { ++ "clkxtal", ++ "aud1pll_ck", ++ "aud2pll_ck", ++ "clkxtal" ++}; ++ ++static const char * const intdir_parents[] = { ++ "clkxtal", ++ "syspll_d2", ++ "univpll_d2", ++ "sgmiipll_ck" ++}; ++ ++static const char * const aud_intbus_parents[] = { ++ "clkxtal", ++ "syspll1_d4", ++ "syspll4_d2", ++ "syspll3_d2" ++}; ++ ++static const char * const pmicspi_parents[] = { ++ "clkxtal", ++ "clk_null", ++ "clk_null", ++ "clk_null", ++ "clk_null", ++ "univpll2_d16" ++}; ++ ++static const char * const atb_parents[] = { ++ "clkxtal", ++ "syspll1_d2", ++ "syspll_d5" ++}; ++ ++static const char * const audio_parents[] = { ++ "clkxtal", ++ "syspll3_d4", ++ "syspll4_d4", ++ "univpll1_d16" ++}; ++ ++static const char * const usb20_parents[] = { ++ "clkxtal", ++ "univpll3_d4", ++ "syspll1_d8", ++ "clkxtal" ++}; ++ ++static const char * const aud1_parents[] = { ++ "clkxtal", ++ "aud1pll_ck" ++}; ++ ++static const char * const aud2_parents[] = { ++ "clkxtal", ++ "aud2pll_ck" ++}; ++ ++static const char * const asm_l_parents[] = { ++ "clkxtal", ++ "syspll_d5", ++ "univpll2_d2", ++ "univpll2_d4" ++}; ++ ++static const char * const apll1_ck_parents[] = { ++ "aud1_sel", ++ "aud2_sel" ++}; ++ ++static const char * const peribus_ck_parents[] = { ++ "syspll1_d8", ++ "syspll1_d4" ++}; ++ ++static const struct mtk_gate_regs apmixed_cg_regs = { ++ .set_ofs = 0x8, ++ .clr_ofs = 0x8, ++ .sta_ofs = 0x8, ++}; ++ ++static const struct mtk_gate_regs infra_cg_regs = { ++ .set_ofs = 0x40, ++ .clr_ofs = 0x44, ++ .sta_ofs = 0x48, ++}; ++ ++static const struct mtk_gate_regs top0_cg_regs = { ++ .set_ofs = 0x120, ++ .clr_ofs = 0x120, ++ .sta_ofs = 0x120, ++}; ++ ++static const struct mtk_gate_regs top1_cg_regs = { ++ .set_ofs = 0x128, ++ .clr_ofs = 0x128, ++ .sta_ofs = 0x128, ++}; ++ ++static const struct mtk_gate_regs peri0_cg_regs = { ++ .set_ofs = 0x8, ++ .clr_ofs = 0x10, ++ .sta_ofs = 0x18, ++}; ++ ++static const struct mtk_gate_regs peri1_cg_regs = { ++ .set_ofs = 0xC, ++ .clr_ofs = 0x14, ++ .sta_ofs = 0x1C, ++}; ++ ++static const struct mtk_pll_data plls[] = { ++ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, ++ PLL_AO, 21, 0x0204, 24, 0, 0x0204, 0), ++ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001, ++ HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0), ++ PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001, ++ HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14), ++ PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001, ++ 0, 21, 0x0300, 1, 0, 0x0304, 0), ++ PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001, ++ 0, 21, 0x0314, 1, 0, 0x0318, 0), ++ PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0x00000001, ++ 0, 31, 0x0324, 1, 0, 0x0328, 0), ++ PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0x00000001, ++ 0, 31, 0x0334, 1, 0, 0x0338, 0), ++ PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0x00000001, ++ 0, 21, 0x0344, 1, 0, 0x0348, 0), ++ PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001, ++ 0, 21, 0x0358, 1, 0, 0x035C, 0), ++}; ++ ++static const struct mtk_gate apmixed_clks[] = { ++ GATE_APMIXED(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5), ++}; ++ ++static const struct mtk_gate infra_clks[] = { ++ GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0), ++ GATE_INFRA(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 2), ++ GATE_INFRA(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 5), ++ GATE_INFRA(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 16), ++ GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 18), ++ GATE_INFRA(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 22), ++}; ++ ++static const struct mtk_fixed_clk top_fixed_clks[] = { ++ FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal", ++ 31250000), ++ FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal", ++ 31250000), ++ FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal", ++ 125000000), ++ FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal", ++ 125000000), ++ FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal", ++ 250000000), ++ FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal", ++ 250000000), ++ FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal", ++ 33333333), ++ FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal", ++ 50000000), ++ FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal", ++ 50000000), ++ FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal", ++ 50000000), ++}; ++ ++static const struct mtk_fixed_factor top_divs[] = { ++ FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4), ++ FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500), ++ FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125), ++ FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500), ++ FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1), ++ FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024), ++ FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1), ++ FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), ++ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), ++ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4), ++ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8), ++ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16), ++ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12), ++ FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24), ++ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), ++ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10), ++ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20), ++ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14), ++ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28), ++ FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112), ++ FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), ++ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), ++ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4), ++ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8), ++ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16), ++ FACTOR(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32), ++ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6), ++ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12), ++ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24), ++ FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48), ++ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), ++ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10), ++ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20), ++ FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80), ++ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), ++ FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320), ++ FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25), ++ FACTOR(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1), ++ FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2), ++ FACTOR(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1), ++ FACTOR(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1), ++ FACTOR(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2), ++ FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4), ++ FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1), ++ FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1), ++ FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1), ++}; ++ ++static const struct mtk_gate top_clks[] = { ++ /* TOP0 */ ++ GATE_TOP0(CLK_TOP_APLL1_DIV_PD, "apll1_ck_div_pd", "apll1_ck_div", 0), ++ GATE_TOP0(CLK_TOP_APLL2_DIV_PD, "apll2_ck_div_pd", "apll2_ck_div", 1), ++ GATE_TOP0(CLK_TOP_I2S0_MCK_DIV_PD, "i2s0_mck_div_pd", "i2s0_mck_div", ++ 2), ++ GATE_TOP0(CLK_TOP_I2S1_MCK_DIV_PD, "i2s1_mck_div_pd", "i2s1_mck_div", ++ 3), ++ GATE_TOP0(CLK_TOP_I2S2_MCK_DIV_PD, "i2s2_mck_div_pd", "i2s2_mck_div", ++ 4), ++ GATE_TOP0(CLK_TOP_I2S3_MCK_DIV_PD, "i2s3_mck_div_pd", "i2s3_mck_div", ++ 5), ++ ++ /* TOP1 */ ++ GATE_TOP1(CLK_TOP_A1SYS_HP_DIV_PD, "a1sys_div_pd", "a1sys_div", 0), ++ GATE_TOP1(CLK_TOP_A2SYS_HP_DIV_PD, "a2sys_div_pd", "a2sys_div", 16), ++}; ++ ++static const struct mtk_clk_divider top_adj_divs[] = { ++ DIV_ADJ(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_sel", ++ 0x120, 24, 3), ++ DIV_ADJ(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_sel", ++ 0x120, 28, 3), ++ DIV_ADJ(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_sel", ++ 0x124, 0, 7), ++ DIV_ADJ(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_sel", ++ 0x124, 8, 7), ++ DIV_ADJ(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "aud_i2s2_mck", ++ 0x124, 16, 7), ++ DIV_ADJ(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_sel", ++ 0x124, 24, 7), ++ DIV_ADJ(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel", ++ 0x128, 8, 7), ++ DIV_ADJ(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel", ++ 0x128, 24, 7), ++}; ++ ++static const struct mtk_gate peri_clks[] = { ++ /* PERI0 */ ++ GATE_PERI0(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", 1), ++ GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", 2), ++ GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", 3), ++ GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", 4), ++ GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", 5), ++ GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", 6), ++ GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", 7), ++ GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", 8), ++ GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", 9), ++ GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", 12), ++ GATE_PERI0(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", 13), ++ GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", 14), ++ GATE_PERI0(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", 17), ++ GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", 18), ++ GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", 19), ++ GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", 20), ++ GATE_PERI0(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", 21), ++ GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", 22), ++ GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", 23), ++ GATE_PERI0(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", 24), ++ GATE_PERI0(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", 25), ++ GATE_PERI0(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", 26), ++ GATE_PERI0(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", 27), ++ GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", 28), ++ GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "nfi_infra_sel", 29), ++ GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", 30), ++ GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", 31), ++ ++ /* PERI1 */ ++ GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", 1), ++ GATE_PERI1(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", 2), ++}; ++ ++static struct mtk_composite infra_muxes[] __initdata = { ++ MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents, ++ 0x000, 2, 2), ++}; ++ ++static struct mtk_composite top_muxes[] = { ++ /* CLK_CFG_0 */ ++ MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, ++ 0x040, 0, 3, 7), ++ MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, ++ 0x040, 8, 1, 15), ++ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, ++ 0x040, 16, 1, 23), ++ MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, ++ 0x040, 24, 3, 31), ++ ++ /* CLK_CFG_1 */ ++ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, ++ 0x050, 0, 2, 7), ++ MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents, ++ 0x050, 8, 1, 15), ++ MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents, ++ 0x050, 16, 4, 23), ++ MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, ++ 0x050, 24, 3, 31), ++ ++ /* CLK_CFG_2 */ ++ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, ++ 0x060, 0, 1, 7), ++ MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents, ++ 0x060, 8, 3, 15), ++ MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents, ++ 0x060, 16, 3, 23), ++ MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents, ++ 0x060, 24, 3, 31), ++ ++ /* CLK_CFG_3 */ ++ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents, ++ 0x070, 0, 3, 7), ++ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_0_parents, ++ 0x070, 8, 3, 15), ++ MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", a1sys_hp_parents, ++ 0x070, 16, 2, 23), ++ MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", a1sys_hp_parents, ++ 0x070, 24, 2, 31), ++ ++ /* CLK_CFG_4 */ ++ MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents, ++ 0x080, 0, 2, 7), ++ MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, ++ 0x080, 8, 2, 15), ++ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, ++ 0x080, 16, 3, 23), ++ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", ddrphycfg_parents, ++ 0x080, 24, 2, 31), ++ ++ /* CLK_CFG_5 */ ++ MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, ++ 0x090, 0, 2, 7), ++ MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", eth_parents, ++ 0x090, 8, 3, 15), ++ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, ++ 0x090, 16, 2, 23), ++ MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents, ++ 0x090, 24, 2, 31), ++ ++ /* CLK_CFG_6 */ ++ MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, ++ 0x0A0, 0, 1, 7), ++ MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, ++ 0x0A0, 8, 1, 15), ++ MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", f10m_ref_parents, ++ 0x0A0, 16, 1, 23), ++ MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", f10m_ref_parents, ++ 0x0A0, 24, 1, 31), ++ ++ /* CLK_CFG_7 */ ++ MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", asm_l_parents, ++ 0x0B0, 0, 2, 7), ++ MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_l_parents, ++ 0x0B0, 8, 2, 15), ++ MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_l_parents, ++ 0x0B0, 16, 2, 23), ++ ++ /* CLK_AUDDIV_0 */ ++ MUX(CLK_TOP_APLL1_SEL, "apll1_ck_sel", apll1_ck_parents, ++ 0x120, 6, 1), ++ MUX(CLK_TOP_APLL2_SEL, "apll2_ck_sel", apll1_ck_parents, ++ 0x120, 7, 1), ++ MUX(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", apll1_ck_parents, ++ 0x120, 8, 1), ++ MUX(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", apll1_ck_parents, ++ 0x120, 9, 1), ++ MUX(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", apll1_ck_parents, ++ 0x120, 10, 1), ++ MUX(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", apll1_ck_parents, ++ 0x120, 11, 1), ++}; ++ ++static struct mtk_composite peri_muxes[] = { ++ /* PERI_GLOBALCON_CKSEL */ ++ MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1), ++}; ++ ++static int mtk_topckgen_init(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ void __iomem *base; ++ struct device_node *node = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); ++ ++ 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_composites(top_muxes, ARRAY_SIZE(top_muxes), ++ base, &mt7622_clk_lock, clk_data); ++ ++ mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), ++ base, &mt7622_clk_lock, clk_data); ++ ++ mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), ++ clk_data); ++ ++ clk_prepare_enable(clk_data->clks[CLK_TOP_AXI_SEL]); ++ clk_prepare_enable(clk_data->clks[CLK_TOP_MEM_SEL]); ++ clk_prepare_enable(clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); ++ ++ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++} ++ ++static int __init mtk_infrasys_init(struct platform_device *pdev) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ struct clk_onecell_data *clk_data; ++ int r; ++ ++ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); ++ ++ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), ++ clk_data); ++ ++ mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), ++ clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, ++ clk_data); ++ if (r) ++ return r; ++ ++ mtk_register_reset_controller(node, 1, 0x30); ++ ++ return 0; ++} ++ ++static int mtk_apmixedsys_init(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ struct device_node *node = pdev->dev.of_node; ++ ++ clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); ++ if (!clk_data) ++ return -ENOMEM; ++ ++ mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), ++ clk_data); ++ ++ mtk_clk_register_gates(node, apmixed_clks, ++ ARRAY_SIZE(apmixed_clks), clk_data); ++ ++ clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); ++ clk_prepare_enable(clk_data->clks[CLK_APMIXED_MAIN_CORE_EN]); ++ ++ return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++} ++ ++static int mtk_pericfg_init(struct platform_device *pdev) ++{ ++ struct clk_onecell_data *clk_data; ++ void __iomem *base; ++ int r; ++ struct device_node *node = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); ++ ++ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), ++ clk_data); ++ ++ mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, ++ &mt7622_clk_lock, clk_data); ++ ++ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ if (r) ++ return r; ++ ++ clk_prepare_enable(clk_data->clks[CLK_PERI_UART0_PD]); ++ ++ mtk_register_reset_controller(node, 2, 0x0); ++ ++ return 0; ++} ++ ++static const struct of_device_id of_match_clk_mt7622[] = { ++ { ++ .compatible = "mediatek,mt7622-apmixedsys", ++ .data = mtk_apmixedsys_init, ++ }, { ++ .compatible = "mediatek,mt7622-infracfg", ++ .data = mtk_infrasys_init, ++ }, { ++ .compatible = "mediatek,mt7622-topckgen", ++ .data = mtk_topckgen_init, ++ }, { ++ .compatible = "mediatek,mt7622-pericfg", ++ .data = mtk_pericfg_init, ++ }, { ++ /* sentinel */ ++ } ++}; ++ ++static int clk_mt7622_probe(struct platform_device *pdev) ++{ ++ int (*clk_init)(struct platform_device *); ++ int r; ++ ++ clk_init = of_device_get_match_data(&pdev->dev); ++ if (!clk_init) ++ return -EINVAL; ++ ++ r = clk_init(pdev); ++ if (r) ++ dev_err(&pdev->dev, ++ "could not register clock provider: %s: %d\n", ++ pdev->name, r); ++ ++ return r; ++} ++ ++static struct platform_driver clk_mt7622_drv = { ++ .probe = clk_mt7622_probe, ++ .driver = { ++ .name = "clk-mt7622", ++ .of_match_table = of_match_clk_mt7622, ++ }, ++}; ++ ++static int clk_mt7622_init(void) ++{ ++ return platform_driver_register(&clk_mt7622_drv); ++} ++ ++arch_initcall(clk_mt7622_init); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0151-arm64-dts-mt8173-remove-mediatek-mt8135-mmc-from-mmc.patch b/target/linux/mediatek/patches-4.14/0151-arm64-dts-mt8173-remove-mediatek-mt8135-mmc-from-mmc.patch new file mode 100644 index 0000000000..6c8c3c081f --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0151-arm64-dts-mt8173-remove-mediatek-mt8135-mmc-from-mmc.patch @@ -0,0 +1,66 @@ +From fa69904d3b7357a5be43771f764e10fd99ebbb11 Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:30 +0800 +Subject: [PATCH 151/224] arm64: dts: mt8173: remove "mediatek, mt8135-mmc" + from mmc nodes + +devicetree bindings has been updated to support multi-platforms, +so that each platform has its owns compatible name. +And, this compatible name may used in driver to distinguish with +other platform. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +Acked-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + arch/arm64/boot/dts/mediatek/mt8173.dtsi | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +index b99a27372965..26396ef53bde 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi +@@ -682,8 +682,7 @@ + }; + + mmc0: mmc@11230000 { +- compatible = "mediatek,mt8173-mmc", +- "mediatek,mt8135-mmc"; ++ compatible = "mediatek,mt8173-mmc"; + reg = <0 0x11230000 0 0x1000>; + interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_LOW>; + clocks = <&pericfg CLK_PERI_MSDC30_0>, +@@ -693,8 +692,7 @@ + }; + + mmc1: mmc@11240000 { +- compatible = "mediatek,mt8173-mmc", +- "mediatek,mt8135-mmc"; ++ compatible = "mediatek,mt8173-mmc"; + reg = <0 0x11240000 0 0x1000>; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>; + clocks = <&pericfg CLK_PERI_MSDC30_1>, +@@ -704,8 +702,7 @@ + }; + + mmc2: mmc@11250000 { +- compatible = "mediatek,mt8173-mmc", +- "mediatek,mt8135-mmc"; ++ compatible = "mediatek,mt8173-mmc"; + reg = <0 0x11250000 0 0x1000>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_LOW>; + clocks = <&pericfg CLK_PERI_MSDC30_2>, +@@ -715,8 +712,7 @@ + }; + + mmc3: mmc@11260000 { +- compatible = "mediatek,mt8173-mmc", +- "mediatek,mt8135-mmc"; ++ compatible = "mediatek,mt8173-mmc"; + reg = <0 0x11260000 0 0x1000>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_LOW>; + clocks = <&pericfg CLK_PERI_MSDC30_3>, +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0152-mmc-mediatek-make-hs400_tune_response-only-for-mt817.patch b/target/linux/mediatek/patches-4.14/0152-mmc-mediatek-make-hs400_tune_response-only-for-mt817.patch new file mode 100644 index 0000000000..3c665dc317 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0152-mmc-mediatek-make-hs400_tune_response-only-for-mt817.patch @@ -0,0 +1,75 @@ +From bc70c7f1174b937af2784977281a1567f69dd2b6 Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:31 +0800 +Subject: [PATCH 152/224] mmc: mediatek: make hs400_tune_response only for + mt8173 + +the origin design of hs400_tune_response is for mt8173 because of +mt8173 has a special design. for doing that, we add a new member +"compatible", by now it's only for mt8173. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index 643c795f1bdd..ab2fbbbdfda3 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -300,6 +300,7 @@ struct msdc_save_para { + + struct mtk_mmc_compatible { + u8 clk_div_bits; ++ bool hs400_tune; /* only used for MT8173 */ + }; + + struct msdc_tune_para { +@@ -360,18 +361,22 @@ struct msdc_host { + + static const struct mtk_mmc_compatible mt8135_compat = { + .clk_div_bits = 8, ++ .hs400_tune = false, + }; + + static const struct mtk_mmc_compatible mt8173_compat = { + .clk_div_bits = 8, ++ .hs400_tune = true, + }; + + static const struct mtk_mmc_compatible mt2701_compat = { + .clk_div_bits = 12, ++ .hs400_tune = false, + }; + + static const struct mtk_mmc_compatible mt2712_compat = { + .clk_div_bits = 12, ++ .hs400_tune = false, + }; + + static const struct of_device_id msdc_of_ids[] = { +@@ -666,7 +671,8 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + host->base + PAD_CMD_TUNE); + } + +- if (timing == MMC_TIMING_MMC_HS400) ++ if (timing == MMC_TIMING_MMC_HS400 && ++ host->dev_comp->hs400_tune) + sdr_set_field(host->base + PAD_CMD_TUNE, + MSDC_PAD_TUNE_CMDRRDLY, + host->hs400_cmd_int_delay); +@@ -1594,7 +1600,8 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode) + struct msdc_host *host = mmc_priv(mmc); + int ret; + +- if (host->hs400_mode) ++ if (host->hs400_mode && ++ host->dev_comp->hs400_tune) + ret = hs400_tune_response(mmc, opcode); + else + ret = msdc_tune_response(mmc, opcode); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0153-mmc-mediatek-add-pad_tune0-support.patch b/target/linux/mediatek/patches-4.14/0153-mmc-mediatek-add-pad_tune0-support.patch new file mode 100644 index 0000000000..d0f81be5a8 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0153-mmc-mediatek-add-pad_tune0-support.patch @@ -0,0 +1,261 @@ +From a10349f1710a11239c58da3a7e5b353c6b2070c2 Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:32 +0800 +Subject: [PATCH 153/224] mmc: mediatek: add pad_tune0 support + +from mt2701, the register of PAD_TUNE has been phased out, +while there is a new register of PAD_TUNE0 + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 51 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 33 insertions(+), 18 deletions(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index ab2fbbbdfda3..bcd83d6f2b86 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -75,6 +75,7 @@ + #define MSDC_PATCH_BIT 0xb0 + #define MSDC_PATCH_BIT1 0xb4 + #define MSDC_PAD_TUNE 0xec ++#define MSDC_PAD_TUNE0 0xf0 + #define PAD_DS_TUNE 0x188 + #define PAD_CMD_TUNE 0x18c + #define EMMC50_CFG0 0x208 +@@ -301,6 +302,7 @@ struct msdc_save_para { + struct mtk_mmc_compatible { + u8 clk_div_bits; + bool hs400_tune; /* only used for MT8173 */ ++ u32 pad_tune_reg; + }; + + struct msdc_tune_para { +@@ -362,21 +364,25 @@ struct msdc_host { + static const struct mtk_mmc_compatible mt8135_compat = { + .clk_div_bits = 8, + .hs400_tune = false, ++ .pad_tune_reg = MSDC_PAD_TUNE, + }; + + static const struct mtk_mmc_compatible mt8173_compat = { + .clk_div_bits = 8, + .hs400_tune = true, ++ .pad_tune_reg = MSDC_PAD_TUNE, + }; + + static const struct mtk_mmc_compatible mt2701_compat = { + .clk_div_bits = 12, + .hs400_tune = false, ++ .pad_tune_reg = MSDC_PAD_TUNE0, + }; + + static const struct mtk_mmc_compatible mt2712_compat = { + .clk_div_bits = 12, + .hs400_tune = false, ++ .pad_tune_reg = MSDC_PAD_TUNE0, + }; + + static const struct of_device_id msdc_of_ids[] = { +@@ -581,6 +587,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + u32 flags; + u32 div; + u32 sclk; ++ u32 tune_reg = host->dev_comp->pad_tune_reg; + + if (!hz) { + dev_dbg(host->dev, "set mclk to 0\n"); +@@ -663,10 +670,10 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + */ + if (host->sclk <= 52000000) { + writel(host->def_tune_para.iocon, host->base + MSDC_IOCON); +- writel(host->def_tune_para.pad_tune, host->base + MSDC_PAD_TUNE); ++ writel(host->def_tune_para.pad_tune, host->base + tune_reg); + } else { + writel(host->saved_tune_para.iocon, host->base + MSDC_IOCON); +- writel(host->saved_tune_para.pad_tune, host->base + MSDC_PAD_TUNE); ++ writel(host->saved_tune_para.pad_tune, host->base + tune_reg); + writel(host->saved_tune_para.pad_cmd_tune, + host->base + PAD_CMD_TUNE); + } +@@ -1224,6 +1231,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) + static void msdc_init_hw(struct msdc_host *host) + { + u32 val; ++ u32 tune_reg = host->dev_comp->pad_tune_reg; + + /* Configure to MMC/SD mode, clock free running */ + sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN); +@@ -1239,7 +1247,7 @@ static void msdc_init_hw(struct msdc_host *host) + val = readl(host->base + MSDC_INT); + writel(val, host->base + MSDC_INT); + +- writel(0, host->base + MSDC_PAD_TUNE); ++ writel(0, host->base + tune_reg); + writel(0, host->base + MSDC_IOCON); + sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0); + writel(0x403c0046, host->base + MSDC_PATCH_BIT); +@@ -1259,7 +1267,7 @@ static void msdc_init_hw(struct msdc_host *host) + sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3); + + host->def_tune_para.iocon = readl(host->base + MSDC_IOCON); +- host->def_tune_para.pad_tune = readl(host->base + MSDC_PAD_TUNE); ++ host->def_tune_para.pad_tune = readl(host->base + tune_reg); + dev_dbg(host->dev, "init hardware done!"); + } + +@@ -1402,18 +1410,19 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode) + struct msdc_delay_phase internal_delay_phase; + u8 final_delay, final_maxlen; + u32 internal_delay = 0; ++ u32 tune_reg = host->dev_comp->pad_tune_reg; + int cmd_err; + int i, j; + + if (mmc->ios.timing == MMC_TIMING_MMC_HS200 || + mmc->ios.timing == MMC_TIMING_UHS_SDR104) +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_CMDRRDLY, + host->hs200_cmd_int_delay); + + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL); + for (i = 0 ; i < PAD_DELAY_MAX; i++) { +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_CMDRDLY, i); + /* + * Using the same parameters, it may sometimes pass the test, +@@ -1437,7 +1446,7 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode) + + sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL); + for (i = 0; i < PAD_DELAY_MAX; i++) { +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_CMDRDLY, i); + /* + * Using the same parameters, it may sometimes pass the test, +@@ -1462,12 +1471,12 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode) + final_maxlen = final_fall_delay.maxlen; + if (final_maxlen == final_rise_delay.maxlen) { + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL); +- sdr_set_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, ++ sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRDLY, + final_rise_delay.final_phase); + final_delay = final_rise_delay.final_phase; + } else { + sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL); +- sdr_set_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, ++ sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRDLY, + final_fall_delay.final_phase); + final_delay = final_fall_delay.final_phase; + } +@@ -1475,7 +1484,7 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode) + goto skip_internal; + + for (i = 0; i < PAD_DELAY_MAX; i++) { +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_CMDRRDLY, i); + mmc_send_tuning(mmc, opcode, &cmd_err); + if (!cmd_err) +@@ -1483,7 +1492,7 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode) + } + dev_dbg(host->dev, "Final internal delay: 0x%x\n", internal_delay); + internal_delay_phase = get_best_delay(host, internal_delay); +- sdr_set_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, ++ sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRRDLY, + internal_delay_phase.final_phase); + skip_internal: + dev_dbg(host->dev, "Final cmd pad delay: %x\n", final_delay); +@@ -1545,12 +1554,13 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode) + u32 rise_delay = 0, fall_delay = 0; + struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0,}; + u8 final_delay, final_maxlen; ++ u32 tune_reg = host->dev_comp->pad_tune_reg; + int i, ret; + + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL); + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL); + for (i = 0 ; i < PAD_DELAY_MAX; i++) { +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_DATRRDLY, i); + ret = mmc_send_tuning(mmc, opcode, NULL); + if (!ret) +@@ -1565,7 +1575,7 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode) + sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL); + sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL); + for (i = 0; i < PAD_DELAY_MAX; i++) { +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_DATRRDLY, i); + ret = mmc_send_tuning(mmc, opcode, NULL); + if (!ret) +@@ -1578,14 +1588,14 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode) + if (final_maxlen == final_rise_delay.maxlen) { + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL); + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL); +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_DATRRDLY, + final_rise_delay.final_phase); + final_delay = final_rise_delay.final_phase; + } else { + sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL); + sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL); +- sdr_set_field(host->base + MSDC_PAD_TUNE, ++ sdr_set_field(host->base + tune_reg, + MSDC_PAD_TUNE_DATRRDLY, + final_fall_delay.final_phase); + final_delay = final_fall_delay.final_phase; +@@ -1599,6 +1609,7 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode) + { + struct msdc_host *host = mmc_priv(mmc); + int ret; ++ u32 tune_reg = host->dev_comp->pad_tune_reg; + + if (host->hs400_mode && + host->dev_comp->hs400_tune) +@@ -1616,7 +1627,7 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode) + } + + host->saved_tune_para.iocon = readl(host->base + MSDC_IOCON); +- host->saved_tune_para.pad_tune = readl(host->base + MSDC_PAD_TUNE); ++ host->saved_tune_para.pad_tune = readl(host->base + tune_reg); + host->saved_tune_para.pad_cmd_tune = readl(host->base + PAD_CMD_TUNE); + return ret; + } +@@ -1857,10 +1868,12 @@ static int msdc_drv_remove(struct platform_device *pdev) + #ifdef CONFIG_PM + static void msdc_save_reg(struct msdc_host *host) + { ++ u32 tune_reg = host->dev_comp->pad_tune_reg; ++ + host->save_para.msdc_cfg = readl(host->base + MSDC_CFG); + host->save_para.iocon = readl(host->base + MSDC_IOCON); + host->save_para.sdc_cfg = readl(host->base + SDC_CFG); +- host->save_para.pad_tune = readl(host->base + MSDC_PAD_TUNE); ++ host->save_para.pad_tune = readl(host->base + tune_reg); + host->save_para.patch_bit0 = readl(host->base + MSDC_PATCH_BIT); + host->save_para.patch_bit1 = readl(host->base + MSDC_PATCH_BIT1); + host->save_para.pad_ds_tune = readl(host->base + PAD_DS_TUNE); +@@ -1870,10 +1883,12 @@ static void msdc_save_reg(struct msdc_host *host) + + static void msdc_restore_reg(struct msdc_host *host) + { ++ u32 tune_reg = host->dev_comp->pad_tune_reg; ++ + writel(host->save_para.msdc_cfg, host->base + MSDC_CFG); + writel(host->save_para.iocon, host->base + MSDC_IOCON); + writel(host->save_para.sdc_cfg, host->base + SDC_CFG); +- writel(host->save_para.pad_tune, host->base + MSDC_PAD_TUNE); ++ writel(host->save_para.pad_tune, host->base + tune_reg); + writel(host->save_para.patch_bit0, host->base + MSDC_PATCH_BIT); + writel(host->save_para.patch_bit1, host->base + MSDC_PATCH_BIT1); + writel(host->save_para.pad_ds_tune, host->base + PAD_DS_TUNE); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0154-mmc-mediatek-add-async-fifo-and-data-tune-support.patch b/target/linux/mediatek/patches-4.14/0154-mmc-mediatek-add-async-fifo-and-data-tune-support.patch new file mode 100644 index 0000000000..0bd5ca13bc --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0154-mmc-mediatek-add-async-fifo-and-data-tune-support.patch @@ -0,0 +1,175 @@ +From 830574225e621809600902b69bbdd563e67ef4eb Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:33 +0800 +Subject: [PATCH 154/224] mmc: mediatek: add async fifo and data tune support + +mt2701/mt2712 supports async fifo & data tune, which can improve +host stability. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 52 +++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 50 insertions(+), 2 deletions(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index bcd83d6f2b86..8113bacc1540 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -74,6 +74,7 @@ + #define MSDC_DMA_CFG 0x9c + #define MSDC_PATCH_BIT 0xb0 + #define MSDC_PATCH_BIT1 0xb4 ++#define MSDC_PATCH_BIT2 0xb8 + #define MSDC_PAD_TUNE 0xec + #define MSDC_PAD_TUNE0 0xf0 + #define PAD_DS_TUNE 0x188 +@@ -216,11 +217,20 @@ + #define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */ + #define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ + ++#define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */ ++#define MSDC_PATCH_BIT2_CFGCRCSTS (0x1 << 28) /* RW */ ++#define MSDC_PB2_RESPWAIT (0x3 << 2) /* RW */ ++#define MSDC_PB2_RESPSTSENSEL (0x7 << 16) /* RW */ ++#define MSDC_PB2_CRCSTSENSEL (0x7 << 29) /* RW */ ++ + #define MSDC_PAD_TUNE_DATWRDLY (0x1f << 0) /* RW */ + #define MSDC_PAD_TUNE_DATRRDLY (0x1f << 8) /* RW */ + #define MSDC_PAD_TUNE_CMDRDLY (0x1f << 16) /* RW */ + #define MSDC_PAD_TUNE_CMDRRDLY (0x1f << 22) /* RW */ + #define MSDC_PAD_TUNE_CLKTDLY (0x1f << 27) /* RW */ ++#define MSDC_PAD_TUNE_RXDLYSEL (0x1 << 15) /* RW */ ++#define MSDC_PAD_TUNE_RD_SEL (0x1 << 13) /* RW */ ++#define MSDC_PAD_TUNE_CMD_SEL (0x1 << 21) /* RW */ + + #define PAD_DS_TUNE_DLY1 (0x1f << 2) /* RW */ + #define PAD_DS_TUNE_DLY2 (0x1f << 7) /* RW */ +@@ -294,6 +304,7 @@ struct msdc_save_para { + u32 pad_tune; + u32 patch_bit0; + u32 patch_bit1; ++ u32 patch_bit2; + u32 pad_ds_tune; + u32 pad_cmd_tune; + u32 emmc50_cfg0; +@@ -303,6 +314,8 @@ struct mtk_mmc_compatible { + u8 clk_div_bits; + bool hs400_tune; /* only used for MT8173 */ + u32 pad_tune_reg; ++ bool async_fifo; ++ bool data_tune; + }; + + struct msdc_tune_para { +@@ -365,24 +378,32 @@ static const struct mtk_mmc_compatible mt8135_compat = { + .clk_div_bits = 8, + .hs400_tune = false, + .pad_tune_reg = MSDC_PAD_TUNE, ++ .async_fifo = false, ++ .data_tune = false, + }; + + static const struct mtk_mmc_compatible mt8173_compat = { + .clk_div_bits = 8, + .hs400_tune = true, + .pad_tune_reg = MSDC_PAD_TUNE, ++ .async_fifo = false, ++ .data_tune = false, + }; + + static const struct mtk_mmc_compatible mt2701_compat = { + .clk_div_bits = 12, + .hs400_tune = false, + .pad_tune_reg = MSDC_PAD_TUNE0, ++ .async_fifo = true, ++ .data_tune = true, + }; + + static const struct mtk_mmc_compatible mt2712_compat = { + .clk_div_bits = 12, + .hs400_tune = false, + .pad_tune_reg = MSDC_PAD_TUNE0, ++ .async_fifo = true, ++ .data_tune = true, + }; + + static const struct of_device_id msdc_of_ids[] = { +@@ -1252,8 +1273,29 @@ static void msdc_init_hw(struct msdc_host *host) + sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0); + writel(0x403c0046, host->base + MSDC_PATCH_BIT); + sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1); +- writel(0xffff0089, host->base + MSDC_PATCH_BIT1); ++ writel(0xffff4089, host->base + MSDC_PATCH_BIT1); + sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL); ++ if (host->dev_comp->async_fifo) { ++ sdr_set_field(host->base + MSDC_PATCH_BIT2, ++ MSDC_PB2_RESPWAIT, 3); ++ sdr_set_field(host->base + MSDC_PATCH_BIT2, ++ MSDC_PB2_RESPSTSENSEL, 2); ++ sdr_set_field(host->base + MSDC_PATCH_BIT2, ++ MSDC_PB2_CRCSTSENSEL, 2); ++ /* use async fifo, then no need tune internal delay */ ++ sdr_clr_bits(host->base + MSDC_PATCH_BIT2, ++ MSDC_PATCH_BIT2_CFGRESP); ++ sdr_set_bits(host->base + MSDC_PATCH_BIT2, ++ MSDC_PATCH_BIT2_CFGCRCSTS); ++ } ++ ++ if (host->dev_comp->data_tune) { ++ sdr_set_bits(host->base + tune_reg, ++ MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL); ++ } else { ++ /* choose clock tune */ ++ sdr_set_bits(host->base + tune_reg, MSDC_PAD_TUNE_RXDLYSEL); ++ } + + /* Configure to enable SDIO mode. + * it's must otherwise sdio cmd5 failed +@@ -1268,6 +1310,8 @@ static void msdc_init_hw(struct msdc_host *host) + + host->def_tune_para.iocon = readl(host->base + MSDC_IOCON); + host->def_tune_para.pad_tune = readl(host->base + tune_reg); ++ host->saved_tune_para.iocon = readl(host->base + MSDC_IOCON); ++ host->saved_tune_para.pad_tune = readl(host->base + tune_reg); + dev_dbg(host->dev, "init hardware done!"); + } + +@@ -1480,7 +1524,7 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode) + final_fall_delay.final_phase); + final_delay = final_fall_delay.final_phase; + } +- if (host->hs200_cmd_int_delay) ++ if (host->dev_comp->async_fifo || host->hs200_cmd_int_delay) + goto skip_internal; + + for (i = 0; i < PAD_DELAY_MAX; i++) { +@@ -1638,6 +1682,8 @@ static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) + host->hs400_mode = true; + + writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); ++ /* hs400 mode must set it to 0 */ ++ sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS); + return 0; + } + +@@ -1876,6 +1922,7 @@ static void msdc_save_reg(struct msdc_host *host) + host->save_para.pad_tune = readl(host->base + tune_reg); + host->save_para.patch_bit0 = readl(host->base + MSDC_PATCH_BIT); + host->save_para.patch_bit1 = readl(host->base + MSDC_PATCH_BIT1); ++ host->save_para.patch_bit2 = readl(host->base + MSDC_PATCH_BIT2); + host->save_para.pad_ds_tune = readl(host->base + PAD_DS_TUNE); + host->save_para.pad_cmd_tune = readl(host->base + PAD_CMD_TUNE); + host->save_para.emmc50_cfg0 = readl(host->base + EMMC50_CFG0); +@@ -1891,6 +1938,7 @@ static void msdc_restore_reg(struct msdc_host *host) + writel(host->save_para.pad_tune, host->base + tune_reg); + writel(host->save_para.patch_bit0, host->base + MSDC_PATCH_BIT); + writel(host->save_para.patch_bit1, host->base + MSDC_PATCH_BIT1); ++ writel(host->save_para.patch_bit2, host->base + MSDC_PATCH_BIT2); + writel(host->save_para.pad_ds_tune, host->base + PAD_DS_TUNE); + writel(host->save_para.pad_cmd_tune, host->base + PAD_CMD_TUNE); + writel(host->save_para.emmc50_cfg0, host->base + EMMC50_CFG0); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0155-mmc-mediatek-add-busy_check-support.patch b/target/linux/mediatek/patches-4.14/0155-mmc-mediatek-add-busy_check-support.patch new file mode 100644 index 0000000000..1e7aa7e7d7 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0155-mmc-mediatek-add-busy_check-support.patch @@ -0,0 +1,72 @@ +From 788d269aee4c612d5cd97b896ea5d22f19137097 Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:34 +0800 +Subject: [PATCH 155/224] mmc: mediatek: add busy_check support + +bit7 of PATCH_BIT1 has different meaning in new design, to +compatible with previous platform, clear this bit in new +platform. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index 8113bacc1540..eceaee86ba4d 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -316,6 +316,7 @@ struct mtk_mmc_compatible { + u32 pad_tune_reg; + bool async_fifo; + bool data_tune; ++ bool busy_check; + }; + + struct msdc_tune_para { +@@ -380,6 +381,7 @@ static const struct mtk_mmc_compatible mt8135_compat = { + .pad_tune_reg = MSDC_PAD_TUNE, + .async_fifo = false, + .data_tune = false, ++ .busy_check = false, + }; + + static const struct mtk_mmc_compatible mt8173_compat = { +@@ -388,6 +390,7 @@ static const struct mtk_mmc_compatible mt8173_compat = { + .pad_tune_reg = MSDC_PAD_TUNE, + .async_fifo = false, + .data_tune = false, ++ .busy_check = false, + }; + + static const struct mtk_mmc_compatible mt2701_compat = { +@@ -396,6 +399,7 @@ static const struct mtk_mmc_compatible mt2701_compat = { + .pad_tune_reg = MSDC_PAD_TUNE0, + .async_fifo = true, + .data_tune = true, ++ .busy_check = false, + }; + + static const struct mtk_mmc_compatible mt2712_compat = { +@@ -404,6 +408,7 @@ static const struct mtk_mmc_compatible mt2712_compat = { + .pad_tune_reg = MSDC_PAD_TUNE0, + .async_fifo = true, + .data_tune = true, ++ .busy_check = true, + }; + + static const struct of_device_id msdc_of_ids[] = { +@@ -1275,6 +1280,8 @@ static void msdc_init_hw(struct msdc_host *host) + sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1); + writel(0xffff4089, host->base + MSDC_PATCH_BIT1); + sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL); ++ if (host->dev_comp->busy_check) ++ sdr_clr_bits(host->base + MSDC_PATCH_BIT1, (1 << 7)); + if (host->dev_comp->async_fifo) { + sdr_set_field(host->base + MSDC_PATCH_BIT2, + MSDC_PB2_RESPWAIT, 3); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0156-mmc-mediatek-add-stop_clk-fix-and-enhance_rx-support.patch b/target/linux/mediatek/patches-4.14/0156-mmc-mediatek-add-stop_clk-fix-and-enhance_rx-support.patch new file mode 100644 index 0000000000..04c4ca5216 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0156-mmc-mediatek-add-stop_clk-fix-and-enhance_rx-support.patch @@ -0,0 +1,173 @@ +From 9257240bcaf8f9ee6878357e00e7ab511ad6d325 Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:35 +0800 +Subject: [PATCH 156/224] mmc: mediatek: add stop_clk fix and enhance_rx + support + +mt2712 supports stop_clk fix and enhance_rx, which can improve +host stability. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 43 insertions(+), 4 deletions(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index eceaee86ba4d..94d16a3a8d94 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -67,6 +67,7 @@ + #define SDC_RESP2 0x48 + #define SDC_RESP3 0x4c + #define SDC_BLK_NUM 0x50 ++#define SDC_ADV_CFG0 0x64 + #define EMMC_IOCON 0x7c + #define SDC_ACMD_RESP 0x80 + #define MSDC_DMA_SA 0x90 +@@ -80,6 +81,7 @@ + #define PAD_DS_TUNE 0x188 + #define PAD_CMD_TUNE 0x18c + #define EMMC50_CFG0 0x208 ++#define SDC_FIFO_CFG 0x228 + + /*--------------------------------------------------------------------------*/ + /* Register Mask */ +@@ -188,6 +190,9 @@ + #define SDC_STS_CMDBUSY (0x1 << 1) /* RW */ + #define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */ + ++/* SDC_ADV_CFG0 mask */ ++#define SDC_RX_ENHANCE_EN (0x1 << 20) /* RW */ ++ + /* MSDC_DMA_CTRL mask */ + #define MSDC_DMA_CTRL_START (0x1 << 0) /* W */ + #define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */ +@@ -217,6 +222,8 @@ + #define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */ + #define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ + ++#define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8) /* RW */ ++ + #define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */ + #define MSDC_PATCH_BIT2_CFGCRCSTS (0x1 << 28) /* RW */ + #define MSDC_PB2_RESPWAIT (0x3 << 2) /* RW */ +@@ -242,6 +249,9 @@ + #define EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW */ + #define EMMC50_CFG_CFCSTS_SEL (0x1 << 4) /* RW */ + ++#define SDC_FIFO_CFG_WRVALIDSEL (0x1 << 24) /* RW */ ++#define SDC_FIFO_CFG_RDVALIDSEL (0x1 << 25) /* RW */ ++ + #define REQ_CMD_EIO (0x1 << 0) + #define REQ_CMD_TMO (0x1 << 1) + #define REQ_DAT_ERR (0x1 << 2) +@@ -308,6 +318,7 @@ struct msdc_save_para { + u32 pad_ds_tune; + u32 pad_cmd_tune; + u32 emmc50_cfg0; ++ u32 sdc_fifo_cfg; + }; + + struct mtk_mmc_compatible { +@@ -317,6 +328,8 @@ struct mtk_mmc_compatible { + bool async_fifo; + bool data_tune; + bool busy_check; ++ bool stop_clk_fix; ++ bool enhance_rx; + }; + + struct msdc_tune_para { +@@ -382,6 +395,8 @@ static const struct mtk_mmc_compatible mt8135_compat = { + .async_fifo = false, + .data_tune = false, + .busy_check = false, ++ .stop_clk_fix = false, ++ .enhance_rx = false, + }; + + static const struct mtk_mmc_compatible mt8173_compat = { +@@ -391,6 +406,8 @@ static const struct mtk_mmc_compatible mt8173_compat = { + .async_fifo = false, + .data_tune = false, + .busy_check = false, ++ .stop_clk_fix = false, ++ .enhance_rx = false, + }; + + static const struct mtk_mmc_compatible mt2701_compat = { +@@ -400,6 +417,8 @@ static const struct mtk_mmc_compatible mt2701_compat = { + .async_fifo = true, + .data_tune = true, + .busy_check = false, ++ .stop_clk_fix = false, ++ .enhance_rx = false, + }; + + static const struct mtk_mmc_compatible mt2712_compat = { +@@ -409,6 +428,8 @@ static const struct mtk_mmc_compatible mt2712_compat = { + .async_fifo = true, + .data_tune = true, + .busy_check = true, ++ .stop_clk_fix = true, ++ .enhance_rx = true, + }; + + static const struct of_device_id msdc_of_ids[] = { +@@ -1280,15 +1301,31 @@ static void msdc_init_hw(struct msdc_host *host) + sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1); + writel(0xffff4089, host->base + MSDC_PATCH_BIT1); + sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL); ++ ++ if (host->dev_comp->stop_clk_fix) { ++ sdr_set_field(host->base + MSDC_PATCH_BIT1, ++ MSDC_PATCH_BIT1_STOP_DLY, 3); ++ sdr_clr_bits(host->base + SDC_FIFO_CFG, ++ SDC_FIFO_CFG_WRVALIDSEL); ++ sdr_clr_bits(host->base + SDC_FIFO_CFG, ++ SDC_FIFO_CFG_RDVALIDSEL); ++ } ++ + if (host->dev_comp->busy_check) + sdr_clr_bits(host->base + MSDC_PATCH_BIT1, (1 << 7)); ++ + if (host->dev_comp->async_fifo) { + sdr_set_field(host->base + MSDC_PATCH_BIT2, + MSDC_PB2_RESPWAIT, 3); +- sdr_set_field(host->base + MSDC_PATCH_BIT2, +- MSDC_PB2_RESPSTSENSEL, 2); +- sdr_set_field(host->base + MSDC_PATCH_BIT2, +- MSDC_PB2_CRCSTSENSEL, 2); ++ if (host->dev_comp->enhance_rx) { ++ sdr_set_bits(host->base + SDC_ADV_CFG0, ++ SDC_RX_ENHANCE_EN); ++ } else { ++ sdr_set_field(host->base + MSDC_PATCH_BIT2, ++ MSDC_PB2_RESPSTSENSEL, 2); ++ sdr_set_field(host->base + MSDC_PATCH_BIT2, ++ MSDC_PB2_CRCSTSENSEL, 2); ++ } + /* use async fifo, then no need tune internal delay */ + sdr_clr_bits(host->base + MSDC_PATCH_BIT2, + MSDC_PATCH_BIT2_CFGRESP); +@@ -1933,6 +1970,7 @@ static void msdc_save_reg(struct msdc_host *host) + host->save_para.pad_ds_tune = readl(host->base + PAD_DS_TUNE); + host->save_para.pad_cmd_tune = readl(host->base + PAD_CMD_TUNE); + host->save_para.emmc50_cfg0 = readl(host->base + EMMC50_CFG0); ++ host->save_para.sdc_fifo_cfg = readl(host->base + SDC_FIFO_CFG); + } + + static void msdc_restore_reg(struct msdc_host *host) +@@ -1949,6 +1987,7 @@ static void msdc_restore_reg(struct msdc_host *host) + writel(host->save_para.pad_ds_tune, host->base + PAD_DS_TUNE); + writel(host->save_para.pad_cmd_tune, host->base + PAD_CMD_TUNE); + writel(host->save_para.emmc50_cfg0, host->base + EMMC50_CFG0); ++ writel(host->save_para.sdc_fifo_cfg, host->base + SDC_FIFO_CFG); + } + + static int msdc_runtime_suspend(struct device *dev) +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch b/target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch new file mode 100644 index 0000000000..89cb7c8617 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0157-mmc-mediatek-add-support-of-source_cg-clock.patch @@ -0,0 +1,90 @@ +From 3c6b94d7091f0793445f2faf777e584af643e9da Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:36 +0800 +Subject: [PATCH 157/224] mmc: mediatek: add support of source_cg clock + +source clock need an independent cg to control, when doing clk mode +switch, need gate source clock to avoid hw issue(multi-bit sync hw hang) + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index 94d16a3a8d94..a2f26c9b17b4 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -372,6 +372,7 @@ struct msdc_host { + + struct clk *src_clk; /* msdc source clock */ + struct clk *h_clk; /* msdc h_clk */ ++ struct clk *src_clk_cg; /* msdc source clock control gate */ + u32 mclk; /* mmc subsystem clock frequency */ + u32 src_clk_freq; /* source clock frequency */ + u32 sclk; /* SD/MS bus clock frequency */ +@@ -616,6 +617,7 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) + + static void msdc_gate_clock(struct msdc_host *host) + { ++ clk_disable_unprepare(host->src_clk_cg); + clk_disable_unprepare(host->src_clk); + clk_disable_unprepare(host->h_clk); + } +@@ -624,6 +626,7 @@ static void msdc_ungate_clock(struct msdc_host *host) + { + clk_prepare_enable(host->h_clk); + clk_prepare_enable(host->src_clk); ++ clk_prepare_enable(host->src_clk_cg); + while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) + cpu_relax(); + } +@@ -692,6 +695,15 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + sclk = (host->src_clk_freq >> 2) / div; + } + } ++ sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN); ++ /* ++ * As src_clk/HCLK use the same bit to gate/ungate, ++ * So if want to only gate src_clk, need gate its parent(mux). ++ */ ++ if (host->src_clk_cg) ++ clk_disable_unprepare(host->src_clk_cg); ++ else ++ clk_disable_unprepare(clk_get_parent(host->src_clk)); + if (host->dev_comp->clk_div_bits == 8) + sdr_set_field(host->base + MSDC_CFG, + MSDC_CFG_CKMOD | MSDC_CFG_CKDIV, +@@ -700,10 +712,14 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + sdr_set_field(host->base + MSDC_CFG, + MSDC_CFG_CKMOD_EXTRA | MSDC_CFG_CKDIV_EXTRA, + (mode << 12) | div); ++ if (host->src_clk_cg) ++ clk_prepare_enable(host->src_clk_cg); ++ else ++ clk_prepare_enable(clk_get_parent(host->src_clk)); + +- sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN); + while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) + cpu_relax(); ++ sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN); + host->sclk = sclk; + host->mclk = hz; + host->timing = timing; +@@ -1822,6 +1838,11 @@ static int msdc_drv_probe(struct platform_device *pdev) + goto host_free; + } + ++ /*source clock control gate is optional clock*/ ++ host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg"); ++ if (IS_ERR(host->src_clk_cg)) ++ host->src_clk_cg = NULL; ++ + host->irq = platform_get_irq(pdev, 0); + if (host->irq < 0) { + ret = -EINVAL; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0158-mmc-mediatek-add-latch-ck-support.patch b/target/linux/mediatek/patches-4.14/0158-mmc-mediatek-add-latch-ck-support.patch new file mode 100644 index 0000000000..c2c00e8712 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0158-mmc-mediatek-add-latch-ck-support.patch @@ -0,0 +1,50 @@ +From de14d1d0dc7ecf5c3e7e2a591b4f14e688fa52e6 Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:37 +0800 +Subject: [PATCH 158/224] mmc: mediatek: add latch-ck support + +some platform(eg.mt2701) does not support "stop clk fix", in +this case, need set correct latch-ck to avoid crc error caused +by stop clock block-internally. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index a2f26c9b17b4..d75a93d6803f 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -378,6 +378,7 @@ struct msdc_host { + u32 sclk; /* SD/MS bus clock frequency */ + unsigned char timing; + bool vqmmc_enabled; ++ u32 latch_ck; + u32 hs400_ds_delay; + u32 hs200_cmd_int_delay; /* cmd internal delay for HS200/SDR104 */ + u32 hs400_cmd_int_delay; /* cmd internal delay for HS400 */ +@@ -1661,6 +1662,8 @@ static int msdc_tune_data(struct mmc_host *mmc, u32 opcode) + u32 tune_reg = host->dev_comp->pad_tune_reg; + int i, ret; + ++ sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_INT_DAT_LATCH_CK_SEL, ++ host->latch_ck); + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_DSPL); + sdr_clr_bits(host->base + MSDC_IOCON, MSDC_IOCON_W_DSPL); + for (i = 0 ; i < PAD_DELAY_MAX; i++) { +@@ -1773,6 +1776,9 @@ static const struct mmc_host_ops mt_msdc_ops = { + static void msdc_of_property_parse(struct platform_device *pdev, + struct msdc_host *host) + { ++ of_property_read_u32(pdev->dev.of_node, "mediatek,latch-ck", ++ &host->latch_ck); ++ + of_property_read_u32(pdev->dev.of_node, "hs400-ds-delay", + &host->hs400_ds_delay); + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0159-mmc-mediatek-improve-eMMC-hs400-mode-read-performanc.patch b/target/linux/mediatek/patches-4.14/0159-mmc-mediatek-improve-eMMC-hs400-mode-read-performanc.patch new file mode 100644 index 0000000000..9fd4f553ec --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0159-mmc-mediatek-improve-eMMC-hs400-mode-read-performanc.patch @@ -0,0 +1,73 @@ +From 29e154716049310bb8c559f742bf2b460d5b6bbc Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:38 +0800 +Subject: [PATCH 159/224] mmc: mediatek: improve eMMC hs400 mode read + performance + +enlarge outstanding value to improve read performance + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index d75a93d6803f..95759bba0dd0 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -81,6 +81,7 @@ + #define PAD_DS_TUNE 0x188 + #define PAD_CMD_TUNE 0x18c + #define EMMC50_CFG0 0x208 ++#define EMMC50_CFG3 0x220 + #define SDC_FIFO_CFG 0x228 + + /*--------------------------------------------------------------------------*/ +@@ -249,6 +250,8 @@ + #define EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW */ + #define EMMC50_CFG_CFCSTS_SEL (0x1 << 4) /* RW */ + ++#define EMMC50_CFG3_OUTS_WR (0x1f << 0) /* RW */ ++ + #define SDC_FIFO_CFG_WRVALIDSEL (0x1 << 24) /* RW */ + #define SDC_FIFO_CFG_RDVALIDSEL (0x1 << 25) /* RW */ + +@@ -318,6 +321,7 @@ struct msdc_save_para { + u32 pad_ds_tune; + u32 pad_cmd_tune; + u32 emmc50_cfg0; ++ u32 emmc50_cfg3; + u32 sdc_fifo_cfg; + }; + +@@ -1747,6 +1751,9 @@ static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) + writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); + /* hs400 mode must set it to 0 */ + sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS); ++ /* to improve read performance, set outstanding to 2 */ ++ sdr_set_field(host->base + EMMC50_CFG3, EMMC50_CFG3_OUTS_WR, 2); ++ + return 0; + } + +@@ -1997,6 +2004,7 @@ static void msdc_save_reg(struct msdc_host *host) + host->save_para.pad_ds_tune = readl(host->base + PAD_DS_TUNE); + host->save_para.pad_cmd_tune = readl(host->base + PAD_CMD_TUNE); + host->save_para.emmc50_cfg0 = readl(host->base + EMMC50_CFG0); ++ host->save_para.emmc50_cfg3 = readl(host->base + EMMC50_CFG3); + host->save_para.sdc_fifo_cfg = readl(host->base + SDC_FIFO_CFG); + } + +@@ -2014,6 +2022,7 @@ static void msdc_restore_reg(struct msdc_host *host) + writel(host->save_para.pad_ds_tune, host->base + PAD_DS_TUNE); + writel(host->save_para.pad_cmd_tune, host->base + PAD_CMD_TUNE); + writel(host->save_para.emmc50_cfg0, host->base + EMMC50_CFG0); ++ writel(host->save_para.emmc50_cfg3, host->base + EMMC50_CFG3); + writel(host->save_para.sdc_fifo_cfg, host->base + SDC_FIFO_CFG); + } + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0160-mmc-mediatek-perfer-to-use-rise-edge-latching-for-cm.patch b/target/linux/mediatek/patches-4.14/0160-mmc-mediatek-perfer-to-use-rise-edge-latching-for-cm.patch new file mode 100644 index 0000000000..c34bf12445 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0160-mmc-mediatek-perfer-to-use-rise-edge-latching-for-cm.patch @@ -0,0 +1,33 @@ +From 81fdc4983e33ef01935a9bf01187951aad34e2ac Mon Sep 17 00:00:00 2001 +From: Chaotian Jing <chaotian.jing@mediatek.com> +Date: Mon, 16 Oct 2017 09:46:39 +0800 +Subject: [PATCH 160/224] mmc: mediatek: perfer to use rise edge latching for + cmd line + +data lines have applied to perfer to use rise edge, also need +apply it to cmd line. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Tested-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + drivers/mmc/host/mtk-sd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index 95759bba0dd0..27a62254f12f 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -1550,7 +1550,8 @@ static int msdc_tune_response(struct mmc_host *mmc, u32 opcode) + } + final_rise_delay = get_best_delay(host, rise_delay); + /* if rising edge has enough margin, then do not scan falling edge */ +- if (final_rise_delay.maxlen >= 12 && final_rise_delay.start < 4) ++ if (final_rise_delay.maxlen >= 12 || ++ (final_rise_delay.start == 0 && final_rise_delay.maxlen >= 4)) + goto skip_fall; + + sdr_set_bits(host->base + MSDC_IOCON, MSDC_IOCON_RSPL); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0161-pwm-mediatek-Add-MT2712-MT7622-support.patch b/target/linux/mediatek/patches-4.14/0161-pwm-mediatek-Add-MT2712-MT7622-support.patch new file mode 100644 index 0000000000..2d91ab98a9 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0161-pwm-mediatek-Add-MT2712-MT7622-support.patch @@ -0,0 +1,150 @@ +From 7cc8226e45b2c6b9f06ce82ba6995b8f911afe25 Mon Sep 17 00:00:00 2001 +From: Zhi Mao <zhi.mao@mediatek.com> +Date: Wed, 25 Oct 2017 18:11:01 +0800 +Subject: [PATCH 161/224] pwm: mediatek: Add MT2712/MT7622 support + +Add support for MT2712 and MT7622. Due to register offset address of +pwm7 for MT2712 is not fixed 0x40, add mtk_pwm_reg_offset array for PWM +register offset. + +Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Zhi Mao <zhi.mao@mediatek.com> +Signed-off-by: Thierry Reding <thierry.reding@gmail.com> +--- + drivers/pwm/pwm-mediatek.c | 53 ++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 44 insertions(+), 9 deletions(-) + +diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c +index b52f3afb2ba1..f5d97e0ad52b 100644 +--- a/drivers/pwm/pwm-mediatek.c ++++ b/drivers/pwm/pwm-mediatek.c +@@ -16,6 +16,7 @@ + #include <linux/module.h> + #include <linux/clk.h> + #include <linux/of.h> ++#include <linux/of_device.h> + #include <linux/platform_device.h> + #include <linux/pwm.h> + #include <linux/slab.h> +@@ -40,11 +41,19 @@ enum { + MTK_CLK_PWM3, + MTK_CLK_PWM4, + MTK_CLK_PWM5, ++ MTK_CLK_PWM6, ++ MTK_CLK_PWM7, ++ MTK_CLK_PWM8, + MTK_CLK_MAX, + }; + +-static const char * const mtk_pwm_clk_name[] = { +- "main", "top", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5" ++static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = { ++ "main", "top", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7", ++ "pwm8" ++}; ++ ++struct mtk_pwm_platform_data { ++ unsigned int num_pwms; + }; + + /** +@@ -59,6 +68,10 @@ struct mtk_pwm_chip { + struct clk *clks[MTK_CLK_MAX]; + }; + ++static const unsigned int mtk_pwm_reg_offset[] = { ++ 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220 ++}; ++ + static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) + { + return container_of(chip, struct mtk_pwm_chip, chip); +@@ -103,14 +116,14 @@ static void mtk_pwm_clk_disable(struct pwm_chip *chip, struct pwm_device *pwm) + static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, + unsigned int offset) + { +- return readl(chip->regs + 0x10 + (num * 0x40) + offset); ++ return readl(chip->regs + mtk_pwm_reg_offset[num] + offset); + } + + static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, + unsigned int num, unsigned int offset, + u32 value) + { +- writel(value, chip->regs + 0x10 + (num * 0x40) + offset); ++ writel(value, chip->regs + mtk_pwm_reg_offset[num] + offset); + } + + static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, +@@ -185,6 +198,7 @@ static const struct pwm_ops mtk_pwm_ops = { + + static int mtk_pwm_probe(struct platform_device *pdev) + { ++ const struct mtk_pwm_platform_data *data; + struct mtk_pwm_chip *pc; + struct resource *res; + unsigned int i; +@@ -194,15 +208,22 @@ static int mtk_pwm_probe(struct platform_device *pdev) + if (!pc) + return -ENOMEM; + ++ data = of_device_get_match_data(&pdev->dev); ++ if (data == NULL) ++ return -EINVAL; ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pc->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pc->regs)) + return PTR_ERR(pc->regs); + +- for (i = 0; i < MTK_CLK_MAX; i++) { ++ for (i = 0; i < data->num_pwms + 2; i++) { + pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]); +- if (IS_ERR(pc->clks[i])) ++ if (IS_ERR(pc->clks[i])) { ++ dev_err(&pdev->dev, "clock: %s fail: %ld\n", ++ mtk_pwm_clk_name[i], PTR_ERR(pc->clks[i])); + return PTR_ERR(pc->clks[i]); ++ } + } + + platform_set_drvdata(pdev, pc); +@@ -210,7 +231,7 @@ static int mtk_pwm_probe(struct platform_device *pdev) + pc->chip.dev = &pdev->dev; + pc->chip.ops = &mtk_pwm_ops; + pc->chip.base = -1; +- pc->chip.npwm = 5; ++ pc->chip.npwm = data->num_pwms; + + ret = pwmchip_add(&pc->chip); + if (ret < 0) { +@@ -228,9 +249,23 @@ static int mtk_pwm_remove(struct platform_device *pdev) + return pwmchip_remove(&pc->chip); + } + ++static const struct mtk_pwm_platform_data mt2712_pwm_data = { ++ .num_pwms = 8, ++}; ++ ++static const struct mtk_pwm_platform_data mt7622_pwm_data = { ++ .num_pwms = 6, ++}; ++ ++static const struct mtk_pwm_platform_data mt7623_pwm_data = { ++ .num_pwms = 5, ++}; ++ + static const struct of_device_id mtk_pwm_of_match[] = { +- { .compatible = "mediatek,mt7623-pwm" }, +- { } ++ { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data }, ++ { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data }, ++ { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data }, ++ { }, + }; + MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0162-mtd-nand-mtk-use-nand_reset-to-reset-NAND-devices-in.patch b/target/linux/mediatek/patches-4.14/0162-mtd-nand-mtk-use-nand_reset-to-reset-NAND-devices-in.patch new file mode 100644 index 0000000000..df2bd3056f --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0162-mtd-nand-mtk-use-nand_reset-to-reset-NAND-devices-in.patch @@ -0,0 +1,46 @@ +From fb607c7c1eaeb47ec2ffed99cab571892cb6af7d Mon Sep 17 00:00:00 2001 +From: Xiaolei Li <xiaolei.li@mediatek.com> +Date: Thu, 2 Nov 2017 10:05:07 +0800 +Subject: [PATCH 162/224] mtd: nand: mtk: use nand_reset() to reset NAND + devices in resume function + +Previously, we only select chips and then send reset command to a NAND +device during resuming nand driver. There is a lack of deselecting chips. +It is advised to reset and initialize a NAND device using nand_reset(). + +Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> +--- + drivers/mtd/nand/mtk_nand.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c +index d86a7d131cc0..6d0101e13ef6 100644 +--- a/drivers/mtd/nand/mtk_nand.c ++++ b/drivers/mtd/nand/mtk_nand.c +@@ -1540,7 +1540,6 @@ static int mtk_nfc_resume(struct device *dev) + struct mtk_nfc *nfc = dev_get_drvdata(dev); + struct mtk_nfc_nand_chip *chip; + struct nand_chip *nand; +- struct mtd_info *mtd; + int ret; + u32 i; + +@@ -1553,11 +1552,8 @@ static int mtk_nfc_resume(struct device *dev) + /* reset NAND chip if VCC was powered off */ + list_for_each_entry(chip, &nfc->chips, node) { + nand = &chip->nand; +- mtd = nand_to_mtd(nand); +- for (i = 0; i < chip->nsels; i++) { +- nand->select_chip(mtd, i); +- nand->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); +- } ++ for (i = 0; i < chip->nsels; i++) ++ nand_reset(nand, i); + } + + return 0; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0164-cpufreq-mediatek-add-mt2712-into-compatible-list.patch b/target/linux/mediatek/patches-4.14/0164-cpufreq-mediatek-add-mt2712-into-compatible-list.patch new file mode 100644 index 0000000000..f44eabfe7c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0164-cpufreq-mediatek-add-mt2712-into-compatible-list.patch @@ -0,0 +1,29 @@ +From f027d8b7248cef5b3d3eb8ac68e1040fba340995 Mon Sep 17 00:00:00 2001 +From: Andrew-sh Cheng <andrew-sh.cheng@mediatek.com> +Date: Fri, 8 Dec 2017 14:07:55 +0800 +Subject: [PATCH 164/224] cpufreq: mediatek: add mt2712 into compatible list + +Support mt2712 in mediatek-cpufreq.c + +Signed-off-by: Andrew-sh Cheng <andrew-sh.cheng@mediatek.com> +Acked-by: Viresh Kumar <viresh.kumar@linaro.org> +Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +--- + drivers/cpufreq/mediatek-cpufreq.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c +index 18c4bd9a5c65..62aec5cdbb26 100644 +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -574,6 +574,7 @@ static struct platform_driver mtk_cpufreq_platdrv = { + /* List of machines supported by this driver */ + static const struct of_device_id mtk_cpufreq_machines[] __initconst = { + { .compatible = "mediatek,mt2701", }, ++ { .compatible = "mediatek,mt2712", }, + { .compatible = "mediatek,mt7622", }, + { .compatible = "mediatek,mt7623", }, + { .compatible = "mediatek,mt817x", }, +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0165-mtd-nand-mtk-update-DT-bindings.patch b/target/linux/mediatek/patches-4.14/0165-mtd-nand-mtk-update-DT-bindings.patch new file mode 100644 index 0000000000..d60383eadd --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0165-mtd-nand-mtk-update-DT-bindings.patch @@ -0,0 +1,46 @@ +From 42611c6d9f12d16ce4247d76b16218e54ef5b949 Mon Sep 17 00:00:00 2001 +From: RogerCC Lin <rogercc.lin@mediatek.com> +Date: Thu, 30 Nov 2017 22:10:43 +0800 +Subject: [PATCH 165/224] mtd: nand: mtk: update DT bindings + +Add MT7622 NAND Flash Controller dt bindings documentation. + +Signed-off-by: RogerCC Lin <rogercc.lin@mediatek.com> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> +--- + Documentation/devicetree/bindings/mtd/mtk-nand.txt | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt +index dbf9e054c11c..0025bc4c94a0 100644 +--- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt ++++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt +@@ -12,8 +12,10 @@ tree nodes. + + The first part of NFC is NAND Controller Interface (NFI) HW. + Required NFI properties: +-- compatible: Should be one of "mediatek,mt2701-nfc", +- "mediatek,mt2712-nfc". ++- compatible: Should be one of ++ "mediatek,mt2701-nfc", ++ "mediatek,mt2712-nfc", ++ "mediatek,mt7622-nfc". + - reg: Base physical address and size of NFI. + - interrupts: Interrupts of NFI. + - clocks: NFI required clocks. +@@ -142,7 +144,10 @@ Example: + ============== + + Required BCH properties: +-- compatible: Should be one of "mediatek,mt2701-ecc", "mediatek,mt2712-ecc". ++- compatible: Should be one of ++ "mediatek,mt2701-ecc", ++ "mediatek,mt2712-ecc", ++ "mediatek,mt7622-ecc". + - reg: Base physical address and size of ECC. + - interrupts: Interrupts of ECC. + - clocks: ECC required clocks. +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0166-mtd-nand-mtk-Support-different-MTK-NAND-flash-contro.patch b/target/linux/mediatek/patches-4.14/0166-mtd-nand-mtk-Support-different-MTK-NAND-flash-contro.patch new file mode 100644 index 0000000000..b890a8d766 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0166-mtd-nand-mtk-Support-different-MTK-NAND-flash-contro.patch @@ -0,0 +1,389 @@ +From fd1a1eabf2473e769b5cafc704e0336d11f61961 Mon Sep 17 00:00:00 2001 +From: RogerCC Lin <rogercc.lin@mediatek.com> +Date: Thu, 30 Nov 2017 22:10:44 +0800 +Subject: [PATCH 166/224] mtd: nand: mtk: Support different MTK NAND flash + controller IP + +MT7622 uses an MTK's earlier NAND flash controller IP which support +different sector size, max spare size per sector and paraity bits..., +some register's offset and definition also been changed in the NAND +flash controller, this patch is the preparation to support MT7622 +NAND flash controller. + +MT7622 NFC and ECC engine are similar to MT2701's, except below +differences: +(1)MT7622 NFC's max sector size(ECC data size) is 512 bytes, and + MT2701's is 1024, and MT7622's max sector number is 8. +(2)The parity bit of MT7622 is 13, MT2701 is 14. +(3)MT7622 ECC supports less ECC strength, max to 16 bit ecc strength. +(4)MT7622 supports less spare size per sector, max spare size per + sector is 28 bytes. +(5)Some register's offset are different, include ECC_ENCIRQ_EN, + ECC_ENCIRQ_STA, ECC_DECDONE, ECC_DECIRQ_EN and ECC_DECIRQ_STA. +(6)ENC_MODE of ECC_ENCCNFG register is moved from bit 5-6 to bit 4-5. + +Signed-off-by: RogerCC Lin <rogercc.lin@mediatek.com> +Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> +--- + drivers/mtd/nand/mtk_ecc.c | 100 ++++++++++++++++++++++++++++++-------------- + drivers/mtd/nand/mtk_ecc.h | 3 +- + drivers/mtd/nand/mtk_nand.c | 27 ++++++++---- + 3 files changed, 89 insertions(+), 41 deletions(-) + +diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c +index c51d214d169e..6610eefaa92b 100644 +--- a/drivers/mtd/nand/mtk_ecc.c ++++ b/drivers/mtd/nand/mtk_ecc.c +@@ -34,34 +34,28 @@ + + #define ECC_ENCCON (0x00) + #define ECC_ENCCNFG (0x04) +-#define ECC_MODE_SHIFT (5) + #define ECC_MS_SHIFT (16) + #define ECC_ENCDIADDR (0x08) + #define ECC_ENCIDLE (0x0C) +-#define ECC_ENCIRQ_EN (0x80) +-#define ECC_ENCIRQ_STA (0x84) + #define ECC_DECCON (0x100) + #define ECC_DECCNFG (0x104) + #define DEC_EMPTY_EN BIT(31) + #define DEC_CNFG_CORRECT (0x3 << 12) + #define ECC_DECIDLE (0x10C) + #define ECC_DECENUM0 (0x114) +-#define ECC_DECDONE (0x124) +-#define ECC_DECIRQ_EN (0x200) +-#define ECC_DECIRQ_STA (0x204) + + #define ECC_TIMEOUT (500000) + + #define ECC_IDLE_REG(op) ((op) == ECC_ENCODE ? ECC_ENCIDLE : ECC_DECIDLE) + #define ECC_CTL_REG(op) ((op) == ECC_ENCODE ? ECC_ENCCON : ECC_DECCON) +-#define ECC_IRQ_REG(op) ((op) == ECC_ENCODE ? \ +- ECC_ENCIRQ_EN : ECC_DECIRQ_EN) + + struct mtk_ecc_caps { + u32 err_mask; + const u8 *ecc_strength; ++ const u32 *ecc_regs; + u8 num_ecc_strength; +- u32 encode_parity_reg0; ++ u8 ecc_mode_shift; ++ u32 parity_bits; + int pg_irq_sel; + }; + +@@ -89,6 +83,33 @@ static const u8 ecc_strength_mt2712[] = { + 40, 44, 48, 52, 56, 60, 68, 72, 80 + }; + ++enum mtk_ecc_regs { ++ ECC_ENCPAR00, ++ ECC_ENCIRQ_EN, ++ ECC_ENCIRQ_STA, ++ ECC_DECDONE, ++ ECC_DECIRQ_EN, ++ ECC_DECIRQ_STA, ++}; ++ ++static int mt2701_ecc_regs[] = { ++ [ECC_ENCPAR00] = 0x10, ++ [ECC_ENCIRQ_EN] = 0x80, ++ [ECC_ENCIRQ_STA] = 0x84, ++ [ECC_DECDONE] = 0x124, ++ [ECC_DECIRQ_EN] = 0x200, ++ [ECC_DECIRQ_STA] = 0x204, ++}; ++ ++static int mt2712_ecc_regs[] = { ++ [ECC_ENCPAR00] = 0x300, ++ [ECC_ENCIRQ_EN] = 0x80, ++ [ECC_ENCIRQ_STA] = 0x84, ++ [ECC_DECDONE] = 0x124, ++ [ECC_DECIRQ_EN] = 0x200, ++ [ECC_DECIRQ_STA] = 0x204, ++}; ++ + static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + enum mtk_ecc_operation op) + { +@@ -107,32 +128,30 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + static irqreturn_t mtk_ecc_irq(int irq, void *id) + { + struct mtk_ecc *ecc = id; +- enum mtk_ecc_operation op; + u32 dec, enc; + +- dec = readw(ecc->regs + ECC_DECIRQ_STA) & ECC_IRQ_EN; ++ dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA]) ++ & ECC_IRQ_EN; + if (dec) { +- op = ECC_DECODE; +- dec = readw(ecc->regs + ECC_DECDONE); ++ dec = readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]); + if (dec & ecc->sectors) { + /* + * Clear decode IRQ status once again to ensure that + * there will be no extra IRQ. + */ +- readw(ecc->regs + ECC_DECIRQ_STA); ++ readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_STA]); + ecc->sectors = 0; + complete(&ecc->done); + } else { + return IRQ_HANDLED; + } + } else { +- enc = readl(ecc->regs + ECC_ENCIRQ_STA) & ECC_IRQ_EN; +- if (enc) { +- op = ECC_ENCODE; ++ enc = readl(ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_STA]) ++ & ECC_IRQ_EN; ++ if (enc) + complete(&ecc->done); +- } else { ++ else + return IRQ_NONE; +- } + } + + return IRQ_HANDLED; +@@ -160,7 +179,7 @@ static int mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + /* configure ECC encoder (in bits) */ + enc_sz = config->len << 3; + +- reg = ecc_bit | (config->mode << ECC_MODE_SHIFT); ++ reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift); + reg |= (enc_sz << ECC_MS_SHIFT); + writel(reg, ecc->regs + ECC_ENCCNFG); + +@@ -171,9 +190,9 @@ static int mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + } else { + /* configure ECC decoder (in bits) */ + dec_sz = (config->len << 3) + +- config->strength * ECC_PARITY_BITS; ++ config->strength * ecc->caps->parity_bits; + +- reg = ecc_bit | (config->mode << ECC_MODE_SHIFT); ++ reg = ecc_bit | (config->mode << ecc->caps->ecc_mode_shift); + reg |= (dec_sz << ECC_MS_SHIFT) | DEC_CNFG_CORRECT; + reg |= DEC_EMPTY_EN; + writel(reg, ecc->regs + ECC_DECCNFG); +@@ -291,7 +310,12 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config) + */ + if (ecc->caps->pg_irq_sel && config->mode == ECC_NFI_MODE) + reg_val |= ECC_PG_IRQ_SEL; +- writew(reg_val, ecc->regs + ECC_IRQ_REG(op)); ++ if (op == ECC_ENCODE) ++ writew(reg_val, ecc->regs + ++ ecc->caps->ecc_regs[ECC_ENCIRQ_EN]); ++ else ++ writew(reg_val, ecc->regs + ++ ecc->caps->ecc_regs[ECC_DECIRQ_EN]); + } + + writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op)); +@@ -310,13 +334,17 @@ void mtk_ecc_disable(struct mtk_ecc *ecc) + + /* disable it */ + mtk_ecc_wait_idle(ecc, op); +- if (op == ECC_DECODE) ++ if (op == ECC_DECODE) { + /* + * Clear decode IRQ status in case there is a timeout to wait + * decode IRQ. + */ +- readw(ecc->regs + ECC_DECIRQ_STA); +- writew(0, ecc->regs + ECC_IRQ_REG(op)); ++ readw(ecc->regs + ecc->caps->ecc_regs[ECC_DECDONE]); ++ writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_DECIRQ_EN]); ++ } else { ++ writew(0, ecc->regs + ecc->caps->ecc_regs[ECC_ENCIRQ_EN]); ++ } ++ + writew(ECC_OP_DISABLE, ecc->regs + ECC_CTL_REG(op)); + + mutex_unlock(&ecc->lock); +@@ -367,11 +395,11 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, + mtk_ecc_wait_idle(ecc, ECC_ENCODE); + + /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ +- len = (config->strength * ECC_PARITY_BITS + 7) >> 3; ++ len = (config->strength * ecc->caps->parity_bits + 7) >> 3; + + /* write the parity bytes generated by the ECC back to temp buffer */ + __ioread32_copy(ecc->eccdata, +- ecc->regs + ecc->caps->encode_parity_reg0, ++ ecc->regs + ecc->caps->ecc_regs[ECC_ENCPAR00], + round_up(len, 4)); + + /* copy into possibly unaligned OOB region with actual length */ +@@ -404,19 +432,29 @@ void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p) + } + EXPORT_SYMBOL(mtk_ecc_adjust_strength); + ++unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc) ++{ ++ return ecc->caps->parity_bits; ++} ++EXPORT_SYMBOL(mtk_ecc_get_parity_bits); ++ + static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { + .err_mask = 0x3f, + .ecc_strength = ecc_strength_mt2701, ++ .ecc_regs = mt2701_ecc_regs, + .num_ecc_strength = 20, +- .encode_parity_reg0 = 0x10, ++ .ecc_mode_shift = 5, ++ .parity_bits = 14, + .pg_irq_sel = 0, + }; + + static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { + .err_mask = 0x7f, + .ecc_strength = ecc_strength_mt2712, ++ .ecc_regs = mt2712_ecc_regs, + .num_ecc_strength = 23, +- .encode_parity_reg0 = 0x300, ++ .ecc_mode_shift = 5, ++ .parity_bits = 14, + .pg_irq_sel = 1, + }; + +@@ -452,7 +490,7 @@ static int mtk_ecc_probe(struct platform_device *pdev) + + max_eccdata_size = ecc->caps->num_ecc_strength - 1; + max_eccdata_size = ecc->caps->ecc_strength[max_eccdata_size]; +- max_eccdata_size = (max_eccdata_size * ECC_PARITY_BITS + 7) >> 3; ++ max_eccdata_size = (max_eccdata_size * ecc->caps->parity_bits + 7) >> 3; + max_eccdata_size = round_up(max_eccdata_size, 4); + ecc->eccdata = devm_kzalloc(dev, max_eccdata_size, GFP_KERNEL); + if (!ecc->eccdata) +diff --git a/drivers/mtd/nand/mtk_ecc.h b/drivers/mtd/nand/mtk_ecc.h +index d245c14f1b80..a455df080952 100644 +--- a/drivers/mtd/nand/mtk_ecc.h ++++ b/drivers/mtd/nand/mtk_ecc.h +@@ -14,8 +14,6 @@ + + #include <linux/types.h> + +-#define ECC_PARITY_BITS (14) +- + enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1}; + enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE}; + +@@ -43,6 +41,7 @@ int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation); + int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *); + void mtk_ecc_disable(struct mtk_ecc *); + void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p); ++unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc); + + struct mtk_ecc *of_mtk_ecc_get(struct device_node *); + void mtk_ecc_release(struct mtk_ecc *); +diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c +index 6d0101e13ef6..7349aa846f9a 100644 +--- a/drivers/mtd/nand/mtk_nand.c ++++ b/drivers/mtd/nand/mtk_nand.c +@@ -97,7 +97,6 @@ + + #define MTK_TIMEOUT (500000) + #define MTK_RESET_TIMEOUT (1000000) +-#define MTK_MAX_SECTOR (16) + #define MTK_NAND_MAX_NSELS (2) + #define MTK_NFC_MIN_SPARE (16) + #define ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt) \ +@@ -109,6 +108,8 @@ struct mtk_nfc_caps { + u8 num_spare_size; + u8 pageformat_spare_shift; + u8 nfi_clk_div; ++ u8 max_sector; ++ u32 max_sector_size; + }; + + struct mtk_nfc_bad_mark_ctl { +@@ -450,7 +451,7 @@ static inline u8 mtk_nfc_read_byte(struct mtd_info *mtd) + * set to max sector to allow the HW to continue reading over + * unaligned accesses + */ +- reg = (MTK_MAX_SECTOR << CON_SEC_SHIFT) | CON_BRD; ++ reg = (nfc->caps->max_sector << CON_SEC_SHIFT) | CON_BRD; + nfi_writel(nfc, reg, NFI_CON); + + /* trigger to fetch data */ +@@ -481,7 +482,7 @@ static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte) + reg = nfi_readw(nfc, NFI_CNFG) | CNFG_BYTE_RW; + nfi_writew(nfc, reg, NFI_CNFG); + +- reg = MTK_MAX_SECTOR << CON_SEC_SHIFT | CON_BWR; ++ reg = nfc->caps->max_sector << CON_SEC_SHIFT | CON_BWR; + nfi_writel(nfc, reg, NFI_CON); + + nfi_writew(nfc, STAR_EN, NFI_STRDATA); +@@ -1126,9 +1127,11 @@ static void mtk_nfc_set_fdm(struct mtk_nfc_fdm *fdm, struct mtd_info *mtd) + { + struct nand_chip *nand = mtd_to_nand(mtd); + struct mtk_nfc_nand_chip *chip = to_mtk_nand(nand); ++ struct mtk_nfc *nfc = nand_get_controller_data(nand); + u32 ecc_bytes; + +- ecc_bytes = DIV_ROUND_UP(nand->ecc.strength * ECC_PARITY_BITS, 8); ++ ecc_bytes = DIV_ROUND_UP(nand->ecc.strength * ++ mtk_ecc_get_parity_bits(nfc->ecc), 8); + + fdm->reg_size = chip->spare_per_sector - ecc_bytes; + if (fdm->reg_size > NFI_FDM_MAX_SIZE) +@@ -1208,7 +1211,8 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) + * this controller only supports 512 and 1024 sizes + */ + if (nand->ecc.size < 1024) { +- if (mtd->writesize > 512) { ++ if (mtd->writesize > 512 && ++ nfc->caps->max_sector_size > 512) { + nand->ecc.size = 1024; + nand->ecc.strength <<= 1; + } else { +@@ -1223,7 +1227,8 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) + return ret; + + /* calculate oob bytes except ecc parity data */ +- free = ((nand->ecc.strength * ECC_PARITY_BITS) + 7) >> 3; ++ free = (nand->ecc.strength * mtk_ecc_get_parity_bits(nfc->ecc) ++ + 7) >> 3; + free = spare - free; + + /* +@@ -1233,10 +1238,12 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd) + */ + if (free > NFI_FDM_MAX_SIZE) { + spare -= NFI_FDM_MAX_SIZE; +- nand->ecc.strength = (spare << 3) / ECC_PARITY_BITS; ++ nand->ecc.strength = (spare << 3) / ++ mtk_ecc_get_parity_bits(nfc->ecc); + } else if (free < 0) { + spare -= NFI_FDM_MIN_SIZE; +- nand->ecc.strength = (spare << 3) / ECC_PARITY_BITS; ++ nand->ecc.strength = (spare << 3) / ++ mtk_ecc_get_parity_bits(nfc->ecc); + } + } + +@@ -1389,6 +1396,8 @@ static const struct mtk_nfc_caps mtk_nfc_caps_mt2701 = { + .num_spare_size = 16, + .pageformat_spare_shift = 4, + .nfi_clk_div = 1, ++ .max_sector = 16, ++ .max_sector_size = 1024, + }; + + static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = { +@@ -1396,6 +1405,8 @@ static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = { + .num_spare_size = 19, + .pageformat_spare_shift = 16, + .nfi_clk_div = 2, ++ .max_sector = 16, ++ .max_sector_size = 1024, + }; + + static const struct of_device_id mtk_nfc_id_table[] = { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0167-mtd-nand-mtk-Support-MT7622-NAND-flash-controller.patch b/target/linux/mediatek/patches-4.14/0167-mtd-nand-mtk-Support-MT7622-NAND-flash-controller.patch new file mode 100644 index 0000000000..d7550ee7e8 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0167-mtd-nand-mtk-Support-MT7622-NAND-flash-controller.patch @@ -0,0 +1,116 @@ +From f395a149fbbc190afbadbdcf9ce95f85f78da22f Mon Sep 17 00:00:00 2001 +From: RogerCC Lin <rogercc.lin@mediatek.com> +Date: Thu, 30 Nov 2017 22:10:45 +0800 +Subject: [PATCH 167/224] mtd: nand: mtk: Support MT7622 NAND flash controller. + +Add tables to support MT7622 NAND flash controller. + +Signed-off-by: RogerCC Lin <rogercc.lin@mediatek.com> +Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> +--- + drivers/mtd/nand/mtk_ecc.c | 26 ++++++++++++++++++++++++++ + drivers/mtd/nand/mtk_nand.c | 16 ++++++++++++++++ + 2 files changed, 42 insertions(+) + +diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c +index 6610eefaa92b..40d86a861a70 100644 +--- a/drivers/mtd/nand/mtk_ecc.c ++++ b/drivers/mtd/nand/mtk_ecc.c +@@ -83,6 +83,10 @@ static const u8 ecc_strength_mt2712[] = { + 40, 44, 48, 52, 56, 60, 68, 72, 80 + }; + ++static const u8 ecc_strength_mt7622[] = { ++ 4, 6, 8, 10, 12, 14, 16 ++}; ++ + enum mtk_ecc_regs { + ECC_ENCPAR00, + ECC_ENCIRQ_EN, +@@ -110,6 +114,15 @@ static int mt2712_ecc_regs[] = { + [ECC_DECIRQ_STA] = 0x204, + }; + ++static int mt7622_ecc_regs[] = { ++ [ECC_ENCPAR00] = 0x10, ++ [ECC_ENCIRQ_EN] = 0x30, ++ [ECC_ENCIRQ_STA] = 0x34, ++ [ECC_DECDONE] = 0x11c, ++ [ECC_DECIRQ_EN] = 0x140, ++ [ECC_DECIRQ_STA] = 0x144, ++}; ++ + static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, + enum mtk_ecc_operation op) + { +@@ -458,6 +471,16 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { + .pg_irq_sel = 1, + }; + ++static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = { ++ .err_mask = 0x3f, ++ .ecc_strength = ecc_strength_mt7622, ++ .ecc_regs = mt7622_ecc_regs, ++ .num_ecc_strength = 7, ++ .ecc_mode_shift = 4, ++ .parity_bits = 13, ++ .pg_irq_sel = 0, ++}; ++ + static const struct of_device_id mtk_ecc_dt_match[] = { + { + .compatible = "mediatek,mt2701-ecc", +@@ -465,6 +488,9 @@ static const struct of_device_id mtk_ecc_dt_match[] = { + }, { + .compatible = "mediatek,mt2712-ecc", + .data = &mtk_ecc_caps_mt2712, ++ }, { ++ .compatible = "mediatek,mt7622-ecc", ++ .data = &mtk_ecc_caps_mt7622, + }, + {}, + }; +diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c +index 7349aa846f9a..8f71b405d639 100644 +--- a/drivers/mtd/nand/mtk_nand.c ++++ b/drivers/mtd/nand/mtk_nand.c +@@ -174,6 +174,10 @@ static const u8 spare_size_mt2712[] = { + 74 + }; + ++static const u8 spare_size_mt7622[] = { ++ 16, 26, 27, 28 ++}; ++ + static inline struct mtk_nfc_nand_chip *to_mtk_nand(struct nand_chip *nand) + { + return container_of(nand, struct mtk_nfc_nand_chip, nand); +@@ -1409,6 +1413,15 @@ static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = { + .max_sector_size = 1024, + }; + ++static const struct mtk_nfc_caps mtk_nfc_caps_mt7622 = { ++ .spare_size = spare_size_mt7622, ++ .num_spare_size = 4, ++ .pageformat_spare_shift = 4, ++ .nfi_clk_div = 1, ++ .max_sector = 8, ++ .max_sector_size = 512, ++}; ++ + static const struct of_device_id mtk_nfc_id_table[] = { + { + .compatible = "mediatek,mt2701-nfc", +@@ -1416,6 +1429,9 @@ static const struct of_device_id mtk_nfc_id_table[] = { + }, { + .compatible = "mediatek,mt2712-nfc", + .data = &mtk_nfc_caps_mt2712, ++ }, { ++ .compatible = "mediatek,mt7622-nfc", ++ .data = &mtk_nfc_caps_mt7622, + }, + {} + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0168-mmc-dt-bindings-add-mmc-support-to-MT7623-SoC.patch b/target/linux/mediatek/patches-4.14/0168-mmc-dt-bindings-add-mmc-support-to-MT7623-SoC.patch new file mode 100644 index 0000000000..c68b21fdbd --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0168-mmc-dt-bindings-add-mmc-support-to-MT7623-SoC.patch @@ -0,0 +1,31 @@ +From bb37b1aa5d1aadfcecd9189a653856099fbed507 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 7 Dec 2017 14:43:22 +0800 +Subject: [PATCH 168/224] mmc: dt-bindings: add mmc support to MT7623 SoC + +Add the devicetree binding for MT7623 SoC using MT2701 as the fallback. + +Cc: devicetree@vger.kernel.org +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +--- + Documentation/devicetree/bindings/mmc/mtk-sd.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt +index 72d2a734ab85..9b8017670870 100644 +--- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt ++++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt +@@ -12,6 +12,8 @@ Required properties: + "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 + "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 + "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 ++ "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC ++ + - reg: physical base address of the controller and length + - interrupts: Should contain MSDC interrupt number + - clocks: Should contain phandle for the clock feeding the MMC controller +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0169-dt-bindings-pinctrl-add-bindings-for-MediaTek-MT7622.patch b/target/linux/mediatek/patches-4.14/0169-dt-bindings-pinctrl-add-bindings-for-MediaTek-MT7622.patch new file mode 100644 index 0000000000..b8679be22d --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0169-dt-bindings-pinctrl-add-bindings-for-MediaTek-MT7622.patch @@ -0,0 +1,377 @@ +From 4e4c2d695a5daf6dc55b8713af720ef15b52c0e7 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Tue, 12 Dec 2017 14:24:18 +0800 +Subject: [PATCH 169/224] dt-bindings: pinctrl: add bindings for MediaTek + MT7622 SoC + +Add devicetree bindings for MediaTek MT7622 pinctrl driver. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Biao Huang <biao.huang@mediatek.com> +Acked-by: Rob Herring <robh@kernel.org> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +--- + .../devicetree/bindings/pinctrl/pinctrl-mt7622.txt | 351 +++++++++++++++++++++ + 1 file changed, 351 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt + +diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt +new file mode 100644 +index 000000000000..f18ed99f6e14 +--- /dev/null ++++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt +@@ -0,0 +1,351 @@ ++== MediaTek MT7622 pinctrl controller == ++ ++Required properties for the root node: ++ - compatible: Should be one of the following ++ "mediatek,mt7622-pinctrl" for MT7622 SoC ++ - reg: offset and length of the pinctrl space ++ ++ - gpio-controller: Marks the device node as a GPIO controller. ++ - #gpio-cells: Should be two. The first cell is the pin number and the ++ second is the GPIO flags. ++ ++Please refer to pinctrl-bindings.txt in this directory for details of the ++common pinctrl bindings used by client devices, including the meaning of the ++phrase "pin configuration node". ++ ++MT7622 pin configuration nodes act as a container for an arbitrary number of ++subnodes. Each of these subnodes represents some desired configuration for a ++pin, a group, or a list of pins or groups. This configuration can include the ++mux function to select on those pin(s)/group(s), and various pin configuration ++parameters, such as pull-up, slew rate, etc. ++ ++We support 2 types of configuration nodes. Those nodes can be either pinmux ++nodes or pinconf nodes. Each configuration node can consist of multiple nodes ++describing the pinmux and pinconf options. ++ ++The name of each subnode doesn't matter as long as it is unique; all subnodes ++should be enumerated and processed purely based on their content. ++ ++== pinmux nodes content == ++ ++The following generic properties as defined in pinctrl-bindings.txt are valid ++to specify in a pinmux subnode: ++ ++Required properties are: ++ - groups: An array of strings. Each string contains the name of a group. ++ Valid values for these names are listed below. ++ - function: A string containing the name of the function to mux to the ++ group. Valid values for function names are listed below. ++ ++== pinconf nodes content == ++ ++The following generic properties as defined in pinctrl-bindings.txt are valid ++to specify in a pinconf subnode: ++ ++Required properties are: ++ - pins: An array of strings. Each string contains the name of a pin. ++ Valid values for these names are listed below. ++ - groups: An array of strings. Each string contains the name of a group. ++ Valid values for these names are listed below. ++ ++Optional properies are: ++ bias-disable, bias-pull, bias-pull-down, input-enable, ++ input-schmitt-enable, input-schmitt-disable, output-enable ++ output-low, output-high, drive-strength, slew-rate ++ ++ Valid arguments for 'slew-rate' are '0' for no slew rate controlled and '1' for ++ slower slew rate respectively. ++ Valid arguments for 'drive-strength', 4, 8, 12, or 16 in mA. ++ ++The following specific properties as defined are valid to specify in a pinconf ++subnode: ++ ++Optional properties are: ++ - mediatek,tdsel: An integer describing the steps for output level shifter duty ++ cycle when asserted (high pulse width adjustment). Valid arguments are from 0 ++ to 15. ++ - mediatek,rdsel: An integer describing the steps for input level shifter duty ++ cycle when asserted (high pulse width adjustment). Valid arguments are from 0 ++ to 63. ++ ++== Valid values for pins, function and groups on MT7622 == ++ ++Valid values for pins are: ++pins can be referenced via the pin names as the below table shown and the ++related physical number is also put ahead of those names which helps cross ++references to pins between groups to know whether pins assignment conflict ++happens among devices try to acquire those available pins. ++ ++ Pin #: Valid values for pins ++ ----------------------------- ++ PIN 0: "GPIO_A" ++ PIN 1: "I2S1_IN" ++ PIN 2: "I2S1_OUT" ++ PIN 3: "I2S_BCLK" ++ PIN 4: "I2S_WS" ++ PIN 5: "I2S_MCLK" ++ PIN 6: "TXD0" ++ PIN 7: "RXD0" ++ PIN 8: "SPI_WP" ++ PIN 9: "SPI_HOLD" ++ PIN 10: "SPI_CLK" ++ PIN 11: "SPI_MOSI" ++ PIN 12: "SPI_MISO" ++ PIN 13: "SPI_CS" ++ PIN 14: "I2C_SDA" ++ PIN 15: "I2C_SCL" ++ PIN 16: "I2S2_IN" ++ PIN 17: "I2S3_IN" ++ PIN 18: "I2S4_IN" ++ PIN 19: "I2S2_OUT" ++ PIN 20: "I2S3_OUT" ++ PIN 21: "I2S4_OUT" ++ PIN 22: "GPIO_B" ++ PIN 23: "MDC" ++ PIN 24: "MDIO" ++ PIN 25: "G2_TXD0" ++ PIN 26: "G2_TXD1" ++ PIN 27: "G2_TXD2" ++ PIN 28: "G2_TXD3" ++ PIN 29: "G2_TXEN" ++ PIN 30: "G2_TXC" ++ PIN 31: "G2_RXD0" ++ PIN 32: "G2_RXD1" ++ PIN 33: "G2_RXD2" ++ PIN 34: "G2_RXD3" ++ PIN 35: "G2_RXDV" ++ PIN 36: "G2_RXC" ++ PIN 37: "NCEB" ++ PIN 38: "NWEB" ++ PIN 39: "NREB" ++ PIN 40: "NDL4" ++ PIN 41: "NDL5" ++ PIN 42: "NDL6" ++ PIN 43: "NDL7" ++ PIN 44: "NRB" ++ PIN 45: "NCLE" ++ PIN 46: "NALE" ++ PIN 47: "NDL0" ++ PIN 48: "NDL1" ++ PIN 49: "NDL2" ++ PIN 50: "NDL3" ++ PIN 51: "MDI_TP_P0" ++ PIN 52: "MDI_TN_P0" ++ PIN 53: "MDI_RP_P0" ++ PIN 54: "MDI_RN_P0" ++ PIN 55: "MDI_TP_P1" ++ PIN 56: "MDI_TN_P1" ++ PIN 57: "MDI_RP_P1" ++ PIN 58: "MDI_RN_P1" ++ PIN 59: "MDI_RP_P2" ++ PIN 60: "MDI_RN_P2" ++ PIN 61: "MDI_TP_P2" ++ PIN 62: "MDI_TN_P2" ++ PIN 63: "MDI_TP_P3" ++ PIN 64: "MDI_TN_P3" ++ PIN 65: "MDI_RP_P3" ++ PIN 66: "MDI_RN_P3" ++ PIN 67: "MDI_RP_P4" ++ PIN 68: "MDI_RN_P4" ++ PIN 69: "MDI_TP_P4" ++ PIN 70: "MDI_TN_P4" ++ PIN 71: "PMIC_SCL" ++ PIN 72: "PMIC_SDA" ++ PIN 73: "SPIC1_CLK" ++ PIN 74: "SPIC1_MOSI" ++ PIN 75: "SPIC1_MISO" ++ PIN 76: "SPIC1_CS" ++ PIN 77: "GPIO_D" ++ PIN 78: "WATCHDOG" ++ PIN 79: "RTS3_N" ++ PIN 80: "CTS3_N" ++ PIN 81: "TXD3" ++ PIN 82: "RXD3" ++ PIN 83: "PERST0_N" ++ PIN 84: "PERST1_N" ++ PIN 85: "WLED_N" ++ PIN 86: "EPHY_LED0_N" ++ PIN 87: "AUXIN0" ++ PIN 88: "AUXIN1" ++ PIN 89: "AUXIN2" ++ PIN 90: "AUXIN3" ++ PIN 91: "TXD4" ++ PIN 92: "RXD4" ++ PIN 93: "RTS4_N" ++ PIN 94: "CST4_N" ++ PIN 95: "PWM1" ++ PIN 96: "PWM2" ++ PIN 97: "PWM3" ++ PIN 98: "PWM4" ++ PIN 99: "PWM5" ++ PIN 100: "PWM6" ++ PIN 101: "PWM7" ++ PIN 102: "GPIO_E" ++ ++Valid values for function are: ++ "emmc", "eth", "i2c", "i2s", "ir", "led", "flash", "pcie", ++ "pmic", "pwm", "sd", "spi", "tdm", "uart", "watchdog" ++ ++Valid values for groups are: ++additional data is put followingly with valid value allowing us to know which ++applicable function and which relevant pins (in pin#) are able applied for that ++group. ++ ++ Valid value function pins (in pin#) ++ ------------------------------------------------------------------------- ++ "emmc" "emmc" 40, 41, 42, 43, 44, 45, ++ 47, 48, 49, 50 ++ "emmc_rst" "emmc" 37 ++ "esw" "eth" 51, 52, 53, 54, 55, 56, ++ 57, 58, 59, 60, 61, 62, ++ 63, 64, 65, 66, 67, 68, ++ 69, 70 ++ "esw_p0_p1" "eth" 51, 52, 53, 54, 55, 56, ++ 57, 58 ++ "esw_p2_p3_p4" "eth" 59, 60, 61, 62, 63, 64, ++ 65, 66, 67, 68, 69, 70 ++ "rgmii_via_esw" "eth" 59, 60, 61, 62, 63, 64, ++ 65, 66, 67, 68, 69, 70 ++ "rgmii_via_gmac1" "eth" 59, 60, 61, 62, 63, 64, ++ 65, 66, 67, 68, 69, 70 ++ "rgmii_via_gmac2" "eth" 25, 26, 27, 28, 29, 30, ++ 31, 32, 33, 34, 35, 36 ++ "mdc_mdio" "eth" 23, 24 ++ "i2c0" "i2c" 14, 15 ++ "i2c1_0" "i2c" 55, 56 ++ "i2c1_1" "i2c" 73, 74 ++ "i2c1_2" "i2c" 87, 88 ++ "i2c2_0" "i2c" 57, 58 ++ "i2c2_1" "i2c" 75, 76 ++ "i2c2_2" "i2c" 89, 90 ++ "i2s_in_mclk_bclk_ws" "i2s" 3, 4, 5 ++ "i2s1_in_data" "i2s" 1 ++ "i2s2_in_data" "i2s" 16 ++ "i2s3_in_data" "i2s" 17 ++ "i2s4_in_data" "i2s" 18 ++ "i2s_out_mclk_bclk_ws" "i2s" 3, 4, 5 ++ "i2s1_out_data" "i2s" 2 ++ "i2s2_out_data" "i2s" 19 ++ "i2s3_out_data" "i2s" 20 ++ "i2s4_out_data" "i2s" 21 ++ "ir_0_tx" "ir" 16 ++ "ir_1_tx" "ir" 59 ++ "ir_2_tx" "ir" 99 ++ "ir_0_rx" "ir" 17 ++ "ir_1_rx" "ir" 60 ++ "ir_2_rx" "ir" 100 ++ "ephy_leds" "led" 86, 91, 92, 93, 94 ++ "ephy0_led" "led" 86 ++ "ephy1_led" "led" 91 ++ "ephy2_led" "led" 92 ++ "ephy3_led" "led" 93 ++ "ephy4_led" "led" 94 ++ "wled" "led" 85 ++ "par_nand" "flash" 37, 38, 39, 40, 41, 42, ++ 43, 44, 45, 46, 47, 48, ++ 49, 50 ++ "snfi" "flash" 8, 9, 10, 11, 12, 13 ++ "spi_nor" "flash" 8, 9, 10, 11, 12, 13 ++ "pcie0_0_waken" "pcie" 14 ++ "pcie0_1_waken" "pcie" 79 ++ "pcie1_0_waken" "pcie" 14 ++ "pcie0_0_clkreq" "pcie" 15 ++ "pcie0_1_clkreq" "pcie" 80 ++ "pcie1_0_clkreq" "pcie" 15 ++ "pcie0_pad_perst" "pcie" 83 ++ "pcie1_pad_perst" "pcie" 84 ++ "pmic_bus" "pmic" 71, 72 ++ "pwm_ch1_0" "pwm" 51 ++ "pwm_ch1_1" "pwm" 73 ++ "pwm_ch1_2" "pwm" 95 ++ "pwm_ch2_0" "pwm" 52 ++ "pwm_ch2_1" "pwm" 74 ++ "pwm_ch2_2" "pwm" 96 ++ "pwm_ch3_0" "pwm" 53 ++ "pwm_ch3_1" "pwm" 75 ++ "pwm_ch3_2" "pwm" 97 ++ "pwm_ch4_0" "pwm" 54 ++ "pwm_ch4_1" "pwm" 67 ++ "pwm_ch4_2" "pwm" 76 ++ "pwm_ch4_3" "pwm" 98 ++ "pwm_ch5_0" "pwm" 68 ++ "pwm_ch5_1" "pwm" 77 ++ "pwm_ch5_2" "pwm" 99 ++ "pwm_ch6_0" "pwm" 69 ++ "pwm_ch6_1" "pwm" 78 ++ "pwm_ch6_2" "pwm" 81 ++ "pwm_ch6_3" "pwm" 100 ++ "pwm_ch7_0" "pwm" 70 ++ "pwm_ch7_1" "pwm" 82 ++ "pwm_ch7_2" "pwm" 101 ++ "sd_0" "sd" 16, 17, 18, 19, 20, 21 ++ "sd_1" "sd" 25, 26, 27, 28, 29, 30 ++ "spic0_0" "spi" 63, 64, 65, 66 ++ "spic0_1" "spi" 79, 80, 81, 82 ++ "spic1_0" "spi" 67, 68, 69, 70 ++ "spic1_1" "spi" 73, 74, 75, 76 ++ "spic2_0_wp_hold" "spi" 8, 9 ++ "spic2_0" "spi" 10, 11, 12, 13 ++ "tdm_0_out_mclk_bclk_ws" "tdm" 8, 9, 10 ++ "tdm_0_in_mclk_bclk_ws" "tdm" 11, 12, 13 ++ "tdm_0_out_data" "tdm" 20 ++ "tdm_0_in_data" "tdm" 21 ++ "tdm_1_out_mclk_bclk_ws" "tdm" 57, 58, 59 ++ "tdm_1_in_mclk_bclk_ws" "tdm" 60, 61, 62 ++ "tdm_1_out_data" "tdm" 55 ++ "tdm_1_in_data" "tdm" 56 ++ "uart0_0_tx_rx" "uart" 6, 7 ++ "uart1_0_tx_rx" "uart" 55, 56 ++ "uart1_0_rts_cts" "uart" 57, 58 ++ "uart1_1_tx_rx" "uart" 73, 74 ++ "uart1_1_rts_cts" "uart" 75, 76 ++ "uart2_0_tx_rx" "uart" 3, 4 ++ "uart2_0_rts_cts" "uart" 1, 2 ++ "uart2_1_tx_rx" "uart" 51, 52 ++ "uart2_1_rts_cts" "uart" 53, 54 ++ "uart2_2_tx_rx" "uart" 59, 60 ++ "uart2_2_rts_cts" "uart" 61, 62 ++ "uart2_3_tx_rx" "uart" 95, 96 ++ "uart3_0_tx_rx" "uart" 57, 58 ++ "uart3_1_tx_rx" "uart" 81, 82 ++ "uart3_1_rts_cts" "uart" 79, 80 ++ "uart4_0_tx_rx" "uart" 61, 62 ++ "uart4_1_tx_rx" "uart" 91, 92 ++ "uart4_1_rts_cts" "uart" 93, 94 ++ "uart4_2_tx_rx" "uart" 97, 98 ++ "uart4_2_rts_cts" "uart" 95, 96 ++ "watchdog" "watchdog" 78 ++ ++Example: ++ ++ pio: pinctrl@10211000 { ++ compatible = "mediatek,mt7622-pinctrl"; ++ reg = <0 0x10211000 0 0x1000>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ pinctrl_eth_default: eth-default { ++ mux-mdio { ++ groups = "mdc_mdio"; ++ function = "eth"; ++ drive-strength = <12>; ++ }; ++ ++ mux-gmac2 { ++ groups = "gmac2"; ++ function = "eth"; ++ drive-strength = <12>; ++ }; ++ ++ mux-esw { ++ groups = "esw"; ++ function = "eth"; ++ drive-strength = <8>; ++ }; ++ ++ conf-mdio { ++ pins = "MDC"; ++ bias-pull-up; ++ }; ++ }; ++ }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0170-pinctrl-mediatek-cleanup-for-placing-all-drivers-und.patch b/target/linux/mediatek/patches-4.14/0170-pinctrl-mediatek-cleanup-for-placing-all-drivers-und.patch new file mode 100644 index 0000000000..264cfda099 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0170-pinctrl-mediatek-cleanup-for-placing-all-drivers-und.patch @@ -0,0 +1,37 @@ +From 547700768b2e7a105ed27a3b955fd9b7142987d7 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Tue, 12 Dec 2017 14:24:19 +0800 +Subject: [PATCH 170/224] pinctrl: mediatek: cleanup for placing all drivers + under the menu + +Since lots of MediaTek drivers had been added, it seems slightly better +for that adding cleanup for placing MediaTek pinctrl drivers under the +independent menu as other kinds of drivers usually was done. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Biao Huang <biao.huang@mediatek.com> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +--- + drivers/pinctrl/mediatek/Kconfig | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig +index fac9866311f3..03b3023d5fe5 100644 +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -1,4 +1,5 @@ +-if ARCH_MEDIATEK || COMPILE_TEST ++menu "MediaTek pinctrl drivers" ++ depends on ARCH_MEDIATEK || COMPILE_TEST + + config PINCTRL_MTK + bool +@@ -46,4 +47,4 @@ config PINCTRL_MT6397 + default MFD_MT6397 + select PINCTRL_MTK + +-endif ++endmenu +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0171-pinctrl-mediatek-add-pinctrl-driver-for-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0171-pinctrl-mediatek-add-pinctrl-driver-for-MT7622-SoC.patch new file mode 100644 index 0000000000..312900ca37 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0171-pinctrl-mediatek-add-pinctrl-driver-for-MT7622-SoC.patch @@ -0,0 +1,1686 @@ +From 4318e143fe3ac617de20cf72aa32fd9d3ad92ee6 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Tue, 12 Dec 2017 14:24:20 +0800 +Subject: [PATCH 171/224] pinctrl: mediatek: add pinctrl driver for MT7622 SoC + +Add support for pinctrl on MT7622 SoC. The IO core found on the SoC has +the registers for pinctrl, pinconf and gpio mixed up in the same register +range. However, the IO core for the MT7622 SoC is completely distinct from +anyone of previous MediaTek SoCs which already had support, such as +the hardware internal, register address map and register detailed +definition for each pin. + +Therefore, instead, the driver is being newly implemented by reusing +generic methods provided from the core layer with GENERIC_PINCONF, +GENERIC_PINCTRL_GROUPS, and GENERIC_PINMUX_FUNCTIONS for the sake of code +simplicity and rid of superfluous code. Where the function of pins +determined by groups is utilized in this driver which can help developers +less confused with what combinations of pins effective on the SoC and even +reducing the mistakes during the integration of those relevant boards. + +As the gpio_chip handling is also only a few lines, the driver also +implements the gpio functionality directly through GPIOLIB. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Biao Huang <biao.huang@mediatek.com> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +--- + drivers/pinctrl/Makefile | 2 +- + drivers/pinctrl/mediatek/Kconfig | 10 + + drivers/pinctrl/mediatek/Makefile | 3 +- + drivers/pinctrl/mediatek/pinctrl-mt7622.c | 1595 +++++++++++++++++++++++++++++ + 4 files changed, 1608 insertions(+), 2 deletions(-) + create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7622.c + +diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile +index c16e27900dbb..3a798d5b0900 100644 +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -63,5 +63,5 @@ obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ + obj-y += ti/ + obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ + obj-$(CONFIG_ARCH_VT8500) += vt8500/ +-obj-$(CONFIG_PINCTRL_MTK) += mediatek/ ++obj-y += mediatek/ + obj-$(CONFIG_PINCTRL_ZX) += zte/ +diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig +index 03b3023d5fe5..3e598740b379 100644 +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -32,6 +32,16 @@ config PINCTRL_MT8127 + select PINCTRL_MTK + + # For ARMv8 SoCs ++config PINCTRL_MT7622 ++ bool "MediaTek MT7622 pin control" ++ depends on OF ++ depends on ARM64 || COMPILE_TEST ++ select GENERIC_PINCONF ++ select GENERIC_PINCTRL_GROUPS ++ select GENERIC_PINMUX_FUNCTIONS ++ select GPIOLIB ++ select OF_GPIO ++ + config PINCTRL_MT8173 + bool "Mediatek MT8173 pin control" + depends on OF +diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile +index e59c613d4ddd..6e3ca6bbda7a 100644 +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -1,9 +1,10 @@ + # Core +-obj-y += pinctrl-mtk-common.o ++obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o + + # SoC Drivers + obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o + obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o + obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o ++obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o + obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o + obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o +diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c +new file mode 100644 +index 000000000000..3824d82888ac +--- /dev/null ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c +@@ -0,0 +1,1595 @@ ++/* ++ * MediaTek MT7622 Pinctrl Driver ++ * ++ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/gpio.h> ++#include <linux/gpio/driver.h> ++#include <linux/io.h> ++#include <linux/init.h> ++#include <linux/mfd/syscon.h> ++#include <linux/of.h> ++#include <linux/of_platform.h> ++#include <linux/platform_device.h> ++#include <linux/pinctrl/pinctrl.h> ++#include <linux/pinctrl/pinmux.h> ++#include <linux/pinctrl/pinconf.h> ++#include <linux/pinctrl/pinconf-generic.h> ++#include <linux/regmap.h> ++ ++#include "../core.h" ++#include "../pinconf.h" ++#include "../pinmux.h" ++ ++#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME ++#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), } ++#define PINCTRL_PIN_GROUP(name, id) \ ++ { \ ++ name, \ ++ id##_pins, \ ++ ARRAY_SIZE(id##_pins), \ ++ id##_funcs, \ ++ } ++ ++#define MTK_GPIO_MODE 1 ++#define MTK_INPUT 0 ++#define MTK_OUTPUT 1 ++#define MTK_DISABLE 0 ++#define MTK_ENABLE 1 ++ ++/* Custom pinconf parameters */ ++#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1) ++#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2) ++ ++/* List these attributes which could be modified for the pin */ ++enum { ++ PINCTRL_PIN_REG_MODE, ++ PINCTRL_PIN_REG_DIR, ++ PINCTRL_PIN_REG_DI, ++ PINCTRL_PIN_REG_DO, ++ PINCTRL_PIN_REG_SR, ++ PINCTRL_PIN_REG_SMT, ++ PINCTRL_PIN_REG_PD, ++ PINCTRL_PIN_REG_PU, ++ PINCTRL_PIN_REG_E4, ++ PINCTRL_PIN_REG_E8, ++ PINCTRL_PIN_REG_TDSEL, ++ PINCTRL_PIN_REG_RDSEL, ++ PINCTRL_PIN_REG_MAX, ++}; ++ ++/* struct mtk_pin_field - the structure that holds the information of the field ++ * used to describe the attribute for the pin ++ * @offset: the register offset relative to the base address ++ * @mask: the mask used to filter out the field from the register ++ * @bitpos: the start bit relative to the register ++ * @next: the indication that the field would be extended to the ++ next register ++ */ ++struct mtk_pin_field { ++ u32 offset; ++ u32 mask; ++ u8 bitpos; ++ u8 next; ++}; ++ ++/* struct mtk_pin_field_calc - the structure that holds the range providing ++ * the guide used to look up the relevant field ++ * @s_pin: the start pin within the range ++ * @e_pin: the end pin within the range ++ * @s_addr: the start address for the range ++ * @x_addrs: the address distance between two consecutive registers ++ * within the range ++ * @s_bit: the start bit for the first register within the range ++ * @x_bits: the bit distance between two consecutive pins within ++ * the range ++ */ ++struct mtk_pin_field_calc { ++ u16 s_pin; ++ u16 e_pin; ++ u32 s_addr; ++ u8 x_addrs; ++ u8 s_bit; ++ u8 x_bits; ++}; ++ ++/* struct mtk_pin_reg_calc - the structure that holds all ranges used to ++ * determine which register the pin would make use of ++ * for certain pin attribute. ++ * @range: the start address for the range ++ * @nranges: the number of items in the range ++ */ ++struct mtk_pin_reg_calc { ++ const struct mtk_pin_field_calc *range; ++ unsigned int nranges; ++}; ++ ++/* struct mtk_pin_soc - the structure that holds SoC-specific data */ ++struct mtk_pin_soc { ++ const struct mtk_pin_reg_calc *reg_cal; ++ const struct pinctrl_pin_desc *pins; ++ unsigned int npins; ++ const struct group_desc *grps; ++ unsigned int ngrps; ++ const struct function_desc *funcs; ++ unsigned int nfuncs; ++}; ++ ++struct mtk_pinctrl { ++ struct pinctrl_dev *pctrl; ++ void __iomem *base; ++ struct device *dev; ++ struct gpio_chip chip; ++ const struct mtk_pin_soc *soc; ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_mode_range[] = { ++ {0, 0, 0x320, 0x10, 16, 4}, ++ {1, 4, 0x3a0, 0x10, 16, 4}, ++ {5, 5, 0x320, 0x10, 0, 4}, ++ {6, 6, 0x300, 0x10, 4, 4}, ++ {7, 7, 0x300, 0x10, 4, 4}, ++ {8, 9, 0x350, 0x10, 20, 4}, ++ {10, 10, 0x300, 0x10, 8, 4}, ++ {11, 11, 0x300, 0x10, 8, 4}, ++ {12, 12, 0x300, 0x10, 8, 4}, ++ {13, 13, 0x300, 0x10, 8, 4}, ++ {14, 15, 0x320, 0x10, 4, 4}, ++ {16, 17, 0x320, 0x10, 20, 4}, ++ {18, 21, 0x310, 0x10, 16, 4}, ++ {22, 22, 0x380, 0x10, 16, 4}, ++ {23, 23, 0x300, 0x10, 24, 4}, ++ {24, 24, 0x300, 0x10, 24, 4}, ++ {25, 25, 0x300, 0x10, 12, 4}, ++ {25, 25, 0x300, 0x10, 12, 4}, ++ {26, 26, 0x300, 0x10, 12, 4}, ++ {27, 27, 0x300, 0x10, 12, 4}, ++ {28, 28, 0x300, 0x10, 12, 4}, ++ {29, 29, 0x300, 0x10, 12, 4}, ++ {30, 30, 0x300, 0x10, 12, 4}, ++ {31, 31, 0x300, 0x10, 12, 4}, ++ {32, 32, 0x300, 0x10, 12, 4}, ++ {33, 33, 0x300, 0x10, 12, 4}, ++ {34, 34, 0x300, 0x10, 12, 4}, ++ {35, 35, 0x300, 0x10, 12, 4}, ++ {36, 36, 0x300, 0x10, 12, 4}, ++ {37, 37, 0x300, 0x10, 20, 4}, ++ {38, 38, 0x300, 0x10, 20, 4}, ++ {39, 39, 0x300, 0x10, 20, 4}, ++ {40, 40, 0x300, 0x10, 20, 4}, ++ {41, 41, 0x300, 0x10, 20, 4}, ++ {42, 42, 0x300, 0x10, 20, 4}, ++ {43, 43, 0x300, 0x10, 20, 4}, ++ {44, 44, 0x300, 0x10, 20, 4}, ++ {45, 46, 0x300, 0x10, 20, 4}, ++ {47, 47, 0x300, 0x10, 20, 4}, ++ {48, 48, 0x300, 0x10, 20, 4}, ++ {49, 49, 0x300, 0x10, 20, 4}, ++ {50, 50, 0x300, 0x10, 20, 4}, ++ {51, 70, 0x330, 0x10, 4, 4}, ++ {71, 71, 0x300, 0x10, 16, 4}, ++ {72, 72, 0x300, 0x10, 16, 4}, ++ {73, 76, 0x310, 0x10, 0, 4}, ++ {77, 77, 0x320, 0x10, 28, 4}, ++ {78, 78, 0x320, 0x10, 12, 4}, ++ {79, 82, 0x3a0, 0x10, 0, 4}, ++ {83, 83, 0x350, 0x10, 28, 4}, ++ {84, 84, 0x330, 0x10, 0, 4}, ++ {85, 90, 0x360, 0x10, 4, 4}, ++ {91, 94, 0x390, 0x10, 16, 4}, ++ {95, 97, 0x380, 0x10, 20, 4}, ++ {98, 101, 0x390, 0x10, 0, 4}, ++ {102, 102, 0x360, 0x10, 0, 4}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_dir_range[] = { ++ {0, 102, 0x0, 0x10, 0, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_di_range[] = { ++ {0, 102, 0x200, 0x10, 0, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_do_range[] = { ++ {0, 102, 0x100, 0x10, 0, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_sr_range[] = { ++ {0, 31, 0x910, 0x10, 0, 1}, ++ {32, 50, 0xa10, 0x10, 0, 1}, ++ {51, 70, 0x810, 0x10, 0, 1}, ++ {71, 72, 0xb10, 0x10, 0, 1}, ++ {73, 86, 0xb10, 0x10, 4, 1}, ++ {87, 90, 0xc10, 0x10, 0, 1}, ++ {91, 102, 0xb10, 0x10, 18, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_smt_range[] = { ++ {0, 31, 0x920, 0x10, 0, 1}, ++ {32, 50, 0xa20, 0x10, 0, 1}, ++ {51, 70, 0x820, 0x10, 0, 1}, ++ {71, 72, 0xb20, 0x10, 0, 1}, ++ {73, 86, 0xb20, 0x10, 4, 1}, ++ {87, 90, 0xc20, 0x10, 0, 1}, ++ {91, 102, 0xb20, 0x10, 18, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_pu_range[] = { ++ {0, 31, 0x930, 0x10, 0, 1}, ++ {32, 50, 0xa30, 0x10, 0, 1}, ++ {51, 70, 0x830, 0x10, 0, 1}, ++ {71, 72, 0xb30, 0x10, 0, 1}, ++ {73, 86, 0xb30, 0x10, 4, 1}, ++ {87, 90, 0xc30, 0x10, 0, 1}, ++ {91, 102, 0xb30, 0x10, 18, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_pd_range[] = { ++ {0, 31, 0x940, 0x10, 0, 1}, ++ {32, 50, 0xa40, 0x10, 0, 1}, ++ {51, 70, 0x840, 0x10, 0, 1}, ++ {71, 72, 0xb40, 0x10, 0, 1}, ++ {73, 86, 0xb40, 0x10, 4, 1}, ++ {87, 90, 0xc40, 0x10, 0, 1}, ++ {91, 102, 0xb40, 0x10, 18, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_e4_range[] = { ++ {0, 31, 0x960, 0x10, 0, 1}, ++ {32, 50, 0xa60, 0x10, 0, 1}, ++ {51, 70, 0x860, 0x10, 0, 1}, ++ {71, 72, 0xb60, 0x10, 0, 1}, ++ {73, 86, 0xb60, 0x10, 4, 1}, ++ {87, 90, 0xc60, 0x10, 0, 1}, ++ {91, 102, 0xb60, 0x10, 18, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_e8_range[] = { ++ {0, 31, 0x970, 0x10, 0, 1}, ++ {32, 50, 0xa70, 0x10, 0, 1}, ++ {51, 70, 0x870, 0x10, 0, 1}, ++ {71, 72, 0xb70, 0x10, 0, 1}, ++ {73, 86, 0xb70, 0x10, 4, 1}, ++ {87, 90, 0xc70, 0x10, 0, 1}, ++ {91, 102, 0xb70, 0x10, 18, 1}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_tdsel_range[] = { ++ {0, 31, 0x980, 0x4, 0, 4}, ++ {32, 50, 0xa80, 0x4, 0, 4}, ++ {51, 70, 0x880, 0x4, 0, 4}, ++ {71, 72, 0xb80, 0x4, 0, 4}, ++ {73, 86, 0xb80, 0x4, 16, 4}, ++ {87, 90, 0xc80, 0x4, 0, 4}, ++ {91, 102, 0xb88, 0x4, 8, 4}, ++}; ++ ++static const struct mtk_pin_field_calc mt7622_pin_rdsel_range[] = { ++ {0, 31, 0x990, 0x4, 0, 6}, ++ {32, 50, 0xa90, 0x4, 0, 6}, ++ {51, 58, 0x890, 0x4, 0, 6}, ++ {59, 60, 0x894, 0x4, 28, 6}, ++ {61, 62, 0x894, 0x4, 16, 6}, ++ {63, 66, 0x898, 0x4, 8, 6}, ++ {67, 68, 0x89c, 0x4, 12, 6}, ++ {69, 70, 0x89c, 0x4, 0, 6}, ++ {71, 72, 0xb90, 0x4, 0, 6}, ++ {73, 86, 0xb90, 0x4, 24, 6}, ++ {87, 90, 0xc90, 0x4, 0, 6}, ++ {91, 102, 0xb9c, 0x4, 12, 6}, ++}; ++ ++static const struct mtk_pin_reg_calc mt7622_reg_cals[PINCTRL_PIN_REG_MAX] = { ++ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7622_pin_mode_range), ++ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7622_pin_dir_range), ++ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7622_pin_di_range), ++ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7622_pin_do_range), ++ [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt7622_pin_sr_range), ++ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7622_pin_smt_range), ++ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7622_pin_pu_range), ++ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7622_pin_pd_range), ++ [PINCTRL_PIN_REG_E4] = MTK_RANGE(mt7622_pin_e4_range), ++ [PINCTRL_PIN_REG_E8] = MTK_RANGE(mt7622_pin_e8_range), ++ [PINCTRL_PIN_REG_TDSEL] = MTK_RANGE(mt7622_pin_tdsel_range), ++ [PINCTRL_PIN_REG_RDSEL] = MTK_RANGE(mt7622_pin_rdsel_range), ++}; ++ ++static const struct pinctrl_pin_desc mt7622_pins[] = { ++ PINCTRL_PIN(0, "GPIO_A"), ++ PINCTRL_PIN(1, "I2S1_IN"), ++ PINCTRL_PIN(2, "I2S1_OUT"), ++ PINCTRL_PIN(3, "I2S_BCLK"), ++ PINCTRL_PIN(4, "I2S_WS"), ++ PINCTRL_PIN(5, "I2S_MCLK"), ++ PINCTRL_PIN(6, "TXD0"), ++ PINCTRL_PIN(7, "RXD0"), ++ PINCTRL_PIN(8, "SPI_WP"), ++ PINCTRL_PIN(9, "SPI_HOLD"), ++ PINCTRL_PIN(10, "SPI_CLK"), ++ PINCTRL_PIN(11, "SPI_MOSI"), ++ PINCTRL_PIN(12, "SPI_MISO"), ++ PINCTRL_PIN(13, "SPI_CS"), ++ PINCTRL_PIN(14, "I2C_SDA"), ++ PINCTRL_PIN(15, "I2C_SCL"), ++ PINCTRL_PIN(16, "I2S2_IN"), ++ PINCTRL_PIN(17, "I2S3_IN"), ++ PINCTRL_PIN(18, "I2S4_IN"), ++ PINCTRL_PIN(19, "I2S2_OUT"), ++ PINCTRL_PIN(20, "I2S3_OUT"), ++ PINCTRL_PIN(21, "I2S4_OUT"), ++ PINCTRL_PIN(22, "GPIO_B"), ++ PINCTRL_PIN(23, "MDC"), ++ PINCTRL_PIN(24, "MDIO"), ++ PINCTRL_PIN(25, "G2_TXD0"), ++ PINCTRL_PIN(26, "G2_TXD1"), ++ PINCTRL_PIN(27, "G2_TXD2"), ++ PINCTRL_PIN(28, "G2_TXD3"), ++ PINCTRL_PIN(29, "G2_TXEN"), ++ PINCTRL_PIN(30, "G2_TXC"), ++ PINCTRL_PIN(31, "G2_RXD0"), ++ PINCTRL_PIN(32, "G2_RXD1"), ++ PINCTRL_PIN(33, "G2_RXD2"), ++ PINCTRL_PIN(34, "G2_RXD3"), ++ PINCTRL_PIN(35, "G2_RXDV"), ++ PINCTRL_PIN(36, "G2_RXC"), ++ PINCTRL_PIN(37, "NCEB"), ++ PINCTRL_PIN(38, "NWEB"), ++ PINCTRL_PIN(39, "NREB"), ++ PINCTRL_PIN(40, "NDL4"), ++ PINCTRL_PIN(41, "NDL5"), ++ PINCTRL_PIN(42, "NDL6"), ++ PINCTRL_PIN(43, "NDL7"), ++ PINCTRL_PIN(44, "NRB"), ++ PINCTRL_PIN(45, "NCLE"), ++ PINCTRL_PIN(46, "NALE"), ++ PINCTRL_PIN(47, "NDL0"), ++ PINCTRL_PIN(48, "NDL1"), ++ PINCTRL_PIN(49, "NDL2"), ++ PINCTRL_PIN(50, "NDL3"), ++ PINCTRL_PIN(51, "MDI_TP_P0"), ++ PINCTRL_PIN(52, "MDI_TN_P0"), ++ PINCTRL_PIN(53, "MDI_RP_P0"), ++ PINCTRL_PIN(54, "MDI_RN_P0"), ++ PINCTRL_PIN(55, "MDI_TP_P1"), ++ PINCTRL_PIN(56, "MDI_TN_P1"), ++ PINCTRL_PIN(57, "MDI_RP_P1"), ++ PINCTRL_PIN(58, "MDI_RN_P1"), ++ PINCTRL_PIN(59, "MDI_RP_P2"), ++ PINCTRL_PIN(60, "MDI_RN_P2"), ++ PINCTRL_PIN(61, "MDI_TP_P2"), ++ PINCTRL_PIN(62, "MDI_TN_P2"), ++ PINCTRL_PIN(63, "MDI_TP_P3"), ++ PINCTRL_PIN(64, "MDI_TN_P3"), ++ PINCTRL_PIN(65, "MDI_RP_P3"), ++ PINCTRL_PIN(66, "MDI_RN_P3"), ++ PINCTRL_PIN(67, "MDI_RP_P4"), ++ PINCTRL_PIN(68, "MDI_RN_P4"), ++ PINCTRL_PIN(69, "MDI_TP_P4"), ++ PINCTRL_PIN(70, "MDI_TN_P4"), ++ PINCTRL_PIN(71, "PMIC_SCL"), ++ PINCTRL_PIN(72, "PMIC_SDA"), ++ PINCTRL_PIN(73, "SPIC1_CLK"), ++ PINCTRL_PIN(74, "SPIC1_MOSI"), ++ PINCTRL_PIN(75, "SPIC1_MISO"), ++ PINCTRL_PIN(76, "SPIC1_CS"), ++ PINCTRL_PIN(77, "GPIO_D"), ++ PINCTRL_PIN(78, "WATCHDOG"), ++ PINCTRL_PIN(79, "RTS3_N"), ++ PINCTRL_PIN(80, "CTS3_N"), ++ PINCTRL_PIN(81, "TXD3"), ++ PINCTRL_PIN(82, "RXD3"), ++ PINCTRL_PIN(83, "PERST0_N"), ++ PINCTRL_PIN(84, "PERST1_N"), ++ PINCTRL_PIN(85, "WLED_N"), ++ PINCTRL_PIN(86, "EPHY_LED0_N"), ++ PINCTRL_PIN(87, "AUXIN0"), ++ PINCTRL_PIN(88, "AUXIN1"), ++ PINCTRL_PIN(89, "AUXIN2"), ++ PINCTRL_PIN(90, "AUXIN3"), ++ PINCTRL_PIN(91, "TXD4"), ++ PINCTRL_PIN(92, "RXD4"), ++ PINCTRL_PIN(93, "RTS4_N"), ++ PINCTRL_PIN(94, "CTS4_N"), ++ PINCTRL_PIN(95, "PWM1"), ++ PINCTRL_PIN(96, "PWM2"), ++ PINCTRL_PIN(97, "PWM3"), ++ PINCTRL_PIN(98, "PWM4"), ++ PINCTRL_PIN(99, "PWM5"), ++ PINCTRL_PIN(100, "PWM6"), ++ PINCTRL_PIN(101, "PWM7"), ++ PINCTRL_PIN(102, "GPIO_E"), ++}; ++ ++/* 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. ++ */ ++ ++/* EMMC */ ++static int mt7622_emmc_pins[] = { 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, }; ++static int mt7622_emmc_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; ++ ++static int mt7622_emmc_rst_pins[] = { 37, }; ++static int mt7622_emmc_rst_funcs[] = { 1, }; ++ ++/* LED for EPHY */ ++static int mt7622_ephy_leds_pins[] = { 86, 91, 92, 93, 94, }; ++static int mt7622_ephy_leds_funcs[] = { 0, 0, 0, 0, 0, }; ++static int mt7622_ephy0_led_pins[] = { 86, }; ++static int mt7622_ephy0_led_funcs[] = { 0, }; ++static int mt7622_ephy1_led_pins[] = { 91, }; ++static int mt7622_ephy1_led_funcs[] = { 2, }; ++static int mt7622_ephy2_led_pins[] = { 92, }; ++static int mt7622_ephy2_led_funcs[] = { 2, }; ++static int mt7622_ephy3_led_pins[] = { 93, }; ++static int mt7622_ephy3_led_funcs[] = { 2, }; ++static int mt7622_ephy4_led_pins[] = { 94, }; ++static int mt7622_ephy4_led_funcs[] = { 2, }; ++ ++/* Embedded Switch */ ++static int mt7622_esw_pins[] = { 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, ++ 62, 63, 64, 65, 66, 67, 68, 69, 70, }; ++static int mt7622_esw_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, }; ++static int mt7622_esw_p0_p1_pins[] = { 51, 52, 53, 54, 55, 56, 57, 58, }; ++static int mt7622_esw_p0_p1_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, }; ++static int mt7622_esw_p2_p3_p4_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66, 67, ++ 68, 69, 70, }; ++static int mt7622_esw_p2_p3_p4_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, }; ++/* RGMII via ESW */ ++static int mt7622_rgmii_via_esw_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66, ++ 67, 68, 69, 70, }; ++static int mt7622_rgmii_via_esw_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, }; ++ ++/* RGMII via GMAC1 */ ++static int mt7622_rgmii_via_gmac1_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66, ++ 67, 68, 69, 70, }; ++static int mt7622_rgmii_via_gmac1_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ++ 2, }; ++ ++/* RGMII via GMAC2 */ ++static int mt7622_rgmii_via_gmac2_pins[] = { 25, 26, 27, 28, 29, 30, 31, 32, ++ 33, 34, 35, 36, }; ++static int mt7622_rgmii_via_gmac2_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, }; ++ ++/* I2C */ ++static int mt7622_i2c0_pins[] = { 14, 15, }; ++static int mt7622_i2c0_funcs[] = { 0, 0, }; ++static int mt7622_i2c1_0_pins[] = { 55, 56, }; ++static int mt7622_i2c1_0_funcs[] = { 0, 0, }; ++static int mt7622_i2c1_1_pins[] = { 73, 74, }; ++static int mt7622_i2c1_1_funcs[] = { 3, 3, }; ++static int mt7622_i2c1_2_pins[] = { 87, 88, }; ++static int mt7622_i2c1_2_funcs[] = { 0, 0, }; ++static int mt7622_i2c2_0_pins[] = { 57, 58, }; ++static int mt7622_i2c2_0_funcs[] = { 0, 0, }; ++static int mt7622_i2c2_1_pins[] = { 75, 76, }; ++static int mt7622_i2c2_1_funcs[] = { 3, 3, }; ++static int mt7622_i2c2_2_pins[] = { 89, 90, }; ++static int mt7622_i2c2_2_funcs[] = { 0, 0, }; ++ ++/* I2S */ ++static int mt7622_i2s_in_mclk_bclk_ws_pins[] = { 3, 4, 5, }; ++static int mt7622_i2s_in_mclk_bclk_ws_funcs[] = { 3, 3, 0, }; ++static int mt7622_i2s1_in_data_pins[] = { 1, }; ++static int mt7622_i2s1_in_data_funcs[] = { 0, }; ++static int mt7622_i2s2_in_data_pins[] = { 16, }; ++static int mt7622_i2s2_in_data_funcs[] = { 0, }; ++static int mt7622_i2s3_in_data_pins[] = { 17, }; ++static int mt7622_i2s3_in_data_funcs[] = { 0, }; ++static int mt7622_i2s4_in_data_pins[] = { 18, }; ++static int mt7622_i2s4_in_data_funcs[] = { 0, }; ++static int mt7622_i2s_out_mclk_bclk_ws_pins[] = { 3, 4, 5, }; ++static int mt7622_i2s_out_mclk_bclk_ws_funcs[] = { 0, 0, 0, }; ++static int mt7622_i2s1_out_data_pins[] = { 2, }; ++static int mt7622_i2s1_out_data_funcs[] = { 0, }; ++static int mt7622_i2s2_out_data_pins[] = { 19, }; ++static int mt7622_i2s2_out_data_funcs[] = { 0, }; ++static int mt7622_i2s3_out_data_pins[] = { 20, }; ++static int mt7622_i2s3_out_data_funcs[] = { 0, }; ++static int mt7622_i2s4_out_data_pins[] = { 21, }; ++static int mt7622_i2s4_out_data_funcs[] = { 0, }; ++ ++/* IR */ ++static int mt7622_ir_0_tx_pins[] = { 16, }; ++static int mt7622_ir_0_tx_funcs[] = { 4, }; ++static int mt7622_ir_1_tx_pins[] = { 59, }; ++static int mt7622_ir_1_tx_funcs[] = { 5, }; ++static int mt7622_ir_2_tx_pins[] = { 99, }; ++static int mt7622_ir_2_tx_funcs[] = { 3, }; ++static int mt7622_ir_0_rx_pins[] = { 17, }; ++static int mt7622_ir_0_rx_funcs[] = { 4, }; ++static int mt7622_ir_1_rx_pins[] = { 60, }; ++static int mt7622_ir_1_rx_funcs[] = { 5, }; ++static int mt7622_ir_2_rx_pins[] = { 100, }; ++static int mt7622_ir_2_rx_funcs[] = { 3, }; ++ ++/* MDIO */ ++static int mt7622_mdc_mdio_pins[] = { 23, 24, }; ++static int mt7622_mdc_mdio_funcs[] = { 0, 0, }; ++ ++/* PCIE */ ++static int mt7622_pcie0_0_waken_pins[] = { 14, }; ++static int mt7622_pcie0_0_waken_funcs[] = { 2, }; ++static int mt7622_pcie0_0_clkreq_pins[] = { 15, }; ++static int mt7622_pcie0_0_clkreq_funcs[] = { 2, }; ++static int mt7622_pcie0_1_waken_pins[] = { 79, }; ++static int mt7622_pcie0_1_waken_funcs[] = { 4, }; ++static int mt7622_pcie0_1_clkreq_pins[] = { 80, }; ++static int mt7622_pcie0_1_clkreq_funcs[] = { 4, }; ++static int mt7622_pcie1_0_waken_pins[] = { 14, }; ++static int mt7622_pcie1_0_waken_funcs[] = { 3, }; ++static int mt7622_pcie1_0_clkreq_pins[] = { 15, }; ++static int mt7622_pcie1_0_clkreq_funcs[] = { 3, }; ++ ++static int mt7622_pcie0_pad_perst_pins[] = { 83, }; ++static int mt7622_pcie0_pad_perst_funcs[] = { 0, }; ++static int mt7622_pcie1_pad_perst_pins[] = { 84, }; ++static int mt7622_pcie1_pad_perst_funcs[] = { 0, }; ++ ++/* PMIC bus */ ++static int mt7622_pmic_bus_pins[] = { 71, 72, }; ++static int mt7622_pmic_bus_funcs[] = { 0, 0, }; ++ ++/* Parallel NAND */ ++static int mt7622_pnand_pins[] = { 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, ++ 48, 49, 50, }; ++static int mt7622_pnand_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, }; ++ ++/* PWM */ ++static int mt7622_pwm_ch1_0_pins[] = { 51, }; ++static int mt7622_pwm_ch1_0_funcs[] = { 3, }; ++static int mt7622_pwm_ch1_1_pins[] = { 73, }; ++static int mt7622_pwm_ch1_1_funcs[] = { 4, }; ++static int mt7622_pwm_ch1_2_pins[] = { 95, }; ++static int mt7622_pwm_ch1_2_funcs[] = { 0, }; ++static int mt7622_pwm_ch2_0_pins[] = { 52, }; ++static int mt7622_pwm_ch2_0_funcs[] = { 3, }; ++static int mt7622_pwm_ch2_1_pins[] = { 74, }; ++static int mt7622_pwm_ch2_1_funcs[] = { 4, }; ++static int mt7622_pwm_ch2_2_pins[] = { 96, }; ++static int mt7622_pwm_ch2_2_funcs[] = { 0, }; ++static int mt7622_pwm_ch3_0_pins[] = { 53, }; ++static int mt7622_pwm_ch3_0_funcs[] = { 3, }; ++static int mt7622_pwm_ch3_1_pins[] = { 75, }; ++static int mt7622_pwm_ch3_1_funcs[] = { 4, }; ++static int mt7622_pwm_ch3_2_pins[] = { 97, }; ++static int mt7622_pwm_ch3_2_funcs[] = { 0, }; ++static int mt7622_pwm_ch4_0_pins[] = { 54, }; ++static int mt7622_pwm_ch4_0_funcs[] = { 3, }; ++static int mt7622_pwm_ch4_1_pins[] = { 67, }; ++static int mt7622_pwm_ch4_1_funcs[] = { 3, }; ++static int mt7622_pwm_ch4_2_pins[] = { 76, }; ++static int mt7622_pwm_ch4_2_funcs[] = { 4, }; ++static int mt7622_pwm_ch4_3_pins[] = { 98, }; ++static int mt7622_pwm_ch4_3_funcs[] = { 0, }; ++static int mt7622_pwm_ch5_0_pins[] = { 68, }; ++static int mt7622_pwm_ch5_0_funcs[] = { 3, }; ++static int mt7622_pwm_ch5_1_pins[] = { 77, }; ++static int mt7622_pwm_ch5_1_funcs[] = { 4, }; ++static int mt7622_pwm_ch5_2_pins[] = { 99, }; ++static int mt7622_pwm_ch5_2_funcs[] = { 0, }; ++static int mt7622_pwm_ch6_0_pins[] = { 69, }; ++static int mt7622_pwm_ch6_0_funcs[] = { 3, }; ++static int mt7622_pwm_ch6_1_pins[] = { 78, }; ++static int mt7622_pwm_ch6_1_funcs[] = { 4, }; ++static int mt7622_pwm_ch6_2_pins[] = { 81, }; ++static int mt7622_pwm_ch6_2_funcs[] = { 4, }; ++static int mt7622_pwm_ch6_3_pins[] = { 100, }; ++static int mt7622_pwm_ch6_3_funcs[] = { 0, }; ++static int mt7622_pwm_ch7_0_pins[] = { 70, }; ++static int mt7622_pwm_ch7_0_funcs[] = { 3, }; ++static int mt7622_pwm_ch7_1_pins[] = { 82, }; ++static int mt7622_pwm_ch7_1_funcs[] = { 4, }; ++static int mt7622_pwm_ch7_2_pins[] = { 101, }; ++static int mt7622_pwm_ch7_2_funcs[] = { 0, }; ++ ++/* SD */ ++static int mt7622_sd_0_pins[] = { 16, 17, 18, 19, 20, 21, }; ++static int mt7622_sd_0_funcs[] = { 2, 2, 2, 2, 2, 2, }; ++static int mt7622_sd_1_pins[] = { 25, 26, 27, 28, 29, 30, }; ++static int mt7622_sd_1_funcs[] = { 2, 2, 2, 2, 2, 2, }; ++ ++/* Serial NAND */ ++static int mt7622_snfi_pins[] = { 8, 9, 10, 11, 12, 13, }; ++static int mt7622_snfi_funcs[] = { 2, 2, 2, 2, 2, 2, }; ++ ++/* SPI NOR */ ++static int mt7622_spi_pins[] = { 8, 9, 10, 11, 12, 13 }; ++static int mt7622_spi_funcs[] = { 0, 0, 0, 0, 0, 0, }; ++ ++/* SPIC */ ++static int mt7622_spic0_0_pins[] = { 63, 64, 65, 66, }; ++static int mt7622_spic0_0_funcs[] = { 4, 4, 4, 4, }; ++static int mt7622_spic0_1_pins[] = { 79, 80, 81, 82, }; ++static int mt7622_spic0_1_funcs[] = { 3, 3, 3, 3, }; ++static int mt7622_spic1_0_pins[] = { 67, 68, 69, 70, }; ++static int mt7622_spic1_0_funcs[] = { 4, 4, 4, 4, }; ++static int mt7622_spic1_1_pins[] = { 73, 74, 75, 76, }; ++static int mt7622_spic1_1_funcs[] = { 0, 0, 0, 0, }; ++static int mt7622_spic2_0_pins[] = { 10, 11, 12, 13, }; ++static int mt7622_spic2_0_funcs[] = { 0, 0, 0, 0, }; ++static int mt7622_spic2_0_wp_hold_pins[] = { 8, 9, }; ++static int mt7622_spic2_0_wp_hold_funcs[] = { 0, 0, }; ++ ++/* TDM */ ++static int mt7622_tdm_0_out_mclk_bclk_ws_pins[] = { 8, 9, 10, }; ++static int mt7622_tdm_0_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, }; ++static int mt7622_tdm_0_in_mclk_bclk_ws_pins[] = { 11, 12, 13, }; ++static int mt7622_tdm_0_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, }; ++static int mt7622_tdm_0_out_data_pins[] = { 20, }; ++static int mt7622_tdm_0_out_data_funcs[] = { 3, }; ++static int mt7622_tdm_0_in_data_pins[] = { 21, }; ++static int mt7622_tdm_0_in_data_funcs[] = { 3, }; ++static int mt7622_tdm_1_out_mclk_bclk_ws_pins[] = { 57, 58, 59, }; ++static int mt7622_tdm_1_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, }; ++static int mt7622_tdm_1_in_mclk_bclk_ws_pins[] = { 60, 61, 62, }; ++static int mt7622_tdm_1_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, }; ++static int mt7622_tdm_1_out_data_pins[] = { 55, }; ++static int mt7622_tdm_1_out_data_funcs[] = { 3, }; ++static int mt7622_tdm_1_in_data_pins[] = { 56, }; ++static int mt7622_tdm_1_in_data_funcs[] = { 3, }; ++ ++/* UART */ ++static int mt7622_uart0_0_tx_rx_pins[] = { 6, 7, }; ++static int mt7622_uart0_0_tx_rx_funcs[] = { 0, 0, }; ++static int mt7622_uart1_0_tx_rx_pins[] = { 55, 56, }; ++static int mt7622_uart1_0_tx_rx_funcs[] = { 2, 2, }; ++static int mt7622_uart1_0_rts_cts_pins[] = { 57, 58, }; ++static int mt7622_uart1_0_rts_cts_funcs[] = { 2, 2, }; ++static int mt7622_uart1_1_tx_rx_pins[] = { 73, 74, }; ++static int mt7622_uart1_1_tx_rx_funcs[] = { 2, 2, }; ++static int mt7622_uart1_1_rts_cts_pins[] = { 75, 76, }; ++static int mt7622_uart1_1_rts_cts_funcs[] = { 2, 2, }; ++static int mt7622_uart2_0_tx_rx_pins[] = { 3, 4, }; ++static int mt7622_uart2_0_tx_rx_funcs[] = { 2, 2, }; ++static int mt7622_uart2_0_rts_cts_pins[] = { 1, 2, }; ++static int mt7622_uart2_0_rts_cts_funcs[] = { 2, 2, }; ++static int mt7622_uart2_1_tx_rx_pins[] = { 51, 52, }; ++static int mt7622_uart2_1_tx_rx_funcs[] = { 0, 0, }; ++static int mt7622_uart2_1_rts_cts_pins[] = { 53, 54, }; ++static int mt7622_uart2_1_rts_cts_funcs[] = { 0, 0, }; ++static int mt7622_uart2_2_tx_rx_pins[] = { 59, 60, }; ++static int mt7622_uart2_2_tx_rx_funcs[] = { 4, 4, }; ++static int mt7622_uart2_2_rts_cts_pins[] = { 61, 62, }; ++static int mt7622_uart2_2_rts_cts_funcs[] = { 4, 4, }; ++static int mt7622_uart2_3_tx_rx_pins[] = { 95, 96, }; ++static int mt7622_uart2_3_tx_rx_funcs[] = { 3, 3, }; ++static int mt7622_uart3_0_tx_rx_pins[] = { 57, 58, }; ++static int mt7622_uart3_0_tx_rx_funcs[] = { 5, 5, }; ++static int mt7622_uart3_1_tx_rx_pins[] = { 81, 82, }; ++static int mt7622_uart3_1_tx_rx_funcs[] = { 0, 0, }; ++static int mt7622_uart3_1_rts_cts_pins[] = { 79, 80, }; ++static int mt7622_uart3_1_rts_cts_funcs[] = { 0, 0, }; ++static int mt7622_uart4_0_tx_rx_pins[] = { 61, 62, }; ++static int mt7622_uart4_0_tx_rx_funcs[] = { 5, 5, }; ++static int mt7622_uart4_1_tx_rx_pins[] = { 91, 92, }; ++static int mt7622_uart4_1_tx_rx_funcs[] = { 0, 0, }; ++static int mt7622_uart4_1_rts_cts_pins[] = { 93, 94 }; ++static int mt7622_uart4_1_rts_cts_funcs[] = { 0, 0, }; ++static int mt7622_uart4_2_tx_rx_pins[] = { 97, 98, }; ++static int mt7622_uart4_2_tx_rx_funcs[] = { 2, 2, }; ++static int mt7622_uart4_2_rts_cts_pins[] = { 95, 96 }; ++static int mt7622_uart4_2_rts_cts_funcs[] = { 2, 2, }; ++ ++/* Watchdog */ ++static int mt7622_watchdog_pins[] = { 78, }; ++static int mt7622_watchdog_funcs[] = { 0, }; ++ ++/* WLAN LED */ ++static int mt7622_wled_pins[] = { 85, }; ++static int mt7622_wled_funcs[] = { 0, }; ++ ++static const struct group_desc mt7622_groups[] = { ++ PINCTRL_PIN_GROUP("emmc", mt7622_emmc), ++ PINCTRL_PIN_GROUP("emmc_rst", mt7622_emmc_rst), ++ PINCTRL_PIN_GROUP("ephy_leds", mt7622_ephy_leds), ++ PINCTRL_PIN_GROUP("ephy0_led", mt7622_ephy0_led), ++ PINCTRL_PIN_GROUP("ephy1_led", mt7622_ephy1_led), ++ PINCTRL_PIN_GROUP("ephy2_led", mt7622_ephy2_led), ++ PINCTRL_PIN_GROUP("ephy3_led", mt7622_ephy3_led), ++ PINCTRL_PIN_GROUP("ephy4_led", mt7622_ephy4_led), ++ PINCTRL_PIN_GROUP("esw", mt7622_esw), ++ PINCTRL_PIN_GROUP("esw_p0_p1", mt7622_esw_p0_p1), ++ PINCTRL_PIN_GROUP("esw_p2_p3_p4", mt7622_esw_p2_p3_p4), ++ PINCTRL_PIN_GROUP("rgmii_via_esw", mt7622_rgmii_via_esw), ++ PINCTRL_PIN_GROUP("rgmii_via_gmac1", mt7622_rgmii_via_gmac1), ++ PINCTRL_PIN_GROUP("rgmii_via_gmac2", mt7622_rgmii_via_gmac2), ++ PINCTRL_PIN_GROUP("i2c0", mt7622_i2c0), ++ PINCTRL_PIN_GROUP("i2c1_0", mt7622_i2c1_0), ++ PINCTRL_PIN_GROUP("i2c1_1", mt7622_i2c1_1), ++ PINCTRL_PIN_GROUP("i2c1_2", mt7622_i2c1_2), ++ PINCTRL_PIN_GROUP("i2c2_0", mt7622_i2c2_0), ++ PINCTRL_PIN_GROUP("i2c2_1", mt7622_i2c2_1), ++ PINCTRL_PIN_GROUP("i2c2_2", mt7622_i2c2_2), ++ PINCTRL_PIN_GROUP("i2s_out_mclk_bclk_ws", mt7622_i2s_out_mclk_bclk_ws), ++ PINCTRL_PIN_GROUP("i2s_in_mclk_bclk_ws", mt7622_i2s_in_mclk_bclk_ws), ++ PINCTRL_PIN_GROUP("i2s1_in_data", mt7622_i2s1_in_data), ++ PINCTRL_PIN_GROUP("i2s2_in_data", mt7622_i2s2_in_data), ++ PINCTRL_PIN_GROUP("i2s3_in_data", mt7622_i2s3_in_data), ++ PINCTRL_PIN_GROUP("i2s4_in_data", mt7622_i2s4_in_data), ++ PINCTRL_PIN_GROUP("i2s1_out_data", mt7622_i2s1_out_data), ++ PINCTRL_PIN_GROUP("i2s2_out_data", mt7622_i2s2_out_data), ++ PINCTRL_PIN_GROUP("i2s3_out_data", mt7622_i2s3_out_data), ++ PINCTRL_PIN_GROUP("i2s4_out_data", mt7622_i2s4_out_data), ++ PINCTRL_PIN_GROUP("ir_0_tx", mt7622_ir_0_tx), ++ PINCTRL_PIN_GROUP("ir_1_tx", mt7622_ir_1_tx), ++ PINCTRL_PIN_GROUP("ir_2_tx", mt7622_ir_2_tx), ++ PINCTRL_PIN_GROUP("ir_0_rx", mt7622_ir_0_rx), ++ PINCTRL_PIN_GROUP("ir_1_rx", mt7622_ir_1_rx), ++ PINCTRL_PIN_GROUP("ir_2_rx", mt7622_ir_2_rx), ++ PINCTRL_PIN_GROUP("mdc_mdio", mt7622_mdc_mdio), ++ PINCTRL_PIN_GROUP("pcie0_0_waken", mt7622_pcie0_0_waken), ++ PINCTRL_PIN_GROUP("pcie0_0_clkreq", mt7622_pcie0_0_clkreq), ++ PINCTRL_PIN_GROUP("pcie0_1_waken", mt7622_pcie0_1_waken), ++ PINCTRL_PIN_GROUP("pcie0_1_clkreq", mt7622_pcie0_1_clkreq), ++ PINCTRL_PIN_GROUP("pcie1_0_waken", mt7622_pcie1_0_waken), ++ PINCTRL_PIN_GROUP("pcie1_0_clkreq", mt7622_pcie1_0_clkreq), ++ PINCTRL_PIN_GROUP("pcie0_pad_perst", mt7622_pcie0_pad_perst), ++ PINCTRL_PIN_GROUP("pcie1_pad_perst", mt7622_pcie1_pad_perst), ++ PINCTRL_PIN_GROUP("par_nand", mt7622_pnand), ++ PINCTRL_PIN_GROUP("pmic_bus", mt7622_pmic_bus), ++ PINCTRL_PIN_GROUP("pwm_ch1_0", mt7622_pwm_ch1_0), ++ PINCTRL_PIN_GROUP("pwm_ch1_1", mt7622_pwm_ch1_1), ++ PINCTRL_PIN_GROUP("pwm_ch1_2", mt7622_pwm_ch1_2), ++ PINCTRL_PIN_GROUP("pwm_ch2_0", mt7622_pwm_ch2_0), ++ PINCTRL_PIN_GROUP("pwm_ch2_1", mt7622_pwm_ch2_1), ++ PINCTRL_PIN_GROUP("pwm_ch2_2", mt7622_pwm_ch2_2), ++ PINCTRL_PIN_GROUP("pwm_ch3_0", mt7622_pwm_ch3_0), ++ PINCTRL_PIN_GROUP("pwm_ch3_1", mt7622_pwm_ch3_1), ++ PINCTRL_PIN_GROUP("pwm_ch3_2", mt7622_pwm_ch3_2), ++ PINCTRL_PIN_GROUP("pwm_ch4_0", mt7622_pwm_ch4_0), ++ PINCTRL_PIN_GROUP("pwm_ch4_1", mt7622_pwm_ch4_1), ++ PINCTRL_PIN_GROUP("pwm_ch4_2", mt7622_pwm_ch4_2), ++ PINCTRL_PIN_GROUP("pwm_ch4_3", mt7622_pwm_ch4_3), ++ PINCTRL_PIN_GROUP("pwm_ch5_0", mt7622_pwm_ch5_0), ++ PINCTRL_PIN_GROUP("pwm_ch5_1", mt7622_pwm_ch5_1), ++ PINCTRL_PIN_GROUP("pwm_ch5_2", mt7622_pwm_ch5_2), ++ PINCTRL_PIN_GROUP("pwm_ch6_0", mt7622_pwm_ch6_0), ++ PINCTRL_PIN_GROUP("pwm_ch6_1", mt7622_pwm_ch6_1), ++ PINCTRL_PIN_GROUP("pwm_ch6_2", mt7622_pwm_ch6_2), ++ PINCTRL_PIN_GROUP("pwm_ch6_3", mt7622_pwm_ch6_3), ++ PINCTRL_PIN_GROUP("pwm_ch7_0", mt7622_pwm_ch7_0), ++ PINCTRL_PIN_GROUP("pwm_ch7_1", mt7622_pwm_ch7_1), ++ PINCTRL_PIN_GROUP("pwm_ch7_2", mt7622_pwm_ch7_2), ++ PINCTRL_PIN_GROUP("sd_0", mt7622_sd_0), ++ PINCTRL_PIN_GROUP("sd_1", mt7622_sd_1), ++ PINCTRL_PIN_GROUP("snfi", mt7622_snfi), ++ PINCTRL_PIN_GROUP("spi_nor", mt7622_spi), ++ PINCTRL_PIN_GROUP("spic0_0", mt7622_spic0_0), ++ PINCTRL_PIN_GROUP("spic0_1", mt7622_spic0_1), ++ PINCTRL_PIN_GROUP("spic1_0", mt7622_spic1_0), ++ PINCTRL_PIN_GROUP("spic1_1", mt7622_spic1_1), ++ PINCTRL_PIN_GROUP("spic2_0", mt7622_spic2_0), ++ PINCTRL_PIN_GROUP("spic2_0_wp_hold", mt7622_spic2_0_wp_hold), ++ PINCTRL_PIN_GROUP("tdm_0_out_mclk_bclk_ws", ++ mt7622_tdm_0_out_mclk_bclk_ws), ++ PINCTRL_PIN_GROUP("tdm_0_in_mclk_bclk_ws", ++ mt7622_tdm_0_in_mclk_bclk_ws), ++ PINCTRL_PIN_GROUP("tdm_0_out_data", mt7622_tdm_0_out_data), ++ PINCTRL_PIN_GROUP("tdm_0_in_data", mt7622_tdm_0_in_data), ++ PINCTRL_PIN_GROUP("tdm_1_out_mclk_bclk_ws", ++ mt7622_tdm_1_out_mclk_bclk_ws), ++ PINCTRL_PIN_GROUP("tdm_1_in_mclk_bclk_ws", ++ mt7622_tdm_1_in_mclk_bclk_ws), ++ PINCTRL_PIN_GROUP("tdm_1_out_data", mt7622_tdm_1_out_data), ++ PINCTRL_PIN_GROUP("tdm_1_in_data", mt7622_tdm_1_in_data), ++ PINCTRL_PIN_GROUP("uart0_0_tx_rx", mt7622_uart0_0_tx_rx), ++ PINCTRL_PIN_GROUP("uart1_0_tx_rx", mt7622_uart1_0_tx_rx), ++ PINCTRL_PIN_GROUP("uart1_0_rts_cts", mt7622_uart1_0_rts_cts), ++ PINCTRL_PIN_GROUP("uart1_1_tx_rx", mt7622_uart1_1_tx_rx), ++ PINCTRL_PIN_GROUP("uart1_1_rts_cts", mt7622_uart1_1_rts_cts), ++ PINCTRL_PIN_GROUP("uart2_0_tx_rx", mt7622_uart2_0_tx_rx), ++ PINCTRL_PIN_GROUP("uart2_0_rts_cts", mt7622_uart2_0_rts_cts), ++ PINCTRL_PIN_GROUP("uart2_1_tx_rx", mt7622_uart2_1_tx_rx), ++ PINCTRL_PIN_GROUP("uart2_1_rts_cts", mt7622_uart2_1_rts_cts), ++ PINCTRL_PIN_GROUP("uart2_2_tx_rx", mt7622_uart2_2_tx_rx), ++ PINCTRL_PIN_GROUP("uart2_2_rts_cts", mt7622_uart2_2_rts_cts), ++ PINCTRL_PIN_GROUP("uart2_3_tx_rx", mt7622_uart2_3_tx_rx), ++ PINCTRL_PIN_GROUP("uart3_0_tx_rx", mt7622_uart3_0_tx_rx), ++ PINCTRL_PIN_GROUP("uart3_1_tx_rx", mt7622_uart3_1_tx_rx), ++ PINCTRL_PIN_GROUP("uart3_1_rts_cts", mt7622_uart3_1_rts_cts), ++ PINCTRL_PIN_GROUP("uart4_0_tx_rx", mt7622_uart4_0_tx_rx), ++ PINCTRL_PIN_GROUP("uart4_1_tx_rx", mt7622_uart4_1_tx_rx), ++ PINCTRL_PIN_GROUP("uart4_1_rts_cts", mt7622_uart4_1_rts_cts), ++ PINCTRL_PIN_GROUP("uart4_2_tx_rx", mt7622_uart4_2_tx_rx), ++ PINCTRL_PIN_GROUP("uart4_2_rts_cts", mt7622_uart4_2_rts_cts), ++ PINCTRL_PIN_GROUP("watchdog", mt7622_watchdog), ++ PINCTRL_PIN_GROUP("wled", mt7622_wled), ++}; ++ ++/* 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 *mt7622_emmc_groups[] = { "emmc", "emmc_rst", }; ++static const char *mt7622_ethernet_groups[] = { "esw", "esw_p0_p1", ++ "esw_p2_p3_p4", "mdc_mdio", ++ "rgmii_via_gmac1", ++ "rgmii_via_gmac2", ++ "rgmii_via_esw", }; ++static const char *mt7622_i2c_groups[] = { "i2c0", "i2c1_0", "i2c1_1", ++ "i2c1_2", "i2c2_0", "i2c2_1", ++ "i2c2_2", }; ++static const char *mt7622_i2s_groups[] = { "i2s_out_mclk_bclk_ws", ++ "i2s_in_mclk_bclk_ws", ++ "i2s1_in_data", "i2s2_in_data", ++ "i2s3_in_data", "i2s4_in_data", ++ "i2s1_out_data", "i2s2_out_data", ++ "i2s3_out_data", "i2s4_out_data", }; ++static const char *mt7622_ir_groups[] = { "ir_0_tx", "ir_1_tx", "ir_2_tx", ++ "ir_0_rx", "ir_1_rx", "ir_2_rx"}; ++static const char *mt7622_led_groups[] = { "ephy_leds", "ephy0_led", ++ "ephy1_led", "ephy2_led", ++ "ephy3_led", "ephy4_led", ++ "wled", }; ++static const char *mt7622_flash_groups[] = { "par_nand", "snfi", "spi_nor"}; ++static const char *mt7622_pcie_groups[] = { "pcie0_0_waken", "pcie0_0_clkreq", ++ "pcie0_1_waken", "pcie0_1_clkreq", ++ "pcie1_0_waken", "pcie1_0_clkreq", ++ "pcie0_pad_perst", ++ "pcie1_pad_perst", }; ++static const char *mt7622_pmic_bus_groups[] = { "pmic_bus", }; ++static const char *mt7622_pwm_groups[] = { "pwm_ch1_0", "pwm_ch1_1", ++ "pwm_ch1_2", "pwm_ch2_0", ++ "pwm_ch2_1", "pwm_ch2_2", ++ "pwm_ch3_0", "pwm_ch3_1", ++ "pwm_ch3_2", "pwm_ch4_0", ++ "pwm_ch4_1", "pwm_ch4_2", ++ "pwm_ch4_3", "pwm_ch5_0", ++ "pwm_ch5_1", "pwm_ch5_2", ++ "pwm_ch6_0", "pwm_ch6_1", ++ "pwm_ch6_2", "pwm_ch6_3", ++ "pwm_ch7_0", "pwm_ch7_1", ++ "pwm_ch7_2", }; ++static const char *mt7622_sd_groups[] = { "sd_0", "sd_1", }; ++static const char *mt7622_spic_groups[] = { "spic0_0", "spic0_1", "spic1_0", ++ "spic1_1", "spic2_0", ++ "spic2_0_wp_hold", }; ++static const char *mt7622_tdm_groups[] = { "tdm_0_out_mclk_bclk_ws", ++ "tdm_0_in_mclk_bclk_ws", ++ "tdm_0_out_data", ++ "tdm_0_in_data", ++ "tdm_1_out_mclk_bclk_ws", ++ "tdm_1_in_mclk_bclk_ws", ++ "tdm_1_out_data", ++ "tdm_1_in_data", }; ++ ++static const char *mt7622_uart_groups[] = { "uart0_0_tx_rx", ++ "uart1_0_tx_rx", "uart1_0_rts_cts", ++ "uart1_1_tx_rx", "uart1_1_rts_cts", ++ "uart2_0_tx_rx", "uart2_0_rts_cts", ++ "uart2_1_tx_rx", "uart2_1_rts_cts", ++ "uart2_2_tx_rx", "uart2_2_rts_cts", ++ "uart2_3_tx_rx", ++ "uart3_0_tx_rx", ++ "uart3_1_tx_rx", "uart3_1_rts_cts", ++ "uart4_0_tx_rx", ++ "uart4_1_tx_rx", "uart4_1_rts_cts", ++ "uart4_2_tx_rx", ++ "uart4_2_rts_cts",}; ++static const char *mt7622_wdt_groups[] = { "watchdog", }; ++ ++static const struct function_desc mt7622_functions[] = { ++ {"emmc", mt7622_emmc_groups, ARRAY_SIZE(mt7622_emmc_groups)}, ++ {"eth", mt7622_ethernet_groups, ARRAY_SIZE(mt7622_ethernet_groups)}, ++ {"i2c", mt7622_i2c_groups, ARRAY_SIZE(mt7622_i2c_groups)}, ++ {"i2s", mt7622_i2s_groups, ARRAY_SIZE(mt7622_i2s_groups)}, ++ {"ir", mt7622_ir_groups, ARRAY_SIZE(mt7622_ir_groups)}, ++ {"led", mt7622_led_groups, ARRAY_SIZE(mt7622_led_groups)}, ++ {"flash", mt7622_flash_groups, ARRAY_SIZE(mt7622_flash_groups)}, ++ {"pcie", mt7622_pcie_groups, ARRAY_SIZE(mt7622_pcie_groups)}, ++ {"pmic", mt7622_pmic_bus_groups, ARRAY_SIZE(mt7622_pmic_bus_groups)}, ++ {"pwm", mt7622_pwm_groups, ARRAY_SIZE(mt7622_pwm_groups)}, ++ {"sd", mt7622_sd_groups, ARRAY_SIZE(mt7622_sd_groups)}, ++ {"spi", mt7622_spic_groups, ARRAY_SIZE(mt7622_spic_groups)}, ++ {"tdm", mt7622_tdm_groups, ARRAY_SIZE(mt7622_tdm_groups)}, ++ {"uart", mt7622_uart_groups, ARRAY_SIZE(mt7622_uart_groups)}, ++ {"watchdog", mt7622_wdt_groups, ARRAY_SIZE(mt7622_wdt_groups)}, ++}; ++ ++static const struct pinconf_generic_params mtk_custom_bindings[] = { ++ {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0}, ++ {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0}, ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++static const struct pin_config_item mtk_conf_items[] = { ++ PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true), ++ PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true), ++}; ++#endif ++ ++static const struct mtk_pin_soc mt7622_data = { ++ .reg_cal = mt7622_reg_cals, ++ .pins = mt7622_pins, ++ .npins = ARRAY_SIZE(mt7622_pins), ++ .grps = mt7622_groups, ++ .ngrps = ARRAY_SIZE(mt7622_groups), ++ .funcs = mt7622_functions, ++ .nfuncs = ARRAY_SIZE(mt7622_functions), ++}; ++ ++static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val) ++{ ++ writel_relaxed(val, pctl->base + reg); ++} ++ ++static u32 mtk_r32(struct mtk_pinctrl *pctl, u32 reg) ++{ ++ return readl_relaxed(pctl->base + reg); ++} ++ ++static void mtk_rmw(struct mtk_pinctrl *pctl, u32 reg, u32 mask, u32 set) ++{ ++ u32 val; ++ ++ val = mtk_r32(pctl, reg); ++ val &= ~mask; ++ val |= set; ++ mtk_w32(pctl, reg, val); ++} ++ ++static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, int pin, ++ const struct mtk_pin_reg_calc *rc, ++ struct mtk_pin_field *pfd) ++{ ++ const struct mtk_pin_field_calc *c, *e; ++ u32 bits; ++ ++ c = rc->range; ++ e = c + rc->nranges; ++ ++ while (c < e) { ++ if (pin >= c->s_pin && pin <= c->e_pin) ++ break; ++ c++; ++ } ++ ++ if (c >= e) { ++ dev_err(hw->dev, "Out of range for pin = %d\n", pin); ++ return -EINVAL; ++ } ++ ++ /* Caculated bits as the overall offset the pin is located at */ ++ bits = c->s_bit + (pin - c->s_pin) * (c->x_bits); ++ ++ /* Fill pfd from bits and 32-bit register applied is assumed */ ++ pfd->offset = c->s_addr + c->x_addrs * (bits / 32); ++ pfd->bitpos = bits % 32; ++ pfd->mask = (1 << c->x_bits) - 1; ++ ++ /* pfd->next is used for indicating that bit wrapping-around happens ++ * which requires the manipulation for bit 0 starting in the next ++ * register to form the complete field read/write. ++ */ ++ pfd->next = pfd->bitpos + c->x_bits - 1 > 31 ? c->x_addrs : 0; ++ ++ return 0; ++} ++ ++static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw, int pin, ++ int field, struct mtk_pin_field *pfd) ++{ ++ const struct mtk_pin_reg_calc *rc; ++ ++ if (field < 0 || field >= PINCTRL_PIN_REG_MAX) { ++ dev_err(hw->dev, "Invalid Field %d\n", field); ++ return -EINVAL; ++ } ++ ++ if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) { ++ rc = &hw->soc->reg_cal[field]; ++ } else { ++ dev_err(hw->dev, "Undefined range for field %d\n", field); ++ return -EINVAL; ++ } ++ ++ return mtk_hw_pin_field_lookup(hw, pin, rc, pfd); ++} ++ ++static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l) ++{ ++ *l = 32 - pf->bitpos; ++ *h = get_count_order(pf->mask) - *l; ++} ++ ++static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw, ++ struct mtk_pin_field *pf, int value) ++{ ++ int nbits_l, nbits_h; ++ ++ mtk_hw_bits_part(pf, &nbits_h, &nbits_l); ++ ++ mtk_rmw(hw, pf->offset, pf->mask << pf->bitpos, ++ (value & pf->mask) << pf->bitpos); ++ ++ mtk_rmw(hw, pf->offset + pf->next, BIT(nbits_h) - 1, ++ (value & pf->mask) >> nbits_l); ++} ++ ++static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw, ++ struct mtk_pin_field *pf, int *value) ++{ ++ int nbits_l, nbits_h, h, l; ++ ++ mtk_hw_bits_part(pf, &nbits_h, &nbits_l); ++ ++ l = (mtk_r32(hw, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1); ++ h = (mtk_r32(hw, pf->offset + pf->next)) & (BIT(nbits_h) - 1); ++ ++ *value = (h << nbits_l) | l; ++} ++ ++static int mtk_hw_set_value(struct mtk_pinctrl *hw, int pin, int field, ++ int value) ++{ ++ struct mtk_pin_field pf; ++ int err; ++ ++ err = mtk_hw_pin_field_get(hw, pin, field, &pf); ++ if (err) ++ return err; ++ ++ if (!pf.next) ++ mtk_rmw(hw, pf.offset, pf.mask << pf.bitpos, ++ (value & pf.mask) << pf.bitpos); ++ else ++ mtk_hw_write_cross_field(hw, &pf, value); ++ ++ return 0; ++} ++ ++static int mtk_hw_get_value(struct mtk_pinctrl *hw, int pin, int field, ++ int *value) ++{ ++ struct mtk_pin_field pf; ++ int err; ++ ++ err = mtk_hw_pin_field_get(hw, pin, field, &pf); ++ if (err) ++ return err; ++ ++ if (!pf.next) ++ *value = (mtk_r32(hw, pf.offset) >> pf.bitpos) & pf.mask; ++ else ++ mtk_hw_read_cross_field(hw, &pf, value); ++ ++ return 0; ++} ++ ++static int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev, ++ unsigned int selector, unsigned int group) ++{ ++ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); ++ struct function_desc *func; ++ struct group_desc *grp; ++ int i; ++ ++ func = pinmux_generic_get_function(pctldev, selector); ++ if (!func) ++ return -EINVAL; ++ ++ grp = pinctrl_generic_get_group(pctldev, group); ++ if (!grp) ++ return -EINVAL; ++ ++ dev_dbg(pctldev->dev, "enable function %s group %s\n", ++ func->name, grp->name); ++ ++ for (i = 0; i < grp->num_pins; i++) { ++ int *pin_modes = grp->data; ++ ++ mtk_hw_set_value(hw, grp->pins[i], PINCTRL_PIN_REG_MODE, ++ pin_modes[i]); ++ } ++ ++ return 0; ++} ++ ++static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned int pin) ++{ ++ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); ++ ++ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_MODE, MTK_GPIO_MODE); ++} ++ ++static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned int pin, bool input) ++{ ++ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); ++ ++ /* hardware would take 0 as input direction */ ++ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR, !input); ++} ++ ++static int mtk_pinconf_get(struct pinctrl_dev *pctldev, ++ unsigned int pin, unsigned long *config) ++{ ++ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); ++ u32 param = pinconf_to_config_param(*config); ++ int val, val2, err, reg, ret = 1; ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PU, &val); ++ if (err) ++ return err; ++ ++ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PD, &val2); ++ if (err) ++ return err; ++ ++ if (val || val2) ++ return -EINVAL; ++ ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ case PIN_CONFIG_SLEW_RATE: ++ reg = (param == PIN_CONFIG_BIAS_PULL_UP) ? ++ PINCTRL_PIN_REG_PU : ++ (param == PIN_CONFIG_BIAS_PULL_DOWN) ? ++ PINCTRL_PIN_REG_PD : PINCTRL_PIN_REG_SR; ++ ++ err = mtk_hw_get_value(hw, pin, reg, &val); ++ if (err) ++ return err; ++ ++ if (!val) ++ return -EINVAL; ++ ++ break; ++ case PIN_CONFIG_INPUT_ENABLE: ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val); ++ if (err) ++ return -EINVAL; ++ ++ /* HW takes input mode as zero; output mode as non-zero */ ++ if ((val && param == PIN_CONFIG_INPUT_ENABLE) || ++ (!val && param == PIN_CONFIG_OUTPUT_ENABLE)) ++ return -EINVAL; ++ ++ break; ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val); ++ if (err) ++ return err; ++ ++ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_SMT, &val2); ++ if (err) ++ return err; ++ ++ if (val || !val2) ++ return -EINVAL; ++ ++ break; ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E4, &val); ++ if (err) ++ return -EINVAL; ++ ++ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E8, &val2); ++ if (err) ++ return -EINVAL; ++ ++ /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1) ++ * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1) ++ */ ++ ret = ((val2 << 1) + val + 1) * 4; ++ ++ break; ++ case MTK_PIN_CONFIG_TDSEL: ++ case MTK_PIN_CONFIG_RDSEL: ++ reg = (param == MTK_PIN_CONFIG_TDSEL) ? ++ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; ++ ++ err = mtk_hw_get_value(hw, pin, reg, &val); ++ if (err) ++ return -EINVAL; ++ ++ ret = val; ++ ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ *config = pinconf_to_config_packed(param, ret); ++ ++ return 0; ++} ++ ++static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, ++ unsigned long *configs, unsigned int num_configs) ++{ ++ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); ++ u32 reg, param, arg; ++ int cfg, err = 0; ++ ++ for (cfg = 0; cfg < num_configs; cfg++) { ++ param = pinconf_to_config_param(configs[cfg]); ++ arg = pinconf_to_config_argument(configs[cfg]); ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ case PIN_CONFIG_BIAS_PULL_UP: ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 : ++ (param == PIN_CONFIG_BIAS_PULL_UP) ? 1 : 2; ++ ++ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PU, ++ arg & 1); ++ if (err) ++ goto err; ++ ++ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PD, ++ !!(arg & 2)); ++ if (err) ++ goto err; ++ break; ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT, ++ MTK_DISABLE); ++ if (err) ++ goto err; ++ case PIN_CONFIG_INPUT_ENABLE: ++ case PIN_CONFIG_SLEW_RATE: ++ reg = (param == PIN_CONFIG_SLEW_RATE) ? ++ PINCTRL_PIN_REG_SR : PINCTRL_PIN_REG_DIR; ++ ++ arg = (param == PIN_CONFIG_INPUT_ENABLE) ? 0 : ++ (param == PIN_CONFIG_OUTPUT_ENABLE) ? 1 : arg; ++ err = mtk_hw_set_value(hw, pin, reg, arg); ++ if (err) ++ goto err; ++ ++ break; ++ case PIN_CONFIG_OUTPUT: ++ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR, ++ MTK_OUTPUT); ++ if (err) ++ goto err; ++ ++ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DO, ++ arg); ++ if (err) ++ goto err; ++ break; ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ /* arg = 1: Input mode & SMT enable ; ++ * arg = 0: Output mode & SMT disable ++ */ ++ arg = arg ? 2 : 1; ++ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR, ++ arg & 1); ++ if (err) ++ goto err; ++ ++ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT, ++ !!(arg & 2)); ++ if (err) ++ goto err; ++ break; ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ /* 4mA when (e8, e4) = (0, 0); ++ * 8mA when (e8, e4) = (0, 1); ++ * 12mA when (e8, e4) = (1, 0); ++ * 16mA when (e8, e4) = (1, 1) ++ */ ++ if (!(arg % 4) && (arg >= 4 && arg <= 16)) { ++ arg = arg / 4 - 1; ++ err = mtk_hw_set_value(hw, pin, ++ PINCTRL_PIN_REG_E4, ++ arg & 0x1); ++ if (err) ++ goto err; ++ ++ err = mtk_hw_set_value(hw, pin, ++ PINCTRL_PIN_REG_E8, ++ (arg & 0x2) >> 1); ++ if (err) ++ goto err; ++ } else { ++ err = -ENOTSUPP; ++ } ++ break; ++ case MTK_PIN_CONFIG_TDSEL: ++ case MTK_PIN_CONFIG_RDSEL: ++ reg = (param == MTK_PIN_CONFIG_TDSEL) ? ++ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; ++ ++ err = mtk_hw_set_value(hw, pin, reg, arg); ++ if (err) ++ goto err; ++ break; ++ default: ++ err = -ENOTSUPP; ++ } ++ } ++err: ++ return err; ++} ++ ++static int mtk_pinconf_group_get(struct pinctrl_dev *pctldev, ++ unsigned int group, unsigned long *config) ++{ ++ const unsigned int *pins; ++ unsigned int i, npins, old = 0; ++ int ret; ++ ++ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < npins; i++) { ++ if (mtk_pinconf_get(pctldev, pins[i], config)) ++ return -ENOTSUPP; ++ ++ /* configs do not match between two pins */ ++ if (i && old != *config) ++ return -ENOTSUPP; ++ ++ old = *config; ++ } ++ ++ return 0; ++} ++ ++static int mtk_pinconf_group_set(struct pinctrl_dev *pctldev, ++ unsigned int group, unsigned long *configs, ++ unsigned int num_configs) ++{ ++ const unsigned int *pins; ++ unsigned int i, npins; ++ int ret; ++ ++ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < npins; i++) { ++ ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct pinctrl_ops mtk_pctlops = { ++ .get_groups_count = pinctrl_generic_get_group_count, ++ .get_group_name = pinctrl_generic_get_group_name, ++ .get_group_pins = pinctrl_generic_get_group_pins, ++ .dt_node_to_map = pinconf_generic_dt_node_to_map_all, ++ .dt_free_map = pinconf_generic_dt_free_map, ++}; ++ ++static const struct pinmux_ops mtk_pmxops = { ++ .get_functions_count = pinmux_generic_get_function_count, ++ .get_function_name = pinmux_generic_get_function_name, ++ .get_function_groups = pinmux_generic_get_function_groups, ++ .set_mux = mtk_pinmux_set_mux, ++ .gpio_request_enable = mtk_pinmux_gpio_request_enable, ++ .gpio_set_direction = mtk_pinmux_gpio_set_direction, ++ .strict = true, ++}; ++ ++static const struct pinconf_ops mtk_confops = { ++ .is_generic = true, ++ .pin_config_get = mtk_pinconf_get, ++ .pin_config_set = mtk_pinconf_set, ++ .pin_config_group_get = mtk_pinconf_group_get, ++ .pin_config_group_set = mtk_pinconf_group_set, ++ .pin_config_config_dbg_show = pinconf_generic_dump_config, ++}; ++ ++static struct pinctrl_desc mtk_desc = { ++ .name = PINCTRL_PINCTRL_DEV, ++ .pctlops = &mtk_pctlops, ++ .pmxops = &mtk_pmxops, ++ .confops = &mtk_confops, ++ .owner = THIS_MODULE, ++}; ++ ++static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) ++{ ++ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent); ++ int value; ++ ++ mtk_hw_get_value(hw, gpio, PINCTRL_PIN_REG_DI, &value); ++ ++ return !!value; ++} ++ ++static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) ++{ ++ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent); ++ ++ mtk_hw_set_value(hw, gpio, PINCTRL_PIN_REG_DO, !!value); ++} ++ ++static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio) ++{ ++ return pinctrl_gpio_direction_input(chip->base + gpio); ++} ++ ++static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio, ++ int value) ++{ ++ mtk_gpio_set(chip, gpio, value); ++ ++ return pinctrl_gpio_direction_output(chip->base + gpio); ++} ++ ++static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np) ++{ ++ struct gpio_chip *chip = &hw->chip; ++ int ret; ++ ++ chip->label = PINCTRL_PINCTRL_DEV; ++ chip->parent = hw->dev; ++ chip->request = gpiochip_generic_request; ++ chip->free = gpiochip_generic_free; ++ chip->direction_input = mtk_gpio_direction_input; ++ chip->direction_output = mtk_gpio_direction_output; ++ chip->get = mtk_gpio_get; ++ chip->set = mtk_gpio_set; ++ chip->base = -1; ++ chip->ngpio = hw->soc->npins; ++ chip->of_node = np; ++ chip->of_gpio_n_cells = 2; ++ ++ ret = gpiochip_add_data(chip, hw); ++ if (ret < 0) ++ return ret; ++ ++ ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0, ++ chip->ngpio); ++ if (ret < 0) { ++ gpiochip_remove(chip); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mtk_build_groups(struct mtk_pinctrl *hw) ++{ ++ int err, i; ++ ++ for (i = 0; i < hw->soc->ngrps; i++) { ++ const struct group_desc *group = hw->soc->grps + i; ++ ++ err = pinctrl_generic_add_group(hw->pctrl, group->name, ++ group->pins, group->num_pins, ++ group->data); ++ if (err) { ++ dev_err(hw->dev, "Failed to register group %s\n", ++ group->name); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++static int mtk_build_functions(struct mtk_pinctrl *hw) ++{ ++ int i, err; ++ ++ for (i = 0; i < hw->soc->nfuncs ; i++) { ++ const struct function_desc *func = hw->soc->funcs + i; ++ ++ err = pinmux_generic_add_function(hw->pctrl, func->name, ++ func->group_names, ++ func->num_group_names, ++ func->data); ++ if (err) { ++ dev_err(hw->dev, "Failed to register function %s\n", ++ func->name); ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id mtk_pinctrl_of_match[] = { ++ { .compatible = "mediatek,mt7622-pinctrl", .data = &mt7622_data}, ++ { } ++}; ++ ++static int mtk_pinctrl_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct mtk_pinctrl *hw; ++ const struct of_device_id *of_id = ++ of_match_device(mtk_pinctrl_of_match, &pdev->dev); ++ int err; ++ ++ hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL); ++ if (!hw) ++ return -ENOMEM; ++ ++ hw->soc = of_id->data; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "missing IO resource\n"); ++ return -ENXIO; ++ } ++ ++ hw->dev = &pdev->dev; ++ hw->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(hw->base)) ++ return PTR_ERR(hw->base); ++ ++ /* Setup pins descriptions per SoC types */ ++ mtk_desc.pins = hw->soc->pins; ++ mtk_desc.npins = hw->soc->npins; ++ mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings); ++ mtk_desc.custom_params = mtk_custom_bindings; ++#ifdef CONFIG_DEBUG_FS ++ mtk_desc.custom_conf_items = mtk_conf_items; ++#endif ++ ++ hw->pctrl = devm_pinctrl_register(&pdev->dev, &mtk_desc, hw); ++ if (IS_ERR(hw->pctrl)) ++ return PTR_ERR(hw->pctrl); ++ ++ /* Setup groups descriptions per SoC types */ ++ err = mtk_build_groups(hw); ++ if (err) { ++ dev_err(&pdev->dev, "Failed to build groups\n"); ++ return 0; ++ } ++ ++ /* Setup functions descriptions per SoC types */ ++ err = mtk_build_functions(hw); ++ if (err) { ++ dev_err(&pdev->dev, "Failed to build functions\n"); ++ return err; ++ } ++ ++ err = mtk_build_gpiochip(hw, pdev->dev.of_node); ++ if (err) { ++ dev_err(&pdev->dev, "Failed to add gpio_chip\n"); ++ return err; ++ } ++ ++ platform_set_drvdata(pdev, hw); ++ ++ return 0; ++} ++ ++static struct platform_driver mtk_pinctrl_driver = { ++ .driver = { ++ .name = "mtk-pinctrl", ++ .of_match_table = mtk_pinctrl_of_match, ++ }, ++ .probe = mtk_pinctrl_probe, ++}; ++ ++static int __init mtk_pinctrl_init(void) ++{ ++ return platform_driver_register(&mtk_pinctrl_driver); ++} ++arch_initcall(mtk_pinctrl_init); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0172-clk-mediatek-group-drivers-under-indpendent-menu.patch b/target/linux/mediatek/patches-4.14/0172-clk-mediatek-group-drivers-under-indpendent-menu.patch new file mode 100644 index 0000000000..ce16723af7 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0172-clk-mediatek-group-drivers-under-indpendent-menu.patch @@ -0,0 +1,228 @@ +From 13ee94af58240b75550f413fece707987d563193 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 20 Dec 2017 14:42:58 +0800 +Subject: [PATCH 172/224] clk: mediatek: group drivers under indpendent menu + +Getting much MediaTek clock driver have been added to CCF, so it's +better adding the cleanup for grouping drivers under the independent +menu to simplify configuration selection. In addition, really trivial +fixups for typos are added in the same patch. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/mediatek/Kconfig | 96 +++++++++++++++++++++++--------------------- + 1 file changed, 50 insertions(+), 46 deletions(-) + +diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig +index 59dc0aad553c..7338f816c603 100644 +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -1,136 +1,139 @@ + # +-# MediaTek SoC drivers ++# MediaTek Clock Drivers + # ++menu "Clock driver for MediaTek SoC" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ + config COMMON_CLK_MEDIATEK + bool + ---help--- +- Mediatek SoCs' clock support. ++ MediaTek SoCs' clock support. + + config COMMON_CLK_MT2701 +- bool "Clock driver for Mediatek MT2701" ++ bool "Clock driver for MediaTek MT2701" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM + ---help--- +- This driver supports Mediatek MT2701 basic clocks. ++ This driver supports MediaTek MT2701 basic clocks. + + config COMMON_CLK_MT2701_MMSYS +- bool "Clock driver for Mediatek MT2701 mmsys" ++ bool "Clock driver for MediaTek MT2701 mmsys" + depends on COMMON_CLK_MT2701 + ---help--- +- This driver supports Mediatek MT2701 mmsys clocks. ++ This driver supports MediaTek MT2701 mmsys clocks. + + config COMMON_CLK_MT2701_IMGSYS +- bool "Clock driver for Mediatek MT2701 imgsys" ++ bool "Clock driver for MediaTek MT2701 imgsys" + depends on COMMON_CLK_MT2701 + ---help--- +- This driver supports Mediatek MT2701 imgsys clocks. ++ This driver supports MediaTek MT2701 imgsys clocks. + + config COMMON_CLK_MT2701_VDECSYS +- bool "Clock driver for Mediatek MT2701 vdecsys" ++ bool "Clock driver for MediaTek MT2701 vdecsys" + depends on COMMON_CLK_MT2701 + ---help--- +- This driver supports Mediatek MT2701 vdecsys clocks. ++ This driver supports MediaTek MT2701 vdecsys clocks. + + config COMMON_CLK_MT2701_HIFSYS +- bool "Clock driver for Mediatek MT2701 hifsys" ++ bool "Clock driver for MediaTek MT2701 hifsys" + depends on COMMON_CLK_MT2701 + ---help--- +- This driver supports Mediatek MT2701 hifsys clocks. ++ This driver supports MediaTek MT2701 hifsys clocks. + + config COMMON_CLK_MT2701_ETHSYS +- bool "Clock driver for Mediatek MT2701 ethsys" ++ bool "Clock driver for MediaTek MT2701 ethsys" + depends on COMMON_CLK_MT2701 + ---help--- +- This driver supports Mediatek MT2701 ethsys clocks. ++ This driver supports MediaTek MT2701 ethsys clocks. + + config COMMON_CLK_MT2701_BDPSYS +- bool "Clock driver for Mediatek MT2701 bdpsys" ++ bool "Clock driver for MediaTek MT2701 bdpsys" + depends on COMMON_CLK_MT2701 + ---help--- +- This driver supports Mediatek MT2701 bdpsys clocks. ++ This driver supports MediaTek MT2701 bdpsys clocks. + + config COMMON_CLK_MT2712 +- bool "Clock driver for Mediatek MT2712" ++ bool "Clock driver for MediaTek MT2712" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + ---help--- +- This driver supports Mediatek MT2712 basic clocks. ++ This driver supports MediaTek MT2712 basic clocks. + + config COMMON_CLK_MT2712_BDPSYS +- bool "Clock driver for Mediatek MT2712 bdpsys" ++ bool "Clock driver for MediaTek MT2712 bdpsys" + depends on COMMON_CLK_MT2712 + ---help--- +- This driver supports Mediatek MT2712 bdpsys clocks. ++ This driver supports MediaTek MT2712 bdpsys clocks. + + config COMMON_CLK_MT2712_IMGSYS +- bool "Clock driver for Mediatek MT2712 imgsys" ++ bool "Clock driver for MediaTek MT2712 imgsys" + depends on COMMON_CLK_MT2712 + ---help--- +- This driver supports Mediatek MT2712 imgsys clocks. ++ This driver supports MediaTek MT2712 imgsys clocks. + + config COMMON_CLK_MT2712_JPGDECSYS +- bool "Clock driver for Mediatek MT2712 jpgdecsys" ++ bool "Clock driver for MediaTek MT2712 jpgdecsys" + depends on COMMON_CLK_MT2712 + ---help--- +- This driver supports Mediatek MT2712 jpgdecsys clocks. ++ This driver supports MediaTek MT2712 jpgdecsys clocks. + + config COMMON_CLK_MT2712_MFGCFG +- bool "Clock driver for Mediatek MT2712 mfgcfg" ++ bool "Clock driver for MediaTek MT2712 mfgcfg" + depends on COMMON_CLK_MT2712 + ---help--- +- This driver supports Mediatek MT2712 mfgcfg clocks. ++ This driver supports MediaTek MT2712 mfgcfg clocks. + + config COMMON_CLK_MT2712_MMSYS +- bool "Clock driver for Mediatek MT2712 mmsys" ++ bool "Clock driver for MediaTek MT2712 mmsys" + depends on COMMON_CLK_MT2712 + ---help--- +- This driver supports Mediatek MT2712 mmsys clocks. ++ This driver supports MediaTek MT2712 mmsys clocks. + + config COMMON_CLK_MT2712_VDECSYS +- bool "Clock driver for Mediatek MT2712 vdecsys" ++ bool "Clock driver for MediaTek MT2712 vdecsys" + depends on COMMON_CLK_MT2712 + ---help--- +- This driver supports Mediatek MT2712 vdecsys clocks. ++ This driver supports MediaTek MT2712 vdecsys clocks. + + config COMMON_CLK_MT2712_VENCSYS +- bool "Clock driver for Mediatek MT2712 vencsys" ++ bool "Clock driver for MediaTek MT2712 vencsys" + depends on COMMON_CLK_MT2712 + ---help--- +- This driver supports Mediatek MT2712 vencsys clocks. ++ This driver supports MediaTek MT2712 vencsys clocks. + + config COMMON_CLK_MT6797 +- bool "Clock driver for Mediatek MT6797" ++ bool "Clock driver for MediaTek MT6797" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + ---help--- +- This driver supports Mediatek MT6797 basic clocks. ++ This driver supports MediaTek MT6797 basic clocks. + + config COMMON_CLK_MT6797_MMSYS +- bool "Clock driver for Mediatek MT6797 mmsys" ++ bool "Clock driver for MediaTek MT6797 mmsys" + depends on COMMON_CLK_MT6797 + ---help--- +- This driver supports Mediatek MT6797 mmsys clocks. ++ This driver supports MediaTek MT6797 mmsys clocks. + + config COMMON_CLK_MT6797_IMGSYS +- bool "Clock driver for Mediatek MT6797 imgsys" ++ bool "Clock driver for MediaTek MT6797 imgsys" + depends on COMMON_CLK_MT6797 + ---help--- +- This driver supports Mediatek MT6797 imgsys clocks. ++ This driver supports MediaTek MT6797 imgsys clocks. + + config COMMON_CLK_MT6797_VDECSYS +- bool "Clock driver for Mediatek MT6797 vdecsys" ++ bool "Clock driver for MediaTek MT6797 vdecsys" + depends on COMMON_CLK_MT6797 + ---help--- +- This driver supports Mediatek MT6797 vdecsys clocks. ++ This driver supports MediaTek MT6797 vdecsys clocks. + + config COMMON_CLK_MT6797_VENCSYS +- bool "Clock driver for Mediatek MT6797 vencsys" ++ bool "Clock driver for MediaTek MT6797 vencsys" + depends on COMMON_CLK_MT6797 + ---help--- +- This driver supports Mediatek MT6797 vencsys clocks. ++ This driver supports MediaTek MT6797 vencsys clocks. + + config COMMON_CLK_MT7622 + bool "Clock driver for MediaTek MT7622" +@@ -163,17 +166,18 @@ config COMMON_CLK_MT7622_AUDSYS + to audio consumers such as I2S and TDM. + + config COMMON_CLK_MT8135 +- bool "Clock driver for Mediatek MT8135" ++ bool "Clock driver for MediaTek MT8135" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM + ---help--- +- This driver supports Mediatek MT8135 clocks. ++ This driver supports MediaTek MT8135 clocks. + + config COMMON_CLK_MT8173 +- bool "Clock driver for Mediatek MT8173" ++ bool "Clock driver for MediaTek MT8173" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + ---help--- +- This driver supports Mediatek MT8173 clocks. ++ This driver supports MediaTek MT8173 clocks. ++endmenu +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0173-clk-mediatek-fixup-test-building-of-MediaTek-clock-d.patch b/target/linux/mediatek/patches-4.14/0173-clk-mediatek-fixup-test-building-of-MediaTek-clock-d.patch new file mode 100644 index 0000000000..386a15a568 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0173-clk-mediatek-fixup-test-building-of-MediaTek-clock-d.patch @@ -0,0 +1,32 @@ +From 3f963310151f6e630f94acf73ff44493619038ff Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 20 Dec 2017 14:42:59 +0800 +Subject: [PATCH 173/224] clk: mediatek: fixup test-building of MediaTek clock + drivers + +Let the build system looking into the directiory where the clock drivers +resides for the COMPILE_TEST alternative dependency allows test-building +the drivers. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile +index c99f363826f0..838000f92b69 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -66,7 +66,7 @@ obj-$(CONFIG_ARCH_MXC) += imx/ + obj-$(CONFIG_MACH_INGENIC) += ingenic/ + obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ + obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ +-obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ ++obj-y += mediatek/ + obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/ + obj-$(CONFIG_MACH_PIC32) += microchip/ + ifeq ($(CONFIG_COMMON_CLK), y) +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0174-dt-bindings-net-mediatek-add-condition-to-property-m.patch b/target/linux/mediatek/patches-4.14/0174-dt-bindings-net-mediatek-add-condition-to-property-m.patch new file mode 100644 index 0000000000..aed5ec59f3 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0174-dt-bindings-net-mediatek-add-condition-to-property-m.patch @@ -0,0 +1,32 @@ +From ee687ebf4708fb9e2a64830cdecd8cf992ef9b2b Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 20 Dec 2017 17:47:05 +0800 +Subject: [PATCH 174/224] dt-bindings: net: mediatek: add condition to property + mediatek, pctl + +The property "mediatek,pctl" is only required for SoCs such as MT2701 and +MT7623, so adding a few words for stating the condition. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Rob Herring <robh@kernel.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + Documentation/devicetree/bindings/net/mediatek-net.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt b/Documentation/devicetree/bindings/net/mediatek-net.txt +index 214eaa9a6683..53c13ee384a4 100644 +--- a/Documentation/devicetree/bindings/net/mediatek-net.txt ++++ b/Documentation/devicetree/bindings/net/mediatek-net.txt +@@ -28,7 +28,7 @@ Required properties: + - mediatek,sgmiisys: phandle to the syscon node that handles the SGMII setup + which is required for those SoCs equipped with SGMII such as MT7622 SoC. + - mediatek,pctl: phandle to the syscon node that handles the ports slew rate +- and driver current ++ and driver current: only for MT2701 and MT7623 SoC + + Optional properties: + - interrupt-parent: Should be the phandle for the interrupt controller +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0175-net-mediatek-remove-superfluous-pin-setup-for-MT7622.patch b/target/linux/mediatek/patches-4.14/0175-net-mediatek-remove-superfluous-pin-setup-for-MT7622.patch new file mode 100644 index 0000000000..3116f03f06 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0175-net-mediatek-remove-superfluous-pin-setup-for-MT7622.patch @@ -0,0 +1,106 @@ +From d96cf7e724105dc73f623c2019ab5bc78cef036e Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 20 Dec 2017 17:47:06 +0800 +Subject: [PATCH 175/224] net: mediatek: remove superfluous pin setup for + MT7622 SoC + +Remove superfluous pin setup to get out of accessing invalid I/O pin +registers because the way for pin configuring tends to be different from +various SoCs and thus it should be better being managed and controlled by +the pinctrl driver which MT7622 already can support. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 +++++++++++++++++------------ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +++ + 2 files changed, 24 insertions(+), 14 deletions(-) + +Index: linux-4.14.37/drivers/net/ethernet/mediatek/mtk_eth_soc.c +=================================================================== +--- linux-4.14.37.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ linux-4.14.37/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1976,14 +1976,16 @@ static int mtk_hw_init(struct mtk_eth *e + } + regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val); + +- /* Set GE2 driving and slew rate */ +- regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00); ++ if (eth->pctl) { ++ /* Set GE2 driving and slew rate */ ++ regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00); + +- /* set GE2 TDSEL */ +- regmap_write(eth->pctl, GPIO_OD33_CTRL8, 0x5); ++ /* set GE2 TDSEL */ ++ regmap_write(eth->pctl, GPIO_OD33_CTRL8, 0x5); + +- /* set GE2 TUNE */ +- regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0); ++ /* set GE2 TUNE */ ++ regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0); ++ } + + /* Set linkdown as the default for each GMAC. Its own MCR would be set + * up with the more appropriate value when mtk_phy_link_adjust call is +@@ -2568,11 +2570,13 @@ static int mtk_probe(struct platform_dev + } + } + +- eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, +- "mediatek,pctl"); +- if (IS_ERR(eth->pctl)) { +- dev_err(&pdev->dev, "no pctl regmap found\n"); +- return PTR_ERR(eth->pctl); ++ if (eth->soc->required_pctl) { ++ eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, ++ "mediatek,pctl"); ++ if (IS_ERR(eth->pctl)) { ++ dev_err(&pdev->dev, "no pctl regmap found\n"); ++ return PTR_ERR(eth->pctl); ++ } + } + + for (i = 0; i < 3; i++) { +@@ -2698,17 +2702,20 @@ static int mtk_remove(struct platform_de + + static const struct mtk_soc_data mt2701_data = { + .caps = MTK_GMAC1_TRGMII, +- .required_clks = MT7623_CLKS_BITMAP ++ .required_clks = MT7623_CLKS_BITMAP, ++ .required_pctl = true, + }; + + static const struct mtk_soc_data mt7622_data = { + .caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW, +- .required_clks = MT7622_CLKS_BITMAP ++ .required_clks = MT7622_CLKS_BITMAP, ++ .required_pctl = false, + }; + + static const struct mtk_soc_data mt7623_data = { + .caps = MTK_GMAC1_TRGMII, +- .required_clks = MT7623_CLKS_BITMAP ++ .required_clks = MT7623_CLKS_BITMAP, ++ .required_pctl = true, + }; + + const struct of_device_id of_mtk_match[] = { +Index: linux-4.14.37/drivers/net/ethernet/mediatek/mtk_eth_soc.h +=================================================================== +--- linux-4.14.37.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ linux-4.14.37/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -574,10 +574,13 @@ struct mtk_rx_ring { + * @caps Flags shown the extra capability for the SoC + * @required_clks Flags shown the bitmap for required clocks on + * the target SoC ++ * @required_pctl A bool value to show whether the SoC requires ++ * the extra setup for those pins used by GMAC. + */ + struct mtk_soc_data { + u32 caps; + u32 required_clks; ++ bool required_pctl; + }; + + /* currently no SoC has more than 2 macs */ diff --git a/target/linux/mediatek/patches-4.14/0176-clk-mediatek-Fix-all-warnings-for-missing-struct-clk.patch b/target/linux/mediatek/patches-4.14/0176-clk-mediatek-Fix-all-warnings-for-missing-struct-clk.patch new file mode 100644 index 0000000000..911082bf4d --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0176-clk-mediatek-Fix-all-warnings-for-missing-struct-clk.patch @@ -0,0 +1,73 @@ +From f42f141077a12e28fe33c0033f698afb1402ec20 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 25 Dec 2017 16:03:57 +0800 +Subject: [PATCH 176/224] clk: mediatek: Fix all warnings for missing struct + clk_onecell_data + +Even though the header file linux/clk-provider.h is already being properly +included in clk-mtk.h, the definition of struct clk_onecell_data still +must depend on CONFIG_COMMON_CLK defined and thus it's possible that +below build warnings occur when CONFIG_COMMON_CLK is not being selected. + +Therefore, these functions which need struct clk_onecell_data without +declaring that structure first requires simply declaring that this struct +exists prior to referencing it in clk-mtk.h + +Changes from v1->v2: +enhance v1 based on two useful solutions Jean Delvare kindly suggested. + +All warnings (new ones prefixed by >>): + +In file included from drivers/clk/mediatek/reset.c:22:0: +>>drivers/clk/mediatek/clk-mtk.h:44:19: warning: 'struct clk_onecell_data' +declared inside parameter list will not be visible outside of +this definition or declaration + int num, struct clk_onecell_data *clk_data); + ^~~~~~~~~~~~~~~~ +drivers/clk/mediatek/clk-mtk.h:63:19: warning: 'struct clk_onecell_data' +declared inside parameter list will not be visible outside of +this definition or declaration + int num, struct clk_onecell_data *clk_data); + ^~~~~~~~~~~~~~~~ +drivers/clk/mediatek/clk-mtk.h:145:10: warning: 'struct clk_onecell_data' +declared inside parameter list will not be visible outside of +this definition or declaration + struct clk_onecell_data *clk_data); + ^~~~~~~~~~~~~~~~ +drivers/clk/mediatek/clk-mtk.h:164:11: warning: 'struct clk_onecell_data' +declared inside parameter list will not be visible outside of +this definition or declaration + struct clk_onecell_data *clk_data); + ^~~~~~~~~~~~~~~~ +drivers/clk/mediatek/clk-mtk.h:190:12: warning: 'struct clk_onecell_data' +declared inside parameter list will not be visible outside of this +definition or declaration + struct clk_onecell_data *clk_data); + ^~~~~~~~~~~~~~~~ + +Reported-by: kbuild test robot <fengguang.wu@intel.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: kbuild-all@01.org +Cc: Stephen Boyd <sboyd@codeaurora.org> +Cc: Jean Delvare <jdelvare@suse.de> +Cc: linux-clk@vger.kernel.org +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/mediatek/clk-mtk.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h +index f10250dcece4..bf8006d41861 100644 +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -20,6 +20,7 @@ + #include <linux/clk-provider.h> + + struct clk; ++struct clk_onecell_data; + + #define MAX_MUX_GATE_BIT 31 + #define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0177-phy-phy-mtk-tphy-use-auto-instead-of-force-to-bypass.patch b/target/linux/mediatek/patches-4.14/0177-phy-phy-mtk-tphy-use-auto-instead-of-force-to-bypass.patch new file mode 100644 index 0000000000..4b230cd622 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0177-phy-phy-mtk-tphy-use-auto-instead-of-force-to-bypass.patch @@ -0,0 +1,80 @@ +From dacdae142ffd909ed6718adb05af74ff800da668 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Thu, 7 Dec 2017 19:53:34 +0800 +Subject: [PATCH 177/224] phy: phy-mtk-tphy: use auto instead of force to + bypass utmi signals + +When system is running, if usb2 phy is forced to bypass utmi signals, +all PLL will be turned off, and it can't detect device connection +anymore, so replace force mode with auto mode which can bypass utmi +signals automatically if no device attached for normal flow. +But keep the force mode to fix RX sensitivity degradation issue. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + drivers/phy/mediatek/phy-mtk-tphy.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c +index 402385f2562a..54cc44b2d289 100644 +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -440,9 +440,9 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy, + u32 index = instance->index; + u32 tmp; + +- /* switch to USB function. (system register, force ip into usb mode) */ ++ /* switch to USB function, and enable usb pll */ + tmp = readl(com + U3P_U2PHYDTM0); +- tmp &= ~P2C_FORCE_UART_EN; ++ tmp &= ~(P2C_FORCE_UART_EN | P2C_FORCE_SUSPENDM); + tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0); + writel(tmp, com + U3P_U2PHYDTM0); + +@@ -502,10 +502,8 @@ static void u2_phy_instance_power_on(struct mtk_tphy *tphy, + u32 index = instance->index; + u32 tmp; + +- /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ + tmp = readl(com + U3P_U2PHYDTM0); +- tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL); +- tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK); ++ tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK); + writel(tmp, com + U3P_U2PHYDTM0); + + /* OTG Enable */ +@@ -540,7 +538,6 @@ static void u2_phy_instance_power_off(struct mtk_tphy *tphy, + + tmp = readl(com + U3P_U2PHYDTM0); + tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN); +- tmp |= P2C_FORCE_SUSPENDM; + writel(tmp, com + U3P_U2PHYDTM0); + + /* OTG Disable */ +@@ -548,18 +545,16 @@ static void u2_phy_instance_power_off(struct mtk_tphy *tphy, + tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN; + writel(tmp, com + U3P_USBPHYACR6); + +- /* let suspendm=0, set utmi into analog power down */ +- tmp = readl(com + U3P_U2PHYDTM0); +- tmp &= ~P2C_RG_SUSPENDM; +- writel(tmp, com + U3P_U2PHYDTM0); +- udelay(1); +- + tmp = readl(com + U3P_U2PHYDTM1); + tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID); + tmp |= P2C_RG_SESSEND; + writel(tmp, com + U3P_U2PHYDTM1); + + if (tphy->pdata->avoid_rx_sen_degradation && index) { ++ tmp = readl(com + U3P_U2PHYDTM0); ++ tmp &= ~(P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM); ++ writel(tmp, com + U3P_U2PHYDTM0); ++ + tmp = readl(com + U3D_U2PHYDCR0); + tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; + writel(tmp, com + U3D_U2PHYDCR0); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0178-phy-phy-mtk-tphy-make-shared-banks-optional-for-V1-T.patch b/target/linux/mediatek/patches-4.14/0178-phy-phy-mtk-tphy-make-shared-banks-optional-for-V1-T.patch new file mode 100644 index 0000000000..78e913ea6f --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0178-phy-phy-mtk-tphy-make-shared-banks-optional-for-V1-T.patch @@ -0,0 +1,35 @@ +From d7a38584713b00cf9ae97aed89d5e8fb7e3c1bea Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Thu, 7 Dec 2017 19:53:35 +0800 +Subject: [PATCH 178/224] phy: phy-mtk-tphy: make shared banks optional for V1 + TPHY + +V1 TPHY for SATA doesn't have shared banks if it isn't shared +with PCIe or USB, so make it optional. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + drivers/phy/mediatek/phy-mtk-tphy.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c +index 54cc44b2d289..11cab1d84a02 100644 +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -1023,9 +1023,10 @@ static int mtk_tphy_probe(struct platform_device *pdev) + tphy->dev = dev; + platform_set_drvdata(pdev, tphy); + +- if (tphy->pdata->version == MTK_PHY_V1) { ++ sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ /* SATA phy of V1 needn't it if not shared with PCIe or USB */ ++ if (sif_res && tphy->pdata->version == MTK_PHY_V1) { + /* get banks shared by multiple phys */ +- sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + tphy->sif_base = devm_ioremap_resource(dev, sif_res); + if (IS_ERR(tphy->sif_base)) { + dev_err(dev, "failed to remap sif regs\n"); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0179-phy-phy-mtk-tphy-use-of_device_get_match_data.patch b/target/linux/mediatek/patches-4.14/0179-phy-phy-mtk-tphy-use-of_device_get_match_data.patch new file mode 100644 index 0000000000..e28ab55c3a --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0179-phy-phy-mtk-tphy-use-of_device_get_match_data.patch @@ -0,0 +1,56 @@ +From 3e53007a55e70d5036a527900befecf9a6316d05 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Thu, 28 Dec 2017 16:40:36 +0530 +Subject: [PATCH 179/224] phy: phy-mtk-tphy: use of_device_get_match_data() + +reduce the boilerplate code to get the specific data + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + drivers/phy/mediatek/phy-mtk-tphy.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c +index 11cab1d84a02..1e96d0740ef5 100644 +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -20,6 +20,7 @@ + #include <linux/iopoll.h> + #include <linux/module.h> + #include <linux/of_address.h> ++#include <linux/of_device.h> + #include <linux/phy/phy.h> + #include <linux/platform_device.h> + +@@ -995,7 +996,6 @@ MODULE_DEVICE_TABLE(of, mtk_tphy_id_table); + + static int mtk_tphy_probe(struct platform_device *pdev) + { +- const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child_np; +@@ -1005,15 +1005,14 @@ static int mtk_tphy_probe(struct platform_device *pdev) + struct resource res; + int port, retval; + +- match = of_match_node(mtk_tphy_id_table, pdev->dev.of_node); +- if (!match) +- return -EINVAL; +- + tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL); + if (!tphy) + return -ENOMEM; + +- tphy->pdata = match->data; ++ tphy->pdata = of_device_get_match_data(dev); ++ if (!tphy->pdata) ++ return -EINVAL; ++ + tphy->nphys = of_get_child_count(np); + tphy->phys = devm_kcalloc(dev, tphy->nphys, + sizeof(*tphy->phys), GFP_KERNEL); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0180-ASoC-mediatek-fix-error-handling-in-mt2701_afe_pcm_d.patch b/target/linux/mediatek/patches-4.14/0180-ASoC-mediatek-fix-error-handling-in-mt2701_afe_pcm_d.patch new file mode 100644 index 0000000000..074baa04b2 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0180-ASoC-mediatek-fix-error-handling-in-mt2701_afe_pcm_d.patch @@ -0,0 +1,86 @@ +From 17508c32dd65649d2617c1c52b32b02bdb54b793 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 2 Jan 2018 19:47:18 +0800 +Subject: [PATCH 180/224] ASoC: mediatek: fix error handling in + mt2701_afe_pcm_dev_probe() + +Fix unbalanced error handling path which will get incorrect counts +if probe failed. The .remove() should be adjusted accordingly. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Tested-by: Garlic Tseng <garlic.tseng@mediatek.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 31 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 17 deletions(-) + +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +index 8fda182f849b..a7362d1cda1b 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +@@ -1590,12 +1590,16 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + } + + platform_set_drvdata(pdev, afe); +- pm_runtime_enable(&pdev->dev); +- if (!pm_runtime_enabled(&pdev->dev)) +- goto err_pm_disable; +- pm_runtime_get_sync(&pdev->dev); + +- ret = snd_soc_register_platform(&pdev->dev, &mtk_afe_pcm_platform); ++ pm_runtime_enable(dev); ++ if (!pm_runtime_enabled(dev)) { ++ ret = mt2701_afe_runtime_resume(dev); ++ if (ret) ++ goto err_pm_disable; ++ } ++ pm_runtime_get_sync(dev); ++ ++ ret = snd_soc_register_platform(dev, &mtk_afe_pcm_platform); + if (ret) { + dev_warn(dev, "err_platform\n"); + goto err_platform; +@@ -1610,35 +1614,28 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + goto err_dai_component; + } + +- mt2701_afe_runtime_resume(&pdev->dev); +- + return 0; + + err_dai_component: +- snd_soc_unregister_component(&pdev->dev); +- ++ snd_soc_unregister_platform(dev); + err_platform: +- snd_soc_unregister_platform(&pdev->dev); +- ++ pm_runtime_put_sync(dev); + err_pm_disable: +- pm_runtime_disable(&pdev->dev); ++ pm_runtime_disable(dev); + + return ret; + } + + static int mt2701_afe_pcm_dev_remove(struct platform_device *pdev) + { +- struct mtk_base_afe *afe = platform_get_drvdata(pdev); +- ++ pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + mt2701_afe_runtime_suspend(&pdev->dev); +- pm_runtime_put_sync(&pdev->dev); + + snd_soc_unregister_component(&pdev->dev); + snd_soc_unregister_platform(&pdev->dev); +- /* disable afe clock */ +- mt2701_afe_disable_clock(afe); ++ + return 0; + } + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0181-ASoC-mediatek-rework-clock-functions-for-MT2701.patch b/target/linux/mediatek/patches-4.14/0181-ASoC-mediatek-rework-clock-functions-for-MT2701.patch new file mode 100644 index 0000000000..579749038c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0181-ASoC-mediatek-rework-clock-functions-for-MT2701.patch @@ -0,0 +1,932 @@ +From d038da516563d910dd39930777f431d4c65a56cd Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 2 Jan 2018 19:47:19 +0800 +Subject: [PATCH 181/224] ASoC: mediatek: rework clock functions for MT2701 + +Reworks clock part to make it more reasonable. The current changes are: + +- Replace regmap operations by CCF APIs. Doing so, we just need to handle + the element clocks and can also get accurate information via CCF. + +- Rename clocks to make them more generic so that the future revisions + of the IP can adapt gracefully. + +- Regroup 'aud_clks[]' by usage - the basic needs and I2S parts: + + The new code just keep the common clocks in array and let SoC self decide + I2S numbers - If future chips have different sets of channels we will + add a little more abstract here. + + Moreover, this patch moves I2S clocks to the struct mt2701_i2s_data + so that we can easily manage them when calls .prepare() and .shutdown(). + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Tested-by: Garlic Tseng <garlic.tseng@mediatek.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c | 518 +++++++--------------- + sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h | 15 +- + sound/soc/mediatek/mt2701/mt2701-afe-common.h | 64 +-- + sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 45 +- + 4 files changed, 200 insertions(+), 442 deletions(-) + +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c +index affa7fb25dd9..75ccdca5811d 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c +@@ -21,442 +21,256 @@ + #include "mt2701-afe-common.h" + #include "mt2701-afe-clock-ctrl.h" + +-static const char *aud_clks[MT2701_CLOCK_NUM] = { +- [MT2701_AUD_INFRA_SYS_AUDIO] = "infra_sys_audio_clk", +- [MT2701_AUD_AUD_MUX1_SEL] = "top_audio_mux1_sel", +- [MT2701_AUD_AUD_MUX2_SEL] = "top_audio_mux2_sel", +- [MT2701_AUD_AUD_MUX1_DIV] = "top_audio_mux1_div", +- [MT2701_AUD_AUD_MUX2_DIV] = "top_audio_mux2_div", +- [MT2701_AUD_AUD_48K_TIMING] = "top_audio_48k_timing", +- [MT2701_AUD_AUD_44K_TIMING] = "top_audio_44k_timing", +- [MT2701_AUD_AUDPLL_MUX_SEL] = "top_audpll_mux_sel", +- [MT2701_AUD_APLL_SEL] = "top_apll_sel", +- [MT2701_AUD_AUD1PLL_98M] = "top_aud1_pll_98M", +- [MT2701_AUD_AUD2PLL_90M] = "top_aud2_pll_90M", +- [MT2701_AUD_HADDS2PLL_98M] = "top_hadds2_pll_98M", +- [MT2701_AUD_HADDS2PLL_294M] = "top_hadds2_pll_294M", +- [MT2701_AUD_AUDPLL] = "top_audpll", +- [MT2701_AUD_AUDPLL_D4] = "top_audpll_d4", +- [MT2701_AUD_AUDPLL_D8] = "top_audpll_d8", +- [MT2701_AUD_AUDPLL_D16] = "top_audpll_d16", +- [MT2701_AUD_AUDPLL_D24] = "top_audpll_d24", +- [MT2701_AUD_AUDINTBUS] = "top_audintbus_sel", +- [MT2701_AUD_CLK_26M] = "clk_26m", +- [MT2701_AUD_SYSPLL1_D4] = "top_syspll1_d4", +- [MT2701_AUD_AUD_K1_SRC_SEL] = "top_aud_k1_src_sel", +- [MT2701_AUD_AUD_K2_SRC_SEL] = "top_aud_k2_src_sel", +- [MT2701_AUD_AUD_K3_SRC_SEL] = "top_aud_k3_src_sel", +- [MT2701_AUD_AUD_K4_SRC_SEL] = "top_aud_k4_src_sel", +- [MT2701_AUD_AUD_K5_SRC_SEL] = "top_aud_k5_src_sel", +- [MT2701_AUD_AUD_K6_SRC_SEL] = "top_aud_k6_src_sel", +- [MT2701_AUD_AUD_K1_SRC_DIV] = "top_aud_k1_src_div", +- [MT2701_AUD_AUD_K2_SRC_DIV] = "top_aud_k2_src_div", +- [MT2701_AUD_AUD_K3_SRC_DIV] = "top_aud_k3_src_div", +- [MT2701_AUD_AUD_K4_SRC_DIV] = "top_aud_k4_src_div", +- [MT2701_AUD_AUD_K5_SRC_DIV] = "top_aud_k5_src_div", +- [MT2701_AUD_AUD_K6_SRC_DIV] = "top_aud_k6_src_div", +- [MT2701_AUD_AUD_I2S1_MCLK] = "top_aud_i2s1_mclk", +- [MT2701_AUD_AUD_I2S2_MCLK] = "top_aud_i2s2_mclk", +- [MT2701_AUD_AUD_I2S3_MCLK] = "top_aud_i2s3_mclk", +- [MT2701_AUD_AUD_I2S4_MCLK] = "top_aud_i2s4_mclk", +- [MT2701_AUD_AUD_I2S5_MCLK] = "top_aud_i2s5_mclk", +- [MT2701_AUD_AUD_I2S6_MCLK] = "top_aud_i2s6_mclk", +- [MT2701_AUD_ASM_M_SEL] = "top_asm_m_sel", +- [MT2701_AUD_ASM_H_SEL] = "top_asm_h_sel", +- [MT2701_AUD_UNIVPLL2_D4] = "top_univpll2_d4", +- [MT2701_AUD_UNIVPLL2_D2] = "top_univpll2_d2", +- [MT2701_AUD_SYSPLL_D5] = "top_syspll_d5", ++static const char *const base_clks[] = { ++ [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel", ++ [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel", ++ [MT2701_AUDSYS_AFE] = "audio_afe_pd", ++ [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd", ++ [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd", ++ [MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd", + }; + + int mt2701_init_clock(struct mtk_base_afe *afe) + { + struct mt2701_afe_private *afe_priv = afe->platform_priv; +- int i = 0; +- +- for (i = 0; i < MT2701_CLOCK_NUM; i++) { +- afe_priv->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]); +- if (IS_ERR(afe_priv->clocks[i])) { +- dev_warn(afe->dev, "%s devm_clk_get %s fail\n", +- __func__, aud_clks[i]); +- return PTR_ERR(aud_clks[i]); ++ int i; ++ ++ for (i = 0; i < MT2701_BASE_CLK_NUM; i++) { ++ afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]); ++ if (IS_ERR(afe_priv->base_ck[i])) { ++ dev_err(afe->dev, "failed to get %s\n", base_clks[i]); ++ return PTR_ERR(afe_priv->base_ck[i]); + } + } + +- return 0; +-} ++ /* Get I2S related clocks */ ++ for (i = 0; i < MT2701_I2S_NUM; i++) { ++ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i]; ++ char name[13]; + +-int mt2701_afe_enable_clock(struct mtk_base_afe *afe) +-{ +- int ret = 0; ++ snprintf(name, sizeof(name), "i2s%d_src_sel", i); ++ i2s_path->sel_ck = devm_clk_get(afe->dev, name); ++ if (IS_ERR(i2s_path->sel_ck)) { ++ dev_err(afe->dev, "failed to get %s\n", name); ++ return PTR_ERR(i2s_path->sel_ck); ++ } + +- ret = mt2701_turn_on_a1sys_clock(afe); +- if (ret) { +- dev_err(afe->dev, "%s turn_on_a1sys_clock fail %d\n", +- __func__, ret); +- return ret; +- } ++ snprintf(name, sizeof(name), "i2s%d_src_div", i); ++ i2s_path->div_ck = devm_clk_get(afe->dev, name); ++ if (IS_ERR(i2s_path->div_ck)) { ++ dev_err(afe->dev, "failed to get %s\n", name); ++ return PTR_ERR(i2s_path->div_ck); ++ } + +- ret = mt2701_turn_on_a2sys_clock(afe); +- if (ret) { +- dev_err(afe->dev, "%s turn_on_a2sys_clock fail %d\n", +- __func__, ret); +- mt2701_turn_off_a1sys_clock(afe); +- return ret; +- } ++ snprintf(name, sizeof(name), "i2s%d_mclk_en", i); ++ i2s_path->mclk_ck = devm_clk_get(afe->dev, name); ++ if (IS_ERR(i2s_path->mclk_ck)) { ++ dev_err(afe->dev, "failed to get %s\n", name); ++ return PTR_ERR(i2s_path->mclk_ck); ++ } + +- ret = mt2701_turn_on_afe_clock(afe); +- if (ret) { +- dev_err(afe->dev, "%s turn_on_afe_clock fail %d\n", +- __func__, ret); +- mt2701_turn_off_a1sys_clock(afe); +- mt2701_turn_off_a2sys_clock(afe); +- return ret; ++ snprintf(name, sizeof(name), "i2so%d_hop_ck", i); ++ i2s_path->hop_ck[I2S_OUT] = devm_clk_get(afe->dev, name); ++ if (IS_ERR(i2s_path->hop_ck[I2S_OUT])) { ++ dev_err(afe->dev, "failed to get %s\n", name); ++ return PTR_ERR(i2s_path->hop_ck[I2S_OUT]); ++ } ++ ++ snprintf(name, sizeof(name), "i2si%d_hop_ck", i); ++ i2s_path->hop_ck[I2S_IN] = devm_clk_get(afe->dev, name); ++ if (IS_ERR(i2s_path->hop_ck[I2S_IN])) { ++ dev_err(afe->dev, "failed to get %s\n", name); ++ return PTR_ERR(i2s_path->hop_ck[I2S_IN]); ++ } ++ ++ snprintf(name, sizeof(name), "asrc%d_out_ck", i); ++ i2s_path->asrco_ck = devm_clk_get(afe->dev, name); ++ if (IS_ERR(i2s_path->asrco_ck)) { ++ dev_err(afe->dev, "failed to get %s\n", name); ++ return PTR_ERR(i2s_path->asrco_ck); ++ } + } + +- regmap_update_bits(afe->regmap, ASYS_TOP_CON, +- AUDIO_TOP_CON0_A1SYS_A2SYS_ON, +- AUDIO_TOP_CON0_A1SYS_A2SYS_ON); +- regmap_update_bits(afe->regmap, AFE_DAC_CON0, +- AFE_DAC_CON0_AFE_ON, +- AFE_DAC_CON0_AFE_ON); +- regmap_write(afe->regmap, PWR2_TOP_CON, +- PWR2_TOP_CON_INIT_VAL); +- regmap_write(afe->regmap, PWR1_ASM_CON1, +- PWR1_ASM_CON1_INIT_VAL); +- regmap_write(afe->regmap, PWR2_ASM_CON1, +- PWR2_ASM_CON1_INIT_VAL); ++ /* Some platforms may support BT path */ ++ afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd"); ++ if (IS_ERR(afe_priv->mrgif_ck)) { ++ if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; + +- return 0; +-} ++ afe_priv->mrgif_ck = NULL; ++ } + +-void mt2701_afe_disable_clock(struct mtk_base_afe *afe) +-{ +- mt2701_turn_off_afe_clock(afe); +- mt2701_turn_off_a1sys_clock(afe); +- mt2701_turn_off_a2sys_clock(afe); +- regmap_update_bits(afe->regmap, ASYS_TOP_CON, +- AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 0); +- regmap_update_bits(afe->regmap, AFE_DAC_CON0, +- AFE_DAC_CON0_AFE_ON, 0); ++ return 0; + } + +-int mt2701_turn_on_a1sys_clock(struct mtk_base_afe *afe) ++int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir) + { + struct mt2701_afe_private *afe_priv = afe->platform_priv; +- int ret = 0; ++ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; ++ int ret; + +- /* Set Mux */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]); ++ ret = clk_prepare_enable(i2s_path->asrco_ck); + if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_AUD_MUX1_SEL], ret); +- goto A1SYS_CLK_AUD_MUX1_SEL_ERR; ++ dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret); ++ return ret; + } + +- ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL], +- afe_priv->clocks[MT2701_AUD_AUD1PLL_98M]); ++ ret = clk_prepare_enable(i2s_path->hop_ck[dir]); + if (ret) { +- dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__, +- aud_clks[MT2701_AUD_AUD_MUX1_SEL], +- aud_clks[MT2701_AUD_AUD1PLL_98M], ret); +- goto A1SYS_CLK_AUD_MUX1_SEL_ERR; ++ dev_err(afe->dev, "failed to enable I2S clock %d\n", ret); ++ goto err_hop_ck; + } + +- /* Set Divider */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, +- aud_clks[MT2701_AUD_AUD_MUX1_DIV], +- ret); +- goto A1SYS_CLK_AUD_MUX1_DIV_ERR; +- } ++ return 0; + +- ret = clk_set_rate(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV], +- MT2701_AUD_AUD_MUX1_DIV_RATE); +- if (ret) { +- dev_err(afe->dev, "%s clk_set_parent %s-%d fail %d\n", __func__, +- aud_clks[MT2701_AUD_AUD_MUX1_DIV], +- MT2701_AUD_AUD_MUX1_DIV_RATE, ret); +- goto A1SYS_CLK_AUD_MUX1_DIV_ERR; +- } ++err_hop_ck: ++ clk_disable_unprepare(i2s_path->asrco_ck); + +- /* Enable clock gate */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_48K_TIMING]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_AUD_48K_TIMING], ret); +- goto A1SYS_CLK_AUD_48K_ERR; +- } ++ return ret; ++} + +- /* Enable infra audio */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_INFRA_SYS_AUDIO], ret); +- goto A1SYS_CLK_INFRA_ERR; +- } ++void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir) ++{ ++ struct mt2701_afe_private *afe_priv = afe->platform_priv; ++ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; + +- return 0; ++ clk_disable_unprepare(i2s_path->hop_ck[dir]); ++ clk_disable_unprepare(i2s_path->asrco_ck); ++} + +-A1SYS_CLK_INFRA_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +-A1SYS_CLK_AUD_48K_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_48K_TIMING]); +-A1SYS_CLK_AUD_MUX1_DIV_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV]); +-A1SYS_CLK_AUD_MUX1_SEL_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]); ++int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id) ++{ ++ struct mt2701_afe_private *afe_priv = afe->platform_priv; ++ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; + +- return ret; ++ return clk_prepare_enable(i2s_path->mclk_ck); + } + +-void mt2701_turn_off_a1sys_clock(struct mtk_base_afe *afe) ++void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id) + { + struct mt2701_afe_private *afe_priv = afe->platform_priv; ++ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; + +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_48K_TIMING]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]); ++ clk_disable_unprepare(i2s_path->mclk_ck); + } + +-int mt2701_turn_on_a2sys_clock(struct mtk_base_afe *afe) ++int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe) + { + struct mt2701_afe_private *afe_priv = afe->platform_priv; +- int ret = 0; + +- /* Set Mux */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_AUD_MUX2_SEL], ret); +- goto A2SYS_CLK_AUD_MUX2_SEL_ERR; +- } ++ return clk_prepare_enable(afe_priv->mrgif_ck); ++} + +- ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL], +- afe_priv->clocks[MT2701_AUD_AUD2PLL_90M]); +- if (ret) { +- dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__, +- aud_clks[MT2701_AUD_AUD_MUX2_SEL], +- aud_clks[MT2701_AUD_AUD2PLL_90M], ret); +- goto A2SYS_CLK_AUD_MUX2_SEL_ERR; +- } ++void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe) ++{ ++ struct mt2701_afe_private *afe_priv = afe->platform_priv; + +- /* Set Divider */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_AUD_MUX2_DIV], ret); +- goto A2SYS_CLK_AUD_MUX2_DIV_ERR; +- } ++ clk_disable_unprepare(afe_priv->mrgif_ck); ++} + +- ret = clk_set_rate(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV], +- MT2701_AUD_AUD_MUX2_DIV_RATE); +- if (ret) { +- dev_err(afe->dev, "%s clk_set_parent %s-%d fail %d\n", __func__, +- aud_clks[MT2701_AUD_AUD_MUX2_DIV], +- MT2701_AUD_AUD_MUX2_DIV_RATE, ret); +- goto A2SYS_CLK_AUD_MUX2_DIV_ERR; +- } ++static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe) ++{ ++ struct mt2701_afe_private *afe_priv = afe->platform_priv; ++ int ret; + +- /* Enable clock gate */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_44K_TIMING]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_AUD_44K_TIMING], ret); +- goto A2SYS_CLK_AUD_44K_ERR; +- } ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); ++ if (ret) ++ return ret; + +- /* Enable infra audio */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_INFRA_SYS_AUDIO], ret); +- goto A2SYS_CLK_INFRA_ERR; +- } ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); ++ if (ret) ++ goto err_audio_a1sys; ++ ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); ++ if (ret) ++ goto err_audio_a2sys; ++ ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); ++ if (ret) ++ goto err_afe_conn; + + return 0; + +-A2SYS_CLK_INFRA_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +-A2SYS_CLK_AUD_44K_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_44K_TIMING]); +-A2SYS_CLK_AUD_MUX2_DIV_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV]); +-A2SYS_CLK_AUD_MUX2_SEL_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]); ++err_afe_conn: ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); ++err_audio_a2sys: ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); ++err_audio_a1sys: ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); + + return ret; + } + +-void mt2701_turn_off_a2sys_clock(struct mtk_base_afe *afe) ++static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe) + { + struct mt2701_afe_private *afe_priv = afe->platform_priv; + +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_44K_TIMING]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]); ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); + } + +-int mt2701_turn_on_afe_clock(struct mtk_base_afe *afe) ++int mt2701_afe_enable_clock(struct mtk_base_afe *afe) + { +- struct mt2701_afe_private *afe_priv = afe->platform_priv; + int ret; + +- /* enable INFRA_SYS */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_INFRA_SYS_AUDIO], ret); +- goto AFE_AUD_INFRA_ERR; +- } +- +- /* Set MT2701_AUD_AUDINTBUS to MT2701_AUD_SYSPLL1_D4 */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUDINTBUS]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_AUDINTBUS], ret); +- goto AFE_AUD_AUDINTBUS_ERR; +- } +- +- ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_AUDINTBUS], +- afe_priv->clocks[MT2701_AUD_SYSPLL1_D4]); +- if (ret) { +- dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__, +- aud_clks[MT2701_AUD_AUDINTBUS], +- aud_clks[MT2701_AUD_SYSPLL1_D4], ret); +- goto AFE_AUD_AUDINTBUS_ERR; +- } +- +- /* Set MT2701_AUD_ASM_H_SEL to MT2701_AUD_UNIVPLL2_D2 */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_ASM_H_SEL]); +- if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_ASM_H_SEL], ret); +- goto AFE_AUD_ASM_H_ERR; +- } +- +- ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_ASM_H_SEL], +- afe_priv->clocks[MT2701_AUD_UNIVPLL2_D2]); +- if (ret) { +- dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__, +- aud_clks[MT2701_AUD_ASM_H_SEL], +- aud_clks[MT2701_AUD_UNIVPLL2_D2], ret); +- goto AFE_AUD_ASM_H_ERR; +- } +- +- /* Set MT2701_AUD_ASM_M_SEL to MT2701_AUD_UNIVPLL2_D4 */ +- ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_ASM_M_SEL]); ++ /* Enable audio system */ ++ ret = mt2701_afe_enable_audsys(afe); + if (ret) { +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[MT2701_AUD_ASM_M_SEL], ret); +- goto AFE_AUD_ASM_M_ERR; ++ dev_err(afe->dev, "failed to enable audio system %d\n", ret); ++ return ret; + } + +- ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_ASM_M_SEL], +- afe_priv->clocks[MT2701_AUD_UNIVPLL2_D4]); +- if (ret) { +- dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__, +- aud_clks[MT2701_AUD_ASM_M_SEL], +- aud_clks[MT2701_AUD_UNIVPLL2_D4], ret); +- goto AFE_AUD_ASM_M_ERR; +- } ++ regmap_update_bits(afe->regmap, ASYS_TOP_CON, ++ AUDIO_TOP_CON0_A1SYS_A2SYS_ON, ++ AUDIO_TOP_CON0_A1SYS_A2SYS_ON); ++ regmap_update_bits(afe->regmap, AFE_DAC_CON0, ++ AFE_DAC_CON0_AFE_ON, ++ AFE_DAC_CON0_AFE_ON); + +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, +- AUDIO_TOP_CON0_PDN_AFE, 0); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, +- AUDIO_TOP_CON0_PDN_APLL_CK, 0); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_A1SYS, 0); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_A2SYS, 0); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_AFE_CONN, 0); ++ /* Configure ASRC */ ++ regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL); ++ regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL); + + return 0; +- +-AFE_AUD_ASM_M_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_M_SEL]); +-AFE_AUD_ASM_H_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_H_SEL]); +-AFE_AUD_AUDINTBUS_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUDINTBUS]); +-AFE_AUD_INFRA_ERR: +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +- +- return ret; + } + +-void mt2701_turn_off_afe_clock(struct mtk_base_afe *afe) ++int mt2701_afe_disable_clock(struct mtk_base_afe *afe) + { +- struct mt2701_afe_private *afe_priv = afe->platform_priv; ++ regmap_update_bits(afe->regmap, ASYS_TOP_CON, ++ AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 0); ++ regmap_update_bits(afe->regmap, AFE_DAC_CON0, ++ AFE_DAC_CON0_AFE_ON, 0); + +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]); +- +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUDINTBUS]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_H_SEL]); +- clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_M_SEL]); +- +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, +- AUDIO_TOP_CON0_PDN_AFE, AUDIO_TOP_CON0_PDN_AFE); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, +- AUDIO_TOP_CON0_PDN_APLL_CK, +- AUDIO_TOP_CON0_PDN_APLL_CK); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_A1SYS, +- AUDIO_TOP_CON4_PDN_A1SYS); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_A2SYS, +- AUDIO_TOP_CON4_PDN_A2SYS); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_AFE_CONN, +- AUDIO_TOP_CON4_PDN_AFE_CONN); ++ mt2701_afe_disable_audsys(afe); ++ ++ return 0; + } + + void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain, + int mclk) + { +- struct mt2701_afe_private *afe_priv = afe->platform_priv; ++ struct mt2701_afe_private *priv = afe->platform_priv; ++ struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id]; + int ret; +- int aud_src_div_id = MT2701_AUD_AUD_K1_SRC_DIV + id; +- int aud_src_clk_id = MT2701_AUD_AUD_K1_SRC_SEL + id; + +- /* Set MCLK Kx_SRC_SEL(domain) */ +- ret = clk_prepare_enable(afe_priv->clocks[aud_src_clk_id]); +- if (ret) +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[aud_src_clk_id], ret); +- +- if (domain == 0) { +- ret = clk_set_parent(afe_priv->clocks[aud_src_clk_id], +- afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]); +- if (ret) +- dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", +- __func__, aud_clks[aud_src_clk_id], +- aud_clks[MT2701_AUD_AUD_MUX1_SEL], ret); +- } else { +- ret = clk_set_parent(afe_priv->clocks[aud_src_clk_id], +- afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]); +- if (ret) +- dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", +- __func__, aud_clks[aud_src_clk_id], +- aud_clks[MT2701_AUD_AUD_MUX2_SEL], ret); +- } +- clk_disable_unprepare(afe_priv->clocks[aud_src_clk_id]); ++ /* Set mclk source */ ++ if (domain == 0) ++ ret = clk_set_parent(i2s_path->sel_ck, ++ priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]); ++ else ++ ret = clk_set_parent(i2s_path->sel_ck, ++ priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]); + +- /* Set MCLK Kx_SRC_DIV(divider) */ +- ret = clk_prepare_enable(afe_priv->clocks[aud_src_div_id]); + if (ret) +- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", +- __func__, aud_clks[aud_src_div_id], ret); ++ dev_err(afe->dev, "failed to set domain%d mclk source %d\n", ++ domain, ret); + +- ret = clk_set_rate(afe_priv->clocks[aud_src_div_id], mclk); ++ /* Set mclk divider */ ++ ret = clk_set_rate(i2s_path->div_ck, mclk); + if (ret) +- dev_err(afe->dev, "%s clk_set_rate %s-%d fail %d\n", __func__, +- aud_clks[aud_src_div_id], mclk, ret); +- clk_disable_unprepare(afe_priv->clocks[aud_src_div_id]); ++ dev_err(afe->dev, "failed to set mclk divider %d\n", ret); + } + + MODULE_DESCRIPTION("MT2701 afe clock control"); +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h +index 6497d570cf09..15417d9d6597 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h +@@ -21,16 +21,15 @@ struct mtk_base_afe; + + int mt2701_init_clock(struct mtk_base_afe *afe); + int mt2701_afe_enable_clock(struct mtk_base_afe *afe); +-void mt2701_afe_disable_clock(struct mtk_base_afe *afe); ++int mt2701_afe_disable_clock(struct mtk_base_afe *afe); + +-int mt2701_turn_on_a1sys_clock(struct mtk_base_afe *afe); +-void mt2701_turn_off_a1sys_clock(struct mtk_base_afe *afe); ++int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir); ++void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir); ++int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id); ++void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id); + +-int mt2701_turn_on_a2sys_clock(struct mtk_base_afe *afe); +-void mt2701_turn_off_a2sys_clock(struct mtk_base_afe *afe); +- +-int mt2701_turn_on_afe_clock(struct mtk_base_afe *afe); +-void mt2701_turn_off_afe_clock(struct mtk_base_afe *afe); ++int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe); ++void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe); + + void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain, + int mclk); +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h +index c19430e98adf..ce5bd4dc864d 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h +@@ -69,53 +69,14 @@ enum { + MT2701_IRQ_ASYS_END, + }; + +-/* 2701 clock def */ +-enum audio_system_clock_type { +- MT2701_AUD_INFRA_SYS_AUDIO, +- MT2701_AUD_AUD_MUX1_SEL, +- MT2701_AUD_AUD_MUX2_SEL, +- MT2701_AUD_AUD_MUX1_DIV, +- MT2701_AUD_AUD_MUX2_DIV, +- MT2701_AUD_AUD_48K_TIMING, +- MT2701_AUD_AUD_44K_TIMING, +- MT2701_AUD_AUDPLL_MUX_SEL, +- MT2701_AUD_APLL_SEL, +- MT2701_AUD_AUD1PLL_98M, +- MT2701_AUD_AUD2PLL_90M, +- MT2701_AUD_HADDS2PLL_98M, +- MT2701_AUD_HADDS2PLL_294M, +- MT2701_AUD_AUDPLL, +- MT2701_AUD_AUDPLL_D4, +- MT2701_AUD_AUDPLL_D8, +- MT2701_AUD_AUDPLL_D16, +- MT2701_AUD_AUDPLL_D24, +- MT2701_AUD_AUDINTBUS, +- MT2701_AUD_CLK_26M, +- MT2701_AUD_SYSPLL1_D4, +- MT2701_AUD_AUD_K1_SRC_SEL, +- MT2701_AUD_AUD_K2_SRC_SEL, +- MT2701_AUD_AUD_K3_SRC_SEL, +- MT2701_AUD_AUD_K4_SRC_SEL, +- MT2701_AUD_AUD_K5_SRC_SEL, +- MT2701_AUD_AUD_K6_SRC_SEL, +- MT2701_AUD_AUD_K1_SRC_DIV, +- MT2701_AUD_AUD_K2_SRC_DIV, +- MT2701_AUD_AUD_K3_SRC_DIV, +- MT2701_AUD_AUD_K4_SRC_DIV, +- MT2701_AUD_AUD_K5_SRC_DIV, +- MT2701_AUD_AUD_K6_SRC_DIV, +- MT2701_AUD_AUD_I2S1_MCLK, +- MT2701_AUD_AUD_I2S2_MCLK, +- MT2701_AUD_AUD_I2S3_MCLK, +- MT2701_AUD_AUD_I2S4_MCLK, +- MT2701_AUD_AUD_I2S5_MCLK, +- MT2701_AUD_AUD_I2S6_MCLK, +- MT2701_AUD_ASM_M_SEL, +- MT2701_AUD_ASM_H_SEL, +- MT2701_AUD_UNIVPLL2_D4, +- MT2701_AUD_UNIVPLL2_D2, +- MT2701_AUD_SYSPLL_D5, +- MT2701_CLOCK_NUM ++enum audio_base_clock { ++ MT2701_TOP_AUD_MCLK_SRC0, ++ MT2701_TOP_AUD_MCLK_SRC1, ++ MT2701_AUDSYS_AFE, ++ MT2701_AUDSYS_AFE_CONN, ++ MT2701_AUDSYS_A1SYS, ++ MT2701_AUDSYS_A2SYS, ++ MT2701_BASE_CLK_NUM, + }; + + static const unsigned int mt2701_afe_backup_list[] = { +@@ -144,7 +105,6 @@ struct mtk_base_irq_data; + + struct mt2701_i2s_data { + int i2s_ctrl_reg; +- int i2s_pwn_shift; + int i2s_asrc_fs_shift; + int i2s_asrc_fs_mask; + }; +@@ -161,11 +121,17 @@ struct mt2701_i2s_path { + int on[I2S_DIR_NUM]; + int occupied[I2S_DIR_NUM]; + const struct mt2701_i2s_data *i2s_data[2]; ++ struct clk *hop_ck[I2S_DIR_NUM]; ++ struct clk *sel_ck; ++ struct clk *div_ck; ++ struct clk *mclk_ck; ++ struct clk *asrco_ck; + }; + + struct mt2701_afe_private { +- struct clk *clocks[MT2701_CLOCK_NUM]; + struct mt2701_i2s_path i2s_path[MT2701_I2S_NUM]; ++ struct clk *base_ck[MT2701_BASE_CLK_NUM]; ++ struct clk *mrgif_ck; + bool mrg_enable[MT2701_STREAM_DIR_NUM]; + }; + +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +index a7362d1cda1b..33f809228f25 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +@@ -97,21 +97,12 @@ static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream, + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); +- struct mt2701_afe_private *afe_priv = afe->platform_priv; + int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); +- int clk_num = MT2701_AUD_AUD_I2S1_MCLK + i2s_num; +- int ret = 0; + + if (i2s_num < 0) + return i2s_num; + +- /* enable mclk */ +- ret = clk_prepare_enable(afe_priv->clocks[clk_num]); +- if (ret) +- dev_err(afe->dev, "Failed to enable mclk for I2S: %d\n", +- i2s_num); +- +- return ret; ++ return mt2701_afe_enable_mclk(afe, i2s_num); + } + + static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream, +@@ -151,9 +142,9 @@ static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream, + /* disable i2s */ + regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, + ASYS_I2S_CON_I2S_EN, 0); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- 1 << i2s_data->i2s_pwn_shift, +- 1 << i2s_data->i2s_pwn_shift); ++ ++ mt2701_afe_disable_i2s(afe, i2s_num, stream_dir); ++ + return 0; + } + +@@ -165,7 +156,6 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, + struct mt2701_afe_private *afe_priv = afe->platform_priv; + int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); + struct mt2701_i2s_path *i2s_path; +- int clk_num = MT2701_AUD_AUD_I2S1_MCLK + i2s_num; + + if (i2s_num < 0) + return; +@@ -185,7 +175,7 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, + + I2S_UNSTART: + /* disable mclk */ +- clk_disable_unprepare(afe_priv->clocks[clk_num]); ++ mt2701_afe_disable_mclk(afe, i2s_num); + } + + static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream, +@@ -251,9 +241,7 @@ static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream, + fs << i2s_data->i2s_asrc_fs_shift); + + /* enable i2s */ +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- 1 << i2s_data->i2s_pwn_shift, +- 0 << i2s_data->i2s_pwn_shift); ++ mt2701_afe_enable_i2s(afe, i2s_num, stream_dir); + + /* reset i2s hw status before enable */ + regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, +@@ -339,9 +327,11 @@ static int mt2701_btmrg_startup(struct snd_pcm_substream *substream, + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); + struct mt2701_afe_private *afe_priv = afe->platform_priv; ++ int ret; + +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_MRGIF, 0); ++ ret = mt2701_enable_btmrg_clk(afe); ++ if (ret) ++ return ret; + + afe_priv->mrg_enable[substream->stream] = 1; + return 0; +@@ -406,9 +396,7 @@ static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream, + AFE_MRGIF_CON_MRG_EN, 0); + regmap_update_bits(afe->regmap, AFE_MRGIF_CON, + AFE_MRGIF_CON_MRG_I2S_EN, 0); +- regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, +- AUDIO_TOP_CON4_PDN_MRGIF, +- AUDIO_TOP_CON4_PDN_MRGIF); ++ mt2701_disable_btmrg_clk(afe); + } + afe_priv->mrg_enable[substream->stream] = 0; + } +@@ -1386,14 +1374,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = { + { + { + .i2s_ctrl_reg = ASYS_I2SO1_CON, +- .i2s_pwn_shift = 6, + .i2s_asrc_fs_shift = 0, + .i2s_asrc_fs_mask = 0x1f, + + }, + { + .i2s_ctrl_reg = ASYS_I2SIN1_CON, +- .i2s_pwn_shift = 0, + .i2s_asrc_fs_shift = 0, + .i2s_asrc_fs_mask = 0x1f, + +@@ -1402,14 +1388,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = { + { + { + .i2s_ctrl_reg = ASYS_I2SO2_CON, +- .i2s_pwn_shift = 7, + .i2s_asrc_fs_shift = 5, + .i2s_asrc_fs_mask = 0x1f, + + }, + { + .i2s_ctrl_reg = ASYS_I2SIN2_CON, +- .i2s_pwn_shift = 1, + .i2s_asrc_fs_shift = 5, + .i2s_asrc_fs_mask = 0x1f, + +@@ -1418,14 +1402,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = { + { + { + .i2s_ctrl_reg = ASYS_I2SO3_CON, +- .i2s_pwn_shift = 8, + .i2s_asrc_fs_shift = 10, + .i2s_asrc_fs_mask = 0x1f, + + }, + { + .i2s_ctrl_reg = ASYS_I2SIN3_CON, +- .i2s_pwn_shift = 2, + .i2s_asrc_fs_shift = 10, + .i2s_asrc_fs_mask = 0x1f, + +@@ -1434,14 +1416,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = { + { + { + .i2s_ctrl_reg = ASYS_I2SO4_CON, +- .i2s_pwn_shift = 9, + .i2s_asrc_fs_shift = 15, + .i2s_asrc_fs_mask = 0x1f, + + }, + { + .i2s_ctrl_reg = ASYS_I2SIN4_CON, +- .i2s_pwn_shift = 3, + .i2s_asrc_fs_shift = 15, + .i2s_asrc_fs_mask = 0x1f, + +@@ -1483,8 +1463,7 @@ static int mt2701_afe_runtime_suspend(struct device *dev) + { + struct mtk_base_afe *afe = dev_get_drvdata(dev); + +- mt2701_afe_disable_clock(afe); +- return 0; ++ return mt2701_afe_disable_clock(afe); + } + + static int mt2701_afe_runtime_resume(struct device *dev) +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0182-ASoC-mediatek-cleanup-audio-driver-for-MT2701.patch b/target/linux/mediatek/patches-4.14/0182-ASoC-mediatek-cleanup-audio-driver-for-MT2701.patch new file mode 100644 index 0000000000..ee439ff531 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0182-ASoC-mediatek-cleanup-audio-driver-for-MT2701.patch @@ -0,0 +1,439 @@ +From 4087c924ec899881951b2170a7bb8888747ec532 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 2 Jan 2018 19:47:20 +0800 +Subject: [PATCH 182/224] ASoC: mediatek: cleanup audio driver for MT2701 + +Cleanup unused code such as 'i2s_num' guard, headers, indentation +and some defines. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c | 14 +--- + sound/soc/mediatek/mt2701/mt2701-afe-common.h | 20 +---- + sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 94 ++++------------------- + sound/soc/mediatek/mt2701/mt2701-reg.h | 41 +--------- + 4 files changed, 24 insertions(+), 145 deletions(-) + +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c +index 75ccdca5811d..56a057c78c9a 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c +@@ -14,10 +14,6 @@ + * GNU General Public License for more details. + */ + +-#include <sound/soc.h> +-#include <linux/regmap.h> +-#include <linux/pm_runtime.h> +- + #include "mt2701-afe-common.h" + #include "mt2701-afe-clock-ctrl.h" + +@@ -223,8 +219,8 @@ int mt2701_afe_enable_clock(struct mtk_base_afe *afe) + } + + regmap_update_bits(afe->regmap, ASYS_TOP_CON, +- AUDIO_TOP_CON0_A1SYS_A2SYS_ON, +- AUDIO_TOP_CON0_A1SYS_A2SYS_ON); ++ ASYS_TOP_CON_ASYS_TIMING_ON, ++ ASYS_TOP_CON_ASYS_TIMING_ON); + regmap_update_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_AFE_ON, + AFE_DAC_CON0_AFE_ON); +@@ -239,7 +235,7 @@ int mt2701_afe_enable_clock(struct mtk_base_afe *afe) + int mt2701_afe_disable_clock(struct mtk_base_afe *afe) + { + regmap_update_bits(afe->regmap, ASYS_TOP_CON, +- AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 0); ++ ASYS_TOP_CON_ASYS_TIMING_ON, 0); + regmap_update_bits(afe->regmap, AFE_DAC_CON0, + AFE_DAC_CON0_AFE_ON, 0); + +@@ -272,7 +268,3 @@ void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain, + if (ret) + dev_err(afe->dev, "failed to set mclk divider %d\n", ret); + } +- +-MODULE_DESCRIPTION("MT2701 afe clock control"); +-MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h +index ce5bd4dc864d..9a2b301a4c21 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h +@@ -16,6 +16,7 @@ + + #ifndef _MT_2701_AFE_COMMON_H_ + #define _MT_2701_AFE_COMMON_H_ ++ + #include <sound/soc.h> + #include <linux/clk.h> + #include <linux/regmap.h> +@@ -25,16 +26,7 @@ + #define MT2701_STREAM_DIR_NUM (SNDRV_PCM_STREAM_LAST + 1) + #define MT2701_PLL_DOMAIN_0_RATE 98304000 + #define MT2701_PLL_DOMAIN_1_RATE 90316800 +-#define MT2701_AUD_AUD_MUX1_DIV_RATE (MT2701_PLL_DOMAIN_0_RATE / 2) +-#define MT2701_AUD_AUD_MUX2_DIV_RATE (MT2701_PLL_DOMAIN_1_RATE / 2) +- +-enum { +- MT2701_I2S_1, +- MT2701_I2S_2, +- MT2701_I2S_3, +- MT2701_I2S_4, +- MT2701_I2S_NUM, +-}; ++#define MT2701_I2S_NUM 4 + + enum { + MT2701_MEMIF_DL1, +@@ -62,8 +54,7 @@ enum { + }; + + enum { +- MT2701_IRQ_ASYS_START, +- MT2701_IRQ_ASYS_IRQ1 = MT2701_IRQ_ASYS_START, ++ MT2701_IRQ_ASYS_IRQ1, + MT2701_IRQ_ASYS_IRQ2, + MT2701_IRQ_ASYS_IRQ3, + MT2701_IRQ_ASYS_END, +@@ -100,9 +91,6 @@ static const unsigned int mt2701_afe_backup_list[] = { + AFE_MEMIF_PBUF_SIZE, + }; + +-struct snd_pcm_substream; +-struct mtk_base_irq_data; +- + struct mt2701_i2s_data { + int i2s_ctrl_reg; + int i2s_asrc_fs_shift; +@@ -120,7 +108,7 @@ struct mt2701_i2s_path { + int mclk_rate; + int on[I2S_DIR_NUM]; + int occupied[I2S_DIR_NUM]; +- const struct mt2701_i2s_data *i2s_data[2]; ++ const struct mt2701_i2s_data *i2s_data[I2S_DIR_NUM]; + struct clk *hop_ck[I2S_DIR_NUM]; + struct clk *sel_ck; + struct clk *div_ck; +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +index 33f809228f25..0edadca12a5e 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +@@ -20,16 +20,12 @@ + #include <linux/of.h> + #include <linux/of_address.h> + #include <linux/pm_runtime.h> +-#include <sound/soc.h> + + #include "mt2701-afe-common.h" +- + #include "mt2701-afe-clock-ctrl.h" + #include "../common/mtk-afe-platform-driver.h" + #include "../common/mtk-afe-fe-dai.h" + +-#define AFE_IRQ_STATUS_BITS 0xff +- + static const struct snd_pcm_hardware mt2701_afe_hardware = { + .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED + | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID, +@@ -107,21 +103,16 @@ static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream, + + static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, ++ int i2s_num, + int dir_invert) + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); + struct mt2701_afe_private *afe_priv = afe->platform_priv; +- int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); +- struct mt2701_i2s_path *i2s_path; ++ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num]; + const struct mt2701_i2s_data *i2s_data; + int stream_dir = substream->stream; + +- if (i2s_num < 0) +- return i2s_num; +- +- i2s_path = &afe_priv->i2s_path[i2s_num]; +- + if (dir_invert) { + if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) + stream_dir = SNDRV_PCM_STREAM_CAPTURE; +@@ -167,11 +158,11 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, + else + goto I2S_UNSTART; + +- mt2701_afe_i2s_path_shutdown(substream, dai, 0); ++ mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 0); + + /* need to disable i2s-out path when disable i2s-in */ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- mt2701_afe_i2s_path_shutdown(substream, dai, 1); ++ mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 1); + + I2S_UNSTART: + /* disable mclk */ +@@ -180,24 +171,19 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, + + static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, ++ int i2s_num, + int dir_invert) + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); + struct mt2701_afe_private *afe_priv = afe->platform_priv; +- int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); +- struct mt2701_i2s_path *i2s_path; ++ struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num]; + const struct mt2701_i2s_data *i2s_data; + struct snd_pcm_runtime * const runtime = substream->runtime; + int reg, fs, w_len = 1; /* now we support bck 64bits only */ + int stream_dir = substream->stream; + unsigned int mask = 0, val = 0; + +- if (i2s_num < 0) +- return i2s_num; +- +- i2s_path = &afe_priv->i2s_path[i2s_num]; +- + if (dir_invert) { + if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) + stream_dir = SNDRV_PCM_STREAM_CAPTURE; +@@ -288,13 +274,13 @@ static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream, + mt2701_mclk_configuration(afe, i2s_num, clk_domain, mclk_rate); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- mt2701_i2s_path_prepare_enable(substream, dai, 0); ++ mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0); + } else { + /* need to enable i2s-out path when enable i2s-in */ + /* prepare for another direction "out" */ +- mt2701_i2s_path_prepare_enable(substream, dai, 1); ++ mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 1); + /* prepare for "in" */ +- mt2701_i2s_path_prepare_enable(substream, dai, 0); ++ mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0); + } + + return 0; +@@ -562,7 +548,6 @@ static const struct snd_soc_dai_ops mt2701_single_memif_dai_ops = { + .hw_free = mtk_afe_fe_hw_free, + .prepare = mtk_afe_fe_prepare, + .trigger = mtk_afe_fe_trigger, +- + }; + + static const struct snd_soc_dai_ops mt2701_dlm_memif_dai_ops = { +@@ -903,31 +888,6 @@ static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s4[] = { + PWR2_TOP_CON, 19, 1, 0), + }; + +-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc0[] = { +- SOC_DAPM_SINGLE_AUTODISABLE("Asrc0 out Switch", AUDIO_TOP_CON4, 14, 1, +- 1), +-}; +- +-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc1[] = { +- SOC_DAPM_SINGLE_AUTODISABLE("Asrc1 out Switch", AUDIO_TOP_CON4, 15, 1, +- 1), +-}; +- +-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc2[] = { +- SOC_DAPM_SINGLE_AUTODISABLE("Asrc2 out Switch", PWR2_TOP_CON, 6, 1, +- 1), +-}; +- +-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc3[] = { +- SOC_DAPM_SINGLE_AUTODISABLE("Asrc3 out Switch", PWR2_TOP_CON, 7, 1, +- 1), +-}; +- +-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc4[] = { +- SOC_DAPM_SINGLE_AUTODISABLE("Asrc4 out Switch", PWR2_TOP_CON, 8, 1, +- 1), +-}; +- + static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0), +@@ -987,19 +947,6 @@ static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = { + SND_SOC_DAPM_MIXER("I18I19", SND_SOC_NOPM, 0, 0, + mt2701_afe_multi_ch_out_i2s3, + ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s3)), +- +- SND_SOC_DAPM_MIXER("ASRC_O0", SND_SOC_NOPM, 0, 0, +- mt2701_afe_multi_ch_out_asrc0, +- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc0)), +- SND_SOC_DAPM_MIXER("ASRC_O1", SND_SOC_NOPM, 0, 0, +- mt2701_afe_multi_ch_out_asrc1, +- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc1)), +- SND_SOC_DAPM_MIXER("ASRC_O2", SND_SOC_NOPM, 0, 0, +- mt2701_afe_multi_ch_out_asrc2, +- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc2)), +- SND_SOC_DAPM_MIXER("ASRC_O3", SND_SOC_NOPM, 0, 0, +- mt2701_afe_multi_ch_out_asrc3, +- ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc3)), + }; + + static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { +@@ -1009,7 +956,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { + + {"I2S0 Playback", NULL, "O15"}, + {"I2S0 Playback", NULL, "O16"}, +- + {"I2S1 Playback", NULL, "O17"}, + {"I2S1 Playback", NULL, "O18"}, + {"I2S2 Playback", NULL, "O19"}, +@@ -1026,7 +972,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { + + {"I00", NULL, "I2S0 Capture"}, + {"I01", NULL, "I2S0 Capture"}, +- + {"I02", NULL, "I2S1 Capture"}, + {"I03", NULL, "I2S1 Capture"}, + /* I02,03 link to UL2, also need to open I2S0 */ +@@ -1034,15 +979,10 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { + + {"I26", NULL, "BT Capture"}, + +- {"ASRC_O0", "Asrc0 out Switch", "DLM"}, +- {"ASRC_O1", "Asrc1 out Switch", "DLM"}, +- {"ASRC_O2", "Asrc2 out Switch", "DLM"}, +- {"ASRC_O3", "Asrc3 out Switch", "DLM"}, +- +- {"I12I13", "Multich I2S0 Out Switch", "ASRC_O0"}, +- {"I14I15", "Multich I2S1 Out Switch", "ASRC_O1"}, +- {"I16I17", "Multich I2S2 Out Switch", "ASRC_O2"}, +- {"I18I19", "Multich I2S3 Out Switch", "ASRC_O3"}, ++ {"I12I13", "Multich I2S0 Out Switch", "DLM"}, ++ {"I14I15", "Multich I2S1 Out Switch", "DLM"}, ++ {"I16I17", "Multich I2S2 Out Switch", "DLM"}, ++ {"I18I19", "Multich I2S3 Out Switch", "DLM"}, + + { "I12", NULL, "I12I13" }, + { "I13", NULL, "I12I13" }, +@@ -1067,7 +1007,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { + { "O21", "I18 Switch", "I18" }, + { "O22", "I19 Switch", "I19" }, + { "O31", "I35 Switch", "I35" }, +- + }; + + static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = { +@@ -1484,12 +1423,13 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); + if (!afe) + return -ENOMEM; ++ + afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), + GFP_KERNEL); + if (!afe->platform_priv) + return -ENOMEM; +- afe_priv = afe->platform_priv; + ++ afe_priv = afe->platform_priv; + afe->dev = &pdev->dev; + dev = afe->dev; + +@@ -1524,7 +1464,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + afe->memif_size = MT2701_MEMIF_NUM; + afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), + GFP_KERNEL); +- + if (!afe->memif) + return -ENOMEM; + +@@ -1537,7 +1476,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + afe->irqs_size = MT2701_IRQ_ASYS_END; + afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), + GFP_KERNEL); +- + if (!afe->irqs) + return -ENOMEM; + +@@ -1555,7 +1493,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + afe->mtk_afe_hardware = &mt2701_afe_hardware; + afe->memif_fs = mt2701_memif_fs; + afe->irq_fs = mt2701_irq_fs; +- + afe->reg_back_up_list = mt2701_afe_backup_list; + afe->reg_back_up_list_num = ARRAY_SIZE(mt2701_afe_backup_list); + afe->runtime_resume = mt2701_afe_runtime_resume; +@@ -1646,4 +1583,3 @@ module_platform_driver(mt2701_afe_pcm_driver); + MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 2701"); + MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); + MODULE_LICENSE("GPL v2"); +- +diff --git a/sound/soc/mediatek/mt2701/mt2701-reg.h b/sound/soc/mediatek/mt2701/mt2701-reg.h +index bb62b1c55957..f17c76f37b5f 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-reg.h ++++ b/sound/soc/mediatek/mt2701/mt2701-reg.h +@@ -17,17 +17,6 @@ + #ifndef _MT2701_REG_H_ + #define _MT2701_REG_H_ + +-#include <linux/delay.h> +-#include <linux/module.h> +-#include <linux/of.h> +-#include <linux/of_address.h> +-#include <linux/pm_runtime.h> +-#include <sound/soc.h> +-#include "mt2701-afe-common.h" +- +-/***************************************************************************** +- * R E G I S T E R D E F I N I T I O N +- *****************************************************************************/ + #define AUDIO_TOP_CON0 0x0000 + #define AUDIO_TOP_CON4 0x0010 + #define AUDIO_TOP_CON5 0x0014 +@@ -109,18 +98,6 @@ + #define AFE_DAI_BASE 0x1370 + #define AFE_DAI_CUR 0x137c + +-/* AUDIO_TOP_CON0 (0x0000) */ +-#define AUDIO_TOP_CON0_A1SYS_A2SYS_ON (0x3 << 0) +-#define AUDIO_TOP_CON0_PDN_AFE (0x1 << 2) +-#define AUDIO_TOP_CON0_PDN_APLL_CK (0x1 << 23) +- +-/* AUDIO_TOP_CON4 (0x0010) */ +-#define AUDIO_TOP_CON4_I2SO1_PWN (0x1 << 6) +-#define AUDIO_TOP_CON4_PDN_A1SYS (0x1 << 21) +-#define AUDIO_TOP_CON4_PDN_A2SYS (0x1 << 22) +-#define AUDIO_TOP_CON4_PDN_AFE_CONN (0x1 << 23) +-#define AUDIO_TOP_CON4_PDN_MRGIF (0x1 << 25) +- + /* AFE_DAIBT_CON0 (0x001c) */ + #define AFE_DAIBT_CON0_DAIBT_EN (0x1 << 0) + #define AFE_DAIBT_CON0_BT_FUNC_EN (0x1 << 1) +@@ -137,22 +114,8 @@ + #define AFE_MRGIF_CON_I2S_MODE_MASK (0xf << 20) + #define AFE_MRGIF_CON_I2S_MODE_32K (0x4 << 20) + +-/* ASYS_I2SO1_CON (0x061c) */ +-#define ASYS_I2SO1_CON_FS (0x1f << 8) +-#define ASYS_I2SO1_CON_FS_SET(x) ((x) << 8) +-#define ASYS_I2SO1_CON_MULTI_CH (0x1 << 16) +-#define ASYS_I2SO1_CON_SIDEGEN (0x1 << 30) +-#define ASYS_I2SO1_CON_I2S_EN (0x1 << 0) +-/* 0:EIAJ 1:I2S */ +-#define ASYS_I2SO1_CON_I2S_MODE (0x1 << 3) +-#define ASYS_I2SO1_CON_WIDE_MODE (0x1 << 1) +-#define ASYS_I2SO1_CON_WIDE_MODE_SET(x) ((x) << 1) +- +-/* PWR2_TOP_CON (0x0634) */ +-#define PWR2_TOP_CON_INIT_VAL (0xffe1ffff) +- +-/* ASYS_IRQ_CLR (0x07c0) */ +-#define ASYS_IRQ_CLR_ALL (0xffffffff) ++/* ASYS_TOP_CON (0x0600) */ ++#define ASYS_TOP_CON_ASYS_TIMING_ON (0x3 << 0) + + /* PWR2_ASM_CON1 (0x1070) */ + #define PWR2_ASM_CON1_INIT_VAL (0x492492) +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0183-ASoC-mediatek-update-clock-related-properties-of-MT2.patch b/target/linux/mediatek/patches-4.14/0183-ASoC-mediatek-update-clock-related-properties-of-MT2.patch new file mode 100644 index 0000000000..7aa20b76e7 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0183-ASoC-mediatek-update-clock-related-properties-of-MT2.patch @@ -0,0 +1,263 @@ +From d5b391bb7208c8a7b6b874c1357d3cd110537167 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 2 Jan 2018 19:47:21 +0800 +Subject: [PATCH 183/224] ASoC: mediatek: update clock related properties of + MT2701 AFE + +Add 'assigned-clocks*' properties which are used to initialize default +domain sources of audio system. we could configure different sets of +input clocks through DTS now. Hence driver no longer cares about that. + +Also we change some 'clock-names' to make them more generic so that +other chips can reuse gracefully. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + .../devicetree/bindings/sound/mt2701-afe-pcm.txt | 207 +++++++++------------ + 1 file changed, 91 insertions(+), 116 deletions(-) + +diff --git a/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt b/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt +index 77a57f84bed4..0450baad2813 100644 +--- a/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt ++++ b/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt +@@ -6,51 +6,44 @@ Required properties: + - interrupts: should contain AFE and ASYS interrupts + - interrupt-names: should be "afe" and "asys" + - power-domains: should define the power domain ++- clocks: Must contain an entry for each entry in clock-names ++ See ../clocks/clock-bindings.txt for details + - clock-names: should have these clock names: +- "infra_sys_audio_clk", + "top_audio_mux1_sel", + "top_audio_mux2_sel", +- "top_audio_mux1_div", +- "top_audio_mux2_div", +- "top_audio_48k_timing", +- "top_audio_44k_timing", +- "top_audpll_mux_sel", +- "top_apll_sel", +- "top_aud1_pll_98M", +- "top_aud2_pll_90M", +- "top_hadds2_pll_98M", +- "top_hadds2_pll_294M", +- "top_audpll", +- "top_audpll_d4", +- "top_audpll_d8", +- "top_audpll_d16", +- "top_audpll_d24", +- "top_audintbus_sel", +- "clk_26m", +- "top_syspll1_d4", +- "top_aud_k1_src_sel", +- "top_aud_k2_src_sel", +- "top_aud_k3_src_sel", +- "top_aud_k4_src_sel", +- "top_aud_k5_src_sel", +- "top_aud_k6_src_sel", +- "top_aud_k1_src_div", +- "top_aud_k2_src_div", +- "top_aud_k3_src_div", +- "top_aud_k4_src_div", +- "top_aud_k5_src_div", +- "top_aud_k6_src_div", +- "top_aud_i2s1_mclk", +- "top_aud_i2s2_mclk", +- "top_aud_i2s3_mclk", +- "top_aud_i2s4_mclk", +- "top_aud_i2s5_mclk", +- "top_aud_i2s6_mclk", +- "top_asm_m_sel", +- "top_asm_h_sel", +- "top_univpll2_d4", +- "top_univpll2_d2", +- "top_syspll_d5"; ++ "i2s0_src_sel", ++ "i2s1_src_sel", ++ "i2s2_src_sel", ++ "i2s3_src_sel", ++ "i2s0_src_div", ++ "i2s1_src_div", ++ "i2s2_src_div", ++ "i2s3_src_div", ++ "i2s0_mclk_en", ++ "i2s1_mclk_en", ++ "i2s2_mclk_en", ++ "i2s3_mclk_en", ++ "i2so0_hop_ck", ++ "i2so1_hop_ck", ++ "i2so2_hop_ck", ++ "i2so3_hop_ck", ++ "i2si0_hop_ck", ++ "i2si1_hop_ck", ++ "i2si2_hop_ck", ++ "i2si3_hop_ck", ++ "asrc0_out_ck", ++ "asrc1_out_ck", ++ "asrc2_out_ck", ++ "asrc3_out_ck", ++ "audio_afe_pd", ++ "audio_afe_conn_pd", ++ "audio_a1sys_pd", ++ "audio_a2sys_pd", ++ "audio_mrgif_pd"; ++- assigned-clocks: list of input clocks and dividers for the audio system. ++ See ../clocks/clock-bindings.txt for details. ++- assigned-clocks-parents: parent of input clocks of assigned clocks. ++- assigned-clock-rates: list of clock frequencies of assigned clocks. + + Example: + +@@ -62,93 +55,75 @@ Example: + <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "afe", "asys"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>; +- clocks = <&infracfg CLK_INFRA_AUDIO>, +- <&topckgen CLK_TOP_AUD_MUX1_SEL>, ++ clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>, + <&topckgen CLK_TOP_AUD_MUX2_SEL>, +- <&topckgen CLK_TOP_AUD_MUX1_DIV>, +- <&topckgen CLK_TOP_AUD_MUX2_DIV>, +- <&topckgen CLK_TOP_AUD_48K_TIMING>, +- <&topckgen CLK_TOP_AUD_44K_TIMING>, +- <&topckgen CLK_TOP_AUDPLL_MUX_SEL>, +- <&topckgen CLK_TOP_APLL_SEL>, +- <&topckgen CLK_TOP_AUD1PLL_98M>, +- <&topckgen CLK_TOP_AUD2PLL_90M>, +- <&topckgen CLK_TOP_HADDS2PLL_98M>, +- <&topckgen CLK_TOP_HADDS2PLL_294M>, +- <&topckgen CLK_TOP_AUDPLL>, +- <&topckgen CLK_TOP_AUDPLL_D4>, +- <&topckgen CLK_TOP_AUDPLL_D8>, +- <&topckgen CLK_TOP_AUDPLL_D16>, +- <&topckgen CLK_TOP_AUDPLL_D24>, +- <&topckgen CLK_TOP_AUDINTBUS_SEL>, +- <&clk26m>, +- <&topckgen CLK_TOP_SYSPLL1_D4>, + <&topckgen CLK_TOP_AUD_K1_SRC_SEL>, + <&topckgen CLK_TOP_AUD_K2_SRC_SEL>, + <&topckgen CLK_TOP_AUD_K3_SRC_SEL>, + <&topckgen CLK_TOP_AUD_K4_SRC_SEL>, +- <&topckgen CLK_TOP_AUD_K5_SRC_SEL>, +- <&topckgen CLK_TOP_AUD_K6_SRC_SEL>, + <&topckgen CLK_TOP_AUD_K1_SRC_DIV>, + <&topckgen CLK_TOP_AUD_K2_SRC_DIV>, + <&topckgen CLK_TOP_AUD_K3_SRC_DIV>, + <&topckgen CLK_TOP_AUD_K4_SRC_DIV>, +- <&topckgen CLK_TOP_AUD_K5_SRC_DIV>, +- <&topckgen CLK_TOP_AUD_K6_SRC_DIV>, + <&topckgen CLK_TOP_AUD_I2S1_MCLK>, + <&topckgen CLK_TOP_AUD_I2S2_MCLK>, + <&topckgen CLK_TOP_AUD_I2S3_MCLK>, + <&topckgen CLK_TOP_AUD_I2S4_MCLK>, +- <&topckgen CLK_TOP_AUD_I2S5_MCLK>, +- <&topckgen CLK_TOP_AUD_I2S6_MCLK>, +- <&topckgen CLK_TOP_ASM_M_SEL>, +- <&topckgen CLK_TOP_ASM_H_SEL>, +- <&topckgen CLK_TOP_UNIVPLL2_D4>, +- <&topckgen CLK_TOP_UNIVPLL2_D2>, +- <&topckgen CLK_TOP_SYSPLL_D5>; ++ <&audiosys CLK_AUD_I2SO1>, ++ <&audiosys CLK_AUD_I2SO2>, ++ <&audiosys CLK_AUD_I2SO3>, ++ <&audiosys CLK_AUD_I2SO4>, ++ <&audiosys CLK_AUD_I2SIN1>, ++ <&audiosys CLK_AUD_I2SIN2>, ++ <&audiosys CLK_AUD_I2SIN3>, ++ <&audiosys CLK_AUD_I2SIN4>, ++ <&audiosys CLK_AUD_ASRCO1>, ++ <&audiosys CLK_AUD_ASRCO2>, ++ <&audiosys CLK_AUD_ASRCO3>, ++ <&audiosys CLK_AUD_ASRCO4>, ++ <&audiosys CLK_AUD_AFE>, ++ <&audiosys CLK_AUD_AFE_CONN>, ++ <&audiosys CLK_AUD_A1SYS>, ++ <&audiosys CLK_AUD_A2SYS>, ++ <&audiosys CLK_AUD_AFE_MRGIF>; + +- clock-names = "infra_sys_audio_clk", +- "top_audio_mux1_sel", ++ clock-names = "top_audio_mux1_sel", + "top_audio_mux2_sel", +- "top_audio_mux1_div", +- "top_audio_mux2_div", +- "top_audio_48k_timing", +- "top_audio_44k_timing", +- "top_audpll_mux_sel", +- "top_apll_sel", +- "top_aud1_pll_98M", +- "top_aud2_pll_90M", +- "top_hadds2_pll_98M", +- "top_hadds2_pll_294M", +- "top_audpll", +- "top_audpll_d4", +- "top_audpll_d8", +- "top_audpll_d16", +- "top_audpll_d24", +- "top_audintbus_sel", +- "clk_26m", +- "top_syspll1_d4", +- "top_aud_k1_src_sel", +- "top_aud_k2_src_sel", +- "top_aud_k3_src_sel", +- "top_aud_k4_src_sel", +- "top_aud_k5_src_sel", +- "top_aud_k6_src_sel", +- "top_aud_k1_src_div", +- "top_aud_k2_src_div", +- "top_aud_k3_src_div", +- "top_aud_k4_src_div", +- "top_aud_k5_src_div", +- "top_aud_k6_src_div", +- "top_aud_i2s1_mclk", +- "top_aud_i2s2_mclk", +- "top_aud_i2s3_mclk", +- "top_aud_i2s4_mclk", +- "top_aud_i2s5_mclk", +- "top_aud_i2s6_mclk", +- "top_asm_m_sel", +- "top_asm_h_sel", +- "top_univpll2_d4", +- "top_univpll2_d2", +- "top_syspll_d5"; ++ "i2s0_src_sel", ++ "i2s1_src_sel", ++ "i2s2_src_sel", ++ "i2s3_src_sel", ++ "i2s0_src_div", ++ "i2s1_src_div", ++ "i2s2_src_div", ++ "i2s3_src_div", ++ "i2s0_mclk_en", ++ "i2s1_mclk_en", ++ "i2s2_mclk_en", ++ "i2s3_mclk_en", ++ "i2so0_hop_ck", ++ "i2so1_hop_ck", ++ "i2so2_hop_ck", ++ "i2so3_hop_ck", ++ "i2si0_hop_ck", ++ "i2si1_hop_ck", ++ "i2si2_hop_ck", ++ "i2si3_hop_ck", ++ "asrc0_out_ck", ++ "asrc1_out_ck", ++ "asrc2_out_ck", ++ "asrc3_out_ck", ++ "audio_afe_pd", ++ "audio_afe_conn_pd", ++ "audio_a1sys_pd", ++ "audio_a2sys_pd", ++ "audio_mrgif_pd"; ++ ++ assigned-clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>, ++ <&topckgen CLK_TOP_AUD_MUX2_SEL>, ++ <&topckgen CLK_TOP_AUD_MUX1_DIV>, ++ <&topckgen CLK_TOP_AUD_MUX2_DIV>; ++ assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL_98M>, ++ <&topckgen CLK_TOP_AUD2PLL_90M>; ++ assigned-clock-rates = <0>, <0>, <49152000>, <45158400>; + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0184-ASoC-mediatek-add-some-core-clocks-for-MT2701-AFE.patch b/target/linux/mediatek/patches-4.14/0184-ASoC-mediatek-add-some-core-clocks-for-MT2701-AFE.patch new file mode 100644 index 0000000000..d64d5a7072 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0184-ASoC-mediatek-add-some-core-clocks-for-MT2701-AFE.patch @@ -0,0 +1,100 @@ +From e0e3768b73daae674c69db1f71718894274b7bfc Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Thu, 4 Jan 2018 15:44:07 +0800 +Subject: [PATCH 184/224] ASoC: mediatek: add some core clocks for MT2701 AFE + +Add three core clocks for MT2701 AFE. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c | 30 ++++++++++++++++++++++- + sound/soc/mediatek/mt2701/mt2701-afe-common.h | 3 +++ + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c +index 56a057c78c9a..949fc3a1d025 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c +@@ -18,8 +18,11 @@ + #include "mt2701-afe-clock-ctrl.h" + + static const char *const base_clks[] = { ++ [MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk", + [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel", + [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel", ++ [MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp", ++ [MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp", + [MT2701_AUDSYS_AFE] = "audio_afe_pd", + [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd", + [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd", +@@ -169,10 +172,26 @@ static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe) + struct mt2701_afe_private *afe_priv = afe->platform_priv; + int ret; + +- ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); ++ /* Enable infra clock gate */ ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); + if (ret) + return ret; + ++ /* Enable top a1sys clock gate */ ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); ++ if (ret) ++ goto err_a1sys; ++ ++ /* Enable top a2sys clock gate */ ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); ++ if (ret) ++ goto err_a2sys; ++ ++ /* Internal clock gates */ ++ ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); ++ if (ret) ++ goto err_afe; ++ + ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); + if (ret) + goto err_audio_a1sys; +@@ -193,6 +212,12 @@ static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe) + clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); + err_audio_a1sys: + clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); ++err_afe: ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); ++err_a2sys: ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); ++err_a1sys: ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); + + return ret; + } +@@ -205,6 +230,9 @@ static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe) + clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); + clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); + clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); ++ clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); + } + + int mt2701_afe_enable_clock(struct mtk_base_afe *afe) +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h +index 9a2b301a4c21..ae8ddeacfbfe 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h +@@ -61,8 +61,11 @@ enum { + }; + + enum audio_base_clock { ++ MT2701_INFRA_SYS_AUDIO, + MT2701_TOP_AUD_MCLK_SRC0, + MT2701_TOP_AUD_MCLK_SRC1, ++ MT2701_TOP_AUD_A1SYS, ++ MT2701_TOP_AUD_A2SYS, + MT2701_AUDSYS_AFE, + MT2701_AUDSYS_AFE_CONN, + MT2701_AUDSYS_A1SYS, +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0185-ASoC-mediatek-modify-MT2701-AFE-driver-to-adapt-mfd-.patch b/target/linux/mediatek/patches-4.14/0185-ASoC-mediatek-modify-MT2701-AFE-driver-to-adapt-mfd-.patch new file mode 100644 index 0000000000..fe5f9d398e --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0185-ASoC-mediatek-modify-MT2701-AFE-driver-to-adapt-mfd-.patch @@ -0,0 +1,135 @@ +From 310ca2954c7cce10d716001ff869bc255494e3df Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Thu, 4 Jan 2018 15:44:08 +0800 +Subject: [PATCH 185/224] ASoC: mediatek: modify MT2701 AFE driver to adapt mfd + device + +As the new MFD parent is in place, modify MT2701 AFE driver to adapt it. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 45 +++++++++++++----------------- + sound/soc/mediatek/mt2701/mt2701-reg.h | 1 - + 2 files changed, 20 insertions(+), 26 deletions(-) + +diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +index 0edadca12a5e..f0cd08fa5c5d 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +@@ -17,6 +17,7 @@ + + #include <linux/delay.h> + #include <linux/module.h> ++#include <linux/mfd/syscon.h> + #include <linux/of.h> + #include <linux/of_address.h> + #include <linux/pm_runtime.h> +@@ -1368,14 +1369,6 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = { + }, + }; + +-static const struct regmap_config mt2701_afe_regmap_config = { +- .reg_bits = 32, +- .reg_stride = 4, +- .val_bits = 32, +- .max_register = AFE_END_ADDR, +- .cache_type = REGCACHE_NONE, +-}; +- + static irqreturn_t mt2701_asys_isr(int irq_id, void *dev) + { + int id; +@@ -1414,9 +1407,9 @@ static int mt2701_afe_runtime_resume(struct device *dev) + + static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + { ++ struct snd_soc_component *component; + struct mtk_base_afe *afe; + struct mt2701_afe_private *afe_priv; +- struct resource *res; + struct device *dev; + int i, irq_id, ret; + +@@ -1446,17 +1439,11 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + return ret; + } + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- +- afe->base_addr = devm_ioremap_resource(&pdev->dev, res); +- +- if (IS_ERR(afe->base_addr)) +- return PTR_ERR(afe->base_addr); +- +- afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, +- &mt2701_afe_regmap_config); +- if (IS_ERR(afe->regmap)) +- return PTR_ERR(afe->regmap); ++ afe->regmap = syscon_node_to_regmap(dev->parent->of_node); ++ if (!afe->regmap) { ++ dev_err(dev, "could not get regmap from parent\n"); ++ return -ENODEV; ++ } + + mutex_init(&afe->irq_alloc_lock); + +@@ -1490,6 +1477,12 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + = &mt2701_i2s_data[i][I2S_IN]; + } + ++ component = kzalloc(sizeof(*component), GFP_KERNEL); ++ if (!component) ++ return -ENOMEM; ++ ++ component->regmap = afe->regmap; ++ + afe->mtk_afe_hardware = &mt2701_afe_hardware; + afe->memif_fs = mt2701_memif_fs; + afe->irq_fs = mt2701_irq_fs; +@@ -1502,7 +1495,7 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + ret = mt2701_init_clock(afe); + if (ret) { + dev_err(dev, "init clock error\n"); +- return ret; ++ goto err_init_clock; + } + + platform_set_drvdata(pdev, afe); +@@ -1521,10 +1514,10 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + goto err_platform; + } + +- ret = snd_soc_register_component(&pdev->dev, +- &mt2701_afe_pcm_dai_component, +- mt2701_afe_pcm_dais, +- ARRAY_SIZE(mt2701_afe_pcm_dais)); ++ ret = snd_soc_add_component(dev, component, ++ &mt2701_afe_pcm_dai_component, ++ mt2701_afe_pcm_dais, ++ ARRAY_SIZE(mt2701_afe_pcm_dais)); + if (ret) { + dev_warn(dev, "err_dai_component\n"); + goto err_dai_component; +@@ -1538,6 +1531,8 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) + pm_runtime_put_sync(dev); + err_pm_disable: + pm_runtime_disable(dev); ++err_init_clock: ++ kfree(component); + + return ret; + } +diff --git a/sound/soc/mediatek/mt2701/mt2701-reg.h b/sound/soc/mediatek/mt2701/mt2701-reg.h +index f17c76f37b5f..18e676974f22 100644 +--- a/sound/soc/mediatek/mt2701/mt2701-reg.h ++++ b/sound/soc/mediatek/mt2701/mt2701-reg.h +@@ -145,5 +145,4 @@ + #define ASYS_I2S_CON_WIDE_MODE_SET(x) ((x) << 1) + #define ASYS_I2S_IN_PHASE_FIX (0x1 << 31) + +-#define AFE_END_ADDR 0x15e0 + #endif +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0186-ASoC-mediatek-update-MT2701-AFE-documentation-to-ada.patch b/target/linux/mediatek/patches-4.14/0186-ASoC-mediatek-update-MT2701-AFE-documentation-to-ada.patch new file mode 100644 index 0000000000..3d515402b5 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0186-ASoC-mediatek-update-MT2701-AFE-documentation-to-ada.patch @@ -0,0 +1,217 @@ +From 018219d340c0f7a10098683b8a4733618ea76ba3 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Thu, 4 Jan 2018 15:44:09 +0800 +Subject: [PATCH 186/224] ASoC: mediatek: update MT2701 AFE documentation to + adapt mfd device + +As the new MFD parent is in place, modify MT2701 AFE documentation to +adapt it. Also add three core clocks in example. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +--- + .../devicetree/bindings/sound/mt2701-afe-pcm.txt | 171 +++++++++++---------- + 1 file changed, 93 insertions(+), 78 deletions(-) + +diff --git a/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt b/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt +index 0450baad2813..6df87b97f7cb 100644 +--- a/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt ++++ b/Documentation/devicetree/bindings/sound/mt2701-afe-pcm.txt +@@ -2,15 +2,17 @@ Mediatek AFE PCM controller for mt2701 + + Required properties: + - compatible = "mediatek,mt2701-audio"; +-- reg: register location and size + - interrupts: should contain AFE and ASYS interrupts + - interrupt-names: should be "afe" and "asys" + - power-domains: should define the power domain + - clocks: Must contain an entry for each entry in clock-names + See ../clocks/clock-bindings.txt for details + - clock-names: should have these clock names: ++ "infra_sys_audio_clk", + "top_audio_mux1_sel", + "top_audio_mux2_sel", ++ "top_audio_a1sys_hp", ++ "top_audio_a2sys_hp", + "i2s0_src_sel", + "i2s1_src_sel", + "i2s2_src_sel", +@@ -45,85 +47,98 @@ Required properties: + - assigned-clocks-parents: parent of input clocks of assigned clocks. + - assigned-clock-rates: list of clock frequencies of assigned clocks. + ++Must be a subnode of MediaTek audsys device tree node. ++See ../arm/mediatek/mediatek,audsys.txt for details about the parent node. ++ + Example: + +- afe: mt2701-afe-pcm@11220000 { +- compatible = "mediatek,mt2701-audio"; +- reg = <0 0x11220000 0 0x2000>, +- <0 0x112A0000 0 0x20000>; +- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>, +- <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>; +- interrupt-names = "afe", "asys"; +- power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>; +- clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>, +- <&topckgen CLK_TOP_AUD_MUX2_SEL>, +- <&topckgen CLK_TOP_AUD_K1_SRC_SEL>, +- <&topckgen CLK_TOP_AUD_K2_SRC_SEL>, +- <&topckgen CLK_TOP_AUD_K3_SRC_SEL>, +- <&topckgen CLK_TOP_AUD_K4_SRC_SEL>, +- <&topckgen CLK_TOP_AUD_K1_SRC_DIV>, +- <&topckgen CLK_TOP_AUD_K2_SRC_DIV>, +- <&topckgen CLK_TOP_AUD_K3_SRC_DIV>, +- <&topckgen CLK_TOP_AUD_K4_SRC_DIV>, +- <&topckgen CLK_TOP_AUD_I2S1_MCLK>, +- <&topckgen CLK_TOP_AUD_I2S2_MCLK>, +- <&topckgen CLK_TOP_AUD_I2S3_MCLK>, +- <&topckgen CLK_TOP_AUD_I2S4_MCLK>, +- <&audiosys CLK_AUD_I2SO1>, +- <&audiosys CLK_AUD_I2SO2>, +- <&audiosys CLK_AUD_I2SO3>, +- <&audiosys CLK_AUD_I2SO4>, +- <&audiosys CLK_AUD_I2SIN1>, +- <&audiosys CLK_AUD_I2SIN2>, +- <&audiosys CLK_AUD_I2SIN3>, +- <&audiosys CLK_AUD_I2SIN4>, +- <&audiosys CLK_AUD_ASRCO1>, +- <&audiosys CLK_AUD_ASRCO2>, +- <&audiosys CLK_AUD_ASRCO3>, +- <&audiosys CLK_AUD_ASRCO4>, +- <&audiosys CLK_AUD_AFE>, +- <&audiosys CLK_AUD_AFE_CONN>, +- <&audiosys CLK_AUD_A1SYS>, +- <&audiosys CLK_AUD_A2SYS>, +- <&audiosys CLK_AUD_AFE_MRGIF>; ++ audsys: audio-subsystem@11220000 { ++ compatible = "mediatek,mt2701-audsys", "syscon", "simple-mfd"; ++ ... ++ ++ afe: audio-controller { ++ compatible = "mediatek,mt2701-audio"; ++ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>, ++ <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-names = "afe", "asys"; ++ power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>; ++ ++ clocks = <&infracfg CLK_INFRA_AUDIO>, ++ <&topckgen CLK_TOP_AUD_MUX1_SEL>, ++ <&topckgen CLK_TOP_AUD_MUX2_SEL>, ++ <&topckgen CLK_TOP_AUD_48K_TIMING>, ++ <&topckgen CLK_TOP_AUD_44K_TIMING>, ++ <&topckgen CLK_TOP_AUD_K1_SRC_SEL>, ++ <&topckgen CLK_TOP_AUD_K2_SRC_SEL>, ++ <&topckgen CLK_TOP_AUD_K3_SRC_SEL>, ++ <&topckgen CLK_TOP_AUD_K4_SRC_SEL>, ++ <&topckgen CLK_TOP_AUD_K1_SRC_DIV>, ++ <&topckgen CLK_TOP_AUD_K2_SRC_DIV>, ++ <&topckgen CLK_TOP_AUD_K3_SRC_DIV>, ++ <&topckgen CLK_TOP_AUD_K4_SRC_DIV>, ++ <&topckgen CLK_TOP_AUD_I2S1_MCLK>, ++ <&topckgen CLK_TOP_AUD_I2S2_MCLK>, ++ <&topckgen CLK_TOP_AUD_I2S3_MCLK>, ++ <&topckgen CLK_TOP_AUD_I2S4_MCLK>, ++ <&audsys CLK_AUD_I2SO1>, ++ <&audsys CLK_AUD_I2SO2>, ++ <&audsys CLK_AUD_I2SO3>, ++ <&audsys CLK_AUD_I2SO4>, ++ <&audsys CLK_AUD_I2SIN1>, ++ <&audsys CLK_AUD_I2SIN2>, ++ <&audsys CLK_AUD_I2SIN3>, ++ <&audsys CLK_AUD_I2SIN4>, ++ <&audsys CLK_AUD_ASRCO1>, ++ <&audsys CLK_AUD_ASRCO2>, ++ <&audsys CLK_AUD_ASRCO3>, ++ <&audsys CLK_AUD_ASRCO4>, ++ <&audsys CLK_AUD_AFE>, ++ <&audsys CLK_AUD_AFE_CONN>, ++ <&audsys CLK_AUD_A1SYS>, ++ <&audsys CLK_AUD_A2SYS>, ++ <&audsys CLK_AUD_AFE_MRGIF>; + +- clock-names = "top_audio_mux1_sel", +- "top_audio_mux2_sel", +- "i2s0_src_sel", +- "i2s1_src_sel", +- "i2s2_src_sel", +- "i2s3_src_sel", +- "i2s0_src_div", +- "i2s1_src_div", +- "i2s2_src_div", +- "i2s3_src_div", +- "i2s0_mclk_en", +- "i2s1_mclk_en", +- "i2s2_mclk_en", +- "i2s3_mclk_en", +- "i2so0_hop_ck", +- "i2so1_hop_ck", +- "i2so2_hop_ck", +- "i2so3_hop_ck", +- "i2si0_hop_ck", +- "i2si1_hop_ck", +- "i2si2_hop_ck", +- "i2si3_hop_ck", +- "asrc0_out_ck", +- "asrc1_out_ck", +- "asrc2_out_ck", +- "asrc3_out_ck", +- "audio_afe_pd", +- "audio_afe_conn_pd", +- "audio_a1sys_pd", +- "audio_a2sys_pd", +- "audio_mrgif_pd"; ++ clock-names = "infra_sys_audio_clk", ++ "top_audio_mux1_sel", ++ "top_audio_mux2_sel", ++ "top_audio_a1sys_hp", ++ "top_audio_a2sys_hp", ++ "i2s0_src_sel", ++ "i2s1_src_sel", ++ "i2s2_src_sel", ++ "i2s3_src_sel", ++ "i2s0_src_div", ++ "i2s1_src_div", ++ "i2s2_src_div", ++ "i2s3_src_div", ++ "i2s0_mclk_en", ++ "i2s1_mclk_en", ++ "i2s2_mclk_en", ++ "i2s3_mclk_en", ++ "i2so0_hop_ck", ++ "i2so1_hop_ck", ++ "i2so2_hop_ck", ++ "i2so3_hop_ck", ++ "i2si0_hop_ck", ++ "i2si1_hop_ck", ++ "i2si2_hop_ck", ++ "i2si3_hop_ck", ++ "asrc0_out_ck", ++ "asrc1_out_ck", ++ "asrc2_out_ck", ++ "asrc3_out_ck", ++ "audio_afe_pd", ++ "audio_afe_conn_pd", ++ "audio_a1sys_pd", ++ "audio_a2sys_pd", ++ "audio_mrgif_pd"; + +- assigned-clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>, +- <&topckgen CLK_TOP_AUD_MUX2_SEL>, +- <&topckgen CLK_TOP_AUD_MUX1_DIV>, +- <&topckgen CLK_TOP_AUD_MUX2_DIV>; +- assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL_98M>, +- <&topckgen CLK_TOP_AUD2PLL_90M>; +- assigned-clock-rates = <0>, <0>, <49152000>, <45158400>; ++ assigned-clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>, ++ <&topckgen CLK_TOP_AUD_MUX2_SEL>, ++ <&topckgen CLK_TOP_AUD_MUX1_DIV>, ++ <&topckgen CLK_TOP_AUD_MUX2_DIV>; ++ assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL_98M>, ++ <&topckgen CLK_TOP_AUD2PLL_90M>; ++ assigned-clock-rates = <0>, <0>, <49152000>, <45158400>; ++ }; + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0187-usb-mtu3-fix-error-code-for-getting-extcon-device.patch b/target/linux/mediatek/patches-4.14/0187-usb-mtu3-fix-error-code-for-getting-extcon-device.patch new file mode 100644 index 0000000000..4d79623e5d --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0187-usb-mtu3-fix-error-code-for-getting-extcon-device.patch @@ -0,0 +1,31 @@ +From 3d5564bbc0a39ba07d1bbdaec1f69a3d39c4495e Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Wed, 3 Jan 2018 16:53:17 +0800 +Subject: [PATCH 187/224] usb: mtu3: fix error code for getting extcon device + +When failing to get extcon device, extcon_get_edev_by_phandle() +may return different error codes, but not only -EPROBE_DEFER, +so can't always return -EPROBE_DEFER, and fix it. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/mtu3/mtu3_plat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index 9ff33579b42e..a2523ead46cf 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -317,7 +317,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0); + if (IS_ERR(otg_sx->edev)) { + dev_err(ssusb->dev, "couldn't get extcon device\n"); +- return -EPROBE_DEFER; ++ return PTR_ERR(otg_sx->edev); + } + } + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch b/target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch new file mode 100644 index 0000000000..105d6f156b --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0188-usb-mtu3-supports-remote-wakeup-for-mt2712-with-two-.patch @@ -0,0 +1,245 @@ +From 354655aaf0f71ce2b567cbc02afb0664c99e434e Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Wed, 3 Jan 2018 16:53:18 +0800 +Subject: [PATCH 188/224] usb: mtu3: supports remote wakeup for mt2712 with two + SSUSB IPs + +The old way of usb wakeup only supports platform with single SSUSB IP, +such as mt8173, but mt2712 has two SSUSB IPs, so rebuild its flow and +also supports the new glue layer of usb wakeup on mt2712 which is +different from mt8173. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/mtu3/mtu3.h | 11 +++-- + drivers/usb/mtu3/mtu3_dr.h | 3 +- + drivers/usb/mtu3/mtu3_host.c | 115 +++++++++++++++++++++---------------------- + drivers/usb/mtu3/mtu3_plat.c | 8 +-- + 4 files changed, 70 insertions(+), 67 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h +index d80e4e813248..ed3aec46eda1 100644 +--- a/drivers/usb/mtu3/mtu3.h ++++ b/drivers/usb/mtu3/mtu3.h +@@ -238,7 +238,10 @@ struct otg_switch_mtk { + * @u3p_dis_msk: mask of disabling usb3 ports, for example, bit0==1 to + * disable u3port0, bit1==1 to disable u3port1,... etc + * @dbgfs_root: only used when supports manual dual-role switch via debugfs +- * @wakeup_en: it's true when supports remote wakeup in host mode ++ * @uwk_en: it's true when supports remote wakeup in host mode ++ * @uwk: syscon including usb wakeup glue layer between SSUSB IP and SPM ++ * @uwk_reg_base: the base address of the wakeup glue layer in @uwk ++ * @uwk_vers: the version of the wakeup glue layer + */ + struct ssusb_mtk { + struct device *dev; +@@ -262,8 +265,10 @@ struct ssusb_mtk { + int u3p_dis_msk; + struct dentry *dbgfs_root; + /* usb wakeup for host mode */ +- bool wakeup_en; +- struct regmap *pericfg; ++ bool uwk_en; ++ struct regmap *uwk; ++ u32 uwk_reg_base; ++ u32 uwk_vers; + }; + + /** +diff --git a/drivers/usb/mtu3/mtu3_dr.h b/drivers/usb/mtu3/mtu3_dr.h +index 0f0cbac00192..1fa62ce136b6 100644 +--- a/drivers/usb/mtu3/mtu3_dr.h ++++ b/drivers/usb/mtu3/mtu3_dr.h +@@ -27,8 +27,7 @@ int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, + struct device_node *dn); + int ssusb_host_enable(struct ssusb_mtk *ssusb); + int ssusb_host_disable(struct ssusb_mtk *ssusb, bool suspend); +-int ssusb_wakeup_enable(struct ssusb_mtk *ssusb); +-void ssusb_wakeup_disable(struct ssusb_mtk *ssusb); ++void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable); + + #else + +diff --git a/drivers/usb/mtu3/mtu3_host.c b/drivers/usb/mtu3/mtu3_host.c +index ec76b86dd887..1a1b6cf432a1 100644 +--- a/drivers/usb/mtu3/mtu3_host.c ++++ b/drivers/usb/mtu3/mtu3_host.c +@@ -27,66 +27,77 @@ + #include "mtu3.h" + #include "mtu3_dr.h" + +-#define PERI_WK_CTRL1 0x404 +-#define UWK_CTL1_IS_C(x) (((x) & 0xf) << 26) +-#define UWK_CTL1_IS_E BIT(25) +-#define UWK_CTL1_IDDIG_C(x) (((x) & 0xf) << 11) /* cycle debounce */ +-#define UWK_CTL1_IDDIG_E BIT(10) /* enable debounce */ +-#define UWK_CTL1_IDDIG_P BIT(9) /* polarity */ +-#define UWK_CTL1_IS_P BIT(6) /* polarity for ip sleep */ ++/* mt8173 etc */ ++#define PERI_WK_CTRL1 0x4 ++#define WC1_IS_C(x) (((x) & 0xf) << 26) /* cycle debounce */ ++#define WC1_IS_EN BIT(25) ++#define WC1_IS_P BIT(6) /* polarity for ip sleep */ ++ ++/* mt2712 etc */ ++#define PERI_SSUSB_SPM_CTRL 0x0 ++#define SSC_IP_SLEEP_EN BIT(4) ++#define SSC_SPM_INT_EN BIT(1) ++ ++enum ssusb_uwk_vers { ++ SSUSB_UWK_V1 = 1, ++ SSUSB_UWK_V2, ++}; + + /* + * ip-sleep wakeup mode: + * all clocks can be turn off, but power domain should be kept on + */ +-static void ssusb_wakeup_ip_sleep_en(struct ssusb_mtk *ssusb) ++static void ssusb_wakeup_ip_sleep_set(struct ssusb_mtk *ssusb, bool enable) + { +- u32 tmp; +- struct regmap *pericfg = ssusb->pericfg; +- +- regmap_read(pericfg, PERI_WK_CTRL1, &tmp); +- tmp &= ~UWK_CTL1_IS_P; +- tmp &= ~(UWK_CTL1_IS_C(0xf)); +- tmp |= UWK_CTL1_IS_C(0x8); +- regmap_write(pericfg, PERI_WK_CTRL1, tmp); +- regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E); +- +- regmap_read(pericfg, PERI_WK_CTRL1, &tmp); +- dev_dbg(ssusb->dev, "%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n", +- __func__, tmp); +-} +- +-static void ssusb_wakeup_ip_sleep_dis(struct ssusb_mtk *ssusb) +-{ +- u32 tmp; +- +- regmap_read(ssusb->pericfg, PERI_WK_CTRL1, &tmp); +- tmp &= ~UWK_CTL1_IS_E; +- regmap_write(ssusb->pericfg, PERI_WK_CTRL1, tmp); ++ u32 reg, msk, val; ++ ++ switch (ssusb->uwk_vers) { ++ case SSUSB_UWK_V1: ++ reg = ssusb->uwk_reg_base + PERI_WK_CTRL1; ++ msk = WC1_IS_EN | WC1_IS_C(0xf) | WC1_IS_P; ++ val = enable ? (WC1_IS_EN | WC1_IS_C(0x8)) : 0; ++ break; ++ case SSUSB_UWK_V2: ++ reg = ssusb->uwk_reg_base + PERI_SSUSB_SPM_CTRL; ++ msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN; ++ val = enable ? msk : 0; ++ break; ++ default: ++ return; ++ }; ++ regmap_update_bits(ssusb->uwk, reg, msk, val); + } + + int ssusb_wakeup_of_property_parse(struct ssusb_mtk *ssusb, + struct device_node *dn) + { +- struct device *dev = ssusb->dev; ++ struct of_phandle_args args; ++ int ret; + +- /* +- * Wakeup function is optional, so it is not an error if this property +- * does not exist, and in such case, no need to get relative +- * properties anymore. +- */ +- ssusb->wakeup_en = of_property_read_bool(dn, "mediatek,enable-wakeup"); +- if (!ssusb->wakeup_en) ++ /* wakeup function is optional */ ++ ssusb->uwk_en = of_property_read_bool(dn, "wakeup-source"); ++ if (!ssusb->uwk_en) + return 0; + +- ssusb->pericfg = syscon_regmap_lookup_by_phandle(dn, +- "mediatek,syscon-wakeup"); +- if (IS_ERR(ssusb->pericfg)) { +- dev_err(dev, "fail to get pericfg regs\n"); +- return PTR_ERR(ssusb->pericfg); +- } ++ ret = of_parse_phandle_with_fixed_args(dn, ++ "mediatek,syscon-wakeup", 2, 0, &args); ++ if (ret) ++ return ret; + +- return 0; ++ ssusb->uwk_reg_base = args.args[0]; ++ ssusb->uwk_vers = args.args[1]; ++ ssusb->uwk = syscon_node_to_regmap(args.np); ++ of_node_put(args.np); ++ dev_info(ssusb->dev, "uwk - reg:0x%x, version:%d\n", ++ ssusb->uwk_reg_base, ssusb->uwk_vers); ++ ++ return PTR_ERR_OR_ZERO(ssusb->uwk); ++} ++ ++void ssusb_wakeup_set(struct ssusb_mtk *ssusb, bool enable) ++{ ++ if (ssusb->uwk_en) ++ ssusb_wakeup_ip_sleep_set(ssusb, enable); + } + + static void host_ports_num_get(struct ssusb_mtk *ssusb) +@@ -244,17 +255,3 @@ void ssusb_host_exit(struct ssusb_mtk *ssusb) + of_platform_depopulate(ssusb->dev); + ssusb_host_cleanup(ssusb); + } +- +-int ssusb_wakeup_enable(struct ssusb_mtk *ssusb) +-{ +- if (ssusb->wakeup_en) +- ssusb_wakeup_ip_sleep_en(ssusb); +- +- return 0; +-} +- +-void ssusb_wakeup_disable(struct ssusb_mtk *ssusb) +-{ +- if (ssusb->wakeup_en) +- ssusb_wakeup_ip_sleep_dis(ssusb); +-} +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index a2523ead46cf..4cafd4ca8457 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -291,8 +291,10 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb) + + /* if host role is supported */ + ret = ssusb_wakeup_of_property_parse(ssusb, node); +- if (ret) ++ if (ret) { ++ dev_err(dev, "failed to parse uwk property\n"); + return ret; ++ } + + /* optional property, ignore the error if it does not exist */ + of_property_read_u32(node, "mediatek,u3p-dis-msk", +@@ -466,7 +468,7 @@ static int __maybe_unused mtu3_suspend(struct device *dev) + ssusb_host_disable(ssusb, true); + ssusb_phy_power_off(ssusb); + ssusb_clks_disable(ssusb); +- ssusb_wakeup_enable(ssusb); ++ ssusb_wakeup_set(ssusb, true); + + return 0; + } +@@ -482,7 +484,7 @@ static int __maybe_unused mtu3_resume(struct device *dev) + if (!ssusb->is_host) + return 0; + +- ssusb_wakeup_disable(ssusb); ++ ssusb_wakeup_set(ssusb, false); + ret = ssusb_clks_enable(ssusb); + if (ret) + goto clks_err; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0189-dt-bindings-usb-mtu3-update-USB-wakeup-properties.patch b/target/linux/mediatek/patches-4.14/0189-dt-bindings-usb-mtu3-update-USB-wakeup-properties.patch new file mode 100644 index 0000000000..30de3dd162 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0189-dt-bindings-usb-mtu3-update-USB-wakeup-properties.patch @@ -0,0 +1,52 @@ +From 067ad5fd18e2e7e38b77ca94eebaaf8d9a35d842 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Wed, 3 Jan 2018 16:53:19 +0800 +Subject: [PATCH 189/224] dt-bindings: usb: mtu3: update USB wakeup properties + +Add two arguments in "mediatek,syscon-wakeup" to support multi +wakeup glue layer between SSUSB and SPM, and use standard property +"wakeup-source" to replace the private "mediatek,enable-wakeup" + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Reviewed-by: Rob Herring <robh@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + Documentation/devicetree/bindings/usb/mediatek,mtu3.txt | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +index b2271d8e6b50..d589a1ef96a1 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtu3.txt +@@ -42,9 +42,14 @@ Optional properties: + - enable-manual-drd : supports manual dual-role switch via debugfs; usually + used when receptacle is TYPE-A and also wants to support dual-role + mode. +- - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode +- - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup +- control register, it depends on "mediatek,enable-wakeup". ++ - wakeup-source: enable USB remote wakeup of host mode. ++ - mediatek,syscon-wakeup : phandle to syscon used to access the register ++ of the USB wakeup glue layer between SSUSB and SPM; it depends on ++ "wakeup-source", and has two arguments: ++ - the first one : register base address of the glue layer in syscon; ++ - the second one : hardware version of the glue layer ++ - 1 : used by mt8173 etc ++ - 2 : used by mt2712 etc + - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, + bit1 for u3port1, ... etc; + +@@ -71,8 +76,8 @@ ssusb: usb@11271000 { + vbus-supply = <&usb_p0_vbus>; + extcon = <&extcon_usb>; + dr_mode = "otg"; +- mediatek,enable-wakeup; +- mediatek,syscon-wakeup = <&pericfg>; ++ wakeup-source; ++ mediatek,syscon-wakeup = <&pericfg 0x400 1>; + #address-cells = <2>; + #size-cells = <2>; + ranges; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0190-usb-xhci-mtk-supports-remote-wakeup-for-mt2712-with-.patch b/target/linux/mediatek/patches-4.14/0190-usb-xhci-mtk-supports-remote-wakeup-for-mt2712-with-.patch new file mode 100644 index 0000000000..ba7b834f84 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0190-usb-xhci-mtk-supports-remote-wakeup-for-mt2712-with-.patch @@ -0,0 +1,273 @@ +From e6fe50ef22071fe87ce48f79ab4fe21cbec2081b Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Wed, 3 Jan 2018 16:53:20 +0800 +Subject: [PATCH 190/224] usb: xhci-mtk: supports remote wakeup for mt2712 with + two xHCI IPs + +The old way of usb wakeup only supports platform with single xHCI IP, +such as mt8173, but mt2712 has two xHCI IPs, so rebuild its flow and +supports the new glue layer of usb wakeup on mt2712 which is different +from mt8173. +Due to there is a hardware bug with the LINE STATE wakeup mode on +mt8173 which causes wakeup failure by low speed devices, and also +because IP SLEEP mode can cover all functions of LINE STATE mode, +it is unused in fact, and will not support it later, so remove it at +the same time. + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/usb/host/xhci-mtk.c | 177 +++++++++++++++----------------------------- + drivers/usb/host/xhci-mtk.h | 6 +- + 2 files changed, 65 insertions(+), 118 deletions(-) + +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index e5caabe7eebe..8e51b3fec386 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -66,26 +66,21 @@ + /* u2_phy_pll register */ + #define CTRL_U2_FORCE_PLL_STB BIT(28) + +-#define PERI_WK_CTRL0 0x400 +-#define UWK_CTR0_0P_LS_PE BIT(8) /* posedge */ +-#define UWK_CTR0_0P_LS_NE BIT(7) /* negedge for 0p linestate*/ +-#define UWK_CTL1_1P_LS_C(x) (((x) & 0xf) << 1) +-#define UWK_CTL1_1P_LS_E BIT(0) +- +-#define PERI_WK_CTRL1 0x404 +-#define UWK_CTL1_IS_C(x) (((x) & 0xf) << 26) +-#define UWK_CTL1_IS_E BIT(25) +-#define UWK_CTL1_0P_LS_C(x) (((x) & 0xf) << 21) +-#define UWK_CTL1_0P_LS_E BIT(20) +-#define UWK_CTL1_IDDIG_C(x) (((x) & 0xf) << 11) /* cycle debounce */ +-#define UWK_CTL1_IDDIG_E BIT(10) /* enable debounce */ +-#define UWK_CTL1_IDDIG_P BIT(9) /* polarity */ +-#define UWK_CTL1_0P_LS_P BIT(7) +-#define UWK_CTL1_IS_P BIT(6) /* polarity for ip sleep */ +- +-enum ssusb_wakeup_src { +- SSUSB_WK_IP_SLEEP = 1, +- SSUSB_WK_LINE_STATE = 2, ++/* usb remote wakeup registers in syscon */ ++/* mt8173 etc */ ++#define PERI_WK_CTRL1 0x4 ++#define WC1_IS_C(x) (((x) & 0xf) << 26) /* cycle debounce */ ++#define WC1_IS_EN BIT(25) ++#define WC1_IS_P BIT(6) /* polarity for ip sleep */ ++ ++/* mt2712 etc */ ++#define PERI_SSUSB_SPM_CTRL 0x0 ++#define SSC_IP_SLEEP_EN BIT(4) ++#define SSC_SPM_INT_EN BIT(1) ++ ++enum ssusb_uwk_vers { ++ SSUSB_UWK_V1 = 1, ++ SSUSB_UWK_V2, + }; + + static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) +@@ -308,112 +303,58 @@ static void xhci_mtk_clks_disable(struct xhci_hcd_mtk *mtk) + } + + /* only clocks can be turn off for ip-sleep wakeup mode */ +-static void usb_wakeup_ip_sleep_en(struct xhci_hcd_mtk *mtk) ++static void usb_wakeup_ip_sleep_set(struct xhci_hcd_mtk *mtk, bool enable) + { +- u32 tmp; +- struct regmap *pericfg = mtk->pericfg; +- +- regmap_read(pericfg, PERI_WK_CTRL1, &tmp); +- tmp &= ~UWK_CTL1_IS_P; +- tmp &= ~(UWK_CTL1_IS_C(0xf)); +- tmp |= UWK_CTL1_IS_C(0x8); +- regmap_write(pericfg, PERI_WK_CTRL1, tmp); +- regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_IS_E); +- +- regmap_read(pericfg, PERI_WK_CTRL1, &tmp); +- dev_dbg(mtk->dev, "%s(): WK_CTRL1[P6,E25,C26:29]=%#x\n", +- __func__, tmp); ++ u32 reg, msk, val; ++ ++ switch (mtk->uwk_vers) { ++ case SSUSB_UWK_V1: ++ reg = mtk->uwk_reg_base + PERI_WK_CTRL1; ++ msk = WC1_IS_EN | WC1_IS_C(0xf) | WC1_IS_P; ++ val = enable ? (WC1_IS_EN | WC1_IS_C(0x8)) : 0; ++ break; ++ case SSUSB_UWK_V2: ++ reg = mtk->uwk_reg_base + PERI_SSUSB_SPM_CTRL; ++ msk = SSC_IP_SLEEP_EN | SSC_SPM_INT_EN; ++ val = enable ? msk : 0; ++ break; ++ default: ++ return; ++ }; ++ regmap_update_bits(mtk->uwk, reg, msk, val); + } + +-static void usb_wakeup_ip_sleep_dis(struct xhci_hcd_mtk *mtk) ++static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk, ++ struct device_node *dn) + { +- u32 tmp; ++ struct of_phandle_args args; ++ int ret; + +- regmap_read(mtk->pericfg, PERI_WK_CTRL1, &tmp); +- tmp &= ~UWK_CTL1_IS_E; +- regmap_write(mtk->pericfg, PERI_WK_CTRL1, tmp); +-} ++ /* Wakeup function is optional */ ++ mtk->uwk_en = of_property_read_bool(dn, "wakeup-source"); ++ if (!mtk->uwk_en) ++ return 0; + +-/* +-* for line-state wakeup mode, phy's power should not power-down +-* and only support cable plug in/out +-*/ +-static void usb_wakeup_line_state_en(struct xhci_hcd_mtk *mtk) +-{ +- u32 tmp; +- struct regmap *pericfg = mtk->pericfg; +- +- /* line-state of u2-port0 */ +- regmap_read(pericfg, PERI_WK_CTRL1, &tmp); +- tmp &= ~UWK_CTL1_0P_LS_P; +- tmp &= ~(UWK_CTL1_0P_LS_C(0xf)); +- tmp |= UWK_CTL1_0P_LS_C(0x8); +- regmap_write(pericfg, PERI_WK_CTRL1, tmp); +- regmap_read(pericfg, PERI_WK_CTRL1, &tmp); +- regmap_write(pericfg, PERI_WK_CTRL1, tmp | UWK_CTL1_0P_LS_E); +- +- /* line-state of u2-port1 */ +- regmap_read(pericfg, PERI_WK_CTRL0, &tmp); +- tmp &= ~(UWK_CTL1_1P_LS_C(0xf)); +- tmp |= UWK_CTL1_1P_LS_C(0x8); +- regmap_write(pericfg, PERI_WK_CTRL0, tmp); +- regmap_write(pericfg, PERI_WK_CTRL0, tmp | UWK_CTL1_1P_LS_E); +-} ++ ret = of_parse_phandle_with_fixed_args(dn, ++ "mediatek,syscon-wakeup", 2, 0, &args); ++ if (ret) ++ return ret; + +-static void usb_wakeup_line_state_dis(struct xhci_hcd_mtk *mtk) +-{ +- u32 tmp; +- struct regmap *pericfg = mtk->pericfg; +- +- /* line-state of u2-port0 */ +- regmap_read(pericfg, PERI_WK_CTRL1, &tmp); +- tmp &= ~UWK_CTL1_0P_LS_E; +- regmap_write(pericfg, PERI_WK_CTRL1, tmp); +- +- /* line-state of u2-port1 */ +- regmap_read(pericfg, PERI_WK_CTRL0, &tmp); +- tmp &= ~UWK_CTL1_1P_LS_E; +- regmap_write(pericfg, PERI_WK_CTRL0, tmp); +-} ++ mtk->uwk_reg_base = args.args[0]; ++ mtk->uwk_vers = args.args[1]; ++ mtk->uwk = syscon_node_to_regmap(args.np); ++ of_node_put(args.np); ++ dev_info(mtk->dev, "uwk - reg:0x%x, version:%d\n", ++ mtk->uwk_reg_base, mtk->uwk_vers); + +-static void usb_wakeup_enable(struct xhci_hcd_mtk *mtk) +-{ +- if (mtk->wakeup_src == SSUSB_WK_IP_SLEEP) +- usb_wakeup_ip_sleep_en(mtk); +- else if (mtk->wakeup_src == SSUSB_WK_LINE_STATE) +- usb_wakeup_line_state_en(mtk); +-} ++ return PTR_ERR_OR_ZERO(mtk->uwk); + +-static void usb_wakeup_disable(struct xhci_hcd_mtk *mtk) +-{ +- if (mtk->wakeup_src == SSUSB_WK_IP_SLEEP) +- usb_wakeup_ip_sleep_dis(mtk); +- else if (mtk->wakeup_src == SSUSB_WK_LINE_STATE) +- usb_wakeup_line_state_dis(mtk); + } + +-static int usb_wakeup_of_property_parse(struct xhci_hcd_mtk *mtk, +- struct device_node *dn) ++static void usb_wakeup_set(struct xhci_hcd_mtk *mtk, bool enable) + { +- struct device *dev = mtk->dev; +- +- /* +- * wakeup function is optional, so it is not an error if this property +- * does not exist, and in such case, no need to get relative +- * properties anymore. +- */ +- of_property_read_u32(dn, "mediatek,wakeup-src", &mtk->wakeup_src); +- if (!mtk->wakeup_src) +- return 0; +- +- mtk->pericfg = syscon_regmap_lookup_by_phandle(dn, +- "mediatek,syscon-wakeup"); +- if (IS_ERR(mtk->pericfg)) { +- dev_err(dev, "fail to get pericfg regs\n"); +- return PTR_ERR(mtk->pericfg); +- } +- +- return 0; ++ if (mtk->uwk_en) ++ usb_wakeup_ip_sleep_set(mtk, enable); + } + + static int xhci_mtk_setup(struct usb_hcd *hcd); +@@ -595,8 +536,10 @@ static int xhci_mtk_probe(struct platform_device *pdev) + &mtk->u3p_dis_msk); + + ret = usb_wakeup_of_property_parse(mtk, node); +- if (ret) ++ if (ret) { ++ dev_err(dev, "failed to parse uwk property\n"); + return ret; ++ } + + mtk->num_phys = of_count_phandle_with_args(node, + "phys", "#phy-cells"); +@@ -780,7 +723,7 @@ static int __maybe_unused xhci_mtk_suspend(struct device *dev) + xhci_mtk_host_disable(mtk); + xhci_mtk_phy_power_off(mtk); + xhci_mtk_clks_disable(mtk); +- usb_wakeup_enable(mtk); ++ usb_wakeup_set(mtk, true); + return 0; + } + +@@ -790,7 +733,7 @@ static int __maybe_unused xhci_mtk_resume(struct device *dev) + struct usb_hcd *hcd = mtk->hcd; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + +- usb_wakeup_disable(mtk); ++ usb_wakeup_set(mtk, false); + xhci_mtk_clks_enable(mtk); + xhci_mtk_phy_power_on(mtk); + xhci_mtk_host_enable(mtk); +diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h +index 45ff5c67efb5..85c007ee1f52 100644 +--- a/drivers/usb/host/xhci-mtk.h ++++ b/drivers/usb/host/xhci-mtk.h +@@ -131,8 +131,12 @@ struct xhci_hcd_mtk { + struct regmap *pericfg; + struct phy **phys; + int num_phys; +- int wakeup_src; + bool lpm_support; ++ /* usb remote wakeup */ ++ bool uwk_en; ++ struct regmap *uwk; ++ u32 uwk_reg_base; ++ u32 uwk_vers; + }; + + static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd) +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0191-usb-xhci-allow-imod-interval-to-be-configurable.patch b/target/linux/mediatek/patches-4.14/0191-usb-xhci-allow-imod-interval-to-be-configurable.patch new file mode 100644 index 0000000000..8bb6d5c51e --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0191-usb-xhci-allow-imod-interval-to-be-configurable.patch @@ -0,0 +1,155 @@ +From c5c72d252dc8e417388386d5767ea790ee8f5b44 Mon Sep 17 00:00:00 2001 +From: Adam Wallis <awallis@codeaurora.org> +Date: Fri, 8 Dec 2017 17:59:13 +0200 +Subject: [PATCH 191/224] usb: xhci: allow imod-interval to be configurable + +The xHCI driver currently has the IMOD set to 160, which +translates to an IMOD interval of 40,000ns (160 * 250)ns + +Commit 0cbd4b34cda9 ("xhci: mediatek: support MTK xHCI host controller") +introduced a QUIRK for the MTK platform to adjust this interval to 20, +which translates to an IMOD interval of 5,000ns (20 * 250)ns. This is +due to the fact that the MTK controller IMOD interval is 8 times +as much as defined in xHCI spec. + +Instead of adding more quirk bits for additional platforms, this patch +introduces the ability for vendors to set the IMOD_INTERVAL as is +optimal for their platform. By using device_property_read_u32() on +"imod-interval-ns", the IMOD INTERVAL can be specified in nano seconds. +If no interval is specified, the default of 40,000ns (IMOD=160) will be +used. + +No bounds checking has been implemented due to the fact that a vendor +may have violated the spec and would need to specify a value outside of +the max 8,000 IRQs/second limit specified in the xHCI spec. + +Tested-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Reviewed-by: Rob Herring <robh@kernel.org> +Signed-off-by: Adam Wallis <awallis@codeaurora.org> +Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt | 2 ++ + Documentation/devicetree/bindings/usb/usb-xhci.txt | 1 + + drivers/usb/host/xhci-mtk.c | 9 +++++++++ + drivers/usb/host/xhci-pci.c | 3 +++ + drivers/usb/host/xhci-plat.c | 5 +++++ + drivers/usb/host/xhci.c | 6 +----- + drivers/usb/host/xhci.h | 2 ++ + 7 files changed, 23 insertions(+), 5 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +index 30595964876a..9ff560298498 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +@@ -46,6 +46,7 @@ Optional properties: + - pinctrl-names : a pinctrl state named "default" must be defined + - pinctrl-0 : pin control group + See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt ++ - imod-interval-ns: default interrupt moderation interval is 5000ns + + Example: + usb30: usb@11270000 { +@@ -66,6 +67,7 @@ usb30: usb@11270000 { + usb3-lpm-capable; + mediatek,syscon-wakeup = <&pericfg>; + mediatek,wakeup-src = <1>; ++ imod-interval-ns = <10000>; + }; + + 2nd: dual-role mode with xHCI driver +diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt +index 2d80b60eeabe..2390ae58636b 100644 +--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt ++++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt +@@ -28,6 +28,7 @@ Optional properties: + - clocks: reference to a clock + - usb3-lpm-capable: determines if platform is USB3 LPM capable + - quirk-broken-port-ped: set if the controller has broken port disable mechanism ++ - imod-interval-ns: default interrupt moderation interval is 5000ns + + Example: + usb@f0931000 { +diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c +index 8e51b3fec386..8e4495be6592 100644 +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -629,6 +629,15 @@ static int xhci_mtk_probe(struct platform_device *pdev) + + xhci = hcd_to_xhci(hcd); + xhci->main_hcd = hcd; ++ ++ /* ++ * imod_interval is the interrupt moderation value in nanoseconds. ++ * The increment interval is 8 times as much as that defined in ++ * the xHCI spec on MTK's controller. ++ */ ++ xhci->imod_interval = 5000; ++ device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval); ++ + xhci->shared_hcd = usb_create_shared_hcd(driver, dev, + dev_name(dev), hcd); + if (!xhci->shared_hcd) { +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 8071c8fdd15e..cdd7d7bdfc0f 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -258,6 +258,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd) + if (!xhci->sbrn) + pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn); + ++ /* imod_interval is the interrupt moderation value in nanoseconds. */ ++ xhci->imod_interval = 40000; ++ + retval = xhci_gen_setup(hcd, xhci_pci_quirks); + if (retval) + return retval; +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 163bafde709f..47230453a876 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -265,6 +265,11 @@ static int xhci_plat_probe(struct platform_device *pdev) + if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped")) + xhci->quirks |= XHCI_BROKEN_PORT_PED; + ++ /* imod_interval is the interrupt moderation value in nanoseconds. */ ++ xhci->imod_interval = 40000; ++ device_property_read_u32(sysdev, "imod-interval-ns", ++ &xhci->imod_interval); ++ + hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0); + if (IS_ERR(hcd->usb_phy)) { + ret = PTR_ERR(hcd->usb_phy); +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index b2ff1ff1a02f..ac1b26a81e77 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -597,11 +597,7 @@ int xhci_run(struct usb_hcd *hcd) + "// Set the interrupt modulation register"); + temp = readl(&xhci->ir_set->irq_control); + temp &= ~ER_IRQ_INTERVAL_MASK; +- /* +- * the increment interval is 8 times as much as that defined +- * in xHCI spec on MTK's controller +- */ +- temp |= (u32) ((xhci->quirks & XHCI_MTK_HOST) ? 20 : 160); ++ temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK; + writel(temp, &xhci->ir_set->irq_control); + + /* Set the HCD state before we enable the irqs */ +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 2abaa4d6d39d..614380af0f96 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1723,6 +1723,8 @@ struct xhci_hcd { + u8 max_interrupters; + u8 max_ports; + u8 isoc_threshold; ++ /* imod_interval in ns (I * 250ns) */ ++ u32 imod_interval; + int event_ring_max; + /* 4KB min, 128MB max */ + int page_size; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0192-dt-bindings-usb-mtk-xhci-update-USB-wakeup-propertie.patch b/target/linux/mediatek/patches-4.14/0192-dt-bindings-usb-mtk-xhci-update-USB-wakeup-propertie.patch new file mode 100644 index 0000000000..250d647a98 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0192-dt-bindings-usb-mtk-xhci-update-USB-wakeup-propertie.patch @@ -0,0 +1,54 @@ +From bbbbdd36c7311a786d7392f2394b355b1f78cf8b Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Wed, 3 Jan 2018 16:53:21 +0800 +Subject: [PATCH 192/224] dt-bindings: usb: mtk-xhci: update USB wakeup + properties + +Add two arguments in "mediatek,syscon-wakeup" to support multi +wakeup glue layer between SSUSB and SPM, and use standard property +"wakeup-source" to replace the private "mediatek,wakeup-src" + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Reviewed-by: Rob Herring <robh@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + .../devicetree/bindings/usb/mediatek,mtk-xhci.txt | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +index 9ff560298498..88d9f4a4b280 100644 +--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt ++++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt +@@ -35,10 +35,14 @@ Required properties: + - phys : a list of phandle + phy specifier pairs + + Optional properties: +- - mediatek,wakeup-src : 1: ip sleep wakeup mode; 2: line state wakeup +- mode; +- - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup +- control register, it depends on "mediatek,wakeup-src". ++ - wakeup-source : enable USB remote wakeup; ++ - mediatek,syscon-wakeup : phandle to syscon used to access the register ++ of the USB wakeup glue layer between xHCI and SPM; it depends on ++ "wakeup-source", and has two arguments: ++ - the first one : register base address of the glue layer in syscon; ++ - the second one : hardware version of the glue layer ++ - 1 : used by mt8173 etc ++ - 2 : used by mt2712 etc + - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0, + bit1 for u3port1, ... etc; + - vbus-supply : reference to the VBUS regulator; +@@ -65,8 +69,8 @@ usb30: usb@11270000 { + vusb33-supply = <&mt6397_vusb_reg>; + vbus-supply = <&usb_p1_vbus>; + usb3-lpm-capable; +- mediatek,syscon-wakeup = <&pericfg>; +- mediatek,wakeup-src = <1>; ++ mediatek,syscon-wakeup = <&pericfg 0x400 1>; ++ wakeup-source; + imod-interval-ns = <10000>; + }; + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0193-clk-mediatek-adjust-dependency-of-reset.c-to-avoid-u.patch b/target/linux/mediatek/patches-4.14/0193-clk-mediatek-adjust-dependency-of-reset.c-to-avoid-u.patch new file mode 100644 index 0000000000..19527f1a06 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0193-clk-mediatek-adjust-dependency-of-reset.c-to-avoid-u.patch @@ -0,0 +1,77 @@ +From 0f9391b4ee12cad5c93e109b9eb6c0c6298da0d3 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 5 Jan 2018 16:14:06 +0800 +Subject: [PATCH 193/224] clk: mediatek: adjust dependency of reset.c to avoid + unexpectedly being built + +Changes from v1->v2: +Add 'select RESET_CONTROLLER' under COMMON_CLK_MEDIATEK and enable +reset.c to be built when COMMON_CLK_MEDIATEK is selected. That should +be quite reasonable because the reset controller is tightly embedded +inside and exported from these clock subsystems. At least it can be found +on infracfg and pericfg subsystem that both are really fundamental block +lots of devices must depend on. + +commit 74cb0d6dde8 ("clk: mediatek: fixup test-building of MediaTek clock +drivers") can let the build system looking into the directory where the +clock drivers resides and then allow test-building the drivers. + +But the change also gives rise to certain incorrect behavior which is +reset.c being built even not depending on either COMPILE_TEST or +ARCH_MEDIATEK alternative dependency. To get rid of reset.c being built +unexpectedly on the other platforms, it would be a good change that the +file should be built depending on its own specific configuration rather +than just on generic RESET_CONTROLLER one. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Jean Delvare <jdelvare@suse.de> +Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> +--- + drivers/clk/mediatek/Kconfig | 1 + + drivers/clk/mediatek/Makefile | 4 ++-- + drivers/clk/mediatek/clk-mtk.h | 7 ------- + 3 files changed, 3 insertions(+), 9 deletions(-) + +Index: linux-4.14.25/drivers/clk/mediatek/Kconfig +=================================================================== +--- linux-4.14.25.orig/drivers/clk/mediatek/Kconfig ++++ linux-4.14.25/drivers/clk/mediatek/Kconfig +@@ -6,6 +6,7 @@ menu "Clock driver for MediaTek SoC" + + config COMMON_CLK_MEDIATEK + bool ++ select RESET_CONTROLLER + ---help--- + MediaTek SoCs' clock support. + +Index: linux-4.14.25/drivers/clk/mediatek/Makefile +=================================================================== +--- linux-4.14.25.orig/drivers/clk/mediatek/Makefile ++++ linux-4.14.25/drivers/clk/mediatek/Makefile +@@ -1,6 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o +-obj-$(CONFIG_RESET_CONTROLLER) += reset.o ++obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o + obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o + obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o + obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o +Index: linux-4.14.25/drivers/clk/mediatek/clk-mtk.h +=================================================================== +--- linux-4.14.25.orig/drivers/clk/mediatek/clk-mtk.h ++++ linux-4.14.25/drivers/clk/mediatek/clk-mtk.h +@@ -229,14 +229,7 @@ void mtk_clk_register_plls(struct device + struct clk *mtk_clk_register_ref2usb_tx(const char *name, + const char *parent_name, void __iomem *reg); + +-#ifdef CONFIG_RESET_CONTROLLER + void mtk_register_reset_controller(struct device_node *np, + unsigned int num_regs, int regofs); +-#else +-static inline void mtk_register_reset_controller(struct device_node *np, +- unsigned int num_regs, int regofs) +-{ +-} +-#endif + + #endif /* __DRV_CLK_MTK_H */ diff --git a/target/linux/mediatek/patches-4.14/0194-pinctrl-mediatek-mt7622-fix-potential-uninitialized-.patch b/target/linux/mediatek/patches-4.14/0194-pinctrl-mediatek-mt7622-fix-potential-uninitialized-.patch new file mode 100644 index 0000000000..a71af5005c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0194-pinctrl-mediatek-mt7622-fix-potential-uninitialized-.patch @@ -0,0 +1,54 @@ +From cfcb2cc358f3ff466d4c419d8f6fe0263bdc47b1 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 10 Jan 2018 00:28:24 +0800 +Subject: [PATCH 194/224] pinctrl: mediatek: mt7622: fix potential + uninitialized value being returned + +commit d6ed93551320 ("pinctrl: mediatek: add pinctrl driver for MT7622 +SoC") leads to the following static checker warning: + +drivers/pinctrl/mediatek/pinctrl-mt7622.c:1419 mtk_gpio_get() +error: uninitialized symbol 'value'. +1412 static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) +1413 { +1414 struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent); +1415 int value; +1416 +1417 mtk_hw_get_value(hw, gpio, PINCTRL_PIN_REG_DI, &value); +^^^^^^^^^^^^^^^^ +1418 +1419 return !!value; +1420 } + +The appropriate error handling must be added to avoid the potential error +caused by uninitialized value being returned. + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +--- + drivers/pinctrl/mediatek/pinctrl-mt7622.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c +index 3824d82888ac..dc32e3c3bd73 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mt7622.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c +@@ -1412,9 +1412,11 @@ static struct pinctrl_desc mtk_desc = { + static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) + { + struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent); +- int value; ++ int value, err; + +- mtk_hw_get_value(hw, gpio, PINCTRL_PIN_REG_DI, &value); ++ err = mtk_hw_get_value(hw, gpio, PINCTRL_PIN_REG_DI, &value); ++ if (err) ++ return err; + + return !!value; + } +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0195-pinctrl-mediatek-mt7622-align-error-handling-of-mtk_.patch b/target/linux/mediatek/patches-4.14/0195-pinctrl-mediatek-mt7622-align-error-handling-of-mtk_.patch new file mode 100644 index 0000000000..31f25df2f3 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0195-pinctrl-mediatek-mt7622-align-error-handling-of-mtk_.patch @@ -0,0 +1,55 @@ +From 8d3e3f3159284dba7a86788464edd4d5cdba4f06 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 10 Jan 2018 00:28:25 +0800 +Subject: [PATCH 195/224] pinctrl: mediatek: mt7622: align error handling of + mtk_hw_get_value call + +Make consistent error handling of all mtk_hw_get_value occurrences using +propagating error code from the internal instead of creating a new one. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +--- + drivers/pinctrl/mediatek/pinctrl-mt7622.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c +index dc32e3c3bd73..06e8406c4440 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mt7622.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c +@@ -1160,7 +1160,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, + case PIN_CONFIG_OUTPUT_ENABLE: + err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val); + if (err) +- return -EINVAL; ++ return err; + + /* HW takes input mode as zero; output mode as non-zero */ + if ((val && param == PIN_CONFIG_INPUT_ENABLE) || +@@ -1184,11 +1184,11 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, + case PIN_CONFIG_DRIVE_STRENGTH: + err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E4, &val); + if (err) +- return -EINVAL; ++ return err; + + err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E8, &val2); + if (err) +- return -EINVAL; ++ return err; + + /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1) + * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1) +@@ -1203,7 +1203,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, + + err = mtk_hw_get_value(hw, pin, reg, &val); + if (err) +- return -EINVAL; ++ return err; + + ret = val; + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0196-mtd-mtk-nor-modify-functions-name-more-generally.patch b/target/linux/mediatek/patches-4.14/0196-mtd-mtk-nor-modify-functions-name-more-generally.patch new file mode 100644 index 0000000000..0840f7678e --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0196-mtd-mtk-nor-modify-functions-name-more-generally.patch @@ -0,0 +1,559 @@ +From 4dab73d46eb58c142b5d2e7039f12e4e5df357ad Mon Sep 17 00:00:00 2001 +From: Guochun Mao <guochun.mao@mediatek.com> +Date: Mon, 18 Dec 2017 09:47:35 +0800 +Subject: [PATCH 196/224] mtd: mtk-nor: modify functions' name more generally + +Since more and more Mediatek's SoC can use this driver to +control spi-nor flash, functions' name with "mt8173_" is +no longer properly. Replacing "mt8173_" with "mtk_" will +be more accurate to describe these functions' usable scope. + +Signed-off-by: Guochun Mao <guochun.mao@mediatek.com> +Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr> +--- + drivers/mtd/spi-nor/mtk-quadspi.c | 240 +++++++++++++++++++------------------- + 1 file changed, 120 insertions(+), 120 deletions(-) + +diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c +index abe455ccd68b..5442993b71ff 100644 +--- a/drivers/mtd/spi-nor/mtk-quadspi.c ++++ b/drivers/mtd/spi-nor/mtk-quadspi.c +@@ -110,7 +110,7 @@ + #define MTK_NOR_PRG_REG(n) (MTK_NOR_PRGDATA0_REG + 4 * (n)) + #define MTK_NOR_SHREG(n) (MTK_NOR_SHREG0_REG + 4 * (n)) + +-struct mt8173_nor { ++struct mtk_nor { + struct spi_nor nor; + struct device *dev; + void __iomem *base; /* nor flash base address */ +@@ -118,48 +118,48 @@ struct mt8173_nor { + struct clk *nor_clk; + }; + +-static void mt8173_nor_set_read_mode(struct mt8173_nor *mt8173_nor) ++static void mtk_nor_set_read_mode(struct mtk_nor *mtk_nor) + { +- struct spi_nor *nor = &mt8173_nor->nor; ++ struct spi_nor *nor = &mtk_nor->nor; + + switch (nor->read_proto) { + case SNOR_PROTO_1_1_1: +- writeb(nor->read_opcode, mt8173_nor->base + ++ writeb(nor->read_opcode, mtk_nor->base + + MTK_NOR_PRGDATA3_REG); +- writeb(MTK_NOR_FAST_READ, mt8173_nor->base + ++ writeb(MTK_NOR_FAST_READ, mtk_nor->base + + MTK_NOR_CFG1_REG); + break; + case SNOR_PROTO_1_1_2: +- writeb(nor->read_opcode, mt8173_nor->base + ++ writeb(nor->read_opcode, mtk_nor->base + + MTK_NOR_PRGDATA3_REG); +- writeb(MTK_NOR_DUAL_READ_EN, mt8173_nor->base + ++ writeb(MTK_NOR_DUAL_READ_EN, mtk_nor->base + + MTK_NOR_DUAL_REG); + break; + case SNOR_PROTO_1_1_4: +- writeb(nor->read_opcode, mt8173_nor->base + ++ writeb(nor->read_opcode, mtk_nor->base + + MTK_NOR_PRGDATA4_REG); +- writeb(MTK_NOR_QUAD_READ_EN, mt8173_nor->base + ++ writeb(MTK_NOR_QUAD_READ_EN, mtk_nor->base + + MTK_NOR_DUAL_REG); + break; + default: +- writeb(MTK_NOR_DUAL_DISABLE, mt8173_nor->base + ++ writeb(MTK_NOR_DUAL_DISABLE, mtk_nor->base + + MTK_NOR_DUAL_REG); + break; + } + } + +-static int mt8173_nor_execute_cmd(struct mt8173_nor *mt8173_nor, u8 cmdval) ++static int mtk_nor_execute_cmd(struct mtk_nor *mtk_nor, u8 cmdval) + { + int reg; + u8 val = cmdval & 0x1f; + +- writeb(cmdval, mt8173_nor->base + MTK_NOR_CMD_REG); +- return readl_poll_timeout(mt8173_nor->base + MTK_NOR_CMD_REG, reg, ++ writeb(cmdval, mtk_nor->base + MTK_NOR_CMD_REG); ++ return readl_poll_timeout(mtk_nor->base + MTK_NOR_CMD_REG, reg, + !(reg & val), 100, 10000); + } + +-static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op, +- u8 *tx, int txlen, u8 *rx, int rxlen) ++static int mtk_nor_do_tx_rx(struct mtk_nor *mtk_nor, u8 op, ++ u8 *tx, int txlen, u8 *rx, int rxlen) + { + int len = 1 + txlen + rxlen; + int i, ret, idx; +@@ -167,26 +167,26 @@ static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op, + if (len > MTK_NOR_MAX_SHIFT) + return -EINVAL; + +- writeb(len * 8, mt8173_nor->base + MTK_NOR_CNT_REG); ++ writeb(len * 8, mtk_nor->base + MTK_NOR_CNT_REG); + + /* start at PRGDATA5, go down to PRGDATA0 */ + idx = MTK_NOR_MAX_RX_TX_SHIFT - 1; + + /* opcode */ +- writeb(op, mt8173_nor->base + MTK_NOR_PRG_REG(idx)); ++ writeb(op, mtk_nor->base + MTK_NOR_PRG_REG(idx)); + idx--; + + /* program TX data */ + for (i = 0; i < txlen; i++, idx--) +- writeb(tx[i], mt8173_nor->base + MTK_NOR_PRG_REG(idx)); ++ writeb(tx[i], mtk_nor->base + MTK_NOR_PRG_REG(idx)); + + /* clear out rest of TX registers */ + while (idx >= 0) { +- writeb(0, mt8173_nor->base + MTK_NOR_PRG_REG(idx)); ++ writeb(0, mtk_nor->base + MTK_NOR_PRG_REG(idx)); + idx--; + } + +- ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PRG_CMD); ++ ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PRG_CMD); + if (ret) + return ret; + +@@ -195,20 +195,20 @@ static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op, + + /* read out RX data */ + for (i = 0; i < rxlen; i++, idx--) +- rx[i] = readb(mt8173_nor->base + MTK_NOR_SHREG(idx)); ++ rx[i] = readb(mtk_nor->base + MTK_NOR_SHREG(idx)); + + return 0; + } + + /* Do a WRSR (Write Status Register) command */ +-static int mt8173_nor_wr_sr(struct mt8173_nor *mt8173_nor, u8 sr) ++static int mtk_nor_wr_sr(struct mtk_nor *mtk_nor, u8 sr) + { +- writeb(sr, mt8173_nor->base + MTK_NOR_PRGDATA5_REG); +- writeb(8, mt8173_nor->base + MTK_NOR_CNT_REG); +- return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WRSR_CMD); ++ writeb(sr, mtk_nor->base + MTK_NOR_PRGDATA5_REG); ++ writeb(8, mtk_nor->base + MTK_NOR_CNT_REG); ++ return mtk_nor_execute_cmd(mtk_nor, MTK_NOR_WRSR_CMD); + } + +-static int mt8173_nor_write_buffer_enable(struct mt8173_nor *mt8173_nor) ++static int mtk_nor_write_buffer_enable(struct mtk_nor *mtk_nor) + { + u8 reg; + +@@ -216,27 +216,27 @@ static int mt8173_nor_write_buffer_enable(struct mt8173_nor *mt8173_nor) + * 0: pre-fetch buffer use for read + * 1: pre-fetch buffer use for page program + */ +- writel(MTK_NOR_WR_BUF_ENABLE, mt8173_nor->base + MTK_NOR_CFG2_REG); +- return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg, ++ writel(MTK_NOR_WR_BUF_ENABLE, mtk_nor->base + MTK_NOR_CFG2_REG); ++ return readb_poll_timeout(mtk_nor->base + MTK_NOR_CFG2_REG, reg, + 0x01 == (reg & 0x01), 100, 10000); + } + +-static int mt8173_nor_write_buffer_disable(struct mt8173_nor *mt8173_nor) ++static int mtk_nor_write_buffer_disable(struct mtk_nor *mtk_nor) + { + u8 reg; + +- writel(MTK_NOR_WR_BUF_DISABLE, mt8173_nor->base + MTK_NOR_CFG2_REG); +- return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg, ++ writel(MTK_NOR_WR_BUF_DISABLE, mtk_nor->base + MTK_NOR_CFG2_REG); ++ return readb_poll_timeout(mtk_nor->base + MTK_NOR_CFG2_REG, reg, + MTK_NOR_WR_BUF_DISABLE == (reg & 0x1), 100, + 10000); + } + +-static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor) ++static void mtk_nor_set_addr_width(struct mtk_nor *mtk_nor) + { + u8 val; +- struct spi_nor *nor = &mt8173_nor->nor; ++ struct spi_nor *nor = &mtk_nor->nor; + +- val = readb(mt8173_nor->base + MTK_NOR_DUAL_REG); ++ val = readb(mtk_nor->base + MTK_NOR_DUAL_REG); + + switch (nor->addr_width) { + case 3: +@@ -246,115 +246,115 @@ static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor) + val |= MTK_NOR_4B_ADDR_EN; + break; + default: +- dev_warn(mt8173_nor->dev, "Unexpected address width %u.\n", ++ dev_warn(mtk_nor->dev, "Unexpected address width %u.\n", + nor->addr_width); + break; + } + +- writeb(val, mt8173_nor->base + MTK_NOR_DUAL_REG); ++ writeb(val, mtk_nor->base + MTK_NOR_DUAL_REG); + } + +-static void mt8173_nor_set_addr(struct mt8173_nor *mt8173_nor, u32 addr) ++static void mtk_nor_set_addr(struct mtk_nor *mtk_nor, u32 addr) + { + int i; + +- mt8173_nor_set_addr_width(mt8173_nor); ++ mtk_nor_set_addr_width(mtk_nor); + + for (i = 0; i < 3; i++) { +- writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR0_REG + i * 4); ++ writeb(addr & 0xff, mtk_nor->base + MTK_NOR_RADR0_REG + i * 4); + addr >>= 8; + } + /* Last register is non-contiguous */ +- writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR3_REG); ++ writeb(addr & 0xff, mtk_nor->base + MTK_NOR_RADR3_REG); + } + +-static ssize_t mt8173_nor_read(struct spi_nor *nor, loff_t from, size_t length, +- u_char *buffer) ++static ssize_t mtk_nor_read(struct spi_nor *nor, loff_t from, size_t length, ++ u_char *buffer) + { + int i, ret; + int addr = (int)from; + u8 *buf = (u8 *)buffer; +- struct mt8173_nor *mt8173_nor = nor->priv; ++ struct mtk_nor *mtk_nor = nor->priv; + + /* set mode for fast read mode ,dual mode or quad mode */ +- mt8173_nor_set_read_mode(mt8173_nor); +- mt8173_nor_set_addr(mt8173_nor, addr); ++ mtk_nor_set_read_mode(mtk_nor); ++ mtk_nor_set_addr(mtk_nor, addr); + + for (i = 0; i < length; i++) { +- ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_READ_CMD); ++ ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PIO_READ_CMD); + if (ret < 0) + return ret; +- buf[i] = readb(mt8173_nor->base + MTK_NOR_RDATA_REG); ++ buf[i] = readb(mtk_nor->base + MTK_NOR_RDATA_REG); + } + return length; + } + +-static int mt8173_nor_write_single_byte(struct mt8173_nor *mt8173_nor, +- int addr, int length, u8 *data) ++static int mtk_nor_write_single_byte(struct mtk_nor *mtk_nor, ++ int addr, int length, u8 *data) + { + int i, ret; + +- mt8173_nor_set_addr(mt8173_nor, addr); ++ mtk_nor_set_addr(mtk_nor, addr); + + for (i = 0; i < length; i++) { +- writeb(*data++, mt8173_nor->base + MTK_NOR_WDATA_REG); +- ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_WR_CMD); ++ writeb(*data++, mtk_nor->base + MTK_NOR_WDATA_REG); ++ ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PIO_WR_CMD); + if (ret < 0) + return ret; + } + return 0; + } + +-static int mt8173_nor_write_buffer(struct mt8173_nor *mt8173_nor, int addr, +- const u8 *buf) ++static int mtk_nor_write_buffer(struct mtk_nor *mtk_nor, int addr, ++ const u8 *buf) + { + int i, bufidx, data; + +- mt8173_nor_set_addr(mt8173_nor, addr); ++ mtk_nor_set_addr(mtk_nor, addr); + + bufidx = 0; + for (i = 0; i < SFLASH_WRBUF_SIZE; i += 4) { + data = buf[bufidx + 3]<<24 | buf[bufidx + 2]<<16 | + buf[bufidx + 1]<<8 | buf[bufidx]; + bufidx += 4; +- writel(data, mt8173_nor->base + MTK_NOR_PP_DATA_REG); ++ writel(data, mtk_nor->base + MTK_NOR_PP_DATA_REG); + } +- return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WR_CMD); ++ return mtk_nor_execute_cmd(mtk_nor, MTK_NOR_WR_CMD); + } + +-static ssize_t mt8173_nor_write(struct spi_nor *nor, loff_t to, size_t len, +- const u_char *buf) ++static ssize_t mtk_nor_write(struct spi_nor *nor, loff_t to, size_t len, ++ const u_char *buf) + { + int ret; +- struct mt8173_nor *mt8173_nor = nor->priv; ++ struct mtk_nor *mtk_nor = nor->priv; + size_t i; + +- ret = mt8173_nor_write_buffer_enable(mt8173_nor); ++ ret = mtk_nor_write_buffer_enable(mtk_nor); + if (ret < 0) { +- dev_warn(mt8173_nor->dev, "write buffer enable failed!\n"); ++ dev_warn(mtk_nor->dev, "write buffer enable failed!\n"); + return ret; + } + + for (i = 0; i + SFLASH_WRBUF_SIZE <= len; i += SFLASH_WRBUF_SIZE) { +- ret = mt8173_nor_write_buffer(mt8173_nor, to, buf); ++ ret = mtk_nor_write_buffer(mtk_nor, to, buf); + if (ret < 0) { +- dev_err(mt8173_nor->dev, "write buffer failed!\n"); ++ dev_err(mtk_nor->dev, "write buffer failed!\n"); + return ret; + } + to += SFLASH_WRBUF_SIZE; + buf += SFLASH_WRBUF_SIZE; + } +- ret = mt8173_nor_write_buffer_disable(mt8173_nor); ++ ret = mtk_nor_write_buffer_disable(mtk_nor); + if (ret < 0) { +- dev_warn(mt8173_nor->dev, "write buffer disable failed!\n"); ++ dev_warn(mtk_nor->dev, "write buffer disable failed!\n"); + return ret; + } + + if (i < len) { +- ret = mt8173_nor_write_single_byte(mt8173_nor, to, +- (int)(len - i), (u8 *)buf); ++ ret = mtk_nor_write_single_byte(mtk_nor, to, ++ (int)(len - i), (u8 *)buf); + if (ret < 0) { +- dev_err(mt8173_nor->dev, "write single byte failed!\n"); ++ dev_err(mtk_nor->dev, "write single byte failed!\n"); + return ret; + } + } +@@ -362,72 +362,72 @@ static ssize_t mt8173_nor_write(struct spi_nor *nor, loff_t to, size_t len, + return len; + } + +-static int mt8173_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) ++static int mtk_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) + { + int ret; +- struct mt8173_nor *mt8173_nor = nor->priv; ++ struct mtk_nor *mtk_nor = nor->priv; + + switch (opcode) { + case SPINOR_OP_RDSR: +- ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_RDSR_CMD); ++ ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_RDSR_CMD); + if (ret < 0) + return ret; + if (len == 1) +- *buf = readb(mt8173_nor->base + MTK_NOR_RDSR_REG); ++ *buf = readb(mtk_nor->base + MTK_NOR_RDSR_REG); + else +- dev_err(mt8173_nor->dev, "len should be 1 for read status!\n"); ++ dev_err(mtk_nor->dev, "len should be 1 for read status!\n"); + break; + default: +- ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, NULL, 0, buf, len); ++ ret = mtk_nor_do_tx_rx(mtk_nor, opcode, NULL, 0, buf, len); + break; + } + return ret; + } + +-static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, +- int len) ++static int mtk_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, ++ int len) + { + int ret; +- struct mt8173_nor *mt8173_nor = nor->priv; ++ struct mtk_nor *mtk_nor = nor->priv; + + switch (opcode) { + case SPINOR_OP_WRSR: + /* We only handle 1 byte */ +- ret = mt8173_nor_wr_sr(mt8173_nor, *buf); ++ ret = mtk_nor_wr_sr(mtk_nor, *buf); + break; + default: +- ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, buf, len, NULL, 0); ++ ret = mtk_nor_do_tx_rx(mtk_nor, opcode, buf, len, NULL, 0); + if (ret) +- dev_warn(mt8173_nor->dev, "write reg failure!\n"); ++ dev_warn(mtk_nor->dev, "write reg failure!\n"); + break; + } + return ret; + } + +-static void mt8173_nor_disable_clk(struct mt8173_nor *mt8173_nor) ++static void mtk_nor_disable_clk(struct mtk_nor *mtk_nor) + { +- clk_disable_unprepare(mt8173_nor->spi_clk); +- clk_disable_unprepare(mt8173_nor->nor_clk); ++ clk_disable_unprepare(mtk_nor->spi_clk); ++ clk_disable_unprepare(mtk_nor->nor_clk); + } + +-static int mt8173_nor_enable_clk(struct mt8173_nor *mt8173_nor) ++static int mtk_nor_enable_clk(struct mtk_nor *mtk_nor) + { + int ret; + +- ret = clk_prepare_enable(mt8173_nor->spi_clk); ++ ret = clk_prepare_enable(mtk_nor->spi_clk); + if (ret) + return ret; + +- ret = clk_prepare_enable(mt8173_nor->nor_clk); ++ ret = clk_prepare_enable(mtk_nor->nor_clk); + if (ret) { +- clk_disable_unprepare(mt8173_nor->spi_clk); ++ clk_disable_unprepare(mtk_nor->spi_clk); + return ret; + } + + return 0; + } + +-static int mtk_nor_init(struct mt8173_nor *mt8173_nor, ++static int mtk_nor_init(struct mtk_nor *mtk_nor, + struct device_node *flash_node) + { + const struct spi_nor_hwcaps hwcaps = { +@@ -439,18 +439,18 @@ static int mtk_nor_init(struct mt8173_nor *mt8173_nor, + struct spi_nor *nor; + + /* initialize controller to accept commands */ +- writel(MTK_NOR_ENABLE_SF_CMD, mt8173_nor->base + MTK_NOR_WRPROT_REG); ++ writel(MTK_NOR_ENABLE_SF_CMD, mtk_nor->base + MTK_NOR_WRPROT_REG); + +- nor = &mt8173_nor->nor; +- nor->dev = mt8173_nor->dev; +- nor->priv = mt8173_nor; ++ nor = &mtk_nor->nor; ++ nor->dev = mtk_nor->dev; ++ nor->priv = mtk_nor; + spi_nor_set_flash_node(nor, flash_node); + + /* fill the hooks to spi nor */ +- nor->read = mt8173_nor_read; +- nor->read_reg = mt8173_nor_read_reg; +- nor->write = mt8173_nor_write; +- nor->write_reg = mt8173_nor_write_reg; ++ nor->read = mtk_nor_read; ++ nor->read_reg = mtk_nor_read_reg; ++ nor->write = mtk_nor_write; ++ nor->write_reg = mtk_nor_write_reg; + nor->mtd.name = "mtk_nor"; + /* initialized with NULL */ + ret = spi_nor_scan(nor, NULL, &hwcaps); +@@ -465,34 +465,34 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) + struct device_node *flash_np; + struct resource *res; + int ret; +- struct mt8173_nor *mt8173_nor; ++ struct mtk_nor *mtk_nor; + + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "No DT found\n"); + return -EINVAL; + } + +- mt8173_nor = devm_kzalloc(&pdev->dev, sizeof(*mt8173_nor), GFP_KERNEL); +- if (!mt8173_nor) ++ mtk_nor = devm_kzalloc(&pdev->dev, sizeof(*mtk_nor), GFP_KERNEL); ++ if (!mtk_nor) + return -ENOMEM; +- platform_set_drvdata(pdev, mt8173_nor); ++ platform_set_drvdata(pdev, mtk_nor); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- mt8173_nor->base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(mt8173_nor->base)) +- return PTR_ERR(mt8173_nor->base); ++ mtk_nor->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(mtk_nor->base)) ++ return PTR_ERR(mtk_nor->base); + +- mt8173_nor->spi_clk = devm_clk_get(&pdev->dev, "spi"); +- if (IS_ERR(mt8173_nor->spi_clk)) +- return PTR_ERR(mt8173_nor->spi_clk); ++ mtk_nor->spi_clk = devm_clk_get(&pdev->dev, "spi"); ++ if (IS_ERR(mtk_nor->spi_clk)) ++ return PTR_ERR(mtk_nor->spi_clk); + +- mt8173_nor->nor_clk = devm_clk_get(&pdev->dev, "sf"); +- if (IS_ERR(mt8173_nor->nor_clk)) +- return PTR_ERR(mt8173_nor->nor_clk); ++ mtk_nor->nor_clk = devm_clk_get(&pdev->dev, "sf"); ++ if (IS_ERR(mtk_nor->nor_clk)) ++ return PTR_ERR(mtk_nor->nor_clk); + +- mt8173_nor->dev = &pdev->dev; ++ mtk_nor->dev = &pdev->dev; + +- ret = mt8173_nor_enable_clk(mt8173_nor); ++ ret = mtk_nor_enable_clk(mtk_nor); + if (ret) + return ret; + +@@ -503,20 +503,20 @@ static int mtk_nor_drv_probe(struct platform_device *pdev) + ret = -ENODEV; + goto nor_free; + } +- ret = mtk_nor_init(mt8173_nor, flash_np); ++ ret = mtk_nor_init(mtk_nor, flash_np); + + nor_free: + if (ret) +- mt8173_nor_disable_clk(mt8173_nor); ++ mtk_nor_disable_clk(mtk_nor); + + return ret; + } + + static int mtk_nor_drv_remove(struct platform_device *pdev) + { +- struct mt8173_nor *mt8173_nor = platform_get_drvdata(pdev); ++ struct mtk_nor *mtk_nor = platform_get_drvdata(pdev); + +- mt8173_nor_disable_clk(mt8173_nor); ++ mtk_nor_disable_clk(mtk_nor); + + return 0; + } +@@ -524,18 +524,18 @@ static int mtk_nor_drv_remove(struct platform_device *pdev) + #ifdef CONFIG_PM_SLEEP + static int mtk_nor_suspend(struct device *dev) + { +- struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); ++ struct mtk_nor *mtk_nor = dev_get_drvdata(dev); + +- mt8173_nor_disable_clk(mt8173_nor); ++ mtk_nor_disable_clk(mtk_nor); + + return 0; + } + + static int mtk_nor_resume(struct device *dev) + { +- struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev); ++ struct mtk_nor *mtk_nor = dev_get_drvdata(dev); + +- return mt8173_nor_enable_clk(mt8173_nor); ++ return mtk_nor_enable_clk(mtk_nor); + } + + static const struct dev_pm_ops mtk_nor_dev_pm_ops = { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0197-hwrng-mediatek-Setup-default-RNG-quality.patch b/target/linux/mediatek/patches-4.14/0197-hwrng-mediatek-Setup-default-RNG-quality.patch new file mode 100644 index 0000000000..a766169cc2 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0197-hwrng-mediatek-Setup-default-RNG-quality.patch @@ -0,0 +1,30 @@ +From cd4a7d700a148f89d599ebe53fd97dc64193683a Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 10 Jan 2018 12:02:46 +0800 +Subject: [PATCH 197/224] hwrng: mediatek - Setup default RNG quality + +When hw_random device's quality is non-zero, it will automatically fill +the kernel's entropy pool at boot. For the purpose, one conservative +quality value is being picked up as the default value. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +--- + drivers/char/hw_random/mtk-rng.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c +index 8da7bcf54105..7f99cd52b40e 100644 +--- a/drivers/char/hw_random/mtk-rng.c ++++ b/drivers/char/hw_random/mtk-rng.c +@@ -135,6 +135,7 @@ static int mtk_rng_probe(struct platform_device *pdev) + #endif + priv->rng.read = mtk_rng_read; + priv->rng.priv = (unsigned long)&pdev->dev; ++ priv->rng.quality = 900; + + priv->clk = devm_clk_get(&pdev->dev, "rng"); + if (IS_ERR(priv->clk)) { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0198-dt-bindings-thermal-add-binding-for-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0198-dt-bindings-thermal-add-binding-for-MT7622-SoC.patch new file mode 100644 index 0000000000..068dafda70 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0198-dt-bindings-thermal-add-binding-for-MT7622-SoC.patch @@ -0,0 +1,31 @@ +From bdaa6312375055d3e104869ca04cc463ac0a33d1 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 17 Jan 2018 00:00:39 +0800 +Subject: [PATCH 198/224] dt-bindings: thermal: add binding for MT7622 SoC + +Add devicetree bindings for MediaTek MT7622 thermal controller + +Changes v1 -> v2: add tag from Rob + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Shunli Wang <shunli.wang@mediatek.com> +Reviewed-by: Rob Herring <robh@kernel.org> +--- + Documentation/devicetree/bindings/thermal/mediatek-thermal.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +index 0d73ea5e9c0c..41d6a443ad66 100644 +--- a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt ++++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt +@@ -12,6 +12,7 @@ Required properties: + - "mediatek,mt8173-thermal" : For MT8173 family of SoCs + - "mediatek,mt2701-thermal" : For MT2701 family of SoCs + - "mediatek,mt2712-thermal" : For MT2712 family of SoCs ++ - "mediatek,mt7622-thermal" : For MT7622 SoC + - reg: Address range of the thermal controller + - interrupts: IRQ for the thermal controller + - clocks, clock-names: Clocks needed for the thermal controller. required +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0199-thermal-mtk-Cleanup-unused-defines.patch b/target/linux/mediatek/patches-4.14/0199-thermal-mtk-Cleanup-unused-defines.patch new file mode 100644 index 0000000000..d028e4586c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0199-thermal-mtk-Cleanup-unused-defines.patch @@ -0,0 +1,56 @@ +From 8bf9b7eeef3f5f4866d66878db75b6b944a8eab4 Mon Sep 17 00:00:00 2001 +From: Matthias Brugger <matthias.bgg@gmail.com> +Date: Fri, 1 Dec 2017 11:43:21 +0100 +Subject: [PATCH 199/224] thermal: mtk: Cleanup unused defines + +The mtk_thermal has some defiens which are never used within the driver. +This patch delets them. + +Signed-off-by: Matthias Brugger <mbrugger@suse.com> +Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> +Signed-off-by: Eduardo Valentin <edubezval@gmail.com> +--- + drivers/thermal/mtk_thermal.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c +index 1e61c09153c9..c75661a3801a 100644 +--- a/drivers/thermal/mtk_thermal.c ++++ b/drivers/thermal/mtk_thermal.c +@@ -32,15 +32,10 @@ + #include <linux/types.h> + + /* AUXADC Registers */ +-#define AUXADC_CON0_V 0x000 +-#define AUXADC_CON1_V 0x004 + #define AUXADC_CON1_SET_V 0x008 + #define AUXADC_CON1_CLR_V 0x00c + #define AUXADC_CON2_V 0x010 + #define AUXADC_DATA(channel) (0x14 + (channel) * 4) +-#define AUXADC_MISC_V 0x094 +- +-#define AUXADC_CON1_CHANNEL(x) BIT(x) + + #define APMIXED_SYS_TS_CON1 0x604 + +@@ -158,8 +153,6 @@ + /* The number of sensing points per bank */ + #define MT2712_NUM_SENSORS_PER_ZONE 4 + +-#define THERMAL_NAME "mtk-thermal" +- + struct mtk_thermal; + + struct thermal_bank_cfg { +@@ -765,7 +758,7 @@ static struct platform_driver mtk_thermal_driver = { + .probe = mtk_thermal_probe, + .remove = mtk_thermal_remove, + .driver = { +- .name = THERMAL_NAME, ++ .name = "mtk-thermal", + .of_match_table = mtk_thermal_of_match, + }, + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0200-thermal-mediatek-add-support-for-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0200-thermal-mediatek-add-support-for-MT7622-SoC.patch new file mode 100644 index 0000000000..4f31eb8d65 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0200-thermal-mediatek-add-support-for-MT7622-SoC.patch @@ -0,0 +1,86 @@ +From b93889b200a963acde20e559dbf51886ad6b6229 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Tue, 16 Jan 2018 23:50:48 +0800 +Subject: [PATCH 200/224] thermal: mediatek: add support for MT7622 SoC + +MT7622 SoC has built-in thermal controller with one sensing point, the +patch just is to extend the functionality of the existing logic. + +Changes v1 -> v2: rebase to 4.16-rc1 + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Shunli Wang <shunli.wang@mediatek.com> +--- + drivers/thermal/mtk_thermal.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c +index c75661a3801a..e709acb2235e 100644 +--- a/drivers/thermal/mtk_thermal.c ++++ b/drivers/thermal/mtk_thermal.c +@@ -153,6 +153,12 @@ + /* The number of sensing points per bank */ + #define MT2712_NUM_SENSORS_PER_ZONE 4 + ++#define MT7622_TEMP_AUXADC_CHANNEL 11 ++#define MT7622_NUM_SENSORS 1 ++#define MT7622_NUM_ZONES 1 ++#define MT7622_NUM_SENSORS_PER_ZONE 1 ++#define MT7622_TS1 0 ++ + struct mtk_thermal; + + struct thermal_bank_cfg { +@@ -242,6 +248,12 @@ static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = { + + static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 }; + ++/* MT7622 thermal sensor data */ ++static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, }; ++static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, }; ++static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, }; ++static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, }; ++ + /** + * The MT8173 thermal controller has four banks. Each bank can read up to + * four temperature sensors simultaneously. The MT8173 has a total of 5 +@@ -329,6 +341,25 @@ static const struct mtk_thermal_data mt2712_thermal_data = { + .sensor_mux_values = mt2712_mux_values, + }; + ++/* ++ * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data ++ * access. ++ */ ++static const struct mtk_thermal_data mt7622_thermal_data = { ++ .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL, ++ .num_banks = MT7622_NUM_ZONES, ++ .num_sensors = MT7622_NUM_SENSORS, ++ .bank_data = { ++ { ++ .num_sensors = 1, ++ .sensors = mt7622_bank_data, ++ }, ++ }, ++ .msr = mt7622_msr, ++ .adcpnp = mt7622_adcpnp, ++ .sensor_mux_values = mt7622_mux_values, ++}; ++ + /** + * raw_to_mcelsius - convert a raw ADC value to mcelsius + * @mt: The thermal controller +@@ -631,6 +662,10 @@ static const struct of_device_id mtk_thermal_of_match[] = { + { + .compatible = "mediatek,mt2712-thermal", + .data = (void *)&mt2712_thermal_data, ++ }, ++ { ++ .compatible = "mediatek,mt7622-thermal", ++ .data = (void *)&mt7622_thermal_data, + }, { + }, + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0201-dt-bindings-clock-mediatek-add-missing-required-rese.patch b/target/linux/mediatek/patches-4.14/0201-dt-bindings-clock-mediatek-add-missing-required-rese.patch new file mode 100644 index 0000000000..601e5b9855 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0201-dt-bindings-clock-mediatek-add-missing-required-rese.patch @@ -0,0 +1,73 @@ +From 4a1990ee249df257848f9583cef71478e3411c3e Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 28 Dec 2017 11:24:45 +0800 +Subject: [PATCH 201/224] dt-bindings: clock: mediatek: add missing required + #reset-cells + +All ethsys, pciesys and ssusbsys internally include reset controller, so +explicitly add back these missing cell definitions to related bindings +and examples. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Rob Herring <robh@kernel.org> +Cc: Michael Turquette <mturquette@baylibre.com> +Cc: Stephen Boyd <sboyd@codeaurora.org> +Cc: linux-clk@vger.kernel.org +Reviewed-by: Rob Herring <robh@kernel.org> +--- + Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt | 1 + + Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt | 2 ++ + Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt | 2 ++ + 3 files changed, 5 insertions(+) + +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt +index 7aa3fa167668..52757adf86bb 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt +@@ -9,6 +9,7 @@ Required Properties: + - "mediatek,mt2701-ethsys", "syscon" + - "mediatek,mt7622-ethsys", "syscon" + - #clock-cells: Must be 1 ++- #reset-cells: Must be 1 + + The ethsys controller uses the common clk binding from + Documentation/devicetree/bindings/clock/clock-bindings.txt +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt +index d5d5f1227665..7fe5dc6097a6 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pciesys.txt +@@ -8,6 +8,7 @@ Required Properties: + - compatible: Should be: + - "mediatek,mt7622-pciesys", "syscon" + - #clock-cells: Must be 1 ++- #reset-cells: Must be 1 + + The PCIESYS controller uses the common clk binding from + Documentation/devicetree/bindings/clock/clock-bindings.txt +@@ -19,4 +20,5 @@ pciesys: pciesys@1a100800 { + compatible = "mediatek,mt7622-pciesys", "syscon"; + reg = <0 0x1a100800 0 0x1000>; + #clock-cells = <1>; ++ #reset-cells = <1>; + }; +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt +index 00760019da00..b8184da2508c 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ssusbsys.txt +@@ -8,6 +8,7 @@ Required Properties: + - compatible: Should be: + - "mediatek,mt7622-ssusbsys", "syscon" + - #clock-cells: Must be 1 ++- #reset-cells: Must be 1 + + The SSUSBSYS controller uses the common clk binding from + Documentation/devicetree/bindings/clock/clock-bindings.txt +@@ -19,4 +20,5 @@ ssusbsys: ssusbsys@1a000000 { + compatible = "mediatek,mt7622-ssusbsys", "syscon"; + reg = <0 0x1a000000 0 0x1000>; + #clock-cells = <1>; ++ #reset-cells = <1>; + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0202-mmc-dt-bindings-add-support-for-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0202-mmc-dt-bindings-add-support-for-MT7622-SoC.patch new file mode 100644 index 0000000000..4d19ead2c1 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0202-mmc-dt-bindings-add-support-for-MT7622-SoC.patch @@ -0,0 +1,27 @@ +From 5365d402c8c4f0ff2cf2f26cfb8f46b520719ac0 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 5 Mar 2018 14:47:26 +0800 +Subject: [PATCH 202/224] mmc: dt-bindings: add support for MT7622 SoC + +Add the devicetree binding for MT7622 SoC + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + Documentation/devicetree/bindings/mmc/mtk-sd.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt +index 9b8017670870..f33467a54a05 100644 +--- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt ++++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt +@@ -12,6 +12,7 @@ Required properties: + "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 + "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 + "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 ++ "mediatek,mt7622-mmc": for MT7622 SoC + "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC + + - reg: physical base address of the controller and length +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0203-mmc-mediatek-add-support-for-MT7622-SoC.patch b/target/linux/mediatek/patches-4.14/0203-mmc-mediatek-add-support-for-MT7622-SoC.patch new file mode 100644 index 0000000000..242e5045fa --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0203-mmc-mediatek-add-support-for-MT7622-SoC.patch @@ -0,0 +1,47 @@ +From 9af606beb87182120ab40563cd596a9e1cfc842b Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 2 Feb 2018 14:25:11 +0800 +Subject: [PATCH 203/224] mmc: mediatek: add support for MT7622 SoC + +Just applying the existing logic and adding its own characteristics into +the space pointed by an extra entry of struct of_device_id to have support +of MT7622 SoC. + +Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Tested-by: Jumin Li <jumin.li@mediatek.com> +--- + drivers/mmc/host/mtk-sd.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index 27a62254f12f..f5e0662f2590 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -438,11 +438,23 @@ static const struct mtk_mmc_compatible mt2712_compat = { + .enhance_rx = true, + }; + ++static const struct mtk_mmc_compatible mt7622_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, ++}; ++ + static const struct of_device_id msdc_of_ids[] = { + { .compatible = "mediatek,mt8135-mmc", .data = &mt8135_compat}, + { .compatible = "mediatek,mt8173-mmc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt2701-mmc", .data = &mt2701_compat}, + { .compatible = "mediatek,mt2712-mmc", .data = &mt2712_compat}, ++ { .compatible = "mediatek,mt7622-mmc", .data = &mt7622_compat}, + {} + }; + MODULE_DEVICE_TABLE(of, msdc_of_ids); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0204-dt-bindings-dmaengine-Add-MediaTek-High-Speed-DMA-co.patch b/target/linux/mediatek/patches-4.14/0204-dt-bindings-dmaengine-Add-MediaTek-High-Speed-DMA-co.patch new file mode 100644 index 0000000000..edb3852ce5 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0204-dt-bindings-dmaengine-Add-MediaTek-High-Speed-DMA-co.patch @@ -0,0 +1,57 @@ +From 71198859668501ef57450be07da77e9544f59f1e Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Sat, 13 May 2017 15:16:58 +0800 +Subject: [PATCH 204/224] dt-bindings: dmaengine: Add MediaTek High-Speed DMA + controller bindings + +Document the devicetree bindings for MediaTek High-Speed DMA controller +which could be found on MT7623 SoC or other similar Mediatek SoCs. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + .../devicetree/bindings/dma/mtk-hsdma.txt | 33 ++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + create mode 100644 Documentation/devicetree/bindings/dma/mtk-hsdma.txt + +diff --git a/Documentation/devicetree/bindings/dma/mtk-hsdma.txt b/Documentation/devicetree/bindings/dma/mtk-hsdma.txt +new file mode 100644 +index 000000000000..4bb317359dc6 +--- /dev/null ++++ b/Documentation/devicetree/bindings/dma/mtk-hsdma.txt +@@ -0,0 +1,33 @@ ++MediaTek High-Speed DMA Controller ++================================== ++ ++This device follows the generic DMA bindings defined in dma/dma.txt. ++ ++Required properties: ++ ++- compatible: Must be one of ++ "mediatek,mt7622-hsdma": for MT7622 SoC ++ "mediatek,mt7623-hsdma": for MT7623 SoC ++- reg: Should contain the register's base address and length. ++- interrupts: Should contain a reference to the interrupt used by this ++ device. ++- clocks: Should be the clock specifiers corresponding to the entry in ++ clock-names property. ++- clock-names: Should contain "hsdma" entries. ++- power-domains: Phandle to the power domain that the device is part of ++- #dma-cells: The length of the DMA specifier, must be <1>. This one cell ++ in dmas property of a client device represents the channel ++ number. ++Example: ++ ++ hsdma: dma-controller@1b007000 { ++ compatible = "mediatek,mt7623-hsdma"; ++ reg = <0 0x1b007000 0 0x1000>; ++ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <ðsys CLK_ETHSYS_HSDMA>; ++ clock-names = "hsdma"; ++ power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; ++ #dma-cells = <1>; ++ }; ++ ++DMA clients must use the format described in dma/dma.txt file. +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0205-dmaengine-mediatek-Add-MediaTek-High-Speed-DMA-contr.patch b/target/linux/mediatek/patches-4.14/0205-dmaengine-mediatek-Add-MediaTek-High-Speed-DMA-contr.patch new file mode 100644 index 0000000000..cd6e1004fb --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0205-dmaengine-mediatek-Add-MediaTek-High-Speed-DMA-contr.patch @@ -0,0 +1,1144 @@ +From 2b97c5d7886a920adc8f7c32c2a60583475654f2 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 12 May 2017 17:05:12 +0800 +Subject: [PATCH 205/224] dmaengine: mediatek: Add MediaTek High-Speed DMA + controller for MT7622 and MT7623 SoC + +MediaTek High-Speed DMA controller (HSDMA) on MT7622 and MT7623 SoC has +a single ring is dedicated to memory-to-memory transfer through ring based +descriptor management. + +Even though there is only one physical ring available inside HSDMA, the +driver can be easily extended to the support of multiple virtual channels +processing simultaneously by means of DMA_VIRTUAL_CHANNELS effort. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Randy Dunlap <rdunlap@infradead.org> +Cc: Fengguang Wu <fengguang.wu@intel.com> +Cc: Julia Lawall <julia.lawall@lip6.fr> +--- + drivers/dma/Kconfig | 2 + + drivers/dma/Makefile | 1 + + drivers/dma/mediatek/Kconfig | 13 + + drivers/dma/mediatek/Makefile | 1 + + drivers/dma/mediatek/mtk-hsdma.c | 1056 ++++++++++++++++++++++++++++++++++++++ + 5 files changed, 1073 insertions(+) + create mode 100644 drivers/dma/mediatek/Kconfig + create mode 100644 drivers/dma/mediatek/Makefile + create mode 100644 drivers/dma/mediatek/mtk-hsdma.c + +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +index fadc4d8783bd..3100b6dfa6e8 100644 +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -604,6 +604,8 @@ config ZX_DMA + # driver files + source "drivers/dma/bestcomm/Kconfig" + ++source "drivers/dma/mediatek/Kconfig" ++ + source "drivers/dma/qcom/Kconfig" + + source "drivers/dma/dw/Kconfig" +diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile +index f08f8de1b567..26b0ef43a8f9 100644 +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -71,5 +71,6 @@ obj-$(CONFIG_XGENE_DMA) += xgene-dma.o + obj-$(CONFIG_ZX_DMA) += zx_dma.o + obj-$(CONFIG_ST_FDMA) += st_fdma.o + ++obj-y += mediatek/ + obj-y += qcom/ + obj-y += xilinx/ +diff --git a/drivers/dma/mediatek/Kconfig b/drivers/dma/mediatek/Kconfig +new file mode 100644 +index 000000000000..27bac0bba09e +--- /dev/null ++++ b/drivers/dma/mediatek/Kconfig +@@ -0,0 +1,13 @@ ++ ++config MTK_HSDMA ++ tristate "MediaTek High-Speed DMA controller support" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ ---help--- ++ Enable support for High-Speed DMA controller on MediaTek ++ SoCs. ++ ++ This controller provides the channels which is dedicated to ++ memory-to-memory transfer to offload from CPU through ring- ++ based descriptor management. +diff --git a/drivers/dma/mediatek/Makefile b/drivers/dma/mediatek/Makefile +new file mode 100644 +index 000000000000..6e778f842f01 +--- /dev/null ++++ b/drivers/dma/mediatek/Makefile +@@ -0,0 +1 @@ ++obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o +diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c +new file mode 100644 +index 000000000000..b7ec56ae02a6 +--- /dev/null ++++ b/drivers/dma/mediatek/mtk-hsdma.c +@@ -0,0 +1,1056 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Copyright (c) 2017-2018 MediaTek Inc. ++ ++/* ++ * Driver for MediaTek High-Speed DMA Controller ++ * ++ * Author: Sean Wang <sean.wang@mediatek.com> ++ * ++ */ ++ ++#include <linux/bitops.h> ++#include <linux/clk.h> ++#include <linux/dmaengine.h> ++#include <linux/dma-mapping.h> ++#include <linux/err.h> ++#include <linux/iopoll.h> ++#include <linux/list.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++#include <linux/of_dma.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/refcount.h> ++#include <linux/slab.h> ++ ++#include "../virt-dma.h" ++ ++#define MTK_HSDMA_USEC_POLL 20 ++#define MTK_HSDMA_TIMEOUT_POLL 200000 ++#define MTK_HSDMA_DMA_BUSWIDTHS BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) ++ ++/* The default number of virtual channel */ ++#define MTK_HSDMA_NR_VCHANS 3 ++ ++/* Only one physical channel supported */ ++#define MTK_HSDMA_NR_MAX_PCHANS 1 ++ ++/* Macro for physical descriptor (PD) manipulation */ ++/* The number of PD which must be 2 of power */ ++#define MTK_DMA_SIZE 64 ++#define MTK_HSDMA_NEXT_DESP_IDX(x, y) (((x) + 1) & ((y) - 1)) ++#define MTK_HSDMA_LAST_DESP_IDX(x, y) (((x) - 1) & ((y) - 1)) ++#define MTK_HSDMA_MAX_LEN 0x3f80 ++#define MTK_HSDMA_ALIGN_SIZE 4 ++#define MTK_HSDMA_PLEN_MASK 0x3fff ++#define MTK_HSDMA_DESC_PLEN(x) (((x) & MTK_HSDMA_PLEN_MASK) << 16) ++#define MTK_HSDMA_DESC_PLEN_GET(x) (((x) >> 16) & MTK_HSDMA_PLEN_MASK) ++ ++/* Registers for underlying ring manipulation */ ++#define MTK_HSDMA_TX_BASE 0x0 ++#define MTK_HSDMA_TX_CNT 0x4 ++#define MTK_HSDMA_TX_CPU 0x8 ++#define MTK_HSDMA_TX_DMA 0xc ++#define MTK_HSDMA_RX_BASE 0x100 ++#define MTK_HSDMA_RX_CNT 0x104 ++#define MTK_HSDMA_RX_CPU 0x108 ++#define MTK_HSDMA_RX_DMA 0x10c ++ ++/* Registers for global setup */ ++#define MTK_HSDMA_GLO 0x204 ++#define MTK_HSDMA_GLO_MULTI_DMA BIT(10) ++#define MTK_HSDMA_TX_WB_DDONE BIT(6) ++#define MTK_HSDMA_BURST_64BYTES (0x2 << 4) ++#define MTK_HSDMA_GLO_RX_BUSY BIT(3) ++#define MTK_HSDMA_GLO_RX_DMA BIT(2) ++#define MTK_HSDMA_GLO_TX_BUSY BIT(1) ++#define MTK_HSDMA_GLO_TX_DMA BIT(0) ++#define MTK_HSDMA_GLO_DMA (MTK_HSDMA_GLO_TX_DMA | \ ++ MTK_HSDMA_GLO_RX_DMA) ++#define MTK_HSDMA_GLO_BUSY (MTK_HSDMA_GLO_RX_BUSY | \ ++ MTK_HSDMA_GLO_TX_BUSY) ++#define MTK_HSDMA_GLO_DEFAULT (MTK_HSDMA_GLO_TX_DMA | \ ++ MTK_HSDMA_GLO_RX_DMA | \ ++ MTK_HSDMA_TX_WB_DDONE | \ ++ MTK_HSDMA_BURST_64BYTES | \ ++ MTK_HSDMA_GLO_MULTI_DMA) ++ ++/* Registers for reset */ ++#define MTK_HSDMA_RESET 0x208 ++#define MTK_HSDMA_RST_TX BIT(0) ++#define MTK_HSDMA_RST_RX BIT(16) ++ ++/* Registers for interrupt control */ ++#define MTK_HSDMA_DLYINT 0x20c ++#define MTK_HSDMA_RXDLY_INT_EN BIT(15) ++ ++/* Interrupt fires when the pending number's more than the specified */ ++#define MTK_HSDMA_RXMAX_PINT(x) (((x) & 0x7f) << 8) ++ ++/* Interrupt fires when the pending time's more than the specified in 20 us */ ++#define MTK_HSDMA_RXMAX_PTIME(x) ((x) & 0x7f) ++#define MTK_HSDMA_DLYINT_DEFAULT (MTK_HSDMA_RXDLY_INT_EN | \ ++ MTK_HSDMA_RXMAX_PINT(20) | \ ++ MTK_HSDMA_RXMAX_PTIME(20)) ++#define MTK_HSDMA_INT_STATUS 0x220 ++#define MTK_HSDMA_INT_ENABLE 0x228 ++#define MTK_HSDMA_INT_RXDONE BIT(16) ++ ++enum mtk_hsdma_vdesc_flag { ++ MTK_HSDMA_VDESC_FINISHED = 0x01, ++}; ++ ++#define IS_MTK_HSDMA_VDESC_FINISHED(x) ((x) == MTK_HSDMA_VDESC_FINISHED) ++ ++/** ++ * struct mtk_hsdma_pdesc - This is the struct holding info describing physical ++ * descriptor (PD) and its placement must be kept at ++ * 4-bytes alignment in little endian order. ++ * @desc[1-4]: The control pad used to indicate hardware how to ++ * deal with the descriptor such as source and ++ * destination address and data length. The maximum ++ * data length each pdesc can handle is 0x3f80 bytes ++ */ ++struct mtk_hsdma_pdesc { ++ __le32 desc1; ++ __le32 desc2; ++ __le32 desc3; ++ __le32 desc4; ++} __packed __aligned(4); ++ ++/** ++ * struct mtk_hsdma_vdesc - This is the struct holding info describing virtual ++ * descriptor (VD) ++ * @vd: An instance for struct virt_dma_desc ++ * @len: The total data size device wants to move ++ * @residue: The remaining data size device will move ++ * @dest: The destination address device wants to move to ++ * @src: The source address device wants to move from ++ */ ++struct mtk_hsdma_vdesc { ++ struct virt_dma_desc vd; ++ size_t len; ++ size_t residue; ++ dma_addr_t dest; ++ dma_addr_t src; ++}; ++ ++/** ++ * struct mtk_hsdma_cb - This is the struct holding extra info required for RX ++ * ring to know what relevant VD the the PD is being ++ * mapped to. ++ * @vd: Pointer to the relevant VD. ++ * @flag: Flag indicating what action should be taken when VD ++ * is completed. ++ */ ++struct mtk_hsdma_cb { ++ struct virt_dma_desc *vd; ++ enum mtk_hsdma_vdesc_flag flag; ++}; ++ ++/** ++ * struct mtk_hsdma_ring - This struct holds info describing underlying ring ++ * space ++ * @txd: The descriptor TX ring which describes DMA source ++ * information ++ * @rxd: The descriptor RX ring which describes DMA ++ * destination information ++ * @cb: The extra information pointed at by RX ring ++ * @tphys: The physical addr of TX ring ++ * @rphys: The physical addr of RX ring ++ * @cur_tptr: Pointer to the next free descriptor used by the host ++ * @cur_rptr: Pointer to the last done descriptor by the device ++ */ ++struct mtk_hsdma_ring { ++ struct mtk_hsdma_pdesc *txd; ++ struct mtk_hsdma_pdesc *rxd; ++ struct mtk_hsdma_cb *cb; ++ dma_addr_t tphys; ++ dma_addr_t rphys; ++ u16 cur_tptr; ++ u16 cur_rptr; ++}; ++ ++/** ++ * struct mtk_hsdma_pchan - This is the struct holding info describing physical ++ * channel (PC) ++ * @ring: An instance for the underlying ring ++ * @sz_ring: Total size allocated for the ring ++ * @nr_free: Total number of free rooms in the ring. It would ++ * be accessed and updated frequently between IRQ ++ * context and user context to reflect whether ring ++ * can accept requests from VD. ++ */ ++struct mtk_hsdma_pchan { ++ struct mtk_hsdma_ring ring; ++ size_t sz_ring; ++ atomic_t nr_free; ++}; ++ ++/** ++ * struct mtk_hsdma_vchan - This is the struct holding info describing virtual ++ * channel (VC) ++ * @vc: An instance for struct virt_dma_chan ++ * @issue_completion: The wait for all issued descriptors completited ++ * @issue_synchronize: Bool indicating channel synchronization starts ++ * @desc_hw_processing: List those descriptors the hardware is processing, ++ * which is protected by vc.lock ++ */ ++struct mtk_hsdma_vchan { ++ struct virt_dma_chan vc; ++ struct completion issue_completion; ++ bool issue_synchronize; ++ struct list_head desc_hw_processing; ++}; ++ ++/** ++ * struct mtk_hsdma_soc - This is the struct holding differences among SoCs ++ * @ddone: Bit mask for DDONE ++ * @ls0: Bit mask for LS0 ++ */ ++struct mtk_hsdma_soc { ++ __le32 ddone; ++ __le32 ls0; ++}; ++ ++/** ++ * struct mtk_hsdma_device - This is the struct holding info describing HSDMA ++ * device ++ * @ddev: An instance for struct dma_device ++ * @base: The mapped register I/O base ++ * @clk: The clock that device internal is using ++ * @irq: The IRQ that device are using ++ * @dma_requests: The number of VCs the device supports to ++ * @vc: The pointer to all available VCs ++ * @pc: The pointer to the underlying PC ++ * @pc_refcnt: Track how many VCs are using the PC ++ * @lock: Lock protect agaisting multiple VCs access PC ++ * @soc: The pointer to area holding differences among ++ * vaious platform ++ */ ++struct mtk_hsdma_device { ++ struct dma_device ddev; ++ void __iomem *base; ++ struct clk *clk; ++ u32 irq; ++ ++ u32 dma_requests; ++ struct mtk_hsdma_vchan *vc; ++ struct mtk_hsdma_pchan *pc; ++ refcount_t pc_refcnt; ++ ++ /* Lock used to protect against multiple VCs access PC */ ++ spinlock_t lock; ++ ++ const struct mtk_hsdma_soc *soc; ++}; ++ ++static struct mtk_hsdma_device *to_hsdma_dev(struct dma_chan *chan) ++{ ++ return container_of(chan->device, struct mtk_hsdma_device, ddev); ++} ++ ++static inline struct mtk_hsdma_vchan *to_hsdma_vchan(struct dma_chan *chan) ++{ ++ return container_of(chan, struct mtk_hsdma_vchan, vc.chan); ++} ++ ++static struct mtk_hsdma_vdesc *to_hsdma_vdesc(struct virt_dma_desc *vd) ++{ ++ return container_of(vd, struct mtk_hsdma_vdesc, vd); ++} ++ ++static struct device *hsdma2dev(struct mtk_hsdma_device *hsdma) ++{ ++ return hsdma->ddev.dev; ++} ++ ++static u32 mtk_dma_read(struct mtk_hsdma_device *hsdma, u32 reg) ++{ ++ return readl(hsdma->base + reg); ++} ++ ++static void mtk_dma_write(struct mtk_hsdma_device *hsdma, u32 reg, u32 val) ++{ ++ writel(val, hsdma->base + reg); ++} ++ ++static void mtk_dma_rmw(struct mtk_hsdma_device *hsdma, u32 reg, ++ u32 mask, u32 set) ++{ ++ u32 val; ++ ++ val = mtk_dma_read(hsdma, reg); ++ val &= ~mask; ++ val |= set; ++ mtk_dma_write(hsdma, reg, val); ++} ++ ++static void mtk_dma_set(struct mtk_hsdma_device *hsdma, u32 reg, u32 val) ++{ ++ mtk_dma_rmw(hsdma, reg, 0, val); ++} ++ ++static void mtk_dma_clr(struct mtk_hsdma_device *hsdma, u32 reg, u32 val) ++{ ++ mtk_dma_rmw(hsdma, reg, val, 0); ++} ++ ++static void mtk_hsdma_vdesc_free(struct virt_dma_desc *vd) ++{ ++ kfree(container_of(vd, struct mtk_hsdma_vdesc, vd)); ++} ++ ++static int mtk_hsdma_busy_wait(struct mtk_hsdma_device *hsdma) ++{ ++ u32 status = 0; ++ ++ return readl_poll_timeout(hsdma->base + MTK_HSDMA_GLO, status, ++ !(status & MTK_HSDMA_GLO_BUSY), ++ MTK_HSDMA_USEC_POLL, ++ MTK_HSDMA_TIMEOUT_POLL); ++} ++ ++static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma, ++ struct mtk_hsdma_pchan *pc) ++{ ++ struct mtk_hsdma_ring *ring = &pc->ring; ++ int err; ++ ++ memset(pc, 0, sizeof(*pc)); ++ ++ /* ++ * Allocate ring space where [0 ... MTK_DMA_SIZE - 1] is for TX ring ++ * and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring. ++ */ ++ pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd); ++ ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring, ++ &ring->tphys, GFP_NOWAIT); ++ if (!ring->txd) ++ return -ENOMEM; ++ ++ ring->rxd = &ring->txd[MTK_DMA_SIZE]; ++ ring->rphys = ring->tphys + MTK_DMA_SIZE * sizeof(*ring->txd); ++ ring->cur_tptr = 0; ++ ring->cur_rptr = MTK_DMA_SIZE - 1; ++ ++ ring->cb = kcalloc(MTK_DMA_SIZE, sizeof(*ring->cb), GFP_NOWAIT); ++ if (!ring->cb) { ++ err = -ENOMEM; ++ goto err_free_dma; ++ } ++ ++ atomic_set(&pc->nr_free, MTK_DMA_SIZE - 1); ++ ++ /* Disable HSDMA and wait for the completion */ ++ mtk_dma_clr(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DMA); ++ err = mtk_hsdma_busy_wait(hsdma); ++ if (err) ++ goto err_free_cb; ++ ++ /* Reset */ ++ mtk_dma_set(hsdma, MTK_HSDMA_RESET, ++ MTK_HSDMA_RST_TX | MTK_HSDMA_RST_RX); ++ mtk_dma_clr(hsdma, MTK_HSDMA_RESET, ++ MTK_HSDMA_RST_TX | MTK_HSDMA_RST_RX); ++ ++ /* Setup HSDMA initial pointer in the ring */ ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_BASE, ring->tphys); ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_CNT, MTK_DMA_SIZE); ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, ring->cur_tptr); ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_DMA, 0); ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_BASE, ring->rphys); ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_CNT, MTK_DMA_SIZE); ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_CPU, ring->cur_rptr); ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_DMA, 0); ++ ++ /* Enable HSDMA */ ++ mtk_dma_set(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DMA); ++ ++ /* Setup delayed interrupt */ ++ mtk_dma_write(hsdma, MTK_HSDMA_DLYINT, MTK_HSDMA_DLYINT_DEFAULT); ++ ++ /* Enable interrupt */ ++ mtk_dma_set(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE); ++ ++ return 0; ++ ++err_free_cb: ++ kfree(ring->cb); ++ ++err_free_dma: ++ dma_free_coherent(hsdma2dev(hsdma), ++ pc->sz_ring, ring->txd, ring->tphys); ++ return err; ++} ++ ++static void mtk_hsdma_free_pchan(struct mtk_hsdma_device *hsdma, ++ struct mtk_hsdma_pchan *pc) ++{ ++ struct mtk_hsdma_ring *ring = &pc->ring; ++ ++ /* Disable HSDMA and then wait for the completion */ ++ mtk_dma_clr(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DMA); ++ mtk_hsdma_busy_wait(hsdma); ++ ++ /* Reset pointer in the ring */ ++ mtk_dma_clr(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE); ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_BASE, 0); ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_CNT, 0); ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, 0); ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_BASE, 0); ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_CNT, 0); ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_CPU, MTK_DMA_SIZE - 1); ++ ++ kfree(ring->cb); ++ ++ dma_free_coherent(hsdma2dev(hsdma), ++ pc->sz_ring, ring->txd, ring->tphys); ++} ++ ++static int mtk_hsdma_issue_pending_vdesc(struct mtk_hsdma_device *hsdma, ++ struct mtk_hsdma_pchan *pc, ++ struct mtk_hsdma_vdesc *hvd) ++{ ++ struct mtk_hsdma_ring *ring = &pc->ring; ++ struct mtk_hsdma_pdesc *txd, *rxd; ++ u16 reserved, prev, tlen, num_sgs; ++ unsigned long flags; ++ ++ /* Protect against PC is accessed by multiple VCs simultaneously */ ++ spin_lock_irqsave(&hsdma->lock, flags); ++ ++ /* ++ * Reserve rooms, where pc->nr_free is used to track how many free ++ * rooms in the ring being updated in user and IRQ context. ++ */ ++ num_sgs = DIV_ROUND_UP(hvd->len, MTK_HSDMA_MAX_LEN); ++ reserved = min_t(u16, num_sgs, atomic_read(&pc->nr_free)); ++ ++ if (!reserved) { ++ spin_unlock_irqrestore(&hsdma->lock, flags); ++ return -ENOSPC; ++ } ++ ++ atomic_sub(reserved, &pc->nr_free); ++ ++ while (reserved--) { ++ /* Limit size by PD capability for valid data moving */ ++ tlen = (hvd->len > MTK_HSDMA_MAX_LEN) ? ++ MTK_HSDMA_MAX_LEN : hvd->len; ++ ++ /* ++ * Setup PDs using the remaining VD info mapped on those ++ * reserved rooms. And since RXD is shared memory between the ++ * host and the device allocated by dma_alloc_coherent call, ++ * the helper macro WRITE_ONCE can ensure the data written to ++ * RAM would really happens. ++ */ ++ txd = &ring->txd[ring->cur_tptr]; ++ WRITE_ONCE(txd->desc1, hvd->src); ++ WRITE_ONCE(txd->desc2, ++ hsdma->soc->ls0 | MTK_HSDMA_DESC_PLEN(tlen)); ++ ++ rxd = &ring->rxd[ring->cur_tptr]; ++ WRITE_ONCE(rxd->desc1, hvd->dest); ++ WRITE_ONCE(rxd->desc2, MTK_HSDMA_DESC_PLEN(tlen)); ++ ++ /* Associate VD, the PD belonged to */ ++ ring->cb[ring->cur_tptr].vd = &hvd->vd; ++ ++ /* Move forward the pointer of TX ring */ ++ ring->cur_tptr = MTK_HSDMA_NEXT_DESP_IDX(ring->cur_tptr, ++ MTK_DMA_SIZE); ++ ++ /* Update VD with remaining data */ ++ hvd->src += tlen; ++ hvd->dest += tlen; ++ hvd->len -= tlen; ++ } ++ ++ /* ++ * Tagging flag for the last PD for VD will be responsible for ++ * completing VD. ++ */ ++ if (!hvd->len) { ++ prev = MTK_HSDMA_LAST_DESP_IDX(ring->cur_tptr, MTK_DMA_SIZE); ++ ring->cb[prev].flag = MTK_HSDMA_VDESC_FINISHED; ++ } ++ ++ /* Ensure all changes indeed done before we're going on */ ++ wmb(); ++ ++ /* ++ * Updating into hardware the pointer of TX ring lets HSDMA to take ++ * action for those pending PDs. ++ */ ++ mtk_dma_write(hsdma, MTK_HSDMA_TX_CPU, ring->cur_tptr); ++ ++ spin_unlock_irqrestore(&hsdma->lock, flags); ++ ++ return 0; ++} ++ ++static void mtk_hsdma_issue_vchan_pending(struct mtk_hsdma_device *hsdma, ++ struct mtk_hsdma_vchan *hvc) ++{ ++ struct virt_dma_desc *vd, *vd2; ++ int err; ++ ++ lockdep_assert_held(&hvc->vc.lock); ++ ++ list_for_each_entry_safe(vd, vd2, &hvc->vc.desc_issued, node) { ++ struct mtk_hsdma_vdesc *hvd; ++ ++ hvd = to_hsdma_vdesc(vd); ++ ++ /* Map VD into PC and all VCs shares a single PC */ ++ err = mtk_hsdma_issue_pending_vdesc(hsdma, hsdma->pc, hvd); ++ ++ /* ++ * Move VD from desc_issued to desc_hw_processing when entire ++ * VD is fit into available PDs. Otherwise, the uncompleted ++ * VDs would stay in list desc_issued and then restart the ++ * processing as soon as possible once underlying ring space ++ * got freed. ++ */ ++ if (err == -ENOSPC || hvd->len > 0) ++ break; ++ ++ /* ++ * The extra list desc_hw_processing is used because ++ * hardware can't provide sufficient information allowing us ++ * to know what VDs are still working on the underlying ring. ++ * Through the additional list, it can help us to implement ++ * terminate_all, residue calculation and such thing needed ++ * to know detail descriptor status on the hardware. ++ */ ++ list_move_tail(&vd->node, &hvc->desc_hw_processing); ++ } ++} ++ ++static void mtk_hsdma_free_rooms_in_ring(struct mtk_hsdma_device *hsdma) ++{ ++ struct mtk_hsdma_vchan *hvc; ++ struct mtk_hsdma_pdesc *rxd; ++ struct mtk_hsdma_vdesc *hvd; ++ struct mtk_hsdma_pchan *pc; ++ struct mtk_hsdma_cb *cb; ++ int i = MTK_DMA_SIZE; ++ __le32 desc2; ++ u32 status; ++ u16 next; ++ ++ /* Read IRQ status */ ++ status = mtk_dma_read(hsdma, MTK_HSDMA_INT_STATUS); ++ if (unlikely(!(status & MTK_HSDMA_INT_RXDONE))) ++ goto rx_done; ++ ++ pc = hsdma->pc; ++ ++ /* ++ * Using a fail-safe loop with iterations of up to MTK_DMA_SIZE to ++ * reclaim these finished descriptors: The most number of PDs the ISR ++ * can handle at one time shouldn't be more than MTK_DMA_SIZE so we ++ * take it as limited count instead of just using a dangerous infinite ++ * poll. ++ */ ++ while (i--) { ++ next = MTK_HSDMA_NEXT_DESP_IDX(pc->ring.cur_rptr, ++ MTK_DMA_SIZE); ++ rxd = &pc->ring.rxd[next]; ++ ++ /* ++ * If MTK_HSDMA_DESC_DDONE is no specified, that means data ++ * moving for the PD is still under going. ++ */ ++ desc2 = READ_ONCE(rxd->desc2); ++ if (!(desc2 & hsdma->soc->ddone)) ++ break; ++ ++ cb = &pc->ring.cb[next]; ++ if (unlikely(!cb->vd)) { ++ dev_err(hsdma2dev(hsdma), "cb->vd cannot be null\n"); ++ break; ++ } ++ ++ /* Update residue of VD the associated PD belonged to */ ++ hvd = to_hsdma_vdesc(cb->vd); ++ hvd->residue -= MTK_HSDMA_DESC_PLEN_GET(rxd->desc2); ++ ++ /* Complete VD until the relevant last PD is finished */ ++ if (IS_MTK_HSDMA_VDESC_FINISHED(cb->flag)) { ++ hvc = to_hsdma_vchan(cb->vd->tx.chan); ++ ++ spin_lock(&hvc->vc.lock); ++ ++ /* Remove VD from list desc_hw_processing */ ++ list_del(&cb->vd->node); ++ ++ /* Add VD into list desc_completed */ ++ vchan_cookie_complete(cb->vd); ++ ++ if (hvc->issue_synchronize && ++ list_empty(&hvc->desc_hw_processing)) { ++ complete(&hvc->issue_completion); ++ hvc->issue_synchronize = false; ++ } ++ spin_unlock(&hvc->vc.lock); ++ ++ cb->flag = 0; ++ } ++ ++ cb->vd = 0; ++ ++ /* ++ * Recycle the RXD with the helper WRITE_ONCE that can ensure ++ * data written into RAM would really happens. ++ */ ++ WRITE_ONCE(rxd->desc1, 0); ++ WRITE_ONCE(rxd->desc2, 0); ++ pc->ring.cur_rptr = next; ++ ++ /* Release rooms */ ++ atomic_inc(&pc->nr_free); ++ } ++ ++ /* Ensure all changes indeed done before we're going on */ ++ wmb(); ++ ++ /* Update CPU pointer for those completed PDs */ ++ mtk_dma_write(hsdma, MTK_HSDMA_RX_CPU, pc->ring.cur_rptr); ++ ++ /* ++ * Acking the pending IRQ allows hardware no longer to keep the used ++ * IRQ line in certain trigger state when software has completed all ++ * the finished physical descriptors. ++ */ ++ if (atomic_read(&pc->nr_free) >= MTK_DMA_SIZE - 1) ++ mtk_dma_write(hsdma, MTK_HSDMA_INT_STATUS, status); ++ ++ /* ASAP handles pending VDs in all VCs after freeing some rooms */ ++ for (i = 0; i < hsdma->dma_requests; i++) { ++ hvc = &hsdma->vc[i]; ++ spin_lock(&hvc->vc.lock); ++ mtk_hsdma_issue_vchan_pending(hsdma, hvc); ++ spin_unlock(&hvc->vc.lock); ++ } ++ ++rx_done: ++ /* All completed PDs are cleaned up, so enable interrupt again */ ++ mtk_dma_set(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE); ++} ++ ++static irqreturn_t mtk_hsdma_irq(int irq, void *devid) ++{ ++ struct mtk_hsdma_device *hsdma = devid; ++ ++ /* ++ * Disable interrupt until all completed PDs are cleaned up in ++ * mtk_hsdma_free_rooms call. ++ */ ++ mtk_dma_clr(hsdma, MTK_HSDMA_INT_ENABLE, MTK_HSDMA_INT_RXDONE); ++ ++ mtk_hsdma_free_rooms_in_ring(hsdma); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct virt_dma_desc *mtk_hsdma_find_active_desc(struct dma_chan *c, ++ dma_cookie_t cookie) ++{ ++ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c); ++ struct virt_dma_desc *vd; ++ ++ list_for_each_entry(vd, &hvc->desc_hw_processing, node) ++ if (vd->tx.cookie == cookie) ++ return vd; ++ ++ list_for_each_entry(vd, &hvc->vc.desc_issued, node) ++ if (vd->tx.cookie == cookie) ++ return vd; ++ ++ return NULL; ++} ++ ++static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, ++ dma_cookie_t cookie, ++ struct dma_tx_state *txstate) ++{ ++ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c); ++ struct mtk_hsdma_vdesc *hvd; ++ struct virt_dma_desc *vd; ++ enum dma_status ret; ++ unsigned long flags; ++ size_t bytes = 0; ++ ++ ret = dma_cookie_status(c, cookie, txstate); ++ if (ret == DMA_COMPLETE || !txstate) ++ return ret; ++ ++ spin_lock_irqsave(&hvc->vc.lock, flags); ++ vd = mtk_hsdma_find_active_desc(c, cookie); ++ spin_unlock_irqrestore(&hvc->vc.lock, flags); ++ ++ if (vd) { ++ hvd = to_hsdma_vdesc(vd); ++ bytes = hvd->residue; ++ } ++ ++ dma_set_residue(txstate, bytes); ++ ++ return ret; ++} ++ ++static void mtk_hsdma_issue_pending(struct dma_chan *c) ++{ ++ struct mtk_hsdma_device *hsdma = to_hsdma_dev(c); ++ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&hvc->vc.lock, flags); ++ ++ if (vchan_issue_pending(&hvc->vc)) ++ mtk_hsdma_issue_vchan_pending(hsdma, hvc); ++ ++ spin_unlock_irqrestore(&hvc->vc.lock, flags); ++} ++ ++static struct dma_async_tx_descriptor * ++mtk_hsdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest, ++ dma_addr_t src, size_t len, unsigned long flags) ++{ ++ struct mtk_hsdma_vdesc *hvd; ++ ++ hvd = kzalloc(sizeof(*hvd), GFP_NOWAIT); ++ if (!hvd) ++ return NULL; ++ ++ hvd->len = len; ++ hvd->residue = len; ++ hvd->src = src; ++ hvd->dest = dest; ++ ++ return vchan_tx_prep(to_virt_chan(c), &hvd->vd, flags); ++} ++ ++static int mtk_hsdma_free_inactive_desc(struct dma_chan *c) ++{ ++ struct virt_dma_chan *vc = to_virt_chan(c); ++ unsigned long flags; ++ LIST_HEAD(head); ++ ++ spin_lock_irqsave(&vc->lock, flags); ++ list_splice_tail_init(&vc->desc_allocated, &head); ++ list_splice_tail_init(&vc->desc_submitted, &head); ++ list_splice_tail_init(&vc->desc_issued, &head); ++ spin_unlock_irqrestore(&vc->lock, flags); ++ ++ /* At the point, we don't expect users put descriptor into VC again */ ++ vchan_dma_desc_free_list(vc, &head); ++ ++ return 0; ++} ++ ++static void mtk_hsdma_free_active_desc(struct dma_chan *c) ++{ ++ struct mtk_hsdma_vchan *hvc = to_hsdma_vchan(c); ++ bool sync_needed = false; ++ ++ /* ++ * Once issue_synchronize is being set, which means once the hardware ++ * consumes all descriptors for the channel in the ring, the ++ * synchronization must be be notified immediately it is completed. ++ */ ++ spin_lock(&hvc->vc.lock); ++ if (!list_empty(&hvc->desc_hw_processing)) { ++ hvc->issue_synchronize = true; ++ sync_needed = true; ++ } ++ spin_unlock(&hvc->vc.lock); ++ ++ if (sync_needed) ++ wait_for_completion(&hvc->issue_completion); ++ /* ++ * At the point, we expect that all remaining descriptors in the ring ++ * for the channel should be all processing done. ++ */ ++ WARN_ONCE(!list_empty(&hvc->desc_hw_processing), ++ "Desc pending still in list desc_hw_processing\n"); ++ ++ /* Free all descriptors in list desc_completed */ ++ vchan_synchronize(&hvc->vc); ++ ++ WARN_ONCE(!list_empty(&hvc->vc.desc_completed), ++ "Desc pending still in list desc_completed\n"); ++} ++ ++static int mtk_hsdma_terminate_all(struct dma_chan *c) ++{ ++ /* ++ * Free pending descriptors not processed yet by hardware that have ++ * previously been submitted to the channel. ++ */ ++ mtk_hsdma_free_inactive_desc(c); ++ ++ /* ++ * However, the DMA engine doesn't provide any way to stop these ++ * descriptors being processed currently by hardware. The only way is ++ * to just waiting until these descriptors are all processed completely ++ * through mtk_hsdma_free_active_desc call. ++ */ ++ mtk_hsdma_free_active_desc(c); ++ ++ return 0; ++} ++ ++static int mtk_hsdma_alloc_chan_resources(struct dma_chan *c) ++{ ++ struct mtk_hsdma_device *hsdma = to_hsdma_dev(c); ++ int err; ++ ++ /* ++ * Since HSDMA has only one PC, the resource for PC is being allocated ++ * when the first VC is being created and the other VCs would run on ++ * the same PC. ++ */ ++ if (!refcount_read(&hsdma->pc_refcnt)) { ++ err = mtk_hsdma_alloc_pchan(hsdma, hsdma->pc); ++ if (err) ++ return err; ++ /* ++ * refcount_inc would complain increment on 0; use-after-free. ++ * Thus, we need to explicitly set it as 1 initially. ++ */ ++ refcount_set(&hsdma->pc_refcnt, 1); ++ } else { ++ refcount_inc(&hsdma->pc_refcnt); ++ } ++ ++ return 0; ++} ++ ++static void mtk_hsdma_free_chan_resources(struct dma_chan *c) ++{ ++ struct mtk_hsdma_device *hsdma = to_hsdma_dev(c); ++ ++ /* Free all descriptors in all lists on the VC */ ++ mtk_hsdma_terminate_all(c); ++ ++ /* The resource for PC is not freed until all the VCs are destroyed */ ++ if (!refcount_dec_and_test(&hsdma->pc_refcnt)) ++ return; ++ ++ mtk_hsdma_free_pchan(hsdma, hsdma->pc); ++} ++ ++static int mtk_hsdma_hw_init(struct mtk_hsdma_device *hsdma) ++{ ++ int err; ++ ++ pm_runtime_enable(hsdma2dev(hsdma)); ++ pm_runtime_get_sync(hsdma2dev(hsdma)); ++ ++ err = clk_prepare_enable(hsdma->clk); ++ if (err) ++ return err; ++ ++ mtk_dma_write(hsdma, MTK_HSDMA_INT_ENABLE, 0); ++ mtk_dma_write(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DEFAULT); ++ ++ return 0; ++} ++ ++static int mtk_hsdma_hw_deinit(struct mtk_hsdma_device *hsdma) ++{ ++ mtk_dma_write(hsdma, MTK_HSDMA_GLO, 0); ++ ++ clk_disable_unprepare(hsdma->clk); ++ ++ pm_runtime_put_sync(hsdma2dev(hsdma)); ++ pm_runtime_disable(hsdma2dev(hsdma)); ++ ++ return 0; ++} ++ ++static const struct mtk_hsdma_soc mt7623_soc = { ++ .ddone = BIT(31), ++ .ls0 = BIT(30), ++}; ++ ++static const struct mtk_hsdma_soc mt7622_soc = { ++ .ddone = BIT(15), ++ .ls0 = BIT(14), ++}; ++ ++static const struct of_device_id mtk_hsdma_match[] = { ++ { .compatible = "mediatek,mt7623-hsdma", .data = &mt7623_soc}, ++ { .compatible = "mediatek,mt7622-hsdma", .data = &mt7622_soc}, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, mtk_hsdma_match); ++ ++static int mtk_hsdma_probe(struct platform_device *pdev) ++{ ++ struct mtk_hsdma_device *hsdma; ++ struct mtk_hsdma_vchan *vc; ++ struct dma_device *dd; ++ struct resource *res; ++ int i, err; ++ ++ hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL); ++ if (!hsdma) ++ return -ENOMEM; ++ ++ dd = &hsdma->ddev; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ hsdma->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(hsdma->base)) ++ return PTR_ERR(hsdma->base); ++ ++ hsdma->soc = of_device_get_match_data(&pdev->dev); ++ if (!hsdma->soc) { ++ dev_err(&pdev->dev, "No device match found\n"); ++ return -ENODEV; ++ } ++ ++ hsdma->clk = devm_clk_get(&pdev->dev, "hsdma"); ++ if (IS_ERR(hsdma->clk)) { ++ dev_err(&pdev->dev, "No clock for %s\n", ++ dev_name(&pdev->dev)); ++ return PTR_ERR(hsdma->clk); ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "No irq resource for %s\n", ++ dev_name(&pdev->dev)); ++ return -EINVAL; ++ } ++ hsdma->irq = res->start; ++ ++ refcount_set(&hsdma->pc_refcnt, 0); ++ spin_lock_init(&hsdma->lock); ++ ++ dma_cap_set(DMA_MEMCPY, dd->cap_mask); ++ ++ dd->copy_align = MTK_HSDMA_ALIGN_SIZE; ++ dd->device_alloc_chan_resources = mtk_hsdma_alloc_chan_resources; ++ dd->device_free_chan_resources = mtk_hsdma_free_chan_resources; ++ dd->device_tx_status = mtk_hsdma_tx_status; ++ dd->device_issue_pending = mtk_hsdma_issue_pending; ++ dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy; ++ dd->device_terminate_all = mtk_hsdma_terminate_all; ++ dd->src_addr_widths = MTK_HSDMA_DMA_BUSWIDTHS; ++ dd->dst_addr_widths = MTK_HSDMA_DMA_BUSWIDTHS; ++ dd->directions = BIT(DMA_MEM_TO_MEM); ++ dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; ++ dd->dev = &pdev->dev; ++ INIT_LIST_HEAD(&dd->channels); ++ ++ hsdma->dma_requests = MTK_HSDMA_NR_VCHANS; ++ if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node, ++ "dma-requests", ++ &hsdma->dma_requests)) { ++ dev_info(&pdev->dev, ++ "Using %u as missing dma-requests property\n", ++ MTK_HSDMA_NR_VCHANS); ++ } ++ ++ hsdma->pc = devm_kcalloc(&pdev->dev, MTK_HSDMA_NR_MAX_PCHANS, ++ sizeof(*hsdma->pc), GFP_KERNEL); ++ if (!hsdma->pc) ++ return -ENOMEM; ++ ++ hsdma->vc = devm_kcalloc(&pdev->dev, hsdma->dma_requests, ++ sizeof(*hsdma->vc), GFP_KERNEL); ++ if (!hsdma->vc) ++ return -ENOMEM; ++ ++ for (i = 0; i < hsdma->dma_requests; i++) { ++ vc = &hsdma->vc[i]; ++ vc->vc.desc_free = mtk_hsdma_vdesc_free; ++ vchan_init(&vc->vc, dd); ++ init_completion(&vc->issue_completion); ++ INIT_LIST_HEAD(&vc->desc_hw_processing); ++ } ++ ++ err = dma_async_device_register(dd); ++ if (err) ++ return err; ++ ++ err = of_dma_controller_register(pdev->dev.of_node, ++ of_dma_xlate_by_chan_id, hsdma); ++ if (err) { ++ dev_err(&pdev->dev, ++ "MediaTek HSDMA OF registration failed %d\n", err); ++ goto err_unregister; ++ } ++ ++ mtk_hsdma_hw_init(hsdma); ++ ++ err = devm_request_irq(&pdev->dev, hsdma->irq, ++ mtk_hsdma_irq, 0, ++ dev_name(&pdev->dev), hsdma); ++ if (err) { ++ dev_err(&pdev->dev, ++ "request_irq failed with err %d\n", err); ++ goto err_unregister; ++ } ++ ++ platform_set_drvdata(pdev, hsdma); ++ ++ dev_info(&pdev->dev, "MediaTek HSDMA driver registered\n"); ++ ++ return 0; ++ ++err_unregister: ++ dma_async_device_unregister(dd); ++ ++ return err; ++} ++ ++static int mtk_hsdma_remove(struct platform_device *pdev) ++{ ++ struct mtk_hsdma_device *hsdma = platform_get_drvdata(pdev); ++ struct mtk_hsdma_vchan *vc; ++ int i; ++ ++ /* Kill VC task */ ++ for (i = 0; i < hsdma->dma_requests; i++) { ++ vc = &hsdma->vc[i]; ++ ++ list_del(&vc->vc.chan.device_node); ++ tasklet_kill(&vc->vc.task); ++ } ++ ++ /* Disable DMA interrupt */ ++ mtk_dma_write(hsdma, MTK_HSDMA_INT_ENABLE, 0); ++ ++ /* Waits for any pending IRQ handlers to complete */ ++ synchronize_irq(hsdma->irq); ++ ++ /* Disable hardware */ ++ mtk_hsdma_hw_deinit(hsdma); ++ ++ dma_async_device_unregister(&hsdma->ddev); ++ of_dma_controller_free(pdev->dev.of_node); ++ ++ return 0; ++} ++ ++static struct platform_driver mtk_hsdma_driver = { ++ .probe = mtk_hsdma_probe, ++ .remove = mtk_hsdma_remove, ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = mtk_hsdma_match, ++ }, ++}; ++module_platform_driver(mtk_hsdma_driver); ++ ++MODULE_DESCRIPTION("MediaTek High-Speed DMA Controller Driver"); ++MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); ++MODULE_LICENSE("GPL v2"); +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0206-dt-bindings-clock-mediatek-update-audsys-documentati.patch b/target/linux/mediatek/patches-4.14/0206-dt-bindings-clock-mediatek-update-audsys-documentati.patch new file mode 100644 index 0000000000..d92c0c50fb --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0206-dt-bindings-clock-mediatek-update-audsys-documentati.patch @@ -0,0 +1,50 @@ +From e6d9c3121f2a8b92bd6202d6a32e7d428990d7d7 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 6 Mar 2018 17:09:29 +0800 +Subject: [PATCH 206/224] dt-bindings: clock: mediatek: update audsys + documentation to adapt MFD device + +The MediaTek audio hardware block that exposes functionalities that are +handled by separate subsystems in the kernel. These functions are all +mapped somewhere at 0x112xxxxx, and there are some control bits are mixed +up with other functions within the same registers. + +This patch modifies example to illustrate child nodes. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +--- + .../bindings/arm/mediatek/mediatek,audsys.txt | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt +index 9b8f578d5e19..97b304eaa47c 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt +@@ -13,10 +13,19 @@ The AUDSYS controller uses the common clk binding from + Documentation/devicetree/bindings/clock/clock-bindings.txt + The available clocks are defined in dt-bindings/clock/mt*-clk.h. + ++Required sub-nodes: ++------- ++For common binding part and usage, refer to ++../sonud/mt2701-afe-pcm.txt. ++ + Example: + +-audsys: audsys@11220000 { +- compatible = "mediatek,mt7622-audsys", "syscon"; +- reg = <0 0x11220000 0 0x1000>; +- #clock-cells = <1>; +-}; ++ audsys: clock-controller@11220000 { ++ compatible = "mediatek,mt7622-audsys", "syscon"; ++ reg = <0 0x11220000 0 0x2000>; ++ #clock-cells = <1>; ++ ++ afe: audio-controller { ++ ... ++ }; ++ }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0207-dt-bindings-clock-mediatek-add-audsys-support-for-MT.patch b/target/linux/mediatek/patches-4.14/0207-dt-bindings-clock-mediatek-add-audsys-support-for-MT.patch new file mode 100644 index 0000000000..8349b85ae4 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0207-dt-bindings-clock-mediatek-add-audsys-support-for-MT.patch @@ -0,0 +1,28 @@ +From 301de0fca7698f1ed5ed34fa7c082c3ae62d1e61 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 6 Mar 2018 17:09:30 +0800 +Subject: [PATCH 207/224] dt-bindings: clock: mediatek: add audsys support for + MT2701 + +This patch adds a compatible string for MT2701. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +--- + Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt +index 97b304eaa47c..34a69ba67f13 100644 +--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt ++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt +@@ -6,6 +6,7 @@ The MediaTek AUDSYS controller provides various clocks to the system. + Required Properties: + + - compatible: Should be one of: ++ - "mediatek,mt2701-audsys", "syscon" + - "mediatek,mt7622-audsys", "syscon" + - #clock-cells: Must be 1 + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0208-clk-mediatek-update-missing-clock-data-for-MT7622-au.patch b/target/linux/mediatek/patches-4.14/0208-clk-mediatek-update-missing-clock-data-for-MT7622-au.patch new file mode 100644 index 0000000000..c1f7682eec --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0208-clk-mediatek-update-missing-clock-data-for-MT7622-au.patch @@ -0,0 +1,45 @@ +From 0725349768e96542ef06efbd87925a8603cba16a Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 6 Mar 2018 17:09:26 +0800 +Subject: [PATCH 208/224] clk: mediatek: update missing clock data for MT7622 + audsys + +Add missing clock data 'CLK_AUDIO_AFE_CONN' for MT7622 audsys. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Reviewed-by: Rob Herring <robh@kernel.org> +Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> +--- + drivers/clk/mediatek/clk-mt7622-aud.c | 1 + + include/dt-bindings/clock/mt7622-clk.h | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c +index fad7d9fc53ba..13f752de7adc 100644 +--- a/drivers/clk/mediatek/clk-mt7622-aud.c ++++ b/drivers/clk/mediatek/clk-mt7622-aud.c +@@ -106,6 +106,7 @@ static const struct mtk_gate audio_clks[] = { + GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20), + GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21), + GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22), ++ GATE_AUDIO1(CLK_AUDIO_AFE_CONN, "audio_afe_conn", "a1sys_hp_sel", 23), + /* AUDIO2 */ + GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0), + GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1), +diff --git a/include/dt-bindings/clock/mt7622-clk.h b/include/dt-bindings/clock/mt7622-clk.h +index 3e514ed51d15..e9d77f0e8bce 100644 +--- a/include/dt-bindings/clock/mt7622-clk.h ++++ b/include/dt-bindings/clock/mt7622-clk.h +@@ -235,7 +235,8 @@ + #define CLK_AUDIO_MEM_ASRC3 43 + #define CLK_AUDIO_MEM_ASRC4 44 + #define CLK_AUDIO_MEM_ASRC5 45 +-#define CLK_AUDIO_NR_CLK 46 ++#define CLK_AUDIO_AFE_CONN 46 ++#define CLK_AUDIO_NR_CLK 47 + + /* SSUSBSYS */ + +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0209-clk-mediatek-add-devm_of_platform_populate-for-MT762.patch b/target/linux/mediatek/patches-4.14/0209-clk-mediatek-add-devm_of_platform_populate-for-MT762.patch new file mode 100644 index 0000000000..610dcab7c0 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0209-clk-mediatek-add-devm_of_platform_populate-for-MT762.patch @@ -0,0 +1,47 @@ +From 9dbdf33f1f246ecb6d957504781a970590b2d9f0 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Tue, 6 Mar 2018 17:09:27 +0800 +Subject: [PATCH 209/224] clk: mediatek: add devm_of_platform_populate() for + MT7622 audsys + +Add devm_of_platform_populate() to populate devices which are children +of the root node. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +--- + drivers/clk/mediatek/clk-mt7622-aud.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c +index 13f752de7adc..0a1109ff65b9 100644 +--- a/drivers/clk/mediatek/clk-mt7622-aud.c ++++ b/drivers/clk/mediatek/clk-mt7622-aud.c +@@ -142,6 +142,7 @@ static int clk_mt7622_audiosys_init(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(CLK_AUDIO_NR_CLK); +@@ -150,12 +151,15 @@ static int clk_mt7622_audiosys_init(struct platform_device *pdev) + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +- if (r) ++ if (r) { + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + +- return r; ++ return r; ++ } ++ ++ return devm_of_platform_populate(&pdev->dev); + } + + static const struct of_device_id of_match_clk_mt7622_aud[] = { +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0210-arm64-dts-mt7622-add-clock-controller-device-nodes.patch b/target/linux/mediatek/patches-4.14/0210-arm64-dts-mt7622-add-clock-controller-device-nodes.patch new file mode 100644 index 0000000000..5d892118ec --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0210-arm64-dts-mt7622-add-clock-controller-device-nodes.patch @@ -0,0 +1,135 @@ +From 9c76dd09d27dff05207241aa67a2c6054d057b32 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 28 Dec 2017 10:30:32 +0800 +Subject: [PATCH 210/224] arm64: dts: mt7622: add clock controller device nodes + +Add clock controller nodes for MT7622 and include header for topckgen, +infracfg, pericfg, apmixedsys, ethsys, sgmiisys, pciesys and ssusbsys +for those devices nodes to be added afterwards. + +In addition, provides an oscillator node for the source of PLLs and dummy +clock for PWARP to complement missing support of clock gate for the +wrapper circuit in the driver. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Stephen Boyd <sboyd@codeaurora.org> +--- + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 76 ++++++++++++++++++++++++++++++++ + 1 file changed, 76 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index b111fec2ed9d..73e5d628a8c8 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -8,6 +8,8 @@ + + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> ++#include <dt-bindings/clock/mt7622-clk.h> ++#include <dt-bindings/reset/mt7622-reset.h> + + / { + compatible = "mediatek,mt7622"; +@@ -48,6 +50,19 @@ + clock-frequency = <280000000>; + }; + ++ pwrap_clk: dummy40m { ++ compatible = "fixed-clock"; ++ clock-frequency = <40000000>; ++ #clock-cells = <0>; ++ }; ++ ++ clk25m: oscillator { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <25000000>; ++ clock-output-names = "clkxtal"; ++ }; ++ + psci { + compatible = "arm,psci-0.2"; + method = "smc"; +@@ -78,6 +93,22 @@ + IRQ_TYPE_LEVEL_HIGH)>; + }; + ++ infracfg: infracfg@10000000 { ++ compatible = "mediatek,mt7622-infracfg", ++ "syscon"; ++ reg = <0 0x10000000 0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ pericfg: pericfg@10002000 { ++ compatible = "mediatek,mt7622-pericfg", ++ "syscon"; ++ reg = <0 0x10002000 0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ + sysirq: interrupt-controller@10200620 { + compatible = "mediatek,mt7622-sysirq", + "mediatek,mt6577-sysirq"; +@@ -87,6 +118,20 @@ + reg = <0 0x10200620 0 0x20>; + }; + ++ apmixedsys: apmixedsys@10209000 { ++ compatible = "mediatek,mt7622-apmixedsys", ++ "syscon"; ++ reg = <0 0x10209000 0 0x1000>; ++ #clock-cells = <1>; ++ }; ++ ++ topckgen: topckgen@10210000 { ++ compatible = "mediatek,mt7622-topckgen", ++ "syscon"; ++ reg = <0 0x10210000 0 0x1000>; ++ #clock-cells = <1>; ++ }; ++ + gic: interrupt-controller@10300000 { + compatible = "arm,gic-400"; + interrupt-controller; +@@ -107,4 +152,35 @@ + clock-names = "baud", "bus"; + status = "disabled"; + }; ++ ++ ssusbsys: ssusbsys@1a000000 { ++ compatible = "mediatek,mt7622-ssusbsys", ++ "syscon"; ++ reg = <0 0x1a000000 0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ pciesys: pciesys@1a100800 { ++ compatible = "mediatek,mt7622-pciesys", ++ "syscon"; ++ reg = <0 0x1a100800 0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ ethsys: syscon@1b000000 { ++ compatible = "mediatek,mt7622-ethsys", ++ "syscon"; ++ reg = <0 0x1b000000 0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ sgmiisys: sgmiisys@1b128000 { ++ compatible = "mediatek,mt7622-sgmiisys", ++ "syscon"; ++ reg = <0 0x1b128000 0 0x1000>; ++ #clock-cells = <1>; ++ }; + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0211-arm64-dts-mt7622-add-power-domain-controller-device-.patch b/target/linux/mediatek/patches-4.14/0211-arm64-dts-mt7622-add-power-domain-controller-device-.patch new file mode 100644 index 0000000000..362d40db15 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0211-arm64-dts-mt7622-add-power-domain-controller-device-.patch @@ -0,0 +1,50 @@ +From 79d0293e8f35e87b1f068fc0b7963a86ba56800e Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 28 Dec 2017 15:46:42 +0800 +Subject: [PATCH 211/224] arm64: dts: mt7622: add power domain controller + device nodes + +add power domain controller nodes + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Matthias Brugger <matthias.bgg@gmail.com> +--- + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 73e5d628a8c8..81207e652d59 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -9,6 +9,7 @@ + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/mt7622-clk.h> ++#include <dt-bindings/power/mt7622-power.h> + #include <dt-bindings/reset/mt7622-reset.h> + + / { +@@ -109,6 +110,20 @@ + #reset-cells = <1>; + }; + ++ scpsys: scpsys@10006000 { ++ compatible = "mediatek,mt7622-scpsys", ++ "syscon"; ++ #power-domain-cells = <1>; ++ reg = <0 0x10006000 0 0x1000>; ++ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_LOW>, ++ <GIC_SPI 166 IRQ_TYPE_LEVEL_LOW>, ++ <GIC_SPI 167 IRQ_TYPE_LEVEL_LOW>, ++ <GIC_SPI 168 IRQ_TYPE_LEVEL_LOW>; ++ infracfg = <&infracfg>; ++ clocks = <&topckgen CLK_TOP_HIF_SEL>; ++ clock-names = "hif_sel"; ++ }; ++ + sysirq: interrupt-controller@10200620 { + compatible = "mediatek,mt7622-sysirq", + "mediatek,mt6577-sysirq"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0212-arm64-dts-mt7622-add-pinctrl-related-device-nodes.patch b/target/linux/mediatek/patches-4.14/0212-arm64-dts-mt7622-add-pinctrl-related-device-nodes.patch new file mode 100644 index 0000000000..9858790450 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0212-arm64-dts-mt7622-add-pinctrl-related-device-nodes.patch @@ -0,0 +1,259 @@ +From 927c736a1a169713cd59140db5e82f8ed11dad60 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 29 Dec 2017 11:06:52 +0800 +Subject: [PATCH 212/224] arm64: dts: mt7622: add pinctrl related device nodes + +add pinctrl device nodes and rfb1 board, additionally include all pin +groups possible being used on rfb1 board and available gpio keys. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Matthias Brugger <matthias.bgg@gmail.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 200 +++++++++++++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 7 + + 2 files changed, 207 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index c08309df2cc7..fc8ef78a0a34 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -7,6 +7,8 @@ + */ + + /dts-v1/; ++#include <dt-bindings/input/input.h> ++ + #include "mt7622.dtsi" + + / { +@@ -17,11 +19,209 @@ + bootargs = "console=ttyS0,115200n1"; + }; + ++ gpio-keys { ++ compatible = "gpio-keys-polled"; ++ poll-interval = <100>; ++ ++ factory { ++ label = "factory"; ++ linux,code = <BTN_0>; ++ gpios = <&pio 0 0>; ++ }; ++ ++ wps { ++ label = "wps"; ++ linux,code = <KEY_WPS_BUTTON>; ++ gpios = <&pio 102 0>; ++ }; ++ }; ++ + memory { + reg = <0 0x40000000 0 0x3F000000>; + }; + }; + ++&pio { ++ /* eMMC is shared pin with parallel NAND */ ++ emmc_pins_default: emmc-pins-default { ++ mux { ++ function = "emmc", "emmc_rst"; ++ groups = "emmc"; ++ }; ++ }; ++ ++ emmc_pins_uhs: emmc-pins-uhs { ++ mux { ++ function = "emmc"; ++ groups = "emmc"; ++ }; ++ }; ++ ++ eth_pins: eth-pins { ++ mux { ++ function = "eth"; ++ groups = "mdc_mdio", "rgmii_via_gmac2"; ++ }; ++ }; ++ ++ i2c1_pins: i2c1-pins { ++ mux { ++ function = "i2c"; ++ groups = "i2c1_0"; ++ }; ++ }; ++ ++ i2c2_pins: i2c2-pins { ++ mux { ++ function = "i2c"; ++ groups = "i2c2_0"; ++ }; ++ }; ++ ++ i2s1_pins: i2s1-pins { ++ mux { ++ function = "i2s"; ++ groups = "i2s_out_bclk_ws_mclk", ++ "i2s1_in_data", ++ "i2s1_out_data"; ++ }; ++ }; ++ ++ irrx_pins: irrx-pins { ++ mux { ++ function = "ir"; ++ groups = "ir_1_rx"; ++ }; ++ }; ++ ++ irtx_pins: irtx-pins { ++ mux { ++ function = "ir"; ++ groups = "ir_1_tx"; ++ }; ++ }; ++ ++ /* Parallel nand is shared pin with eMMC */ ++ parallel_nand_pins: parallel-nand-pins { ++ mux { ++ function = "flash"; ++ groups = "par_nand"; ++ }; ++ }; ++ ++ pcie0_pins: pcie0-pins { ++ mux { ++ function = "pcie"; ++ groups = "pcie0_pad_perst", ++ "pcie0_1_waken", ++ "pcie0_1_clkreq"; ++ }; ++ }; ++ ++ pcie1_pins: pcie1-pins { ++ mux { ++ function = "pcie"; ++ groups = "pcie1_pad_perst", ++ "pcie1_0_waken", ++ "pcie1_0_clkreq"; ++ }; ++ }; ++ ++ pmic_bus_pins: pmic-bus-pins { ++ mux { ++ function = "pmic"; ++ groups = "pmic_bus"; ++ }; ++ }; ++ ++ pwm7_pins: pwm1-2-pins { ++ mux { ++ function = "pwm"; ++ groups = "pwm_ch7_2"; ++ }; ++ }; ++ ++ wled_pins: wled-pins { ++ mux { ++ function = "led"; ++ groups = "wled"; ++ }; ++ }; ++ ++ sd0_pins_default: sd0-pins-default { ++ mux { ++ function = "sd"; ++ groups = "sd_0"; ++ }; ++ }; ++ ++ sd0_pins_uhs: sd0-pins-uhs { ++ mux { ++ function = "sd"; ++ groups = "sd_0"; ++ }; ++ }; ++ ++ /* Serial NAND is shared pin with SPI-NOR */ ++ serial_nand_pins: serial-nand-pins { ++ mux { ++ function = "flash"; ++ groups = "snfi"; ++ }; ++ }; ++ ++ spic0_pins: spic0-pins { ++ mux { ++ function = "spi"; ++ groups = "spic0_0"; ++ }; ++ }; ++ ++ spic1_pins: spic1-pins { ++ mux { ++ function = "spi"; ++ groups = "spic1_0"; ++ }; ++ }; ++ ++ /* SPI-NOR is shared pin with serial NAND */ ++ spi_nor_pins: spi-nor-pins { ++ mux { ++ function = "flash"; ++ groups = "spi_nor"; ++ }; ++ }; ++ ++ /* serial NAND is shared pin with SPI-NOR */ ++ serial_nand_pins: serial-nand-pins { ++ mux { ++ function = "flash"; ++ groups = "snfi"; ++ }; ++ }; ++ ++ uart0_pins: uart0-pins { ++ mux { ++ function = "uart"; ++ groups = "uart0_0_tx_rx" ; ++ }; ++ }; ++ ++ uart2_pins: uart2-pins { ++ mux { ++ function = "uart"; ++ groups = "uart2_1_tx_rx" ; ++ }; ++ }; ++ ++ watchdog_pins: watchdog-pins { ++ mux { ++ function = "watchdog"; ++ groups = "watchdog"; ++ }; ++ }; ++}; ++ + &uart0 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 81207e652d59..8211bf72ccaa 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -147,6 +147,13 @@ + #clock-cells = <1>; + }; + ++ pio: pinctrl@10211000 { ++ compatible = "mediatek,mt7622-pinctrl"; ++ reg = <0 0x10211000 0 0x1000>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ + gic: interrupt-controller@10300000 { + compatible = "arm,gic-400"; + interrupt-controller; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0213-arm64-dts-mt7622-add-PMIC-MT6380-related-nodes.patch b/target/linux/mediatek/patches-4.14/0213-arm64-dts-mt7622-add-PMIC-MT6380-related-nodes.patch new file mode 100644 index 0000000000..f02f4b31c4 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0213-arm64-dts-mt7622-add-PMIC-MT6380-related-nodes.patch @@ -0,0 +1,165 @@ +From 78e92290c8c9511d0d540dfd0450e64169f08c20 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 5 Feb 2018 22:44:44 +0800 +Subject: [PATCH 213/224] arm64: dts: mt7622: add PMIC MT6380 related nodes + +Enable pwrap and MT6380 on mt7622-rfb1 board. Also add all mt6380 +regulator nodes in an alone file to allow similar boards using MT6380 +able to resue the configuration. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Mark Brown <broonie@kernel.org> +Cc: Matthias Brugger <matthias.bgg@gmail.com> +Cc: Philippe Ombredanne <pombredanne@nexb.com> +Acked-by: Philippe Ombredanne <pombredanne@nexb.com> +--- + arch/arm64/boot/dts/mediatek/mt6380.dtsi | 86 ++++++++++++++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 8 +++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 12 ++++ + 3 files changed, 106 insertions(+) + create mode 100644 arch/arm64/boot/dts/mediatek/mt6380.dtsi + +diff --git a/arch/arm64/boot/dts/mediatek/mt6380.dtsi b/arch/arm64/boot/dts/mediatek/mt6380.dtsi +new file mode 100644 +index 000000000000..53b335d2de5f +--- /dev/null ++++ b/arch/arm64/boot/dts/mediatek/mt6380.dtsi +@@ -0,0 +1,86 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * dts file for MediaTek MT6380 regulator ++ * ++ * Copyright (c) 2018 MediaTek Inc. ++ * Author: Chenglin Xu <chenglin.xu@mediatek.com> ++ * Sean Wang <sean.wang@mediatek.com> ++ */ ++ ++&pwrap { ++ regulators { ++ compatible = "mediatek,mt6380-regulator"; ++ ++ mt6380_vcpu_reg: buck-vcore1 { ++ regulator-name = "vcore1"; ++ regulator-min-microvolt = < 600000>; ++ regulator-max-microvolt = <1393750>; ++ regulator-ramp-delay = <6250>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6380_vcore_reg: buck-vcore { ++ regulator-name = "vcore"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <1393750>; ++ regulator-ramp-delay = <6250>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6380_vrf_reg: buck-vrf { ++ regulator-name = "vrf"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1575000>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6380_vm_reg: ldo-vm { ++ regulator-name = "vm"; ++ regulator-min-microvolt = <1050000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6380_va_reg: ldo-va { ++ regulator-name = "va"; ++ regulator-min-microvolt = <2200000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6380_vphy_reg: ldo-vphy { ++ regulator-name = "vphy"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6380_vddr_reg: ldo-vddr { ++ regulator-name = "vddr"; ++ regulator-min-microvolt = <1240000>; ++ regulator-max-microvolt = <1840000>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ mt6380_vt_reg: ldo-vt { ++ regulator-name = "vt"; ++ regulator-min-microvolt = <2200000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index fc8ef78a0a34..42bd3a4c9a93 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -10,6 +10,7 @@ + #include <dt-bindings/input/input.h> + + #include "mt7622.dtsi" ++#include "mt6380.dtsi" + + / { + model = "MediaTek MT7622 RFB1 board"; +@@ -222,6 +223,13 @@ + }; + }; + ++&pwrap { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_bus_pins>; ++ ++ status = "okay"; ++}; ++ + &uart0 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 8211bf72ccaa..c387c4cb7d3e 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -102,6 +102,18 @@ + #reset-cells = <1>; + }; + ++ pwrap: pwrap@10001000 { ++ compatible = "mediatek,mt7622-pwrap"; ++ reg = <0 0x10001000 0 0x250>; ++ reg-names = "pwrap"; ++ clocks = <&infracfg CLK_INFRA_PMIC_PD>,<&pwrap_clk>; ++ clock-names = "spi","wrap"; ++ resets = <&infracfg MT7622_INFRA_PMIC_WRAP_RST>; ++ reset-names = "pwrap"; ++ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>; ++ status = "disabled"; ++ }; ++ + pericfg: pericfg@10002000 { + compatible = "mediatek,mt7622-pericfg", + "syscon"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0214-arm64-dts-mt7622-add-cpufreq-related-device-nodes.patch b/target/linux/mediatek/patches-4.14/0214-arm64-dts-mt7622-add-cpufreq-related-device-nodes.patch new file mode 100644 index 0000000000..43692d4344 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0214-arm64-dts-mt7622-add-cpufreq-related-device-nodes.patch @@ -0,0 +1,119 @@ +From 19fc79333af0d3733d4987bc1e554ae7e8a8cb0d Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 28 Dec 2017 16:26:10 +0800 +Subject: [PATCH 214/224] arm64: dts: mt7622: add cpufreq related device nodes + +Add clocks, regulators and opp information into cpu nodes. +In addition, the power supply for cpu nodes is deployed on +mt7622-rfb1 board. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Viresh Kumar <viresh.kumar@linaro.org> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 12 +++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 52 ++++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index 42bd3a4c9a93..b3878656475c 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -20,6 +20,18 @@ + bootargs = "console=ttyS0,115200n1"; + }; + ++ cpus { ++ cpu@0 { ++ proc-supply = <&mt6380_vcpu_reg>; ++ sram-supply = <&mt6380_vm_reg>; ++ }; ++ ++ cpu@1 { ++ proc-supply = <&mt6380_vcpu_reg>; ++ sram-supply = <&mt6380_vm_reg>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys-polled"; + poll-interval = <100>; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index c387c4cb7d3e..7256879de4c9 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -18,6 +18,50 @@ + #address-cells = <2>; + #size-cells = <2>; + ++ cpu_opp_table: opp-table { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ opp-300000000 { ++ opp-hz = /bits/ 64 <30000000>; ++ opp-microvolt = <950000>; ++ }; ++ ++ opp-437500000 { ++ opp-hz = /bits/ 64 <437500000>; ++ opp-microvolt = <1000000>; ++ }; ++ ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <1050000>; ++ }; ++ ++ opp-812500000 { ++ opp-hz = /bits/ 64 <812500000>; ++ opp-microvolt = <1100000>; ++ }; ++ ++ opp-1025000000 { ++ opp-hz = /bits/ 64 <1025000000>; ++ opp-microvolt = <1150000>; ++ }; ++ ++ opp-1137500000 { ++ opp-hz = /bits/ 64 <1137500000>; ++ opp-microvolt = <1200000>; ++ }; ++ ++ opp-1262500000 { ++ opp-hz = /bits/ 64 <1262500000>; ++ opp-microvolt = <1250000>; ++ }; ++ ++ opp-1350000000 { ++ opp-hz = /bits/ 64 <1350000000>; ++ opp-microvolt = <1310000>; ++ }; ++ }; ++ + cpus { + #address-cells = <2>; + #size-cells = <0>; +@@ -26,6 +70,10 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x0>; ++ clocks = <&infracfg CLK_INFRA_MUX1_SEL>, ++ <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>; ++ clock-names = "cpu", "intermediate"; ++ operating-points-v2 = <&cpu_opp_table>; + enable-method = "psci"; + clock-frequency = <1300000000>; + }; +@@ -34,6 +82,10 @@ + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0 0x1>; ++ clocks = <&infracfg CLK_INFRA_MUX1_SEL>, ++ <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>; ++ clock-names = "cpu", "intermediate"; ++ operating-points-v2 = <&cpu_opp_table>; + enable-method = "psci"; + clock-frequency = <1300000000>; + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0215-arm64-dts-mt7622-turn-uart0-clock-to-real-ones.patch b/target/linux/mediatek/patches-4.14/0215-arm64-dts-mt7622-turn-uart0-clock-to-real-ones.patch new file mode 100644 index 0000000000..541c46bf47 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0215-arm64-dts-mt7622-turn-uart0-clock-to-real-ones.patch @@ -0,0 +1,50 @@ +From 84b3092b3773777de1ba1ad142e53247fb881ddd Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 28 Dec 2017 18:00:11 +0800 +Subject: [PATCH 215/224] arm64: dts: mt7622: turn uart0 clock to real ones + +This patch also cleans up two oscillators that provide clocks for MT7623. +Switch the uart clocks to the real ones while at it. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Matthias Brugger <matthias.bgg@gmail.com> +--- + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 15 ++------------- + 1 file changed, 2 insertions(+), 13 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 7256879de4c9..d8a17d10e2ff 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -91,18 +91,6 @@ + }; + }; + +- uart_clk: dummy25m { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <25000000>; +- }; +- +- bus_clk: dummy280m { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-frequency = <280000000>; +- }; +- + pwrap_clk: dummy40m { + compatible = "fixed-clock"; + clock-frequency = <40000000>; +@@ -234,7 +222,8 @@ + "mediatek,mt6577-uart"; + reg = <0 0x11002000 0 0x400>; + interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>; +- clocks = <&uart_clk>, <&bus_clk>; ++ clocks = <&topckgen CLK_TOP_UART_SEL>, ++ <&pericfg CLK_PERI_UART1_PD>; + clock-names = "baud", "bus"; + status = "disabled"; + }; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0216-arm64-dts-mt7622-add-SoC-and-peripheral-related-devi.patch b/target/linux/mediatek/patches-4.14/0216-arm64-dts-mt7622-add-SoC-and-peripheral-related-devi.patch new file mode 100644 index 0000000000..5db0584122 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0216-arm64-dts-mt7622-add-SoC-and-peripheral-related-devi.patch @@ -0,0 +1,427 @@ +From a69ac853def2f93194e244974f611477a1521a4a Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Thu, 28 Dec 2017 18:18:26 +0800 +Subject: [PATCH 216/224] arm64: dts: mt7622: add SoC and peripheral related + device nodes + +Add watchdog, rtc, auxadc, cir, efuse, rng, uart[1-4], pwm, i2c[0-2], +spi[0-1], btif and thermal related nodes. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: Andrew-CT Chen <andrew-ct.chen@mediatek.com> +Cc: Zhiyong Tao <zhiyong.tao@mediatek.com> +Cc: Zhi Mao <zhi.mao@mediatek.com> +Cc: Jun Gao <jun.gao@mediatek.com> +Cc: Leilk Liu <leilk.liu@mediatek.com> +Cc: Matthias Brugger <matthias.bgg@gmail.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 54 ++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 264 +++++++++++++++++++++++++++ + 2 files changed, 318 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index b3878656475c..ba6a79caca21 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -235,6 +235,34 @@ + }; + }; + ++&btif { ++ status = "okay"; ++}; ++ ++&cir { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&irrx_pins>; ++ status = "okay"; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ status = "okay"; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ status = "okay"; ++}; ++ ++&pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm7_pins>; ++ status = "okay"; ++}; ++ + &pwrap { + pinctrl-names = "default"; + pinctrl-0 = <&pmic_bus_pins>; +@@ -242,6 +270,32 @@ + status = "okay"; + }; + ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spic0_pins>; ++ status = "okay"; ++}; ++ ++&spi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spic1_pins>; ++ status = "okay"; ++}; ++ + &uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart2_pins>; ++ status = "okay"; ++}; ++ ++&watchdog { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&watchdog_pins>; + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index d8a17d10e2ff..448cd366995b 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -11,6 +11,7 @@ + #include <dt-bindings/clock/mt7622-clk.h> + #include <dt-bindings/power/mt7622-power.h> + #include <dt-bindings/reset/mt7622-reset.h> ++#include <dt-bindings/thermal/thermal.h> + + / { + compatible = "mediatek,mt7622"; +@@ -74,6 +75,7 @@ + <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cpu_opp_table>; ++ #cooling-cells = <2>; + enable-method = "psci"; + clock-frequency = <1300000000>; + }; +@@ -121,6 +123,58 @@ + }; + }; + ++ thermal-zones { ++ cpu_thermal: cpu-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <1000>; ++ ++ thermal-sensors = <&thermal 0>; ++ ++ trips { ++ cpu_passive: cpu-passive { ++ temperature = <47000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu_active: cpu-active { ++ temperature = <67000>; ++ hysteresis = <2000>; ++ type = "active"; ++ }; ++ ++ cpu_hot: cpu-hot { ++ temperature = <87000>; ++ hysteresis = <2000>; ++ type = "hot"; ++ }; ++ ++ cpu-crit { ++ temperature = <107000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_passive>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ ++ map1 { ++ trip = <&cpu_active>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ ++ map2 { ++ trip = <&cpu_hot>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; +@@ -176,6 +230,16 @@ + clock-names = "hif_sel"; + }; + ++ cir: cir@10009000 { ++ compatible = "mediatek,mt7622-cir"; ++ reg = <0 0x10009000 0 0x1000>; ++ interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&infracfg CLK_INFRA_IRRX_PD>, ++ <&topckgen CLK_TOP_AXI_SEL>; ++ clock-names = "clk", "bus"; ++ status = "disabled"; ++ }; ++ + sysirq: interrupt-controller@10200620 { + compatible = "mediatek,mt7622-sysirq", + "mediatek,mt6577-sysirq"; +@@ -185,6 +249,18 @@ + reg = <0 0x10200620 0 0x20>; + }; + ++ efuse: efuse@10206000 { ++ compatible = "mediatek,mt7622-efuse", ++ "mediatek,efuse"; ++ reg = <0 0x10206000 0 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ thermal_calibration: calib@198 { ++ reg = <0x198 0xc>; ++ }; ++ }; ++ + apmixedsys: apmixedsys@10209000 { + compatible = "mediatek,mt7622-apmixedsys", + "syscon"; +@@ -199,6 +275,14 @@ + #clock-cells = <1>; + }; + ++ rng: rng@1020f000 { ++ compatible = "mediatek,mt7622-rng", ++ "mediatek,mt7623-rng"; ++ reg = <0 0x1020f000 0 0x1000>; ++ clocks = <&infracfg CLK_INFRA_TRNG>; ++ clock-names = "rng"; ++ }; ++ + pio: pinctrl@10211000 { + compatible = "mediatek,mt7622-pinctrl"; + reg = <0 0x10211000 0 0x1000>; +@@ -206,6 +290,21 @@ + #gpio-cells = <2>; + }; + ++ watchdog: watchdog@10212000 { ++ compatible = "mediatek,mt7622-wdt", ++ "mediatek,mt6589-wdt"; ++ reg = <0 0x10212000 0 0x800>; ++ }; ++ ++ rtc: rtc@10212800 { ++ compatible = "mediatek,mt7622-rtc", ++ "mediatek,soc-rtc"; ++ reg = <0 0x10212800 0 0x200>; ++ interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_RTC>; ++ clock-names = "rtc"; ++ }; ++ + gic: interrupt-controller@10300000 { + compatible = "arm,gic-400"; + interrupt-controller; +@@ -217,6 +316,14 @@ + <0 0x10360000 0 0x2000>; + }; + ++ auxadc: adc@11001000 { ++ compatible = "mediatek,mt7622-auxadc"; ++ reg = <0 0x11001000 0 0x1000>; ++ clocks = <&pericfg CLK_PERI_AUXADC_PD>; ++ clock-names = "main"; ++ #io-channel-cells = <1>; ++ }; ++ + uart0: serial@11002000 { + compatible = "mediatek,mt7622-uart", + "mediatek,mt6577-uart"; +@@ -228,6 +335,163 @@ + status = "disabled"; + }; + ++ uart1: serial@11003000 { ++ compatible = "mediatek,mt7622-uart", ++ "mediatek,mt6577-uart"; ++ reg = <0 0x11003000 0 0x400>; ++ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_UART_SEL>, ++ <&pericfg CLK_PERI_UART1_PD>; ++ clock-names = "baud", "bus"; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@11004000 { ++ compatible = "mediatek,mt7622-uart", ++ "mediatek,mt6577-uart"; ++ reg = <0 0x11004000 0 0x400>; ++ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_UART_SEL>, ++ <&pericfg CLK_PERI_UART2_PD>; ++ clock-names = "baud", "bus"; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@11005000 { ++ compatible = "mediatek,mt7622-uart", ++ "mediatek,mt6577-uart"; ++ reg = <0 0x11005000 0 0x400>; ++ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_UART_SEL>, ++ <&pericfg CLK_PERI_UART3_PD>; ++ clock-names = "baud", "bus"; ++ status = "disabled"; ++ }; ++ ++ pwm: pwm@11006000 { ++ compatible = "mediatek,mt7622-pwm"; ++ reg = <0 0x11006000 0 0x1000>; ++ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_PWM_SEL>, ++ <&pericfg CLK_PERI_PWM_PD>, ++ <&pericfg CLK_PERI_PWM1_PD>, ++ <&pericfg CLK_PERI_PWM2_PD>, ++ <&pericfg CLK_PERI_PWM3_PD>, ++ <&pericfg CLK_PERI_PWM4_PD>, ++ <&pericfg CLK_PERI_PWM5_PD>, ++ <&pericfg CLK_PERI_PWM6_PD>; ++ clock-names = "top", "main", "pwm1", "pwm2", "pwm3", "pwm4", ++ "pwm5", "pwm6"; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@11007000 { ++ compatible = "mediatek,mt7622-i2c"; ++ reg = <0 0x11007000 0 0x90>, ++ <0 0x11000100 0 0x80>; ++ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>; ++ clock-div = <16>; ++ clocks = <&pericfg CLK_PERI_I2C0_PD>, ++ <&pericfg CLK_PERI_AP_DMA_PD>; ++ clock-names = "main", "dma"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@11008000 { ++ compatible = "mediatek,mt7622-i2c"; ++ reg = <0 0x11008000 0 0x90>, ++ <0 0x11000180 0 0x80>; ++ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_LOW>; ++ 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"; ++ }; ++ ++ i2c2: i2c@11009000 { ++ compatible = "mediatek,mt7622-i2c"; ++ reg = <0 0x11009000 0 0x90>, ++ <0 0x11000200 0 0x80>; ++ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_LOW>; ++ clock-div = <16>; ++ clocks = <&pericfg CLK_PERI_I2C2_PD>, ++ <&pericfg CLK_PERI_AP_DMA_PD>; ++ clock-names = "main", "dma"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi0: spi@1100a000 { ++ compatible = "mediatek,mt7622-spi"; ++ reg = <0 0x1100a000 0 0x100>; ++ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, ++ <&topckgen CLK_TOP_SPI0_SEL>, ++ <&pericfg CLK_PERI_SPI0_PD>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ thermal: thermal@1100b000 { ++ #thermal-sensor-cells = <1>; ++ compatible = "mediatek,mt7622-thermal"; ++ reg = <0 0x1100b000 0 0x1000>; ++ interrupts = <0 78 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&pericfg CLK_PERI_THERM_PD>, ++ <&pericfg CLK_PERI_AUXADC_PD>; ++ clock-names = "therm", "auxadc"; ++ resets = <&pericfg MT7622_PERI_THERM_SW_RST>; ++ reset-names = "therm"; ++ mediatek,auxadc = <&auxadc>; ++ mediatek,apmixedsys = <&apmixedsys>; ++ nvmem-cells = <&thermal_calibration>; ++ nvmem-cell-names = "calibration-data"; ++ }; ++ ++ btif: serial@1100c000 { ++ compatible = "mediatek,mt7622-btif", ++ "mediatek,mtk-btif"; ++ reg = <0 0x1100c000 0 0x1000>; ++ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&pericfg CLK_PERI_BTIF_PD>; ++ clock-names = "main"; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ status = "disabled"; ++ }; ++ ++ spi1: spi@11016000 { ++ compatible = "mediatek,mt7622-spi"; ++ reg = <0 0x11016000 0 0x100>; ++ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_SYSPLL3_D2>, ++ <&topckgen CLK_TOP_SPI1_SEL>, ++ <&pericfg CLK_PERI_SPI1_PD>; ++ clock-names = "parent-clk", "sel-clk", "spi-clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@11019000 { ++ compatible = "mediatek,mt7622-uart", ++ "mediatek,mt6577-uart"; ++ reg = <0 0x11019000 0 0x400>; ++ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_UART_SEL>, ++ <&pericfg CLK_PERI_UART4_PD>; ++ clock-names = "baud", "bus"; ++ status = "disabled"; ++ }; ++ + ssusbsys: ssusbsys@1a000000 { + compatible = "mediatek,mt7622-ssusbsys", + "syscon"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0217-arm64-dts-mt7622-add-flash-related-device-nodes.patch b/target/linux/mediatek/patches-4.14/0217-arm64-dts-mt7622-add-flash-related-device-nodes.patch new file mode 100644 index 0000000000..fd11853c4a --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0217-arm64-dts-mt7622-add-flash-related-device-nodes.patch @@ -0,0 +1,103 @@ +From 0a84c72d1c606129b8af670cbcc73be4168ab753 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 29 Dec 2017 10:36:37 +0800 +Subject: [PATCH 217/224] arm64: dts: mt7622: add flash related device nodes + +add nodes for NOR flash, parallel Nand flash with error correction code +support. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Cc: RogerCC Lin <rogercc.lin@mediatek.com> +Cc: Guochun Mao <guochun.mao@mediatek.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 21 +++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 34 ++++++++++++++++++++++++++++ + 2 files changed, 55 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index ba6a79caca21..48c5ba472721 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -235,6 +235,10 @@ + }; + }; + ++&bch { ++ status = "disabled"; ++}; ++ + &btif { + status = "okay"; + }; +@@ -257,6 +261,23 @@ + status = "okay"; + }; + ++&nandc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <¶llel_nand_pins>; ++ status = "disabled"; ++}; ++ ++&nor_flash { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_nor_pins>; ++ status = "disabled"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ }; ++}; ++ + &pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pwm7_pins>; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 448cd366995b..d287d75e1a54 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -468,6 +468,40 @@ + status = "disabled"; + }; + ++ nandc: nfi@1100d000 { ++ compatible = "mediatek,mt7622-nfc"; ++ reg = <0 0x1100D000 0 0x1000>; ++ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&pericfg CLK_PERI_NFI_PD>, ++ <&pericfg CLK_PERI_SNFI_PD>; ++ clock-names = "nfi_clk", "pad_clk"; ++ ecc-engine = <&bch>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ bch: ecc@1100e000 { ++ compatible = "mediatek,mt7622-ecc"; ++ reg = <0 0x1100e000 0 0x1000>; ++ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&pericfg CLK_PERI_NFIECC_PD>; ++ clock-names = "nfiecc_clk"; ++ status = "disabled"; ++ }; ++ ++ nor_flash: spi@11014000 { ++ compatible = "mediatek,mt7622-nor", ++ "mediatek,mt8173-nor"; ++ reg = <0 0x11014000 0 0xe0>; ++ clocks = <&pericfg CLK_PERI_FLASH_PD>, ++ <&topckgen CLK_TOP_FLASH_SEL>; ++ clock-names = "spi", "sf"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + spi1: spi@11016000 { + compatible = "mediatek,mt7622-spi"; + reg = <0 0x11016000 0 0x100>; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0218-arm64-dts-mt7622-add-ethernet-device-nodes.patch b/target/linux/mediatek/patches-4.14/0218-arm64-dts-mt7622-add-ethernet-device-nodes.patch new file mode 100644 index 0000000000..82b523c9d1 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0218-arm64-dts-mt7622-add-ethernet-device-nodes.patch @@ -0,0 +1,91 @@ +From 4fbacf244953285ac58cb833060076fafd990588 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 29 Dec 2017 10:45:07 +0800 +Subject: [PATCH 218/224] arm64: dts: mt7622: add ethernet device nodes + +add ethernet device nodes which enable GMAC1 with SGMII interface + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 22 ++++++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 31 ++++++++++++++++++++++++++++ + 2 files changed, 53 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index 48c5ba472721..e2bd93e1b49b 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -249,6 +249,28 @@ + status = "okay"; + }; + ++ð { ++ pinctrl-names = "default"; ++ pinctrl-0 = <ð_pins>; ++ status = "okay"; ++ ++ gmac1: mac@1 { ++ compatible = "mediatek,eth-mac"; ++ reg = <1>; ++ phy-handle = <&phy5>; ++ }; ++ ++ mdio-bus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ phy5: ethernet-phy@5 { ++ reg = <5>; ++ phy-mode = "sgmii"; ++ }; ++ }; ++}; ++ + &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index d287d75e1a54..95f947eb824c 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -550,6 +550,37 @@ + #reset-cells = <1>; + }; + ++ eth: ethernet@1b100000 { ++ compatible = "mediatek,mt7622-eth", ++ "mediatek,mt2701-eth", ++ "syscon"; ++ reg = <0 0x1b100000 0 0x20000>; ++ interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>, ++ <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>, ++ <GIC_SPI 225 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&topckgen CLK_TOP_ETH_SEL>, ++ <ðsys CLK_ETH_ESW_EN>, ++ <ðsys CLK_ETH_GP0_EN>, ++ <ðsys CLK_ETH_GP1_EN>, ++ <ðsys CLK_ETH_GP2_EN>, ++ <&sgmiisys CLK_SGMII_TX250M_EN>, ++ <&sgmiisys CLK_SGMII_RX250M_EN>, ++ <&sgmiisys CLK_SGMII_CDR_REF>, ++ <&sgmiisys CLK_SGMII_CDR_FB>, ++ <&topckgen CLK_TOP_SGMIIPLL>, ++ <&apmixedsys CLK_APMIXED_ETH2PLL>; ++ clock-names = "ethif", "esw", "gp0", "gp1", "gp2", ++ "sgmii_tx250m", "sgmii_rx250m", ++ "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", ++ "eth2pll"; ++ power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; ++ mediatek,ethsys = <ðsys>; ++ mediatek,sgmiisys = <&sgmiisys>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + sgmiisys: sgmiisys@1b128000 { + compatible = "mediatek,mt7622-sgmiisys", + "syscon"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0219-arm64-dts-mt7622-add-PCIe-device-nodes.patch b/target/linux/mediatek/patches-4.14/0219-arm64-dts-mt7622-add-PCIe-device-nodes.patch new file mode 100644 index 0000000000..83ba63ab96 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0219-arm64-dts-mt7622-add-PCIe-device-nodes.patch @@ -0,0 +1,123 @@ +From e84732bd6022dd12839dd34d508eb27428367c24 Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Wed, 20 Dec 2017 15:57:30 +0800 +Subject: [PATCH 219/224] arm64: dts: mt7622: add PCIe device nodes + +This patch adds PCIe support fot MT7622. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 10 ++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 74 ++++++++++++++++++++++++++++ + 2 files changed, 84 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index e2bd93e1b49b..72ef4434bcef 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -54,6 +54,16 @@ + }; + }; + ++&pcie { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie0_pins>; ++ status = "okay"; ++ ++ pcie@0,0 { ++ status = "okay"; ++ }; ++}; ++ + &pio { + /* eMMC is shared pin with parallel NAND */ + emmc_pins_default: emmc-pins-default { +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 95f947eb824c..cc026ebda2f4 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -542,6 +542,80 @@ + #reset-cells = <1>; + }; + ++ pcie: pcie@1a140000 { ++ compatible = "mediatek,mt7622-pcie"; ++ device_type = "pci"; ++ reg = <0 0x1a140000 0 0x1000>, ++ <0 0x1a143000 0 0x1000>, ++ <0 0x1a145000 0 0x1000>; ++ reg-names = "subsys", "port0", "port1"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>, ++ <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&pciesys CLK_PCIE_P0_MAC_EN>, ++ <&pciesys CLK_PCIE_P1_MAC_EN>, ++ <&pciesys CLK_PCIE_P0_AHB_EN>, ++ <&pciesys CLK_PCIE_P0_AHB_EN>, ++ <&pciesys CLK_PCIE_P0_AUX_EN>, ++ <&pciesys CLK_PCIE_P1_AUX_EN>, ++ <&pciesys CLK_PCIE_P0_AXI_EN>, ++ <&pciesys CLK_PCIE_P1_AXI_EN>, ++ <&pciesys CLK_PCIE_P0_OBFF_EN>, ++ <&pciesys CLK_PCIE_P1_OBFF_EN>, ++ <&pciesys CLK_PCIE_P0_PIPE_EN>, ++ <&pciesys CLK_PCIE_P1_PIPE_EN>; ++ clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1", ++ "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1", ++ "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1"; ++ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; ++ bus-range = <0x00 0xff>; ++ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>; ++ status = "disabled"; ++ ++ pcie0: pcie@0,0 { ++ reg = <0x0000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ #interrupt-cells = <1>; ++ ranges; ++ status = "disabled"; ++ ++ num-lanes = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc0 0>, ++ <0 0 0 2 &pcie_intc0 1>, ++ <0 0 0 3 &pcie_intc0 2>, ++ <0 0 0 4 &pcie_intc0 3>; ++ pcie_intc0: interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ }; ++ }; ++ ++ pcie1: pcie@1,0 { ++ reg = <0x0800 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ #interrupt-cells = <1>; ++ ranges; ++ status = "disabled"; ++ ++ num-lanes = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie_intc1 0>, ++ <0 0 0 2 &pcie_intc1 1>, ++ <0 0 0 3 &pcie_intc1 2>, ++ <0 0 0 4 &pcie_intc1 3>; ++ pcie_intc1: interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ }; ++ }; ++ }; ++ + ethsys: syscon@1b000000 { + compatible = "mediatek,mt7622-ethsys", + "syscon"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0220-arm64-dts-mt7622-add-SATA-device-nodes.patch b/target/linux/mediatek/patches-4.14/0220-arm64-dts-mt7622-add-SATA-device-nodes.patch new file mode 100644 index 0000000000..83abf609c9 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0220-arm64-dts-mt7622-add-SATA-device-nodes.patch @@ -0,0 +1,94 @@ +From 0c8d249a70818f4f8e0d5543dc7157dfd8a5265e Mon Sep 17 00:00:00 2001 +From: Ryder Lee <ryder.lee@mediatek.com> +Date: Wed, 20 Dec 2017 16:04:24 +0800 +Subject: [PATCH 220/224] arm64: dts: mt7622: add SATA device nodes + +This patch adds SATA support fot MT7622. + +Signed-off-by: Ryder Lee <ryder.lee@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 8 ++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 40 ++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index 72ef4434bcef..6715ffa5c15e 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -323,6 +323,14 @@ + status = "okay"; + }; + ++&sata { ++ status = "okay"; ++}; ++ ++&sata_phy { ++ status = "okay"; ++}; ++ + &spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spic0_pins>; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index cc026ebda2f4..881bc17f8f0d 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -9,6 +9,7 @@ + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/mt7622-clk.h> ++#include <dt-bindings/phy/phy.h> + #include <dt-bindings/power/mt7622-power.h> + #include <dt-bindings/reset/mt7622-reset.h> + #include <dt-bindings/thermal/thermal.h> +@@ -616,6 +617,45 @@ + }; + }; + ++ sata: sata@1a200000 { ++ compatible = "mediatek,mt7622-ahci", ++ "mediatek,mtk-ahci"; ++ reg = <0 0x1a200000 0 0x1100>; ++ interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "hostc"; ++ clocks = <&pciesys CLK_SATA_AHB_EN>, ++ <&pciesys CLK_SATA_AXI_EN>, ++ <&pciesys CLK_SATA_ASIC_EN>, ++ <&pciesys CLK_SATA_RBC_EN>, ++ <&pciesys CLK_SATA_PM_EN>; ++ clock-names = "ahb", "axi", "asic", "rbc", "pm"; ++ phys = <&sata_port PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ ports-implemented = <0x1>; ++ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>; ++ resets = <&pciesys MT7622_SATA_AXI_BUS_RST>, ++ <&pciesys MT7622_SATA_PHY_SW_RST>, ++ <&pciesys MT7622_SATA_PHY_REG_RST>; ++ reset-names = "axi", "sw", "reg"; ++ mediatek,phy-mode = <&pciesys>; ++ status = "disabled"; ++ }; ++ ++ sata_phy: sata-phy@1a243000 { ++ compatible = "mediatek,generic-tphy-v1"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ sata_port: sata-phy@1a243000 { ++ reg = <0 0x1a243000 0 0x0100>; ++ clocks = <&topckgen CLK_TOP_ETH_500M>; ++ clock-names = "ref"; ++ #phy-cells = <1>; ++ }; ++ }; ++ + ethsys: syscon@1b000000 { + compatible = "mediatek,mt7622-ethsys", + "syscon"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0221-arm64-dts-mt7622-add-usb-device-nodes.patch b/target/linux/mediatek/patches-4.14/0221-arm64-dts-mt7622-add-usb-device-nodes.patch new file mode 100644 index 0000000000..9258093cb2 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0221-arm64-dts-mt7622-add-usb-device-nodes.patch @@ -0,0 +1,126 @@ +From 3e23988f5c9c5d54732eda1e8017409ef223048b Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun <chunfeng.yun@mediatek.com> +Date: Fri, 12 Jan 2018 12:28:31 +0800 +Subject: [PATCH 221/224] arm64: dts: mt7622: add usb device nodes + +add xhci node and usb3 phy nodes + +Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Tested-by: Jumin Li <jumin.li@mediatek.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 28 +++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 51 ++++++++++++++++++++++++++++ + 2 files changed, 79 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index 6715ffa5c15e..cc89e2e3c597 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -52,6 +52,24 @@ + memory { + reg = <0 0x40000000 0 0x3F000000>; + }; ++ ++ 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; ++ }; + }; + + &pcie { +@@ -343,6 +361,16 @@ + status = "okay"; + }; + ++&ssusb { ++ vusb33-supply = <®_3p3v>; ++ vbus-supply = <®_5v>; ++ status = "okay"; ++}; ++ ++&u3phy { ++ status = "okay"; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 881bc17f8f0d..bad1e997359a 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -535,6 +535,57 @@ + #reset-cells = <1>; + }; + ++ ssusb: usb@1a0c0000 { ++ compatible = "mediatek,mt7622-xhci", ++ "mediatek,mtk-xhci"; ++ reg = <0 0x1a0c0000 0 0x01000>, ++ <0 0x1a0c4700 0 0x0100>; ++ reg-names = "mac", "ippc"; ++ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_LOW>; ++ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF1>; ++ clocks = <&ssusbsys CLK_SSUSB_SYS_EN>, ++ <&ssusbsys CLK_SSUSB_REF_EN>, ++ <&ssusbsys CLK_SSUSB_MCU_EN>, ++ <&ssusbsys CLK_SSUSB_DMA_EN>; ++ clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck"; ++ phys = <&u2port0 PHY_TYPE_USB2>, ++ <&u3port0 PHY_TYPE_USB3>, ++ <&u2port1 PHY_TYPE_USB2>; ++ ++ status = "disabled"; ++ }; ++ ++ u3phy: usb-phy@1a0c4000 { ++ compatible = "mediatek,mt7622-u3phy", ++ "mediatek,generic-tphy-v1"; ++ reg = <0 0x1a0c4000 0 0x700>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ u2port0: usb-phy@1a0c4800 { ++ reg = <0 0x1a0c4800 0 0x0100>; ++ #phy-cells = <1>; ++ clocks = <&ssusbsys CLK_SSUSB_U2_PHY_EN>; ++ clock-names = "ref"; ++ }; ++ ++ u3port0: usb-phy@1a0c4900 { ++ reg = <0 0x1a0c4900 0 0x0700>; ++ #phy-cells = <1>; ++ clocks = <&clk25m>; ++ clock-names = "ref"; ++ }; ++ ++ u2port1: usb-phy@1a0c5000 { ++ reg = <0 0x1a0c5000 0 0x0100>; ++ #phy-cells = <1>; ++ clocks = <&ssusbsys CLK_SSUSB_U2_PHY_1P_EN>; ++ clock-names = "ref"; ++ }; ++ }; ++ + pciesys: pciesys@1a100800 { + compatible = "mediatek,mt7622-pciesys", + "syscon"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0222-arm64-dts-mt7622-add-High-Speed-DMA-device-nodes.patch b/target/linux/mediatek/patches-4.14/0222-arm64-dts-mt7622-add-High-Speed-DMA-device-nodes.patch new file mode 100644 index 0000000000..8d22510c8c --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0222-arm64-dts-mt7622-add-High-Speed-DMA-device-nodes.patch @@ -0,0 +1,36 @@ +From c61ef9c4707e38edeafad1bd4d01080d0e0a10da Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 17 Jan 2018 00:52:27 +0800 +Subject: [PATCH 222/224] arm64: dts: mt7622: add High-Speed DMA device nodes + +add High-Speed DMA (HSDMA) nodes + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index bad1e997359a..ffb934b0a097 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -715,6 +715,16 @@ + #reset-cells = <1>; + }; + ++ hsdma: dma-controller@1b007000 { ++ compatible = "mediatek,mt7622-hsdma"; ++ reg = <0 0x1b007000 0 0x1000>; ++ interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <ðsys CLK_ETH_HSDMA_EN>; ++ clock-names = "hsdma"; ++ power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; ++ #dma-cells = <1>; ++ }; ++ + eth: ethernet@1b100000 { + compatible = "mediatek,mt7622-eth", + "mediatek,mt2701-eth", +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0223-arm64-dts-mt7622-add-mmc-related-device-nodes.patch b/target/linux/mediatek/patches-4.14/0223-arm64-dts-mt7622-add-mmc-related-device-nodes.patch new file mode 100644 index 0000000000..c7c437ac28 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0223-arm64-dts-mt7622-add-mmc-related-device-nodes.patch @@ -0,0 +1,207 @@ +From d41d41bfcbd8ad4bcbb1b433f7d5c3b613c58419 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 22 Jan 2018 16:58:36 +0800 +Subject: [PATCH 223/224] arm64: dts: mt7622: add mmc related device nodes + +add mmc device nodes and proper setup for used pins + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Signed-off-by: Jimin Wang <jimin.wang@mediatek.com> +--- + arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 106 +++++++++++++++++++++++++++ + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 20 +++++ + 2 files changed, 126 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +index cc89e2e3c597..45d8655ee423 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -8,6 +8,7 @@ + + /dts-v1/; + #include <dt-bindings/input/input.h> ++#include <dt-bindings/gpio/gpio.h> + + #include "mt7622.dtsi" + #include "mt6380.dtsi" +@@ -53,6 +54,14 @@ + reg = <0 0x40000000 0 0x3F000000>; + }; + ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; +@@ -89,6 +98,23 @@ + function = "emmc", "emmc_rst"; + groups = "emmc"; + }; ++ ++ /* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7", ++ * "NRB","NCLE" pins are used as DAT0,DAT1,DAT2,DAT3,DAT4, ++ * DAT5,DAT6,DAT7,CMD,CLK for eMMC respectively ++ */ ++ conf-cmd-dat { ++ pins = "NDL0", "NDL1", "NDL2", ++ "NDL3", "NDL4", "NDL5", ++ "NDL6", "NDL7", "NRB"; ++ input-enable; ++ bias-pull-up; ++ }; ++ ++ conf-clk { ++ pins = "NCLE"; ++ bias-pull-down; ++ }; + }; + + emmc_pins_uhs: emmc-pins-uhs { +@@ -96,6 +122,21 @@ + function = "emmc"; + groups = "emmc"; + }; ++ ++ conf-cmd-dat { ++ pins = "NDL0", "NDL1", "NDL2", ++ "NDL3", "NDL4", "NDL5", ++ "NDL6", "NDL7", "NRB"; ++ input-enable; ++ drive-strength = <4>; ++ bias-pull-up; ++ }; ++ ++ conf-clk { ++ pins = "NCLE"; ++ drive-strength = <4>; ++ bias-pull-down; ++ }; + }; + + eth_pins: eth-pins { +@@ -194,6 +235,27 @@ + function = "sd"; + groups = "sd_0"; + }; ++ ++ /* "I2S2_OUT, "I2S4_IN"", "I2S3_IN", "I2S2_IN", ++ * "I2S4_OUT", "I2S3_OUT" are used as DAT0, DAT1, ++ * DAT2, DAT3, CMD, CLK for SD respectively. ++ */ ++ conf-cmd-data { ++ pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN", ++ "I2S2_IN","I2S4_OUT"; ++ input-enable; ++ drive-strength = <8>; ++ bias-pull-up; ++ }; ++ conf-clk { ++ pins = "I2S3_OUT"; ++ drive-strength = <12>; ++ bias-pull-down; ++ }; ++ conf-cd { ++ pins = "TXD3"; ++ bias-pull-up; ++ }; + }; + + sd0_pins_uhs: sd0-pins-uhs { +@@ -201,6 +263,18 @@ + function = "sd"; + groups = "sd_0"; + }; ++ ++ conf-cmd-data { ++ pins = "I2S2_OUT", "I2S4_IN", "I2S3_IN", ++ "I2S2_IN","I2S4_OUT"; ++ input-enable; ++ bias-pull-up; ++ }; ++ ++ conf-clk { ++ pins = "I2S3_OUT"; ++ bias-pull-down; ++ }; + }; + + /* Serial NAND is shared pin with SPI-NOR */ +@@ -311,6 +385,38 @@ + status = "okay"; + }; + ++&mmc0 { ++ pinctrl-names = "default", "state_uhs"; ++ pinctrl-0 = <&emmc_pins_default>; ++ pinctrl-1 = <&emmc_pins_uhs>; ++ status = "okay"; ++ bus-width = <8>; ++ max-frequency = <50000000>; ++ cap-mmc-highspeed; ++ mmc-hs200-1_8v; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++ assigned-clocks = <&topckgen CLK_TOP_MSDC30_0_SEL>; ++ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; ++ non-removable; ++}; ++ ++&mmc1 { ++ pinctrl-names = "default", "state_uhs"; ++ pinctrl-0 = <&sd0_pins_default>; ++ pinctrl-1 = <&sd0_pins_uhs>; ++ status = "okay"; ++ bus-width = <4>; ++ max-frequency = <50000000>; ++ cap-sd-highspeed; ++ r_smpl = <1>; ++ cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_3p3v>; ++ assigned-clocks = <&topckgen CLK_TOP_MSDC30_1_SEL>; ++ assigned-clock-parents = <&topckgen CLK_TOP_UNIV48M>; ++}; ++ + &nandc { + pinctrl-names = "default"; + pinctrl-0 = <¶llel_nand_pins>; +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index ffb934b0a097..0f1ebddd6619 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -527,6 +527,26 @@ + status = "disabled"; + }; + ++ mmc0: mmc@11230000 { ++ compatible = "mediatek,mt7622-mmc"; ++ reg = <0 0x11230000 0 0x1000>; ++ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&pericfg CLK_PERI_MSDC30_0_PD>, ++ <&topckgen CLK_TOP_MSDC50_0_SEL>; ++ clock-names = "source", "hclk"; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@11240000 { ++ compatible = "mediatek,mt7622-mmc"; ++ reg = <0 0x11240000 0 0x1000>; ++ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_LOW>; ++ clocks = <&pericfg CLK_PERI_MSDC30_1_PD>, ++ <&topckgen CLK_TOP_AXI_SEL>; ++ clock-names = "source", "hclk"; ++ status = "disabled"; ++ }; ++ + ssusbsys: ssusbsys@1a000000 { + compatible = "mediatek,mt7622-ssusbsys", + "syscon"; +-- +2.11.0 + diff --git a/target/linux/mediatek/patches-4.14/0224-add-mt7622-defconfig-for-testing-these-new-drivers.patch b/target/linux/mediatek/patches-4.14/0224-add-mt7622-defconfig-for-testing-these-new-drivers.patch new file mode 100644 index 0000000000..ba128fcc01 --- /dev/null +++ b/target/linux/mediatek/patches-4.14/0224-add-mt7622-defconfig-for-testing-these-new-drivers.patch @@ -0,0 +1,294 @@ +From 4d4581541ee9bc4b7aee5e75db561a8128f3a8bd Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 1 Dec 2017 10:57:57 +0800 +Subject: [PATCH 224/224] add mt7622 defconfig for testing these new drivers + +--- + arch/arm64/configs/mt7622_rfb1_defconfig | 275 +++++++++++++++++++++++++++++++ + 1 file changed, 275 insertions(+) + create mode 100644 arch/arm64/configs/mt7622_rfb1_defconfig + +diff --git a/arch/arm64/configs/mt7622_rfb1_defconfig b/arch/arm64/configs/mt7622_rfb1_defconfig +new file mode 100644 +index 000000000000..1870c601cc0f +--- /dev/null ++++ b/arch/arm64/configs/mt7622_rfb1_defconfig +@@ -0,0 +1,275 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_DEFAULT_HOSTNAME="(mt7622)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++# CONFIG_CROSS_MEMORY_ATTACH is not set ++CONFIG_NO_HZ_IDLE=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_IRQ_TIME_ACCOUNTING=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++# CONFIG_UTS_NS is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="../prebuilt/bootable/7622_loader/rootfs.cpio.gz" ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_PERF_EVENTS=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_JUMP_LABEL=y ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_PCI=y ++CONFIG_PCI_DEBUG=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_SCHED_MC=y ++CONFIG_NR_CPUS=2 ++CONFIG_PREEMPT=y ++# CONFIG_COMPACTION is not set ++# CONFIG_BOUNCE is not set ++# CONFIG_EFI is not set ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_COMPAT=y ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_ARM_MEDIATEK_CPUFREQ=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_INET=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_IPV6 is not set ++CONFIG_BT=y ++CONFIG_BT_RFCOMM=y ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=y ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=y ++# CONFIG_BT_HS is not set ++# CONFIG_BT_LE is not set ++CONFIG_BT_HCIUART=y ++CONFIG_BT_HCIVHCI=y ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_MTD=y ++# CONFIG_MTD_OF_PARTS is not set ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_MTK=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_MT81xx_NOR=y ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_BLK_DEV is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_ATA=y ++CONFIG_AHCI_MTK=y ++CONFIG_NETDEVICES=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALACRITECH is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_AQUANTIA is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ATHEROS is not set ++# CONFIG_NET_CADENCE is not set ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_BROCADE is not set ++# CONFIG_NET_VENDOR_CAVIUM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++# CONFIG_NET_VENDOR_EXAR is not set ++# CONFIG_NET_VENDOR_HISILICON is not set ++# CONFIG_NET_VENDOR_HP is not set ++# CONFIG_NET_VENDOR_HUAWEI is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MEDIATEK=y ++CONFIG_NET_MEDIATEK_SOC=y ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_REALTEK is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++# CONFIG_NET_VENDOR_RDC is not set ++# CONFIG_NET_VENDOR_ROCKER is not set ++# CONFIG_NET_VENDOR_SAMSUNG is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_NET_VENDOR_SOLARFLARE is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_ICPLUS_PHY=y ++CONFIG_REALTEK_PHY=y ++CONFIG_USB_CATC=y ++CONFIG_USB_KAWETH=y ++CONFIG_USB_PEGASUS=y ++CONFIG_USB_RTL8150=y ++CONFIG_USB_RTL8152=y ++CONFIG_USB_LAN78XX=y ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_CDC_EEM=y ++CONFIG_USB_NET_HUAWEI_CDC_NCM=y ++CONFIG_USB_NET_CDC_MBIM=y ++CONFIG_USB_NET_DM9601=y ++CONFIG_USB_NET_SR9700=y ++CONFIG_USB_NET_SR9800=y ++CONFIG_USB_NET_SMSC75XX=y ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=y ++CONFIG_USB_NET_PLUSB=y ++CONFIG_USB_NET_MCS7830=y ++CONFIG_USB_NET_RNDIS_HOST=y ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_CX82310_ETH=y ++CONFIG_USB_NET_KALMIA=y ++CONFIG_USB_NET_QMI_WWAN=y ++CONFIG_USB_NET_INT51X1=y ++CONFIG_USB_IPHETH=y ++CONFIG_USB_SIERRA_NET=y ++CONFIG_USB_VL600=y ++CONFIG_USB_NET_CH9200=y ++CONFIG_INPUT_EVDEV=y ++CONFIG_INPUT_EVBUG=y ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO_POLLED=y ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_SERIO_LIBPS2=y ++CONFIG_VT_HW_CONSOLE_BINDING=y ++CONFIG_LEGACY_PTY_COUNT=16 ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=3 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=3 ++CONFIG_SERIAL_8250_MT6577=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_DEV_BUS=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MT65XX=y ++CONFIG_I2C_SLAVE=y ++CONFIG_I2C_DEBUG_CORE=y ++CONFIG_I2C_DEBUG_ALGO=y ++CONFIG_I2C_DEBUG_BUS=y ++CONFIG_SPI=y ++CONFIG_SPI_MT65XX=y ++CONFIG_DEBUG_PINCTRL=y ++CONFIG_PINCTRL_MT7622=y ++# CONFIG_PINCTRL_MT8173 is not set ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_POWER_RESET_SYSCON=y ++# CONFIG_HWMON is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_WRITABLE_TRIPS=y ++CONFIG_THERMAL_GOV_FAIR_SHARE=y ++CONFIG_THERMAL_GOV_BANG_BANG=y ++CONFIG_THERMAL_GOV_USER_SPACE=y ++CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y ++CONFIG_CPU_THERMAL=y ++CONFIG_CLOCK_THERMAL=y ++CONFIG_THERMAL_EMULATION=y ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_SYSFS=y ++CONFIG_MEDIATEK_WATCHDOG=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV=y ++CONFIG_MFD_MT6397=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_DEBUG=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=y ++CONFIG_REGULATOR_MT6323=y ++CONFIG_REGULATOR_MT6380=y ++CONFIG_RC_CORE=y ++CONFIG_RC_DEVICES=y ++CONFIG_IR_MTK=y ++CONFIG_MEDIA_SUPPORT=y ++CONFIG_USB=y ++# CONFIG_USB_PCI is not set ++# CONFIG_USB_DEFAULT_PERSIST is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_USB_STORAGE_DEBUG=y ++CONFIG_MMC=y ++CONFIG_MMC_MTK=y ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_USER=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_ACTIVITY=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_MT7622=y ++CONFIG_DMADEVICES=y ++CONFIG_MTK_HSDMA=y ++CONFIG_DMATEST=y ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_MT6797 is not set ++CONFIG_COMMON_CLK_MT7622_ETHSYS=y ++CONFIG_COMMON_CLK_MT7622_HIFSYS=y ++CONFIG_COMMON_CLK_MT7622_AUDSYS=y ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_MTK_PMIC_WRAP=y ++CONFIG_IIO=y ++CONFIG_MEDIATEK_MT6577_AUXADC=y ++CONFIG_PWM=y ++CONFIG_PWM_MEDIATEK=y ++CONFIG_RESET_CONTROLLER=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_MTK_EFUSE=y ++CONFIG_TMPFS=y ++# CONFIG_MISC_FILESYSTEMS is not set ++CONFIG_PRINTK_TIME=y ++CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 ++CONFIG_DYNAMIC_DEBUG=y ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_DEBUG_FS=y ++CONFIG_DEBUG_SECTION_MISMATCH=y ++# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_FTRACE is not set +-- +2.11.0 + |