mediatek: add support for the new MT7623 Arm SoC
authorJohn Crispin <john@openwrt.org>
Mon, 2 Nov 2015 10:18:50 +0000 (10:18 +0000)
committerJohn Crispin <john@openwrt.org>
Mon, 2 Nov 2015 10:18:50 +0000 (10:18 +0000)
the support is still WIP. next steps are to make the pmic and ethernet work.
this is the first commit to make sure nothing gets lost.

Signed-off-by: John Crispin <blogic@openwrt.org>
SVN-Revision: 47354

84 files changed:
target/linux/mediatek/Makefile [new file with mode: 0644]
target/linux/mediatek/base-files.mk [new file with mode: 0644]
target/linux/mediatek/base-files/etc/inittab [new file with mode: 0644]
target/linux/mediatek/base-files/lib/mediatek.sh [new file with mode: 0644]
target/linux/mediatek/base-files/lib/preinit/03_preinit_do_mediatek.sh [new file with mode: 0644]
target/linux/mediatek/config-4.1 [new file with mode: 0644]
target/linux/mediatek/image/Makefile [new file with mode: 0644]
target/linux/mediatek/patches/0001-clk-make-strings-in-parent-name-arrays-const.patch [new file with mode: 0644]
target/linux/mediatek/patches/0002-clk-mediatek-Add-initial-common-clock-support-for-Me.patch [new file with mode: 0644]
target/linux/mediatek/patches/0003-clk-mediatek-Add-reset-controller-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0004-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8135.patch [new file with mode: 0644]
target/linux/mediatek/patches/0005-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8173.patch [new file with mode: 0644]
target/linux/mediatek/patches/0006-soc-mediatek-Add-infracfg-misc-driver-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0007-dt-bindings-soc-Add-documentation-for-the-MediaTek-S.patch [new file with mode: 0644]
target/linux/mediatek/patches/0008-soc-Mediatek-Add-SCPSYS-power-domain-driver.patch [new file with mode: 0644]
target/linux/mediatek/patches/0009-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch [new file with mode: 0644]
target/linux/mediatek/patches/0010-thermal-consistently-use-int-for-temperatures.patch [new file with mode: 0644]
target/linux/mediatek/patches/0011-thermal-trivial-fix-typo-in-comment.patch [new file with mode: 0644]
target/linux/mediatek/patches/0012-thermal-remove-useless-call-to-thermal_zone_device_s.patch [new file with mode: 0644]
target/linux/mediatek/patches/0013-thermal-Use-IS_ENABLED-instead-of-ifdef.patch [new file with mode: 0644]
target/linux/mediatek/patches/0014-thermal-Add-comment-explaining-test-for-critical-tem.patch [new file with mode: 0644]
target/linux/mediatek/patches/0015-thermal-inline-only-once-used-function.patch [new file with mode: 0644]
target/linux/mediatek/patches/0016-thermal-streamline-get_trend-callbacks.patch [new file with mode: 0644]
target/linux/mediatek/patches/0017-thermal-Allow-sensor-ops-to-fail-with-ENOSYS.patch [new file with mode: 0644]
target/linux/mediatek/patches/0018-thermal-of-always-set-sensor-related-callbacks.patch [new file with mode: 0644]
target/linux/mediatek/patches/0019-thermal-Make-struct-thermal_zone_device_ops-const.patch [new file with mode: 0644]
target/linux/mediatek/patches/0020-thermal-thermal-Add-support-for-hardware-tracked-tri.patch [new file with mode: 0644]
target/linux/mediatek/patches/0021-thermal-of-implement-.set_trips-for-device-tree-ther.patch [new file with mode: 0644]
target/linux/mediatek/patches/0022-dt-bindings-thermal-Add-binding-document-for-Mediate.patch [new file with mode: 0644]
target/linux/mediatek/patches/0023-thermal-Add-Mediatek-thermal-controller-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0024-ARM64-dts-mt8173-Add-thermal-auxadc-device-nodes.patch [new file with mode: 0644]
target/linux/mediatek/patches/0025-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch [new file with mode: 0644]
target/linux/mediatek/patches/0026-spi-mediatek-Add-spi-bus-for-Mediatek-MT8173.patch [new file with mode: 0644]
target/linux/mediatek/patches/0027-dt-bindings-pwm-add-Mediatek-display-PWM-bindings.patch [new file with mode: 0644]
target/linux/mediatek/patches/0028-pwm-add-Mediatek-display-PWM-driver-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0029-dt-bindings-Add-I2C-bindings-for-mt65xx-mt81xx.patch [new file with mode: 0644]
target/linux/mediatek/patches/0030-I2C-mediatek-Add-driver-for-MediaTek-I2C-controller.patch [new file with mode: 0644]
target/linux/mediatek/patches/0031-I2C-mediatek-Add-driver-for-MediaTek-MT8173-I2C-cont.patch [new file with mode: 0644]
target/linux/mediatek/patches/0032-dt-bindings-mediatek-Add-MT8173-cpufreq-driver-bindi.patch [new file with mode: 0644]
target/linux/mediatek/patches/0033-cpufreq-mediatek-Add-MT8173-cpufreq-driver.patch [new file with mode: 0644]
target/linux/mediatek/patches/0034-mmc-dt-bindings-add-Mediatek-MMC-bindings.patch [new file with mode: 0644]
target/linux/mediatek/patches/0035-mmc-mediatek-Add-Mediatek-MMC-driver.patch [new file with mode: 0644]
target/linux/mediatek/patches/0036-mmc-mediatek-Add-PM-support-for-MMC-driver.patch [new file with mode: 0644]
target/linux/mediatek/patches/0037-arm64-mediatek-Add-Mediatek-MMC-support-in-defconfig.patch [new file with mode: 0644]
target/linux/mediatek/patches/0038-ARM-multi_v7_defconfig-Enable-Mediatek-MMC-support-m.patch [new file with mode: 0644]
target/linux/mediatek/patches/0039-clocksource-mediatek-Don-t-run-event_handler-if-it-i.patch [new file with mode: 0644]
target/linux/mediatek/patches/0040-clocksource-mediatek-Use-GPT-as-sched-clock-source.patch [new file with mode: 0644]
target/linux/mediatek/patches/0041-arm-mediatek-enable-gpt6-on-boot-up-to-make-arch-tim.patch [new file with mode: 0644]
target/linux/mediatek/patches/0042-ARM-mediatek-add-smp-bringup-code.patch [new file with mode: 0644]
target/linux/mediatek/patches/0043-ARM-dts-mt8127-enable-basic-SMP-bringup-for-mt8127.patch [new file with mode: 0644]
target/linux/mediatek/patches/0044-dt-bindings-Add-usb3.0-phy-binding-for-MT65xx-SoCs.patch [new file with mode: 0644]
target/linux/mediatek/patches/0045-dt-bindings-Add-a-binding-for-Mediatek-xHCI-host-con.patch [new file with mode: 0644]
target/linux/mediatek/patches/0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch [new file with mode: 0644]
target/linux/mediatek/patches/0047-xhci-mediatek-support-MTK-xHCI-host-controller.patch [new file with mode: 0644]
target/linux/mediatek/patches/0048-dt-bindings-mediatek-Modify-pinctrl-bindings-for-mt6.patch [new file with mode: 0644]
target/linux/mediatek/patches/0049-pinctrl-dt-bindings-mt6397-Add-pinfunc-header-file-f.patch [new file with mode: 0644]
target/linux/mediatek/patches/0050-pinctrl-mediatek-data-struct-optimize-and-remove-unu.patch [new file with mode: 0644]
target/linux/mediatek/patches/0051-pinctrl-mediatek-add-mtk_pctrl_spec_pull_set_samereg.patch [new file with mode: 0644]
target/linux/mediatek/patches/0052-pinctrl-mediatek-add-ies-smt-control-to-common-code.patch [new file with mode: 0644]
target/linux/mediatek/patches/0053-pinctrl-mediatek-Add-Pinctrl-GPIO-driver-for-mt6397.patch [new file with mode: 0644]
target/linux/mediatek/patches/0054-pinctrl-mediatek-add-pinctrl-GPIO-EINT-driver-for-mt.patch [new file with mode: 0644]
target/linux/mediatek/patches/0055-mfd-mediatek-Add-GPIO-sub-module-support-into-mfd.patch [new file with mode: 0644]
target/linux/mediatek/patches/0056-ARM-dts-mt8127-add-pinctrl-GPIO-EINT-node-for-mt8127.patch [new file with mode: 0644]
target/linux/mediatek/patches/0057-thermal-oops.patch [new file with mode: 0644]
target/linux/mediatek/patches/0058-dont-disable-clocks.patch [new file with mode: 0644]
target/linux/mediatek/patches/0059-arm-mediatek-basic-mt6323-pmic-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0060-arm-mediatek-select-the-arm-timer-by-default.patch [new file with mode: 0644]
target/linux/mediatek/patches/0061-arm-mediatek-add-mt7623-clock.patch [new file with mode: 0644]
target/linux/mediatek/patches/0062-arm-mediatek-add-mt7623-pinctrl-supoort.patch [new file with mode: 0644]
target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch [new file with mode: 0644]
target/linux/mediatek/patches/0064-arm-mediatek-add-mt7623-pcie-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0065-arm-mediatek-add-mt7623-smp-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0066-arm-mediatek-add-m7623-devicetree.patch [new file with mode: 0644]
target/linux/mediatek/patches/0067-arm-mediatek-add-mt7623-support.patch [new file with mode: 0644]
target/linux/mediatek/patches/0068-SDK_compat.patch [new file with mode: 0644]
target/linux/mediatek/patches/0069-arm-mediatek-add-mt7623-support-to-pmic-wrapper.patch [new file with mode: 0644]
target/linux/mediatek/patches/0070-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch [new file with mode: 0644]
target/linux/mediatek/patches/0071-clk.patch [new file with mode: 0644]
target/linux/mediatek/patches/0072-mfd.patch [new file with mode: 0644]
target/linux/mediatek/patches/0073-clk.patch [new file with mode: 0644]
target/linux/mediatek/patches/0074-dts.patch [new file with mode: 0644]
target/linux/mediatek/patches/0075-sd.patch [new file with mode: 0644]
target/linux/mediatek/patches/0076-reset.patch [new file with mode: 0644]
target/linux/mediatek/profiles/default.mk [new file with mode: 0644]

diff --git a/target/linux/mediatek/Makefile b/target/linux/mediatek/Makefile
new file mode 100644 (file)
index 0000000..d0b266b
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright (c) 2015 OpenWrt.org
+#
+include $(TOPDIR)/rules.mk
+
+ARCH:=arm
+BOARD:=mediatek
+BOARDNAME:=Mediatek Ralink ARM
+FEATURES:=squashfs
+CPU_TYPE:=cortex-a7
+MAINTAINER:=John Crispin <blogic@openwrt.org>
+
+KERNEL_PATCHVER:=4.1
+
+KERNELNAME:=Image dtbs zImage
+
+include $(INCLUDE_DIR)/target.mk
+DEFAULT_PACKAGES += \
+       kmod-leds-gpio kmod-gpio-button-hotplug swconfig
+
+$(eval $(call BuildTarget))
diff --git a/target/linux/mediatek/base-files.mk b/target/linux/mediatek/base-files.mk
new file mode 100644 (file)
index 0000000..fdd2c71
--- /dev/null
@@ -0,0 +1,3 @@
+define Package/base-files/install-target
+       rm -f $(1)/etc/config/network
+endef
diff --git a/target/linux/mediatek/base-files/etc/inittab b/target/linux/mediatek/base-files/etc/inittab
new file mode 100644 (file)
index 0000000..870b3cc
--- /dev/null
@@ -0,0 +1,3 @@
+::sysinit:/etc/init.d/rcS S boot
+::shutdown:/etc/init.d/rcS K shutdown
+ttyS0::askfirst:/bin/ash --login
diff --git a/target/linux/mediatek/base-files/lib/mediatek.sh b/target/linux/mediatek/base-files/lib/mediatek.sh
new file mode 100644 (file)
index 0000000..8466c72
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+
+mediatek_board_detect() {
+       local machine
+       local name
+
+       machine=$(cat /proc/device-tree/model)
+
+       case "$machine" in
+       "MediaTek MT7623 Evaluation Board")
+               name="mt7623_evb"
+               ;;
+       esac
+
+       [ -z "$name" ] && name="unknown"
+
+       [ -e "/tmp/sysinfo/" ] || mkdir -p "/tmp/sysinfo/"
+
+       echo "$name" > /tmp/sysinfo/board_name
+       echo "$machine" > /tmp/sysinfo/model
+}
+
+mediatek_board_name() {
+       local name
+
+       [ -f /tmp/sysinfo/board_name ] && name=$(cat /tmp/sysinfo/board_name)
+       [ -z "$name" ] && name="unknown"
+
+       echo "$name"
+}
diff --git a/target/linux/mediatek/base-files/lib/preinit/03_preinit_do_mediatek.sh b/target/linux/mediatek/base-files/lib/preinit/03_preinit_do_mediatek.sh
new file mode 100644 (file)
index 0000000..9e5a18d
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 The Linux Foundation. All rights reserved.
+#
+
+do_mediatek() {
+       . /lib/mediatek.sh
+
+       mediatek_board_detect
+}
+
+boot_hook_add preinit_main do_mediatek
diff --git a/target/linux/mediatek/config-4.1 b/target/linux/mediatek/config-4.1
new file mode 100644 (file)
index 0000000..5df3c2d
--- /dev/null
@@ -0,0 +1,430 @@
+# CONFIG_AIO is not set
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_APM_EMULATION is not set
+# CONFIG_ARCH_ALPINE is not set
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MEDIATEK=y
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_ARCH_MT7623=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+CONFIG_ARCH_MULTI_V6_V7=y
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARM=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ATAG_DTB_COMPAT is not set
+CONFIG_ARM_CPU_SUSPEND=y
+# CONFIG_ARM_CPU_TOPOLOGY is not set
+# CONFIG_ARM_CRYPTO is not set
+CONFIG_ARM_GIC=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+# CONFIG_ARM_LPAE is not set
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+# CONFIG_ARM_SMMU is not set
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_ARM_UNWIND=y
+CONFIG_ARM_VIRT_EXT=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_AVERAGE=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_BOUNCE=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_CLEANCACHE=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLKSRC_OF=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CMDLINE="earlyprintk console=ttyS0,115200"
+CONFIG_COMMON_CLK=y
+CONFIG_COMPACTION=y
+CONFIG_COREDUMP=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+CONFIG_CRC16=y
+# CONFIG_CRC32_SARWATE is not set
+CONFIG_CRC32_SLICEBY8=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_XZ=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_INCLUDE="debug/8250.S"
+# CONFIG_DEBUG_MT6589_UART0 is not set
+CONFIG_DEBUG_MT8127_UART0=y
+# CONFIG_DEBUG_MT8135_UART3 is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_UART_8250=y
+# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set
+CONFIG_DEBUG_UART_8250_SHIFT=2
+# CONFIG_DEBUG_UART_8250_WORD is not set
+CONFIG_DEBUG_UART_PHYS=0x11004000
+CONFIG_DEBUG_UART_VIRT=0xf1004000
+CONFIG_DEBUG_UNCOMPRESS=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DEVMEM=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+CONFIG_DTC=y
+# CONFIG_DW_DMAC_PCI is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_ELF_CORE=y
+CONFIG_ESW_DOUBLE_VLAN_TAG=y
+CONFIG_FREEZER=y
+CONFIG_GE1_RGMII_AN=y
+# CONFIG_GE1_RGMII_FORCE_1000 is not set
+# CONFIG_GE1_RGMII_NONE is not set
+# CONFIG_GE1_TRGMII_FORCE_2000 is not set
+# CONFIG_GE1_TRGMII_FORCE_2600 is not set
+CONFIG_GE2_INTERNAL_GPHY=y
+# CONFIG_GE2_MII_AN is not set
+# CONFIG_GE2_MII_FORCE_100 is not set
+# CONFIG_GE2_RGMII_AN is not set
+# CONFIG_GE2_RGMII_FORCE_1000 is not set
+# CONFIG_GE2_RVMII_FORCE_100 is not set
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GE_RGMII_INTERNAL_P0_AN=y
+CONFIG_GIGAPHY=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_HAVE_BPF_JIT=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SMP=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_HSU_DMA_PCI is not set
+CONFIG_HWMON=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_SFQ is not set
+CONFIG_HZ_FIXED=0
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MT65XX=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IOMMU_HELPER=y
+# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
+CONFIG_IOMMU_SUPPORT=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_KALLSYMS=y
+CONFIG_LAN_WAN_SUPPORT=y
+# CONFIG_LEDS_REGULATOR is not set
+CONFIG_LIBFDT=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+# CONFIG_LZ4_COMPRESS is not set
+# CONFIG_LZ4_DECOMPRESS is not set
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_MACH_MT6589 is not set
+# CONFIG_MACH_MT6592 is not set
+CONFIG_MACH_MT7623=y
+CONFIG_MACH_MT8127=y
+# CONFIG_MACH_MT8135 is not set
+CONFIG_MAC_TO_GIGAPHY_MODE_ADDR=0x1F
+CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2=0
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MDIO_BOARDINFO=y
+CONFIG_MDIO_GPIO=y
+CONFIG_MEDIATEK_WATCHDOG=y
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MT6323 is not set
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_MTK=y
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PCI is not set
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTK_INFRACFG=y
+CONFIG_MTK_PMIC_WRAP=y
+CONFIG_MTK_SCPSYS=y
+# CONFIG_MTK_SMB_HOOK is not set
+CONFIG_MTK_THERMAL=y
+CONFIG_MTK_TIMER=y
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+# CONFIG_NEON is not set
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NLS=y
+CONFIG_NO_BOOTMEM=y
+CONFIG_NO_HZ=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NR_CPUS=4
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_ADDRESS_PCI=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
+CONFIG_OF_NET=y
+CONFIG_OF_PCI=y
+CONFIG_OF_PCI_IRQ=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OLD_SIGACTION=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PCI=y
+# CONFIG_PCIE_IPROC is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+CONFIG_PCI_MSI=y
+CONFIG_PDMA_NEW=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_MT6397 is not set
+CONFIG_PINCTRL_MT7623=y
+CONFIG_PINCTRL_MT8127=y
+# CONFIG_PINCTRL_MT8135 is not set
+CONFIG_PINCTRL_MTK_COMMON=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMSTB is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+CONFIG_POWER_SUPPLY=y
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_RCU=y
+CONFIG_PRINTK_TIME=y
+CONFIG_RAETH=y
+CONFIG_RAETH_CHECKSUM_OFFLOAD=y
+# CONFIG_RAETH_DVT is not set
+CONFIG_RAETH_GMAC2=y
+# CONFIG_RAETH_HW_LRO is not set
+# CONFIG_RAETH_HW_VLAN_TX is not set
+# CONFIG_RAETH_LRO is not set
+# CONFIG_RAETH_NAPI is not set
+CONFIG_RAETH_QDMA=y
+CONFIG_RAETH_QDMATX_QDMARX=y
+CONFIG_RAETH_SCATTER_GATHER_RX_DMA=y
+# CONFIG_RAETH_SKB_RECYCLE_2K is not set
+# CONFIG_RAETH_SPECIAL_TAG is not set
+# CONFIG_RAETH_TSO is not set
+CONFIG_RA_NAT_NONE=y
+# CONFIG_RA_NETWORK_TASKLET_BH is not set
+CONFIG_RA_NETWORK_WORKQUEUE_BH=y
+# CONFIG_RCU_BOOST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RD_GZIP=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_CMOS is not set
+CONFIG_RT_3052_ESW=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_SCHED_HRTICK=y
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SERIAL_8250_DMA is not set
+CONFIG_SERIAL_8250_MT6577=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MT65XX=y
+CONFIG_SPMI=y
+CONFIG_SRCU=y
+CONFIG_STOP_MACHINE=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_SWCONFIG=y
+CONFIG_SWIOTLB=y
+CONFIG_SWP_EMULATE=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_THERMAL=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_EMULATION is not set
+# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_GOV_STEP_WISE=y
+# CONFIG_THERMAL_GOV_USER_SPACE is not set
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_OF=y
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_STATS=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_UID16=y
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_USB=y
+CONFIG_USB_COMMON=y
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_MT65XX_USB3_PHY=y
+CONFIG_USB_PHY=y
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_MTK=y
+CONFIG_USB_XHCI_PCI=y
+CONFIG_USB_XHCI_PLATFORM=y
+CONFIG_USE_OF=y
+# CONFIG_VDSO is not set
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_WAN_AT_P0=y
+# CONFIG_WAN_AT_P4 is not set
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_XEN is not set
+CONFIG_XPS=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/mediatek/image/Makefile b/target/linux/mediatek/image/Makefile
new file mode 100644 (file)
index 0000000..82525c9
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright (c) 2014 The Linux Foundation. All rights reserved.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+define Image/BuilduImage
+       cat $(LINUX_DIR)/arch/arm/boot/dts/mt7623-evb.dtb >> $(KDIR)/zImage$(1)
+       $(STAGING_DIR_HOST)/bin/lzma e $(KDIR)/zImage$(1) $(KDIR)/zImage$(1).lzma
+       mkimage -A arm -O linux -T kernel -C lzma -a 0x80008000 -e 0x80008000 -n 'MIPS OpenWrt Linux-$(LINUX_VERSION)'  -d $(KDIR)/zImage$(1).lzma $(KDIR)/uImage$(1)
+       $(CP) $(KDIR)/uImage$(1) $(BIN_DIR)/$(IMG_PREFIX)-uImage$(1)
+endef
+
+define Image/BuildKernel
+       $(call Image/BuilduImage)
+ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),)
+       $(call Image/BuilduImage,-initramfs)
+endif
+endef
+
+define Image/Build/squashfs
+       $(call prepare_generic_squashfs,$(KDIR)/root.squashfs)
+endef
+
+define Image/Build
+       $(call Image/Build/$(1),$(1))
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/linux/mediatek/patches/0001-clk-make-strings-in-parent-name-arrays-const.patch b/target/linux/mediatek/patches/0001-clk-make-strings-in-parent-name-arrays-const.patch
new file mode 100644 (file)
index 0000000..3dca509
--- /dev/null
@@ -0,0 +1,100 @@
+From a38e86708141d75c643ffd58865c50a925134e4f Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 23 Apr 2015 10:35:38 +0200
+Subject: [PATCH 01/76] clk: make strings in parent name arrays const
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The clk functions and structs declare the parent_name arrays as
+'const char **parent_names' which means the parent name strings
+are const, but the array itself is not. Use
+'const char * const * parent_names' instead which also makes
+the array const. This allows us to put the parent_name arrays into
+the __initconst section.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
+Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+---
+ drivers/clk/clk-composite.c  |    2 +-
+ drivers/clk/clk-mux.c        |    4 ++--
+ include/linux/clk-provider.h |    8 ++++----
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
+index 956b7e5..077f4c7 100644
+--- a/drivers/clk/clk-composite.c
++++ b/drivers/clk/clk-composite.c
+@@ -188,7 +188,7 @@ static void clk_composite_disable(struct clk_hw *hw)
+ }
+ struct clk *clk_register_composite(struct device *dev, const char *name,
+-                      const char **parent_names, int num_parents,
++                      const char * const *parent_names, int num_parents,
+                       struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+                       struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+                       struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
+index 69a094c..1fa2a8d 100644
+--- a/drivers/clk/clk-mux.c
++++ b/drivers/clk/clk-mux.c
+@@ -114,7 +114,7 @@ const struct clk_ops clk_mux_ro_ops = {
+ EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+-              const char **parent_names, u8 num_parents, unsigned long flags,
++              const char * const *parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u32 mask,
+               u8 clk_mux_flags, u32 *table, spinlock_t *lock)
+ {
+@@ -166,7 +166,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+ EXPORT_SYMBOL_GPL(clk_register_mux_table);
+ struct clk *clk_register_mux(struct device *dev, const char *name,
+-              const char **parent_names, u8 num_parents, unsigned long flags,
++              const char * const *parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_mux_flags, spinlock_t *lock)
+ {
+diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
+index df69531..ec609e5 100644
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -209,7 +209,7 @@ struct clk_ops {
+ struct clk_init_data {
+       const char              *name;
+       const struct clk_ops    *ops;
+-      const char              **parent_names;
++      const char              * const *parent_names;
+       u8                      num_parents;
+       unsigned long           flags;
+ };
+@@ -426,12 +426,12 @@ extern const struct clk_ops clk_mux_ops;
+ extern const struct clk_ops clk_mux_ro_ops;
+ struct clk *clk_register_mux(struct device *dev, const char *name,
+-              const char **parent_names, u8 num_parents, unsigned long flags,
++              const char * const *parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_mux_flags, spinlock_t *lock);
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+-              const char **parent_names, u8 num_parents, unsigned long flags,
++              const char * const *parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u32 mask,
+               u8 clk_mux_flags, u32 *table, spinlock_t *lock);
+@@ -518,7 +518,7 @@ struct clk_composite {
+ };
+ struct clk *clk_register_composite(struct device *dev, const char *name,
+-              const char **parent_names, int num_parents,
++              const char * const *parent_names, int num_parents,
+               struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+               struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+               struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0002-clk-mediatek-Add-initial-common-clock-support-for-Me.patch b/target/linux/mediatek/patches/0002-clk-mediatek-Add-initial-common-clock-support-for-Me.patch
new file mode 100644 (file)
index 0000000..d5f52d1
--- /dev/null
@@ -0,0 +1,977 @@
+From f851b4ea6cae9fd5875036b6d3968375882ce56b Mon Sep 17 00:00:00 2001
+From: James Liao <jamesjj.liao@mediatek.com>
+Date: Thu, 23 Apr 2015 10:35:39 +0200
+Subject: [PATCH 02/76] clk: mediatek: Add initial common clock support for
+ Mediatek SoCs.
+
+This patch adds common clock support for Mediatek SoCs, including plls,
+muxes and clock gates.
+
+Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
+Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/clk/Makefile            |    1 +
+ drivers/clk/mediatek/Makefile   |    1 +
+ drivers/clk/mediatek/clk-gate.c |  137 ++++++++++++++++
+ drivers/clk/mediatek/clk-gate.h |   49 ++++++
+ drivers/clk/mediatek/clk-mtk.c  |  220 ++++++++++++++++++++++++++
+ drivers/clk/mediatek/clk-mtk.h  |  159 +++++++++++++++++++
+ drivers/clk/mediatek/clk-pll.c  |  332 +++++++++++++++++++++++++++++++++++++++
+ 7 files changed, 899 insertions(+)
+ create mode 100644 drivers/clk/mediatek/Makefile
+ create mode 100644 drivers/clk/mediatek/clk-gate.c
+ create mode 100644 drivers/clk/mediatek/clk-gate.h
+ create mode 100644 drivers/clk/mediatek/clk-mtk.c
+ create mode 100644 drivers/clk/mediatek/clk-mtk.h
+ create mode 100644 drivers/clk/mediatek/clk-pll.c
+
+diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
+index 3d00c25..d965b3f 100644
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_ARCH_HI3xxx)            += hisilicon/
+ obj-$(CONFIG_ARCH_HIP04)              += hisilicon/
+ obj-$(CONFIG_ARCH_HIX5HD2)            += hisilicon/
+ obj-$(CONFIG_COMMON_CLK_KEYSTONE)     += keystone/
++obj-$(CONFIG_ARCH_MEDIATEK)           += mediatek/
+ ifeq ($(CONFIG_COMMON_CLK), y)
+ obj-$(CONFIG_ARCH_MMP)                        += mmp/
+ endif
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+new file mode 100644
+index 0000000..c384e97
+--- /dev/null
++++ b/drivers/clk/mediatek/Makefile
+@@ -0,0 +1 @@
++obj-y += clk-mtk.o clk-pll.o clk-gate.o
+diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
+new file mode 100644
+index 0000000..9d77ee3
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-gate.c
+@@ -0,0 +1,137 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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/of.h>
++#include <linux/of_address.h>
++
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/clkdev.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
++{
++      struct mtk_clk_gate *cg = to_clk_gate(hw);
++      u32 val;
++
++      regmap_read(cg->regmap, cg->sta_ofs, &val);
++
++      val &= BIT(cg->bit);
++
++      return val == 0;
++}
++
++static int mtk_cg_bit_is_set(struct clk_hw *hw)
++{
++      struct mtk_clk_gate *cg = to_clk_gate(hw);
++      u32 val;
++
++      regmap_read(cg->regmap, cg->sta_ofs, &val);
++
++      val &= BIT(cg->bit);
++
++      return val != 0;
++}
++
++static void mtk_cg_set_bit(struct clk_hw *hw)
++{
++      struct mtk_clk_gate *cg = to_clk_gate(hw);
++
++      regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
++}
++
++static void mtk_cg_clr_bit(struct clk_hw *hw)
++{
++      struct mtk_clk_gate *cg = to_clk_gate(hw);
++
++      regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
++}
++
++static int mtk_cg_enable(struct clk_hw *hw)
++{
++      mtk_cg_clr_bit(hw);
++
++      return 0;
++}
++
++static void mtk_cg_disable(struct clk_hw *hw)
++{
++      mtk_cg_set_bit(hw);
++}
++
++static int mtk_cg_enable_inv(struct clk_hw *hw)
++{
++      mtk_cg_set_bit(hw);
++
++      return 0;
++}
++
++static void mtk_cg_disable_inv(struct clk_hw *hw)
++{
++      mtk_cg_clr_bit(hw);
++}
++
++const struct clk_ops mtk_clk_gate_ops_setclr = {
++      .is_enabled     = mtk_cg_bit_is_cleared,
++      .enable         = mtk_cg_enable,
++      .disable        = mtk_cg_disable,
++};
++
++const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
++      .is_enabled     = mtk_cg_bit_is_set,
++      .enable         = mtk_cg_enable_inv,
++      .disable        = mtk_cg_disable_inv,
++};
++
++struct clk *mtk_clk_register_gate(
++              const char *name,
++              const char *parent_name,
++              struct regmap *regmap,
++              int set_ofs,
++              int clr_ofs,
++              int sta_ofs,
++              u8 bit,
++              const struct clk_ops *ops)
++{
++      struct mtk_clk_gate *cg;
++      struct clk *clk;
++      struct clk_init_data init;
++
++      cg = kzalloc(sizeof(*cg), GFP_KERNEL);
++      if (!cg)
++              return ERR_PTR(-ENOMEM);
++
++      init.name = name;
++      init.flags = CLK_SET_RATE_PARENT;
++      init.parent_names = parent_name ? &parent_name : NULL;
++      init.num_parents = parent_name ? 1 : 0;
++      init.ops = ops;
++
++      cg->regmap = regmap;
++      cg->set_ofs = set_ofs;
++      cg->clr_ofs = clr_ofs;
++      cg->sta_ofs = sta_ofs;
++      cg->bit = bit;
++
++      cg->hw.init = &init;
++
++      clk = clk_register(NULL, &cg->hw);
++      if (IS_ERR(clk))
++              kfree(cg);
++
++      return clk;
++}
+diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
+new file mode 100644
+index 0000000..6b6780b
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-gate.h
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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 __DRV_CLK_GATE_H
++#define __DRV_CLK_GATE_H
++
++#include <linux/regmap.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++
++struct mtk_clk_gate {
++      struct clk_hw   hw;
++      struct regmap   *regmap;
++      int             set_ofs;
++      int             clr_ofs;
++      int             sta_ofs;
++      u8              bit;
++};
++
++static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
++{
++      return container_of(hw, struct mtk_clk_gate, hw);
++}
++
++extern const struct clk_ops mtk_clk_gate_ops_setclr;
++extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
++
++struct clk *mtk_clk_register_gate(
++              const char *name,
++              const char *parent_name,
++              struct regmap *regmap,
++              int set_ofs,
++              int clr_ofs,
++              int sta_ofs,
++              u8 bit,
++              const struct clk_ops *ops);
++
++#endif /* __DRV_CLK_GATE_H */
+diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
+new file mode 100644
+index 0000000..18444ae
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mtk.c
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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/of.h>
++#include <linux/of_address.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/clkdev.h>
++#include <linux/mfd/syscon.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
++{
++      int i;
++      struct clk_onecell_data *clk_data;
++
++      clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
++      if (!clk_data)
++              return NULL;
++
++      clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
++      if (!clk_data->clks)
++              goto err_out;
++
++      clk_data->clk_num = clk_num;
++
++      for (i = 0; i < clk_num; i++)
++              clk_data->clks[i] = ERR_PTR(-ENOENT);
++
++      return clk_data;
++err_out:
++      kfree(clk_data);
++
++      return NULL;
++}
++
++void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
++              struct clk_onecell_data *clk_data)
++{
++      int i;
++      struct clk *clk;
++
++      for (i = 0; i < num; i++) {
++              const struct mtk_fixed_factor *ff = &clks[i];
++
++              clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
++                              CLK_SET_RATE_PARENT, ff->mult, ff->div);
++
++              if (IS_ERR(clk)) {
++                      pr_err("Failed to register clk %s: %ld\n",
++                                      ff->name, PTR_ERR(clk));
++                      continue;
++              }
++
++              if (clk_data)
++                      clk_data->clks[ff->id] = clk;
++      }
++}
++
++int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
++              int num, struct clk_onecell_data *clk_data)
++{
++      int i;
++      struct clk *clk;
++      struct regmap *regmap;
++
++      if (!clk_data)
++              return -ENOMEM;
++
++      regmap = syscon_node_to_regmap(node);
++      if (IS_ERR(regmap)) {
++              pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
++                              PTR_ERR(regmap));
++              return PTR_ERR(regmap);
++      }
++
++      for (i = 0; i < num; i++) {
++              const struct mtk_gate *gate = &clks[i];
++
++              clk = mtk_clk_register_gate(gate->name, gate->parent_name,
++                              regmap,
++                              gate->regs->set_ofs,
++                              gate->regs->clr_ofs,
++                              gate->regs->sta_ofs,
++                              gate->shift, gate->ops);
++
++              if (IS_ERR(clk)) {
++                      pr_err("Failed to register clk %s: %ld\n",
++                                      gate->name, PTR_ERR(clk));
++                      continue;
++              }
++
++              clk_data->clks[gate->id] = clk;
++      }
++
++      return 0;
++}
++
++struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
++              void __iomem *base, spinlock_t *lock)
++{
++      struct clk *clk;
++      struct clk_mux *mux = NULL;
++      struct clk_gate *gate = NULL;
++      struct clk_divider *div = NULL;
++      struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
++      const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
++      const char * const *parent_names;
++      const char *parent;
++      int num_parents;
++      int ret;
++
++      if (mc->mux_shift >= 0) {
++              mux = kzalloc(sizeof(*mux), GFP_KERNEL);
++              if (!mux)
++                      return ERR_PTR(-ENOMEM);
++
++              mux->reg = base + mc->mux_reg;
++              mux->mask = BIT(mc->mux_width) - 1;
++              mux->shift = mc->mux_shift;
++              mux->lock = lock;
++
++              mux_hw = &mux->hw;
++              mux_ops = &clk_mux_ops;
++
++              parent_names = mc->parent_names;
++              num_parents = mc->num_parents;
++      } else {
++              parent = mc->parent;
++              parent_names = &parent;
++              num_parents = 1;
++      }
++
++      if (mc->gate_shift >= 0) {
++              gate = kzalloc(sizeof(*gate), GFP_KERNEL);
++              if (!gate) {
++                      ret = -ENOMEM;
++                      goto err_out;
++              }
++
++              gate->reg = base + mc->gate_reg;
++              gate->bit_idx = mc->gate_shift;
++              gate->flags = CLK_GATE_SET_TO_DISABLE;
++              gate->lock = lock;
++
++              gate_hw = &gate->hw;
++              gate_ops = &clk_gate_ops;
++      }
++
++      if (mc->divider_shift >= 0) {
++              div = kzalloc(sizeof(*div), GFP_KERNEL);
++              if (!div) {
++                      ret = -ENOMEM;
++                      goto err_out;
++              }
++
++              div->reg = base + mc->divider_reg;
++              div->shift = mc->divider_shift;
++              div->width = mc->divider_width;
++              div->lock = lock;
++
++              div_hw = &div->hw;
++              div_ops = &clk_divider_ops;
++      }
++
++      clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
++              mux_hw, mux_ops,
++              div_hw, div_ops,
++              gate_hw, gate_ops,
++              mc->flags);
++
++      if (IS_ERR(clk)) {
++              kfree(gate);
++              kfree(mux);
++      }
++
++      return clk;
++err_out:
++      kfree(mux);
++
++      return ERR_PTR(ret);
++}
++
++void mtk_clk_register_composites(const struct mtk_composite *mcs,
++              int num, void __iomem *base, spinlock_t *lock,
++              struct clk_onecell_data *clk_data)
++{
++      struct clk *clk;
++      int i;
++
++      for (i = 0; i < num; i++) {
++              const struct mtk_composite *mc = &mcs[i];
++
++              clk = mtk_clk_register_composite(mc, base, lock);
++
++              if (IS_ERR(clk)) {
++                      pr_err("Failed to register clk %s: %ld\n",
++                                      mc->name, PTR_ERR(clk));
++                      continue;
++              }
++
++              if (clk_data)
++                      clk_data->clks[mc->id] = clk;
++      }
++}
+diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
+new file mode 100644
+index 0000000..694fc39
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mtk.h
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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 __DRV_CLK_MTK_H
++#define __DRV_CLK_MTK_H
++
++#include <linux/regmap.h>
++#include <linux/bitops.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++
++#define MAX_MUX_GATE_BIT      31
++#define INVALID_MUX_GATE_BIT  (MAX_MUX_GATE_BIT + 1)
++
++#define MHZ (1000 * 1000)
++
++struct mtk_fixed_factor {
++      int id;
++      const char *name;
++      const char *parent_name;
++      int mult;
++      int div;
++};
++
++#define FACTOR(_id, _name, _parent, _mult, _div) {    \
++              .id = _id,                              \
++              .name = _name,                          \
++              .parent_name = _parent,                 \
++              .mult = _mult,                          \
++              .div = _div,                            \
++      }
++
++extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
++              int num, struct clk_onecell_data *clk_data);
++
++struct mtk_composite {
++      int id;
++      const char *name;
++      const char * const * parent_names;
++      const char *parent;
++      unsigned flags;
++
++      uint32_t mux_reg;
++      uint32_t divider_reg;
++      uint32_t gate_reg;
++
++      signed char mux_shift;
++      signed char mux_width;
++      signed char gate_shift;
++
++      signed char divider_shift;
++      signed char divider_width;
++
++      signed char num_parents;
++};
++
++#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) { \
++              .id = _id,                                              \
++              .name = _name,                                          \
++              .mux_reg = _reg,                                        \
++              .mux_shift = _shift,                                    \
++              .mux_width = _width,                                    \
++              .gate_reg = _reg,                                       \
++              .gate_shift = _gate,                                    \
++              .divider_shift = -1,                                    \
++              .parent_names = _parents,                               \
++              .num_parents = ARRAY_SIZE(_parents),                    \
++              .flags = CLK_SET_RATE_PARENT,                           \
++      }
++
++#define MUX(_id, _name, _parents, _reg, _shift, _width) {             \
++              .id = _id,                                              \
++              .name = _name,                                          \
++              .mux_reg = _reg,                                        \
++              .mux_shift = _shift,                                    \
++              .mux_width = _width,                                    \
++              .gate_shift = -1,                                       \
++              .divider_shift = -1,                                    \
++              .parent_names = _parents,                               \
++              .num_parents = ARRAY_SIZE(_parents),                    \
++              .flags = CLK_SET_RATE_PARENT,                           \
++      }
++
++#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {     \
++              .id = _id,                                              \
++              .parent = _parent,                                      \
++              .name = _name,                                          \
++              .divider_reg = _div_reg,                                \
++              .divider_shift = _div_shift,                            \
++              .divider_width = _div_width,                            \
++              .gate_reg = _gate_reg,                                  \
++              .gate_shift = _gate_shift,                              \
++              .mux_shift = -1,                                        \
++              .flags = 0,                                             \
++      }
++
++struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
++              void __iomem *base, spinlock_t *lock);
++
++void mtk_clk_register_composites(const struct mtk_composite *mcs,
++              int num, void __iomem *base, spinlock_t *lock,
++              struct clk_onecell_data *clk_data);
++
++struct mtk_gate_regs {
++      u32 sta_ofs;
++      u32 clr_ofs;
++      u32 set_ofs;
++};
++
++struct mtk_gate {
++      int id;
++      const char *name;
++      const char *parent_name;
++      const struct mtk_gate_regs *regs;
++      int shift;
++      const struct clk_ops *ops;
++};
++
++int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
++              int num, struct clk_onecell_data *clk_data);
++
++struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
++
++#define HAVE_RST_BAR  BIT(0)
++
++struct mtk_pll_data {
++      int id;
++      const char *name;
++      uint32_t reg;
++      uint32_t pwr_reg;
++      uint32_t en_mask;
++      uint32_t pd_reg;
++      uint32_t tuner_reg;
++      int pd_shift;
++      unsigned int flags;
++      const struct clk_ops *ops;
++      u32 rst_bar_mask;
++      unsigned long fmax;
++      int pcwbits;
++      uint32_t pcw_reg;
++      int pcw_shift;
++};
++
++void __init mtk_clk_register_plls(struct device_node *node,
++              const struct mtk_pll_data *plls, int num_plls,
++              struct clk_onecell_data *clk_data);
++
++#endif /* __DRV_CLK_MTK_H */
+diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
+new file mode 100644
+index 0000000..66154ca
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-pll.c
+@@ -0,0 +1,332 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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/of.h>
++#include <linux/of_address.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/clkdev.h>
++#include <linux/delay.h>
++
++#include "clk-mtk.h"
++
++#define REG_CON0              0
++#define REG_CON1              4
++
++#define CON0_BASE_EN          BIT(0)
++#define CON0_PWR_ON           BIT(0)
++#define CON0_ISO_EN           BIT(1)
++#define CON0_PCW_CHG          BIT(31)
++
++#define AUDPLL_TUNER_EN               BIT(31)
++
++#define POSTDIV_MASK          0x7
++#define INTEGER_BITS          7
++
++/*
++ * MediaTek PLLs are configured through their pcw value. The pcw value describes
++ * a divider in the PLL feedback loop which consists of 7 bits for the integer
++ * part and the remaining bits (if present) for the fractional part. Also they
++ * have a 3 bit power-of-two post divider.
++ */
++
++struct mtk_clk_pll {
++      struct clk_hw   hw;
++      void __iomem    *base_addr;
++      void __iomem    *pd_addr;
++      void __iomem    *pwr_addr;
++      void __iomem    *tuner_addr;
++      void __iomem    *pcw_addr;
++      const struct mtk_pll_data *data;
++};
++
++static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
++{
++      return container_of(hw, struct mtk_clk_pll, hw);
++}
++
++static int mtk_pll_is_prepared(struct clk_hw *hw)
++{
++      struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++
++      return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
++}
++
++static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
++              u32 pcw, int postdiv)
++{
++      int pcwbits = pll->data->pcwbits;
++      int pcwfbits;
++      u64 vco;
++      u8 c = 0;
++
++      /* The fractional part of the PLL divider. */
++      pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
++
++      vco = (u64)fin * pcw;
++
++      if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
++              c = 1;
++
++      vco >>= pcwfbits;
++
++      if (c)
++              vco++;
++
++      return ((unsigned long)vco + postdiv - 1) / postdiv;
++}
++
++static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
++              int postdiv)
++{
++      u32 con1, pd, val;
++      int pll_en;
++
++      /* set postdiv */
++      pd = readl(pll->pd_addr);
++      pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
++      pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
++      writel(pd, pll->pd_addr);
++
++      pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
++
++      /* set pcw */
++      val = readl(pll->pcw_addr);
++
++      val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
++                      pll->data->pcw_shift);
++      val |= pcw << pll->data->pcw_shift;
++      writel(val, pll->pcw_addr);
++
++      con1 = readl(pll->base_addr + REG_CON1);
++
++      if (pll_en)
++              con1 |= CON0_PCW_CHG;
++
++      writel(con1, pll->base_addr + REG_CON1);
++      if (pll->tuner_addr)
++              writel(con1 + 1, pll->tuner_addr);
++
++      if (pll_en)
++              udelay(20);
++}
++
++/*
++ * mtk_pll_calc_values - calculate good values for a given input frequency.
++ * @pll:      The pll
++ * @pcw:      The pcw value (output)
++ * @postdiv:  The post divider (output)
++ * @freq:     The desired target frequency
++ * @fin:      The input frequency
++ *
++ */
++static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
++              u32 freq, u32 fin)
++{
++      unsigned long fmin = 1000 * MHZ;
++      u64 _pcw;
++      u32 val;
++
++      if (freq > pll->data->fmax)
++              freq = pll->data->fmax;
++
++      for (val = 0; val < 4; val++) {
++              *postdiv = 1 << val;
++              if (freq * *postdiv >= fmin)
++                      break;
++      }
++
++      /* _pcw = freq * postdiv / fin * 2^pcwfbits */
++      _pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
++      do_div(_pcw, fin);
++
++      *pcw = (u32)_pcw;
++}
++
++static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
++              unsigned long parent_rate)
++{
++      struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++      u32 pcw = 0;
++      u32 postdiv;
++
++      mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
++      mtk_pll_set_rate_regs(pll, pcw, postdiv);
++
++      return 0;
++}
++
++static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
++              unsigned long parent_rate)
++{
++      struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++      u32 postdiv;
++      u32 pcw;
++
++      postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
++      postdiv = 1 << postdiv;
++
++      pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
++      pcw &= GENMASK(pll->data->pcwbits - 1, 0);
++
++      return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
++}
++
++static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
++              unsigned long *prate)
++{
++      struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++      u32 pcw = 0;
++      int postdiv;
++
++      mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
++
++      return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
++}
++
++static int mtk_pll_prepare(struct clk_hw *hw)
++{
++      struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++      u32 r;
++
++      r = readl(pll->pwr_addr) | CON0_PWR_ON;
++      writel(r, pll->pwr_addr);
++      udelay(1);
++
++      r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
++      writel(r, pll->pwr_addr);
++      udelay(1);
++
++      r = readl(pll->base_addr + REG_CON0);
++      r |= pll->data->en_mask;
++      writel(r, pll->base_addr + REG_CON0);
++
++      if (pll->tuner_addr) {
++              r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
++              writel(r, pll->tuner_addr);
++      }
++
++      udelay(20);
++
++      if (pll->data->flags & HAVE_RST_BAR) {
++              r = readl(pll->base_addr + REG_CON0);
++              r |= pll->data->rst_bar_mask;
++              writel(r, pll->base_addr + REG_CON0);
++      }
++
++      return 0;
++}
++
++static void mtk_pll_unprepare(struct clk_hw *hw)
++{
++      struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
++      u32 r;
++
++      if (pll->data->flags & HAVE_RST_BAR) {
++              r = readl(pll->base_addr + REG_CON0);
++              r &= ~pll->data->rst_bar_mask;
++              writel(r, pll->base_addr + REG_CON0);
++      }
++
++      if (pll->tuner_addr) {
++              r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
++              writel(r, pll->tuner_addr);
++      }
++
++      r = readl(pll->base_addr + REG_CON0);
++      r &= ~CON0_BASE_EN;
++      writel(r, pll->base_addr + REG_CON0);
++
++      r = readl(pll->pwr_addr) | CON0_ISO_EN;
++      writel(r, pll->pwr_addr);
++
++      r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
++      writel(r, pll->pwr_addr);
++}
++
++static const struct clk_ops mtk_pll_ops = {
++      .is_prepared    = mtk_pll_is_prepared,
++      .prepare        = mtk_pll_prepare,
++      .unprepare      = mtk_pll_unprepare,
++      .recalc_rate    = mtk_pll_recalc_rate,
++      .round_rate     = mtk_pll_round_rate,
++      .set_rate       = mtk_pll_set_rate,
++};
++
++static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
++              void __iomem *base)
++{
++      struct mtk_clk_pll *pll;
++      struct clk_init_data init;
++      struct clk *clk;
++      const char *parent_name = "clk26m";
++
++      pll = kzalloc(sizeof(*pll), GFP_KERNEL);
++      if (!pll)
++              return ERR_PTR(-ENOMEM);
++
++      pll->base_addr = base + data->reg;
++      pll->pwr_addr = base + data->pwr_reg;
++      pll->pd_addr = base + data->pd_reg;
++      pll->pcw_addr = base + data->pcw_reg;
++      if (data->tuner_reg)
++              pll->tuner_addr = base + data->tuner_reg;
++      pll->hw.init = &init;
++      pll->data = data;
++
++      init.name = data->name;
++      init.ops = &mtk_pll_ops;
++      init.parent_names = &parent_name;
++      init.num_parents = 1;
++
++      clk = clk_register(NULL, &pll->hw);
++
++      if (IS_ERR(clk))
++              kfree(pll);
++
++      return clk;
++}
++
++void __init mtk_clk_register_plls(struct device_node *node,
++              const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
++{
++      void __iomem *base;
++      int r, i;
++      struct clk *clk;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      for (i = 0; i < num_plls; i++) {
++              const struct mtk_pll_data *pll = &plls[i];
++
++              clk = mtk_clk_register_pll(pll, base);
++
++              if (IS_ERR(clk)) {
++                      pr_err("Failed to register clk %s: %ld\n",
++                                      pll->name, PTR_ERR(clk));
++                      continue;
++              }
++
++              clk_data->clks[pll->id] = clk;
++      }
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++}
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0003-clk-mediatek-Add-reset-controller-support.patch b/target/linux/mediatek/patches/0003-clk-mediatek-Add-reset-controller-support.patch
new file mode 100644 (file)
index 0000000..bb6f64b
--- /dev/null
@@ -0,0 +1,155 @@
+From c91e8490e45c68ea517f70f24568034b7735e8b9 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 23 Apr 2015 10:35:40 +0200
+Subject: [PATCH 03/76] clk: mediatek: Add reset controller support
+
+The pericfg and infracfg units also provide reset lines to several
+other SoC internal units. This adds a function which can be called
+from the pericfg and infracfg initialization functions which will
+register the reset controller using reset_controller_register. The
+reset controller will provide support for resetting the units
+connected to the pericfg and infracfg controller. The units resetted
+by this controller can use the standard reset device tree binding
+to gain access to the reset lines.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
+---
+ drivers/clk/mediatek/Makefile  |    1 +
+ drivers/clk/mediatek/clk-mtk.h |   10 +++++
+ drivers/clk/mediatek/reset.c   |   97 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 108 insertions(+)
+ create mode 100644 drivers/clk/mediatek/reset.c
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index c384e97..0b6f1c3 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1 +1,2 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
++obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
+index 694fc39..61035b9 100644
+--- a/drivers/clk/mediatek/clk-mtk.h
++++ b/drivers/clk/mediatek/clk-mtk.h
+@@ -156,4 +156,14 @@ void __init mtk_clk_register_plls(struct device_node *node,
+               const struct mtk_pll_data *plls, int num_plls,
+               struct clk_onecell_data *clk_data);
++#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/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
+new file mode 100644
+index 0000000..9e9fe4b
+--- /dev/null
++++ b/drivers/clk/mediatek/reset.c
+@@ -0,0 +1,97 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ *
++ * 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/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/reset-controller.h>
++#include <linux/slab.h>
++
++#include "clk-mtk.h"
++
++struct mtk_reset {
++      struct regmap *regmap;
++      int regofs;
++      struct reset_controller_dev rcdev;
++};
++
++static int mtk_reset_assert(struct reset_controller_dev *rcdev,
++                            unsigned long id)
++{
++      struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
++
++      return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
++                      BIT(id % 32), ~0);
++}
++
++static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
++                              unsigned long id)
++{
++      struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
++
++      return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
++                      BIT(id % 32), 0);
++}
++
++static int mtk_reset(struct reset_controller_dev *rcdev,
++                            unsigned long id)
++{
++      int ret;
++
++      ret = mtk_reset_assert(rcdev, id);
++      if (ret)
++              return ret;
++
++      return mtk_reset_deassert(rcdev, id);
++}
++
++static struct reset_control_ops mtk_reset_ops = {
++      .assert = mtk_reset_assert,
++      .deassert = mtk_reset_deassert,
++      .reset = mtk_reset,
++};
++
++void mtk_register_reset_controller(struct device_node *np,
++                      unsigned int num_regs, int regofs)
++{
++      struct mtk_reset *data;
++      int ret;
++      struct regmap *regmap;
++
++      regmap = syscon_node_to_regmap(np);
++      if (IS_ERR(regmap)) {
++              pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
++                              PTR_ERR(regmap));
++              return;
++      }
++
++      data = kzalloc(sizeof(*data), GFP_KERNEL);
++      if (!data)
++              return;
++
++      data->regmap = regmap;
++      data->regofs = regofs;
++      data->rcdev.owner = THIS_MODULE;
++      data->rcdev.nr_resets = num_regs * 32;
++      data->rcdev.ops = &mtk_reset_ops;
++      data->rcdev.of_node = np;
++
++      ret = reset_controller_register(&data->rcdev);
++      if (ret) {
++              pr_err("could not register reset controller: %d\n", ret);
++              kfree(data);
++              return;
++      }
++}
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0004-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8135.patch b/target/linux/mediatek/patches/0004-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8135.patch
new file mode 100644 (file)
index 0000000..8666128
--- /dev/null
@@ -0,0 +1,952 @@
+From 242572135fdb513cba0506415c7e26a0909eb4b5 Mon Sep 17 00:00:00 2001
+From: James Liao <jamesjj.liao@mediatek.com>
+Date: Thu, 23 Apr 2015 10:35:41 +0200
+Subject: [PATCH 04/76] clk: mediatek: Add basic clocks for Mediatek MT8135.
+
+This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs,
+INFRA and PERI clocks.
+
+Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
+Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/clk/mediatek/Makefile                      |    1 +
+ drivers/clk/mediatek/clk-mt8135.c                  |  644 ++++++++++++++++++++
+ include/dt-bindings/clock/mt8135-clk.h             |  194 ++++++
+ .../dt-bindings/reset-controller/mt8135-resets.h   |   64 ++
+ 4 files changed, 903 insertions(+)
+ create mode 100644 drivers/clk/mediatek/clk-mt8135.c
+ create mode 100644 include/dt-bindings/clock/mt8135-clk.h
+ create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 0b6f1c3..12ce576 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,2 +1,3 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
++obj-y += clk-mt8135.o
+diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
+new file mode 100644
+index 0000000..a63435b
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mt8135.c
+@@ -0,0 +1,644 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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/of.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/mfd/syscon.h>
++#include <dt-bindings/clock/mt8135-clk.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++static DEFINE_SPINLOCK(mt8135_clk_lock);
++
++static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
++      FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
++};
++
++static const struct mtk_fixed_factor top_divs[] __initconst = {
++      FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
++      FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
++      FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
++      FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
++
++      FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
++      FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
++      FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
++      FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
++
++      FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
++      FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
++      FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
++      FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
++      FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
++      FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
++
++      FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
++      FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
++      FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
++      FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
++      FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
++      FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
++
++      FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
++
++      FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
++      FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
++
++      FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
++
++      FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
++      FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
++      FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
++
++      FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
++      FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
++
++      FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
++
++      FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1),
++      FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
++      FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
++      FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
++      FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
++
++      FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
++      FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
++      FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
++
++      FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
++      FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1),
++
++      FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1),
++
++      FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
++      FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
++
++      FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
++      FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
++
++      FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
++};
++
++static const char * const axi_parents[] __initconst = {
++      "clk26m",
++      "syspll_d3",
++      "syspll_d4",
++      "syspll_d6",
++      "univpll_d5",
++      "univpll2_d2",
++      "syspll_d3p5"
++};
++
++static const char * const smi_parents[] __initconst = {
++      "clk26m",
++      "clkph_mck",
++      "syspll_d2p5",
++      "syspll_d3",
++      "syspll_d8",
++      "univpll_d5",
++      "univpll1_d2",
++      "univpll1_d6",
++      "mmpll_d3",
++      "mmpll_d4",
++      "mmpll_d5",
++      "mmpll_d6",
++      "mmpll_d7",
++      "vdecpll",
++      "lvdspll"
++};
++
++static const char * const mfg_parents[] __initconst = {
++      "clk26m",
++      "univpll1_d4",
++      "syspll_d2",
++      "syspll_d2p5",
++      "syspll_d3",
++      "univpll_d5",
++      "univpll1_d2",
++      "mmpll_d2",
++      "mmpll_d3",
++      "mmpll_d4",
++      "mmpll_d5",
++      "mmpll_d6",
++      "mmpll_d7"
++};
++
++static const char * const irda_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d8",
++      "univpll1_d6"
++};
++
++static const char * const cam_parents[] __initconst = {
++      "clk26m",
++      "syspll_d3",
++      "syspll_d3p5",
++      "syspll_d4",
++      "univpll_d5",
++      "univpll2_d2",
++      "univpll_d7",
++      "univpll1_d4"
++};
++
++static const char * const aud_intbus_parents[] __initconst = {
++      "clk26m",
++      "syspll_d6",
++      "univpll_d10"
++};
++
++static const char * const jpg_parents[] __initconst = {
++      "clk26m",
++      "syspll_d5",
++      "syspll_d4",
++      "syspll_d3",
++      "univpll_d7",
++      "univpll2_d2",
++      "univpll_d5"
++};
++
++static const char * const disp_parents[] __initconst = {
++      "clk26m",
++      "syspll_d3p5",
++      "syspll_d3",
++      "univpll2_d2",
++      "univpll_d5",
++      "univpll1_d2",
++      "lvdspll",
++      "vdecpll"
++};
++
++static const char * const msdc30_parents[] __initconst = {
++      "clk26m",
++      "syspll_d6",
++      "syspll_d5",
++      "univpll1_d4",
++      "univpll2_d4",
++      "msdcpll"
++};
++
++static const char * const usb20_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d6",
++      "univpll1_d10"
++};
++
++static const char * const venc_parents[] __initconst = {
++      "clk26m",
++      "syspll_d3",
++      "syspll_d8",
++      "univpll_d5",
++      "univpll1_d6",
++      "mmpll_d4",
++      "mmpll_d5",
++      "mmpll_d6"
++};
++
++static const char * const spi_parents[] __initconst = {
++      "clk26m",
++      "syspll_d6",
++      "syspll_d8",
++      "syspll_d10",
++      "univpll1_d6",
++      "univpll1_d8"
++};
++
++static const char * const uart_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d8"
++};
++
++static const char * const mem_parents[] __initconst = {
++      "clk26m",
++      "clkph_mck"
++};
++
++static const char * const camtg_parents[] __initconst = {
++      "clk26m",
++      "univpll_d26",
++      "univpll1_d6",
++      "syspll_d16",
++      "syspll_d8"
++};
++
++static const char * const audio_parents[] __initconst = {
++      "clk26m",
++      "syspll_d24"
++};
++
++static const char * const fix_parents[] __initconst = {
++      "rtc32k",
++      "clk26m",
++      "univpll_d5",
++      "univpll_d7",
++      "univpll1_d2",
++      "univpll1_d4",
++      "univpll1_d6",
++      "univpll1_d8"
++};
++
++static const char * const vdec_parents[] __initconst = {
++      "clk26m",
++      "vdecpll",
++      "clkph_mck",
++      "syspll_d2p5",
++      "syspll_d3",
++      "syspll_d3p5",
++      "syspll_d4",
++      "syspll_d5",
++      "syspll_d6",
++      "syspll_d8",
++      "univpll1_d2",
++      "univpll2_d2",
++      "univpll_d7",
++      "univpll_d10",
++      "univpll2_d4",
++      "lvdspll"
++};
++
++static const char * const ddrphycfg_parents[] __initconst = {
++      "clk26m",
++      "axi_sel",
++      "syspll_d12"
++};
++
++static const char * const dpilvds_parents[] __initconst = {
++      "clk26m",
++      "lvdspll",
++      "lvdspll_d2",
++      "lvdspll_d4",
++      "lvdspll_d8"
++};
++
++static const char * const pmicspi_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d6",
++      "syspll_d8",
++      "syspll_d10",
++      "univpll1_d10",
++      "mempll_mck_d4",
++      "univpll_d26",
++      "syspll_d24"
++};
++
++static const char * const smi_mfg_as_parents[] __initconst = {
++      "clk26m",
++      "smi_sel",
++      "mfg_sel",
++      "mem_sel"
++};
++
++static const char * const gcpu_parents[] __initconst = {
++      "clk26m",
++      "syspll_d4",
++      "univpll_d7",
++      "syspll_d5",
++      "syspll_d6"
++};
++
++static const char * const dpi1_parents[] __initconst = {
++      "clk26m",
++      "tvhdmi_h_ck",
++      "tvhdmi_d2",
++      "tvhdmi_d4"
++};
++
++static const char * const cci_parents[] __initconst = {
++      "clk26m",
++      "mainpll_537p3m",
++      "univpll_d3",
++      "syspll_d2p5",
++      "syspll_d3",
++      "syspll_d5"
++};
++
++static const char * const apll_parents[] __initconst = {
++      "clk26m",
++      "apll_ck",
++      "apll_d4",
++      "apll_d8",
++      "apll_d16",
++      "apll_d24"
++};
++
++static const char * const hdmipll_parents[] __initconst = {
++      "clk26m",
++      "hdmitx_clkdig_cts",
++      "hdmitx_clkdig_d2",
++      "hdmitx_clkdig_d3"
++};
++
++static const struct mtk_composite top_muxes[] __initconst = {
++      /* CLK_CFG_0 */
++      MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
++              0x0140, 0, 3, INVALID_MUX_GATE_BIT),
++      MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
++      MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
++      MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
++      /* CLK_CFG_1 */
++      MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
++      MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
++              0x0144, 8, 2, 15),
++      MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
++      MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
++      /* CLK_CFG_2 */
++      MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
++      MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
++      MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
++      MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
++      /* CLK_CFG_3 */
++      MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
++      /* CLK_CFG_4 */
++      MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
++      MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
++      MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
++      /* CLK_CFG_6 */
++      MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
++      MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
++      MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
++      /* CLK_CFG_7 */
++      MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
++      MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
++      MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
++              0x015c, 16, 2, 23),
++      MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
++      /* CLK_CFG_8 */
++      MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
++      MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
++      MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
++              0x0164, 16, 2, 23),
++      MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
++      /* CLK_CFG_9 */
++      MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
++      MUX_GATE(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
++      MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
++      MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
++};
++
++static const struct mtk_gate_regs infra_cg_regs = {
++      .set_ofs = 0x0040,
++      .clr_ofs = 0x0044,
++      .sta_ofs = 0x0048,
++};
++
++#define GATE_ICG(_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[] __initconst = {
++      GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
++      GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
++      GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
++      GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
++      GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
++      GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
++      GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
++      GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
++      GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
++      GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
++      GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
++      GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
++      GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
++};
++
++static const struct mtk_gate_regs peri0_cg_regs = {
++      .set_ofs = 0x0008,
++      .clr_ofs = 0x0010,
++      .sta_ofs = 0x0018,
++};
++
++static const struct mtk_gate_regs peri1_cg_regs = {
++      .set_ofs = 0x000c,
++      .clr_ofs = 0x0014,
++      .sta_ofs = 0x001c,
++};
++
++#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 const struct mtk_gate peri_gates[] __initconst = {
++      /* PERI0 */
++      GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31),
++      GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30),
++      GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29),
++      GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28),
++      GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27),
++      GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26),
++      GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25),
++      GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24),
++      GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23),
++      GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22),
++      GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21),
++      GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20),
++      GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19),
++      GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18),
++      GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17),
++      GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16),
++      GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15),
++      GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14),
++      GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13),
++      GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
++      GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
++      GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
++      GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
++      GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
++      GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
++      GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
++      GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
++      GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
++      GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
++      GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
++      GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
++      GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
++      /* PERI1 */
++      GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8),
++      GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7),
++      GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6),
++      GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5),
++      GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4),
++      GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3),
++      GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2),
++      GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1),
++      GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0),
++};
++
++static const char * const uart_ck_sel_parents[] __initconst = {
++      "clk26m",
++      "uart_sel",
++};
++
++static const struct mtk_composite peri_clks[] __initconst = {
++      MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
++      MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
++      MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
++      MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
++};
++
++static void __init mtk_topckgen_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++      void __iomem *base;
++      int r;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++
++      mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), 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,
++                      &mt8135_clk_lock, clk_data);
++
++      clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++}
++CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
++
++static void __init mtk_infrasys_init(struct device_node *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);
++
++      clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_register_reset_controller(node, 2, 0x30);
++}
++CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
++
++static void __init mtk_pericfg_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++      int r;
++      void __iomem *base;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
++
++      mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
++                                              clk_data);
++      mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
++                      &mt8135_clk_lock, clk_data);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_register_reset_controller(node, 2, 0);
++}
++CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
++
++#define MT8135_PLL_FMAX               (2000 * MHZ)
++#define CON0_MT8135_RST_BAR   BIT(27)
++
++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
++              .id = _id,                                              \
++              .name = _name,                                          \
++              .reg = _reg,                                            \
++              .pwr_reg = _pwr_reg,                                    \
++              .en_mask = _en_mask,                                    \
++              .flags = _flags,                                        \
++              .rst_bar_mask = CON0_MT8135_RST_BAR,                    \
++              .fmax = MT8135_PLL_FMAX,                                \
++              .pcwbits = _pcwbits,                                    \
++              .pd_reg = _pd_reg,                                      \
++              .pd_shift = _pd_shift,                                  \
++              .tuner_reg = _tuner_reg,                                \
++              .pcw_reg = _pcw_reg,                                    \
++              .pcw_shift = _pcw_shift,                                \
++      }
++
++static const struct mtk_pll_data plls[] = {
++      PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
++      PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
++      PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
++      PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
++      PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
++      PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
++      PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
++      PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8,       0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
++      PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
++      PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c,       0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
++};
++
++static void __init mtk_apmixedsys_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++
++      clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
++      if (!clk_data)
++              return;
++
++      mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
++}
++CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
++              mtk_apmixedsys_init);
+diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
+new file mode 100644
+index 0000000..6dac6c0
+--- /dev/null
++++ b/include/dt-bindings/clock/mt8135-clk.h
+@@ -0,0 +1,194 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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_MT8135_H
++#define _DT_BINDINGS_CLK_MT8135_H
++
++/* TOPCKGEN */
++
++#define CLK_TOP_DSI0_LNTC_DSICLK      1
++#define CLK_TOP_HDMITX_CLKDIG_CTS     2
++#define CLK_TOP_CLKPH_MCK             3
++#define CLK_TOP_CPUM_TCK_IN           4
++#define CLK_TOP_MAINPLL_806M          5
++#define CLK_TOP_MAINPLL_537P3M                6
++#define CLK_TOP_MAINPLL_322P4M                7
++#define CLK_TOP_MAINPLL_230P3M                8
++#define CLK_TOP_UNIVPLL_624M          9
++#define CLK_TOP_UNIVPLL_416M          10
++#define CLK_TOP_UNIVPLL_249P6M                11
++#define CLK_TOP_UNIVPLL_178P3M                12
++#define CLK_TOP_UNIVPLL_48M           13
++#define CLK_TOP_MMPLL_D2              14
++#define CLK_TOP_MMPLL_D3              15
++#define CLK_TOP_MMPLL_D5              16
++#define CLK_TOP_MMPLL_D7              17
++#define CLK_TOP_MMPLL_D4              18
++#define CLK_TOP_MMPLL_D6              19
++#define CLK_TOP_SYSPLL_D2             20
++#define CLK_TOP_SYSPLL_D4             21
++#define CLK_TOP_SYSPLL_D6             22
++#define CLK_TOP_SYSPLL_D8             23
++#define CLK_TOP_SYSPLL_D10            24
++#define CLK_TOP_SYSPLL_D12            25
++#define CLK_TOP_SYSPLL_D16            26
++#define CLK_TOP_SYSPLL_D24            27
++#define CLK_TOP_SYSPLL_D3             28
++#define CLK_TOP_SYSPLL_D2P5           29
++#define CLK_TOP_SYSPLL_D5             30
++#define CLK_TOP_SYSPLL_D3P5           31
++#define CLK_TOP_UNIVPLL1_D2           32
++#define CLK_TOP_UNIVPLL1_D4           33
++#define CLK_TOP_UNIVPLL1_D6           34
++#define CLK_TOP_UNIVPLL1_D8           35
++#define CLK_TOP_UNIVPLL1_D10          36
++#define CLK_TOP_UNIVPLL2_D2           37
++#define CLK_TOP_UNIVPLL2_D4           38
++#define CLK_TOP_UNIVPLL2_D6           39
++#define CLK_TOP_UNIVPLL2_D8           40
++#define CLK_TOP_UNIVPLL_D3            41
++#define CLK_TOP_UNIVPLL_D5            42
++#define CLK_TOP_UNIVPLL_D7            43
++#define CLK_TOP_UNIVPLL_D10           44
++#define CLK_TOP_UNIVPLL_D26           45
++#define CLK_TOP_APLL                  46
++#define CLK_TOP_APLL_D4                       47
++#define CLK_TOP_APLL_D8                       48
++#define CLK_TOP_APLL_D16              49
++#define CLK_TOP_APLL_D24              50
++#define CLK_TOP_LVDSPLL_D2            51
++#define CLK_TOP_LVDSPLL_D4            52
++#define CLK_TOP_LVDSPLL_D8            53
++#define CLK_TOP_LVDSTX_CLKDIG_CT      54
++#define CLK_TOP_VPLL_DPIX             55
++#define CLK_TOP_TVHDMI_H              56
++#define CLK_TOP_HDMITX_CLKDIG_D2      57
++#define CLK_TOP_HDMITX_CLKDIG_D3      58
++#define CLK_TOP_TVHDMI_D2             59
++#define CLK_TOP_TVHDMI_D4             60
++#define CLK_TOP_MEMPLL_MCK_D4         61
++#define CLK_TOP_AXI_SEL                       62
++#define CLK_TOP_SMI_SEL                       63
++#define CLK_TOP_MFG_SEL                       64
++#define CLK_TOP_IRDA_SEL              65
++#define CLK_TOP_CAM_SEL                       66
++#define CLK_TOP_AUD_INTBUS_SEL                67
++#define CLK_TOP_JPG_SEL                       68
++#define CLK_TOP_DISP_SEL              69
++#define CLK_TOP_MSDC30_1_SEL          70
++#define CLK_TOP_MSDC30_2_SEL          71
++#define CLK_TOP_MSDC30_3_SEL          72
++#define CLK_TOP_MSDC30_4_SEL          73
++#define CLK_TOP_USB20_SEL             74
++#define CLK_TOP_VENC_SEL              75
++#define CLK_TOP_SPI_SEL                       76
++#define CLK_TOP_UART_SEL              77
++#define CLK_TOP_MEM_SEL                       78
++#define CLK_TOP_CAMTG_SEL             79
++#define CLK_TOP_AUDIO_SEL             80
++#define CLK_TOP_FIX_SEL                       81
++#define CLK_TOP_VDEC_SEL              82
++#define CLK_TOP_DDRPHYCFG_SEL         83
++#define CLK_TOP_DPILVDS_SEL           84
++#define CLK_TOP_PMICSPI_SEL           85
++#define CLK_TOP_MSDC30_0_SEL          86
++#define CLK_TOP_SMI_MFG_AS_SEL                87
++#define CLK_TOP_GCPU_SEL              88
++#define CLK_TOP_DPI1_SEL              89
++#define CLK_TOP_CCI_SEL                       90
++#define CLK_TOP_APLL_SEL              91
++#define CLK_TOP_HDMIPLL_SEL           92
++#define CLK_TOP_NR_CLK                        93
++
++/* APMIXED_SYS */
++
++#define CLK_APMIXED_ARMPLL1           1
++#define CLK_APMIXED_ARMPLL2           2
++#define CLK_APMIXED_MAINPLL           3
++#define CLK_APMIXED_UNIVPLL           4
++#define CLK_APMIXED_MMPLL             5
++#define CLK_APMIXED_MSDCPLL           6
++#define CLK_APMIXED_TVDPLL            7
++#define CLK_APMIXED_LVDSPLL           8
++#define CLK_APMIXED_AUDPLL            9
++#define CLK_APMIXED_VDECPLL           10
++#define CLK_APMIXED_NR_CLK            11
++
++/* INFRA_SYS */
++
++#define CLK_INFRA_PMIC_WRAP           1
++#define CLK_INFRA_PMICSPI             2
++#define CLK_INFRA_CCIF1_AP_CTRL               3
++#define CLK_INFRA_CCIF0_AP_CTRL               4
++#define CLK_INFRA_KP                  5
++#define CLK_INFRA_CPUM                        6
++#define CLK_INFRA_M4U                 7
++#define CLK_INFRA_MFGAXI              8
++#define CLK_INFRA_DEVAPC              9
++#define CLK_INFRA_AUDIO                       10
++#define CLK_INFRA_MFG_BUS             11
++#define CLK_INFRA_SMI                 12
++#define CLK_INFRA_DBGCLK              13
++#define CLK_INFRA_NR_CLK              14
++
++/* PERI_SYS */
++
++#define CLK_PERI_I2C5                 1
++#define CLK_PERI_I2C4                 2
++#define CLK_PERI_I2C3                 3
++#define CLK_PERI_I2C2                 4
++#define CLK_PERI_I2C1                 5
++#define CLK_PERI_I2C0                 6
++#define CLK_PERI_UART3                        7
++#define CLK_PERI_UART2                        8
++#define CLK_PERI_UART1                        9
++#define CLK_PERI_UART0                        10
++#define CLK_PERI_IRDA                 11
++#define CLK_PERI_NLI                  12
++#define CLK_PERI_MD_HIF                       13
++#define CLK_PERI_AP_HIF                       14
++#define CLK_PERI_MSDC30_3             15
++#define CLK_PERI_MSDC30_2             16
++#define CLK_PERI_MSDC30_1             17
++#define CLK_PERI_MSDC20_2             18
++#define CLK_PERI_MSDC20_1             19
++#define CLK_PERI_AP_DMA                       20
++#define CLK_PERI_USB1                 21
++#define CLK_PERI_USB0                 22
++#define CLK_PERI_PWM                  23
++#define CLK_PERI_PWM7                 24
++#define CLK_PERI_PWM6                 25
++#define CLK_PERI_PWM5                 26
++#define CLK_PERI_PWM4                 27
++#define CLK_PERI_PWM3                 28
++#define CLK_PERI_PWM2                 29
++#define CLK_PERI_PWM1                 30
++#define CLK_PERI_THERM                        31
++#define CLK_PERI_NFI                  32
++#define CLK_PERI_USBSLV                       33
++#define CLK_PERI_USB1_MCU             34
++#define CLK_PERI_USB0_MCU             35
++#define CLK_PERI_GCPU                 36
++#define CLK_PERI_FHCTL                        37
++#define CLK_PERI_SPI1                 38
++#define CLK_PERI_AUXADC                       39
++#define CLK_PERI_PERI_PWRAP           40
++#define CLK_PERI_I2C6                 41
++#define CLK_PERI_UART0_SEL            42
++#define CLK_PERI_UART1_SEL            43
++#define CLK_PERI_UART2_SEL            44
++#define CLK_PERI_UART3_SEL            45
++#define CLK_PERI_NR_CLK                       46
++
++#endif /* _DT_BINDINGS_CLK_MT8135_H */
+diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
+new file mode 100644
+index 0000000..1fb6295
+--- /dev/null
++++ b/include/dt-bindings/reset-controller/mt8135-resets.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * 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_MT8135
++#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
++
++/* INFRACFG resets */
++#define MT8135_INFRA_EMI_REG_RST        0
++#define MT8135_INFRA_DRAMC0_A0_RST      1
++#define MT8135_INFRA_CCIF0_RST          2
++#define MT8135_INFRA_APCIRQ_EINT_RST    3
++#define MT8135_INFRA_APXGPT_RST         4
++#define MT8135_INFRA_SCPSYS_RST         5
++#define MT8135_INFRA_CCIF1_RST          6
++#define MT8135_INFRA_PMIC_WRAP_RST      7
++#define MT8135_INFRA_KP_RST             8
++#define MT8135_INFRA_EMI_RST            32
++#define MT8135_INFRA_DRAMC0_RST         34
++#define MT8135_INFRA_SMI_RST            35
++#define MT8135_INFRA_M4U_RST            36
++
++/*  PERICFG resets */
++#define MT8135_PERI_UART0_SW_RST        0
++#define MT8135_PERI_UART1_SW_RST        1
++#define MT8135_PERI_UART2_SW_RST        2
++#define MT8135_PERI_UART3_SW_RST        3
++#define MT8135_PERI_IRDA_SW_RST         4
++#define MT8135_PERI_PTP_SW_RST          5
++#define MT8135_PERI_AP_HIF_SW_RST       6
++#define MT8135_PERI_GPCU_SW_RST         7
++#define MT8135_PERI_MD_HIF_SW_RST       8
++#define MT8135_PERI_NLI_SW_RST          9
++#define MT8135_PERI_AUXADC_SW_RST       10
++#define MT8135_PERI_DMA_SW_RST          11
++#define MT8135_PERI_NFI_SW_RST          14
++#define MT8135_PERI_PWM_SW_RST          15
++#define MT8135_PERI_THERM_SW_RST        16
++#define MT8135_PERI_MSDC0_SW_RST        17
++#define MT8135_PERI_MSDC1_SW_RST        18
++#define MT8135_PERI_MSDC2_SW_RST        19
++#define MT8135_PERI_MSDC3_SW_RST        20
++#define MT8135_PERI_I2C0_SW_RST         22
++#define MT8135_PERI_I2C1_SW_RST         23
++#define MT8135_PERI_I2C2_SW_RST         24
++#define MT8135_PERI_I2C3_SW_RST         25
++#define MT8135_PERI_I2C4_SW_RST         26
++#define MT8135_PERI_I2C5_SW_RST         27
++#define MT8135_PERI_I2C6_SW_RST         28
++#define MT8135_PERI_USB_SW_RST          29
++#define MT8135_PERI_SPI1_SW_RST         33
++#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
++
++#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0005-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8173.patch b/target/linux/mediatek/patches/0005-clk-mediatek-Add-basic-clocks-for-Mediatek-MT8173.patch
new file mode 100644 (file)
index 0000000..9c0e289
--- /dev/null
@@ -0,0 +1,1179 @@
+From 0efcd47787019284a334186fce134ee475c79211 Mon Sep 17 00:00:00 2001
+From: James Liao <jamesjj.liao@mediatek.com>
+Date: Thu, 23 Apr 2015 10:35:42 +0200
+Subject: [PATCH 05/76] clk: mediatek: Add basic clocks for Mediatek MT8173.
+
+This patch adds basic clocks for MT8173, including TOPCKGEN, PLLs,
+INFRA and PERI clocks.
+
+Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
+Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/clk/mediatek/Makefile                      |    1 +
+ drivers/clk/mediatek/clk-mt8173.c                  |  830 ++++++++++++++++++++
+ include/dt-bindings/clock/mt8173-clk.h             |  235 ++++++
+ .../dt-bindings/reset-controller/mt8173-resets.h   |   63 ++
+ 4 files changed, 1129 insertions(+)
+ create mode 100644 drivers/clk/mediatek/clk-mt8173.c
+ create mode 100644 include/dt-bindings/clock/mt8173-clk.h
+ create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 12ce576..8e4b2a4 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,3 +1,4 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+ obj-y += clk-mt8135.o
++obj-y += clk-mt8173.o
+diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
+new file mode 100644
+index 0000000..357b080
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mt8173.c
+@@ -0,0 +1,830 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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/of.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/mfd/syscon.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++#include <dt-bindings/clock/mt8173-clk.h>
++
++static DEFINE_SPINLOCK(mt8173_clk_lock);
++
++static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
++      FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
++};
++
++static const struct mtk_fixed_factor top_divs[] __initconst = {
++      FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
++      FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
++
++      FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
++      FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
++      FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
++      FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
++
++      FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
++      FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
++
++      FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
++      FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
++      FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
++      FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
++      FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
++
++      FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
++      FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
++      FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
++
++      FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
++      FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
++
++      FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
++      FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
++
++      FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
++      FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
++
++      FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1),
++      FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
++      FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
++      FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
++      FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
++
++      FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
++      FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
++      FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
++
++      FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
++      FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
++
++      FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
++      FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
++      FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
++      FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1),
++      FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
++      FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
++
++      FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
++      FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
++      FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
++      FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
++      FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
++      FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
++      FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
++
++      FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
++      FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
++      FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
++      FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
++      FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
++
++      FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
++      FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
++      FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
++      FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
++
++      FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
++      FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
++
++      FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1),
++      FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
++      FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
++};
++
++static const char * const axi_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d2",
++      "syspll_d5",
++      "syspll1_d4",
++      "univpll_d5",
++      "univpll2_d2",
++      "dmpll_d2",
++      "dmpll_d4"
++};
++
++static const char * const mem_parents[] __initconst = {
++      "clk26m",
++      "dmpll_ck"
++};
++
++static const char * const ddrphycfg_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d8"
++};
++
++static const char * const mm_parents[] __initconst = {
++      "clk26m",
++      "vencpll_d2",
++      "main_h364m",
++      "syspll1_d2",
++      "syspll_d5",
++      "syspll1_d4",
++      "univpll1_d2",
++      "univpll2_d2",
++      "dmpll_d2"
++};
++
++static const char * const pwm_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d4",
++      "univpll3_d2",
++      "univpll1_d4"
++};
++
++static const char * const vdec_parents[] __initconst = {
++      "clk26m",
++      "vcodecpll_ck",
++      "tvdpll_445p5m",
++      "univpll_d3",
++      "vencpll_d2",
++      "syspll_d3",
++      "univpll1_d2",
++      "mmpll_d2",
++      "dmpll_d2",
++      "dmpll_d4"
++};
++
++static const char * const venc_parents[] __initconst = {
++      "clk26m",
++      "vcodecpll_ck",
++      "tvdpll_445p5m",
++      "univpll_d3",
++      "vencpll_d2",
++      "syspll_d3",
++      "univpll1_d2",
++      "univpll2_d2",
++      "dmpll_d2",
++      "dmpll_d4"
++};
++
++static const char * const mfg_parents[] __initconst = {
++      "clk26m",
++      "mmpll_ck",
++      "dmpll_ck",
++      "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[] __initconst = {
++      "clk26m",
++      "univpll_d26",
++      "univpll2_d2",
++      "syspll3_d2",
++      "syspll3_d4",
++      "univpll1_d4"
++};
++
++static const char * const uart_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d8"
++};
++
++static const char * const spi_parents[] __initconst = {
++      "clk26m",
++      "syspll3_d2",
++      "syspll1_d4",
++      "syspll4_d2",
++      "univpll3_d2",
++      "univpll2_d4",
++      "univpll1_d8"
++};
++
++static const char * const usb20_parents[] __initconst = {
++      "clk26m",
++      "univpll1_d8",
++      "univpll3_d4"
++};
++
++static const char * const usb30_parents[] __initconst = {
++      "clk26m",
++      "univpll3_d2",
++      "usb_syspll_125m",
++      "univpll2_d4"
++};
++
++static const char * const msdc50_0_h_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d2",
++      "syspll2_d2",
++      "syspll4_d2",
++      "univpll_d5",
++      "univpll1_d4"
++};
++
++static const char * const msdc50_0_parents[] __initconst = {
++      "clk26m",
++      "msdcpll_ck",
++      "msdcpll_d2",
++      "univpll1_d4",
++      "syspll2_d2",
++      "syspll_d7",
++      "msdcpll_d4",
++      "vencpll_d4",
++      "tvdpll_ck",
++      "univpll_d2",
++      "univpll1_d2",
++      "mmpll_ck",
++      "msdcpll2_ck",
++      "msdcpll2_d2",
++      "msdcpll2_d4"
++};
++
++static const char * const msdc30_1_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d2",
++      "msdcpll_d4",
++      "univpll1_d4",
++      "syspll2_d2",
++      "syspll_d7",
++      "univpll_d7",
++      "vencpll_d4"
++};
++
++static const char * const msdc30_2_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d2",
++      "msdcpll_d4",
++      "univpll1_d4",
++      "syspll2_d2",
++      "syspll_d7",
++      "univpll_d7",
++      "vencpll_d2"
++};
++
++static const char * const msdc30_3_parents[] __initconst = {
++      "clk26m",
++      "msdcpll2_ck",
++      "msdcpll2_d2",
++      "univpll2_d2",
++      "msdcpll2_d4",
++      "msdcpll_d4",
++      "univpll1_d4",
++      "syspll2_d2",
++      "syspll_d7",
++      "univpll_d7",
++      "vencpll_d4",
++      "msdcpll_ck",
++      "msdcpll_d2",
++      "msdcpll_d4"
++};
++
++static const char * const audio_parents[] __initconst = {
++      "clk26m",
++      "syspll3_d4",
++      "syspll4_d4",
++      "syspll1_d16"
++};
++
++static const char * const aud_intbus_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d4",
++      "syspll4_d2",
++      "univpll3_d2",
++      "univpll2_d8",
++      "dmpll_d4",
++      "dmpll_d8"
++};
++
++static const char * const pmicspi_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d8",
++      "syspll3_d4",
++      "syspll1_d16",
++      "univpll3_d4",
++      "univpll_d26",
++      "dmpll_d8",
++      "dmpll_d16"
++};
++
++static const char * const scp_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d2",
++      "univpll_d5",
++      "syspll_d5",
++      "dmpll_d2",
++      "dmpll_d4"
++};
++
++static const char * const atb_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d2",
++      "univpll_d5",
++      "dmpll_d2"
++};
++
++static const char * const venc_lt_parents[] __initconst = {
++      "clk26m",
++      "univpll_d3",
++      "vcodecpll_ck",
++      "tvdpll_445p5m",
++      "vencpll_d2",
++      "syspll_d3",
++      "univpll1_d2",
++      "univpll2_d2",
++      "syspll1_d2",
++      "univpll_d5",
++      "vcodecpll_370p5",
++      "dmpll_ck"
++};
++
++static const char * const dpi0_parents[] __initconst = {
++      "clk26m",
++      "tvdpll_d2",
++      "tvdpll_d4",
++      "clk26m",
++      "clk26m",
++      "tvdpll_d8",
++      "tvdpll_d16"
++};
++
++static const char * const irda_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d4",
++      "syspll2_d4"
++};
++
++static const char * const cci400_parents[] __initconst = {
++      "clk26m",
++      "vencpll_ck",
++      "armca7pll_754m",
++      "armca7pll_502m",
++      "univpll_d2",
++      "syspll_d2",
++      "msdcpll_ck",
++      "dmpll_ck"
++};
++
++static const char * const aud_1_parents[] __initconst = {
++      "clk26m",
++      "apll1_ck",
++      "univpll2_d4",
++      "univpll2_d8"
++};
++
++static const char * const aud_2_parents[] __initconst = {
++      "clk26m",
++      "apll2_ck",
++      "univpll2_d4",
++      "univpll2_d8"
++};
++
++static const char * const mem_mfg_in_parents[] __initconst = {
++      "clk26m",
++      "mmpll_ck",
++      "dmpll_ck",
++      "clk26m"
++};
++
++static const char * const axi_mfg_in_parents[] __initconst = {
++      "clk26m",
++      "axi_sel",
++      "dmpll_d2"
++};
++
++static const char * const scam_parents[] __initconst = {
++      "clk26m",
++      "syspll3_d2",
++      "univpll2_d4",
++      "dmpll_d4"
++};
++
++static const char * const spinfi_ifr_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d8",
++      "univpll3_d4",
++      "syspll4_d2",
++      "univpll2_d4",
++      "univpll3_d2",
++      "syspll1_d4",
++      "univpll1_d4"
++};
++
++static const char * const hdmi_parents[] __initconst = {
++      "clk26m",
++      "hdmitx_dig_cts",
++      "hdmitxpll_d2",
++      "hdmitxpll_d3"
++};
++
++static const char * const dpilvds_parents[] __initconst = {
++      "clk26m",
++      "lvdspll",
++      "lvdspll_d2",
++      "lvdspll_d4",
++      "lvdspll_d8",
++      "fpc_ck"
++};
++
++static const char * const msdc50_2_h_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d2",
++      "syspll2_d2",
++      "syspll4_d2",
++      "univpll_d5",
++      "univpll1_d4"
++};
++
++static const char * const hdcp_parents[] __initconst = {
++      "clk26m",
++      "syspll4_d2",
++      "syspll3_d4",
++      "univpll2_d4"
++};
++
++static const char * const hdcp_24m_parents[] __initconst = {
++      "clk26m",
++      "univpll_d26",
++      "univpll_d52",
++      "univpll2_d8"
++};
++
++static const char * const rtc_parents[] __initconst = {
++      "clkrtc_int",
++      "clkrtc_ext",
++      "clk26m",
++      "univpll3_d8"
++};
++
++static const char * const i2s0_m_ck_parents[] __initconst = {
++      "apll1_div1",
++      "apll2_div1"
++};
++
++static const char * const i2s1_m_ck_parents[] __initconst = {
++      "apll1_div2",
++      "apll2_div2"
++};
++
++static const char * const i2s2_m_ck_parents[] __initconst = {
++      "apll1_div3",
++      "apll2_div3"
++};
++
++static const char * const i2s3_m_ck_parents[] __initconst = {
++      "apll1_div4",
++      "apll2_div4"
++};
++
++static const char * const i2s3_b_ck_parents[] __initconst = {
++      "apll1_div5",
++      "apll2_div5"
++};
++
++static const struct mtk_composite top_muxes[] __initconst = {
++      /* CLK_CFG_0 */
++      MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
++      MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
++      MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
++      MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
++      /* CLK_CFG_1 */
++      MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
++      MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
++      MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
++      MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
++      /* CLK_CFG_2 */
++      MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
++      MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
++      MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
++      MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
++      /* CLK_CFG_3 */
++      MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
++      MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
++      MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
++      MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
++      /* CLK_CFG_4 */
++      MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
++      MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
++      MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
++      MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
++      /* CLK_CFG_5 */
++      MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
++      MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
++      MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
++      MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
++      /* CLK_CFG_6 */
++      MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
++      MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
++      MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
++      MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
++      /* CLK_CFG_7 */
++      MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
++      MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
++      MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
++      MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
++      /* CLK_CFG_12 */
++      MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
++      MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
++      MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
++      /* CLK_CFG_13 */
++      MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
++      MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
++      MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
++      MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
++
++      DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
++      DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
++      DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
++      DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
++      DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
++      DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0),
++
++      DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
++      DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
++      DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
++      DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
++      DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
++      DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4),
++
++      MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
++      MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
++      MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
++      MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
++      MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
++};
++
++static const struct mtk_gate_regs infra_cg_regs = {
++      .set_ofs = 0x0040,
++      .clr_ofs = 0x0044,
++      .sta_ofs = 0x0048,
++};
++
++#define GATE_ICG(_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[] __initconst = {
++      GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
++      GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
++      GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
++      GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
++      GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
++      GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
++      GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
++      GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
++      GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
++      GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
++      GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
++};
++
++static const struct mtk_gate_regs peri0_cg_regs = {
++      .set_ofs = 0x0008,
++      .clr_ofs = 0x0010,
++      .sta_ofs = 0x0018,
++};
++
++static const struct mtk_gate_regs peri1_cg_regs = {
++      .set_ofs = 0x000c,
++      .clr_ofs = 0x0014,
++      .sta_ofs = 0x001c,
++};
++
++#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 const struct mtk_gate peri_gates[] __initconst = {
++      /* PERI0 */
++      GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
++      GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
++      GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2),
++      GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3),
++      GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4),
++      GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5),
++      GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6),
++      GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7),
++      GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8),
++      GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9),
++      GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10),
++      GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11),
++      GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
++      GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
++      GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
++      GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
++      GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
++      GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
++      GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18),
++      GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19),
++      GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20),
++      GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21),
++      GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22),
++      GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23),
++      GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24),
++      GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25),
++      GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26),
++      GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27),
++      GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28),
++      GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29),
++      GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30),
++      GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
++      /* PERI1 */
++      GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0),
++      GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1),
++      GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
++};
++
++static const char * const uart_ck_sel_parents[] __initconst = {
++      "clk26m",
++      "uart_sel",
++};
++
++static const struct mtk_composite peri_clks[] __initconst = {
++      MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
++      MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
++      MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
++      MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
++};
++
++static void __init mtk_topckgen_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++      void __iomem *base;
++      int r;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++
++      mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), 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,
++                      &mt8173_clk_lock, clk_data);
++
++      clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++}
++CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
++
++static void __init mtk_infrasys_init(struct device_node *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);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_register_reset_controller(node, 2, 0x30);
++}
++CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
++
++static void __init mtk_pericfg_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++      int r;
++      void __iomem *base;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
++
++      mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
++                                              clk_data);
++      mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
++                      &mt8173_clk_lock, clk_data);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_register_reset_controller(node, 2, 0);
++}
++CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
++
++#define MT8173_PLL_FMAX               (3000UL * MHZ)
++
++#define CON0_MT8173_RST_BAR   BIT(24)
++
++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
++                      _tuner_reg, _pcw_reg, _pcw_shift) { \
++              .id = _id,                                              \
++              .name = _name,                                          \
++              .reg = _reg,                                            \
++              .pwr_reg = _pwr_reg,                                    \
++              .en_mask = _en_mask,                                    \
++              .flags = _flags,                                        \
++              .rst_bar_mask = CON0_MT8173_RST_BAR,                    \
++              .fmax = MT8173_PLL_FMAX,                                \
++              .pcwbits = _pcwbits,                                    \
++              .pd_reg = _pd_reg,                                      \
++              .pd_shift = _pd_shift,                                  \
++              .tuner_reg = _tuner_reg,                                \
++              .pcw_reg = _pcw_reg,                                    \
++              .pcw_shift = _pcw_shift,                                \
++      }
++
++static const struct mtk_pll_data plls[] = {
++      PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
++      PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
++      PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
++      PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
++      PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
++      PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
++      PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
++      PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
++      PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
++      PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
++      PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
++      PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
++      PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
++      PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
++};
++
++static void __init mtk_apmixedsys_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++
++      clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
++      if (!clk_data)
++              return;
++
++      mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
++
++      clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
++}
++CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
++              mtk_apmixedsys_init);
+diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
+new file mode 100644
+index 0000000..4ad76ed
+--- /dev/null
++++ b/include/dt-bindings/clock/mt8173-clk.h
+@@ -0,0 +1,235 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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_MT8173_H
++#define _DT_BINDINGS_CLK_MT8173_H
++
++/* TOPCKGEN */
++
++#define CLK_TOP_CLKPH_MCK_O           1
++#define CLK_TOP_DPI                   2
++#define CLK_TOP_USB_SYSPLL_125M               3
++#define CLK_TOP_HDMITX_DIG_CTS                4
++#define CLK_TOP_ARMCA7PLL_754M                5
++#define CLK_TOP_ARMCA7PLL_502M                6
++#define CLK_TOP_MAIN_H546M            7
++#define CLK_TOP_MAIN_H364M            8
++#define CLK_TOP_MAIN_H218P4M          9
++#define CLK_TOP_MAIN_H156M            10
++#define CLK_TOP_TVDPLL_445P5M         11
++#define CLK_TOP_TVDPLL_594M           12
++#define CLK_TOP_UNIV_624M             13
++#define CLK_TOP_UNIV_416M             14
++#define CLK_TOP_UNIV_249P6M           15
++#define CLK_TOP_UNIV_178P3M           16
++#define CLK_TOP_UNIV_48M              17
++#define CLK_TOP_CLKRTC_EXT            18
++#define CLK_TOP_CLKRTC_INT            19
++#define CLK_TOP_FPC                   20
++#define CLK_TOP_HDMITXPLL_D2          21
++#define CLK_TOP_HDMITXPLL_D3          22
++#define CLK_TOP_ARMCA7PLL_D2          23
++#define CLK_TOP_ARMCA7PLL_D3          24
++#define CLK_TOP_APLL1                 25
++#define CLK_TOP_APLL2                 26
++#define CLK_TOP_DMPLL                 27
++#define CLK_TOP_DMPLL_D2              28
++#define CLK_TOP_DMPLL_D4              29
++#define CLK_TOP_DMPLL_D8              30
++#define CLK_TOP_DMPLL_D16             31
++#define CLK_TOP_LVDSPLL_D2            32
++#define CLK_TOP_LVDSPLL_D4            33
++#define CLK_TOP_LVDSPLL_D8            34
++#define CLK_TOP_MMPLL                 35
++#define CLK_TOP_MMPLL_D2              36
++#define CLK_TOP_MSDCPLL                       37
++#define CLK_TOP_MSDCPLL_D2            38
++#define CLK_TOP_MSDCPLL_D4            39
++#define CLK_TOP_MSDCPLL2              40
++#define CLK_TOP_MSDCPLL2_D2           41
++#define CLK_TOP_MSDCPLL2_D4           42
++#define CLK_TOP_SYSPLL_D2             43
++#define CLK_TOP_SYSPLL1_D2            44
++#define CLK_TOP_SYSPLL1_D4            45
++#define CLK_TOP_SYSPLL1_D8            46
++#define CLK_TOP_SYSPLL1_D16           47
++#define CLK_TOP_SYSPLL_D3             48
++#define CLK_TOP_SYSPLL2_D2            49
++#define CLK_TOP_SYSPLL2_D4            50
++#define CLK_TOP_SYSPLL_D5             51
++#define CLK_TOP_SYSPLL3_D2            52
++#define CLK_TOP_SYSPLL3_D4            53
++#define CLK_TOP_SYSPLL_D7             54
++#define CLK_TOP_SYSPLL4_D2            55
++#define CLK_TOP_SYSPLL4_D4            56
++#define CLK_TOP_TVDPLL                        57
++#define CLK_TOP_TVDPLL_D2             58
++#define CLK_TOP_TVDPLL_D4             59
++#define CLK_TOP_TVDPLL_D8             60
++#define CLK_TOP_TVDPLL_D16            61
++#define CLK_TOP_UNIVPLL_D2            62
++#define CLK_TOP_UNIVPLL1_D2           63
++#define CLK_TOP_UNIVPLL1_D4           64
++#define CLK_TOP_UNIVPLL1_D8           65
++#define CLK_TOP_UNIVPLL_D3            66
++#define CLK_TOP_UNIVPLL2_D2           67
++#define CLK_TOP_UNIVPLL2_D4           68
++#define CLK_TOP_UNIVPLL2_D8           69
++#define CLK_TOP_UNIVPLL_D5            70
++#define CLK_TOP_UNIVPLL3_D2           71
++#define CLK_TOP_UNIVPLL3_D4           72
++#define CLK_TOP_UNIVPLL3_D8           73
++#define CLK_TOP_UNIVPLL_D7            74
++#define CLK_TOP_UNIVPLL_D26           75
++#define CLK_TOP_UNIVPLL_D52           76
++#define CLK_TOP_VCODECPLL             77
++#define CLK_TOP_VCODECPLL_370P5               78
++#define CLK_TOP_VENCPLL                       79
++#define CLK_TOP_VENCPLL_D2            80
++#define CLK_TOP_VENCPLL_D4            81
++#define CLK_TOP_AXI_SEL                       82
++#define CLK_TOP_MEM_SEL                       83
++#define CLK_TOP_DDRPHYCFG_SEL         84
++#define CLK_TOP_MM_SEL                        85
++#define CLK_TOP_PWM_SEL                       86
++#define CLK_TOP_VDEC_SEL              87
++#define CLK_TOP_VENC_SEL              88
++#define CLK_TOP_MFG_SEL                       89
++#define CLK_TOP_CAMTG_SEL             90
++#define CLK_TOP_UART_SEL              91
++#define CLK_TOP_SPI_SEL                       92
++#define CLK_TOP_USB20_SEL             93
++#define CLK_TOP_USB30_SEL             94
++#define CLK_TOP_MSDC50_0_H_SEL                95
++#define CLK_TOP_MSDC50_0_SEL          96
++#define CLK_TOP_MSDC30_1_SEL          97
++#define CLK_TOP_MSDC30_2_SEL          98
++#define CLK_TOP_MSDC30_3_SEL          99
++#define CLK_TOP_AUDIO_SEL             100
++#define CLK_TOP_AUD_INTBUS_SEL                101
++#define CLK_TOP_PMICSPI_SEL           102
++#define CLK_TOP_SCP_SEL                       103
++#define CLK_TOP_ATB_SEL                       104
++#define CLK_TOP_VENC_LT_SEL           105
++#define CLK_TOP_DPI0_SEL              106
++#define CLK_TOP_IRDA_SEL              107
++#define CLK_TOP_CCI400_SEL            108
++#define CLK_TOP_AUD_1_SEL             109
++#define CLK_TOP_AUD_2_SEL             110
++#define CLK_TOP_MEM_MFG_IN_SEL                111
++#define CLK_TOP_AXI_MFG_IN_SEL                112
++#define CLK_TOP_SCAM_SEL              113
++#define CLK_TOP_SPINFI_IFR_SEL                114
++#define CLK_TOP_HDMI_SEL              115
++#define CLK_TOP_DPILVDS_SEL           116
++#define CLK_TOP_MSDC50_2_H_SEL                117
++#define CLK_TOP_HDCP_SEL              118
++#define CLK_TOP_HDCP_24M_SEL          119
++#define CLK_TOP_RTC_SEL                       120
++#define CLK_TOP_APLL1_DIV0            121
++#define CLK_TOP_APLL1_DIV1            122
++#define CLK_TOP_APLL1_DIV2            123
++#define CLK_TOP_APLL1_DIV3            124
++#define CLK_TOP_APLL1_DIV4            125
++#define CLK_TOP_APLL1_DIV5            126
++#define CLK_TOP_APLL2_DIV0            127
++#define CLK_TOP_APLL2_DIV1            128
++#define CLK_TOP_APLL2_DIV2            129
++#define CLK_TOP_APLL2_DIV3            130
++#define CLK_TOP_APLL2_DIV4            131
++#define CLK_TOP_APLL2_DIV5            132
++#define CLK_TOP_I2S0_M_SEL            133
++#define CLK_TOP_I2S1_M_SEL            134
++#define CLK_TOP_I2S2_M_SEL            135
++#define CLK_TOP_I2S3_M_SEL            136
++#define CLK_TOP_I2S3_B_SEL            137
++#define CLK_TOP_NR_CLK                        138
++
++/* APMIXED_SYS */
++
++#define CLK_APMIXED_ARMCA15PLL        1
++#define CLK_APMIXED_ARMCA7PLL 2
++#define CLK_APMIXED_MAINPLL           3
++#define CLK_APMIXED_UNIVPLL           4
++#define CLK_APMIXED_MMPLL             5
++#define CLK_APMIXED_MSDCPLL           6
++#define CLK_APMIXED_VENCPLL           7
++#define CLK_APMIXED_TVDPLL            8
++#define CLK_APMIXED_MPLL              9
++#define CLK_APMIXED_VCODECPLL         10
++#define CLK_APMIXED_APLL1             11
++#define CLK_APMIXED_APLL2             12
++#define CLK_APMIXED_LVDSPLL           13
++#define CLK_APMIXED_MSDCPLL2          14
++#define CLK_APMIXED_NR_CLK            15
++
++/* INFRA_SYS */
++
++#define CLK_INFRA_DBGCLK              1
++#define CLK_INFRA_SMI                 2
++#define CLK_INFRA_AUDIO                       3
++#define CLK_INFRA_GCE                 4
++#define CLK_INFRA_L2C_SRAM            5
++#define CLK_INFRA_M4U                 6
++#define CLK_INFRA_CPUM                        7
++#define CLK_INFRA_KP                  8
++#define CLK_INFRA_CEC                 9
++#define CLK_INFRA_PMICSPI             10
++#define CLK_INFRA_PMICWRAP            11
++#define CLK_INFRA_NR_CLK              12
++
++/* PERI_SYS */
++
++#define CLK_PERI_NFI                  1
++#define CLK_PERI_THERM                        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_USB0                 11
++#define CLK_PERI_USB1                 12
++#define CLK_PERI_AP_DMA                       13
++#define CLK_PERI_MSDC30_0             14
++#define CLK_PERI_MSDC30_1             15
++#define CLK_PERI_MSDC30_2             16
++#define CLK_PERI_MSDC30_3             17
++#define CLK_PERI_NLI_ARB              18
++#define CLK_PERI_IRDA                 19
++#define CLK_PERI_UART0                        20
++#define CLK_PERI_UART1                        21
++#define CLK_PERI_UART2                        22
++#define CLK_PERI_UART3                        23
++#define CLK_PERI_I2C0                 24
++#define CLK_PERI_I2C1                 25
++#define CLK_PERI_I2C2                 26
++#define CLK_PERI_I2C3                 27
++#define CLK_PERI_I2C4                 28
++#define CLK_PERI_AUXADC                       29
++#define CLK_PERI_SPI0                 30
++#define CLK_PERI_I2C5                 31
++#define CLK_PERI_NFIECC                       32
++#define CLK_PERI_SPI                  33
++#define CLK_PERI_IRRX                 34
++#define CLK_PERI_I2C6                 35
++#define CLK_PERI_UART0_SEL            36
++#define CLK_PERI_UART1_SEL            37
++#define CLK_PERI_UART2_SEL            38
++#define CLK_PERI_UART3_SEL            39
++#define CLK_PERI_NR_CLK                       40
++
++#endif /* _DT_BINDINGS_CLK_MT8173_H */
+diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
+new file mode 100644
+index 0000000..9464b37
+--- /dev/null
++++ b/include/dt-bindings/reset-controller/mt8173-resets.h
+@@ -0,0 +1,63 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * 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_MT8173
++#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
++
++/* INFRACFG resets */
++#define MT8173_INFRA_EMI_REG_RST        0
++#define MT8173_INFRA_DRAMC0_A0_RST      1
++#define MT8173_INFRA_APCIRQ_EINT_RST    3
++#define MT8173_INFRA_APXGPT_RST         4
++#define MT8173_INFRA_SCPSYS_RST         5
++#define MT8173_INFRA_KP_RST             6
++#define MT8173_INFRA_PMIC_WRAP_RST      7
++#define MT8173_INFRA_MPIP_RST           8
++#define MT8173_INFRA_CEC_RST            9
++#define MT8173_INFRA_EMI_RST            32
++#define MT8173_INFRA_DRAMC0_RST         34
++#define MT8173_INFRA_APMIXEDSYS_RST     35
++#define MT8173_INFRA_MIPI_DSI_RST       36
++#define MT8173_INFRA_TRNG_RST           37
++#define MT8173_INFRA_SYSIRQ_RST         38
++#define MT8173_INFRA_MIPI_CSI_RST       39
++#define MT8173_INFRA_GCE_FAXI_RST       40
++#define MT8173_INFRA_MMIOMMURST         47
++
++
++/*  PERICFG resets */
++#define MT8173_PERI_UART0_SW_RST        0
++#define MT8173_PERI_UART1_SW_RST        1
++#define MT8173_PERI_UART2_SW_RST        2
++#define MT8173_PERI_UART3_SW_RST        3
++#define MT8173_PERI_IRRX_SW_RST         4
++#define MT8173_PERI_PWM_SW_RST          8
++#define MT8173_PERI_AUXADC_SW_RST       10
++#define MT8173_PERI_DMA_SW_RST          11
++#define MT8173_PERI_I2C6_SW_RST         13
++#define MT8173_PERI_NFI_SW_RST          14
++#define MT8173_PERI_THERM_SW_RST        16
++#define MT8173_PERI_MSDC2_SW_RST        17
++#define MT8173_PERI_MSDC3_SW_RST        18
++#define MT8173_PERI_MSDC0_SW_RST        19
++#define MT8173_PERI_MSDC1_SW_RST        20
++#define MT8173_PERI_I2C0_SW_RST         22
++#define MT8173_PERI_I2C1_SW_RST         23
++#define MT8173_PERI_I2C2_SW_RST         24
++#define MT8173_PERI_I2C3_SW_RST         25
++#define MT8173_PERI_I2C4_SW_RST         26
++#define MT8173_PERI_HDMI_SW_RST         29
++#define MT8173_PERI_SPI0_SW_RST         33
++
++#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0006-soc-mediatek-Add-infracfg-misc-driver-support.patch b/target/linux/mediatek/patches/0006-soc-mediatek-Add-infracfg-misc-driver-support.patch
new file mode 100644 (file)
index 0000000..f47c193
--- /dev/null
@@ -0,0 +1,179 @@
+From d6d7a7dc1b7db2e3d496bf67b30abc894edbc4bd Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 9 Jun 2015 10:46:59 +0200
+Subject: [PATCH 06/76] soc: mediatek: Add infracfg misc driver support
+
+This adds support for some miscellaneous bits of the infracfg controller.
+The mtk_infracfg_set/clear_bus_protection functions are necessary for
+the scpsys power domain driver to handle the bus protection bits which
+are contained in the infacfg register space.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/soc/mediatek/Kconfig          |    9 ++++
+ drivers/soc/mediatek/Makefile         |    1 +
+ drivers/soc/mediatek/mtk-infracfg.c   |   91 +++++++++++++++++++++++++++++++++
+ include/linux/soc/mediatek/infracfg.h |   26 ++++++++++
+ 4 files changed, 127 insertions(+)
+ create mode 100644 drivers/soc/mediatek/mtk-infracfg.c
+ create mode 100644 include/linux/soc/mediatek/infracfg.h
+
+diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
+index 3c18503..09da41e 100644
+--- a/drivers/soc/mediatek/Kconfig
++++ b/drivers/soc/mediatek/Kconfig
+@@ -1,6 +1,15 @@
+ #
+ # MediaTek SoC drivers
+ #
++config MTK_INFRACFG
++      bool "MediaTek INFRACFG Support"
++      depends on ARCH_MEDIATEK
++      select REGMAP
++      help
++        Say yes here to add support for the MediaTek INFRACFG controller. The
++        INFRACFG controller contains various infrastructure registers not
++        directly associated to any device.
++
+ config MTK_PMIC_WRAP
+       tristate "MediaTek PMIC Wrapper Support"
+       depends on ARCH_MEDIATEK
+diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
+index ecaf4de..3fa940f 100644
+--- a/drivers/soc/mediatek/Makefile
++++ b/drivers/soc/mediatek/Makefile
+@@ -1 +1,2 @@
++obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
+diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
+new file mode 100644
+index 0000000..ca786e0
+--- /dev/null
++++ b/drivers/soc/mediatek/mtk-infracfg.c
+@@ -0,0 +1,91 @@
++/*
++ * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
++ *
++ * 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/export.h>
++#include <linux/jiffies.h>
++#include <linux/regmap.h>
++#include <linux/soc/mediatek/infracfg.h>
++#include <asm/processor.h>
++
++#define INFRA_TOPAXI_PROTECTEN                0x0220
++#define INFRA_TOPAXI_PROTECTSTA1      0x0228
++
++/**
++ * mtk_infracfg_set_bus_protection - enable bus protection
++ * @regmap: The infracfg regmap
++ * @mask: The mask containing the protection bits to be enabled.
++ *
++ * This function enables the bus protection bits for disabled power
++ * domains so that the system does not hanf when some unit accesses the
++ * bus while in power down.
++ */
++int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask)
++{
++      unsigned long expired;
++      u32 val;
++      int ret;
++
++      regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask);
++
++      expired = jiffies + HZ;
++
++      while (1) {
++              ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
++              if (ret)
++                      return ret;
++
++              if ((val & mask) == mask)
++                      break;
++
++              cpu_relax();
++              if (time_after(jiffies, expired))
++                      return -EIO;
++      }
++
++      return 0;
++}
++
++/**
++ * mtk_infracfg_clear_bus_protection - disable bus protection
++ * @regmap: The infracfg regmap
++ * @mask: The mask containing the protection bits to be disabled.
++ *
++ * This function disables the bus protection bits previously enabled with
++ * mtk_infracfg_set_bus_protection.
++ */
++int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask)
++{
++      unsigned long expired;
++      int ret;
++
++      regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
++
++      expired = jiffies + HZ;
++
++      while (1) {
++              u32 val;
++
++              ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
++              if (ret)
++                      return ret;
++
++              if (!(val & mask))
++                      break;
++
++              cpu_relax();
++              if (time_after(jiffies, expired))
++                      return -EIO;
++      }
++
++      return 0;
++}
+diff --git a/include/linux/soc/mediatek/infracfg.h b/include/linux/soc/mediatek/infracfg.h
+new file mode 100644
+index 0000000..a5714e9
+--- /dev/null
++++ b/include/linux/soc/mediatek/infracfg.h
+@@ -0,0 +1,26 @@
++#ifndef __SOC_MEDIATEK_INFRACFG_H
++#define __SOC_MEDIATEK_INFRACFG_H
++
++#define MT8173_TOP_AXI_PROT_EN_MCI_M2         BIT(0)
++#define MT8173_TOP_AXI_PROT_EN_MM_M0          BIT(1)
++#define MT8173_TOP_AXI_PROT_EN_MM_M1          BIT(2)
++#define MT8173_TOP_AXI_PROT_EN_MMAPB_S                BIT(6)
++#define MT8173_TOP_AXI_PROT_EN_L2C_M2         BIT(9)
++#define MT8173_TOP_AXI_PROT_EN_L2SS_SMI               BIT(11)
++#define MT8173_TOP_AXI_PROT_EN_L2SS_ADD               BIT(12)
++#define MT8173_TOP_AXI_PROT_EN_CCI_M2         BIT(13)
++#define MT8173_TOP_AXI_PROT_EN_MFG_S          BIT(14)
++#define MT8173_TOP_AXI_PROT_EN_PERI_M0                BIT(15)
++#define MT8173_TOP_AXI_PROT_EN_PERI_M1                BIT(16)
++#define MT8173_TOP_AXI_PROT_EN_DEBUGSYS               BIT(17)
++#define MT8173_TOP_AXI_PROT_EN_CQ_DMA         BIT(18)
++#define MT8173_TOP_AXI_PROT_EN_GCPU           BIT(19)
++#define MT8173_TOP_AXI_PROT_EN_IOMMU          BIT(20)
++#define MT8173_TOP_AXI_PROT_EN_MFG_M0         BIT(21)
++#define MT8173_TOP_AXI_PROT_EN_MFG_M1         BIT(22)
++#define MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT  BIT(23)
++
++int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
++int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
++
++#endif /* __SOC_MEDIATEK_INFRACFG_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0007-dt-bindings-soc-Add-documentation-for-the-MediaTek-S.patch b/target/linux/mediatek/patches/0007-dt-bindings-soc-Add-documentation-for-the-MediaTek-S.patch
new file mode 100644 (file)
index 0000000..f7bdbd6
--- /dev/null
@@ -0,0 +1,57 @@
+From 06a1fd8a198771abc7c5badcf43a49a715ba4c76 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 9 Jun 2015 10:47:00 +0200
+Subject: [PATCH 07/76] dt-bindings: soc: Add documentation for the MediaTek
+ SCPSYS unit
+
+This adds documentation for the MediaTek SCPSYS unit found in MT8173 SoCs.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ .../devicetree/bindings/soc/mediatek/scpsys.txt    |   34 ++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+
+diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+new file mode 100644
+index 0000000..87f2091
+--- /dev/null
++++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+@@ -0,0 +1,34 @@
++MediaTek SCPSYS
++===============
++
++The System Control Processor System (SCPSYS) has several power management
++related tasks in the system. The tasks include thermal measurement, dynamic
++voltage frequency scaling (DVFS), interrupt filter and lowlevel sleep control.
++The System Power Manager (SPM) inside the SCPSYS is for the MTCMOS power
++domain control.
++
++The driver implements the Generic PM domain bindings described in
++power/power_domain.txt. It provides the power domains defined in
++include/dt-bindings/power/mt8173-power.h.
++
++Required properties:
++- compatible: Must be "mediatek,mt8173-scpsys"
++- #power-domain-cells: Must be 1
++- reg: Address range of the SCPSYS unit
++- infracfg: must contain a phandle to the infracfg controller
++
++Example:
++
++      scpsys: scpsys@10006000 {
++              #power-domain-cells = <1>;
++              compatible = "mediatek,mt8173-scpsys";
++              reg = <0 0x10006000 0 0x1000>;
++              infracfg = <&infracfg>;
++      };
++
++Example consumer:
++
++      afe: mt8173-afe-pcm@11220000 {
++              compatible = "mediatek,mt8173-afe-pcm";
++              power-domains = <&scpsys MT8173_POWER_DOMAIN_AUDIO>;
++      };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0008-soc-Mediatek-Add-SCPSYS-power-domain-driver.patch b/target/linux/mediatek/patches/0008-soc-Mediatek-Add-SCPSYS-power-domain-driver.patch
new file mode 100644 (file)
index 0000000..bbf5ad1
--- /dev/null
@@ -0,0 +1,573 @@
+From 04e2e2a895a95dc9e75403c2e8ea190dce9dc387 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Tue, 9 Jun 2015 10:47:01 +0200
+Subject: [PATCH 08/76] soc: Mediatek: Add SCPSYS power domain driver
+
+This adds a power domain driver for the Mediatek SCPSYS unit.
+
+The System Control Processor System (SCPSYS) has several power
+management related tasks in the system. The tasks include thermal
+measurement, dynamic voltage frequency scaling (DVFS), interrupt
+filter and lowlevel sleep control. The System Power Manager (SPM)
+inside the SCPSYS is for the MTCMOS power domain control.
+
+For now this driver only adds power domain support, the more
+advanced features are not yet supported. The driver implements
+the generic PM domain device tree bindings, the first user will
+most likely be the Mediatek AFE audio driver.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/soc/mediatek/Kconfig             |    9 +
+ drivers/soc/mediatek/Makefile            |    1 +
+ drivers/soc/mediatek/mtk-scpsys.c        |  490 ++++++++++++++++++++++++++++++
+ include/dt-bindings/power/mt8173-power.h |   15 +
+ 4 files changed, 515 insertions(+)
+ create mode 100644 drivers/soc/mediatek/mtk-scpsys.c
+ create mode 100644 include/dt-bindings/power/mt8173-power.h
+
+diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
+index 09da41e..2dc5d90 100644
+--- a/drivers/soc/mediatek/Kconfig
++++ b/drivers/soc/mediatek/Kconfig
+@@ -19,3 +19,12 @@ config MTK_PMIC_WRAP
+         Say yes here to add support for MediaTek PMIC Wrapper found
+         on different MediaTek SoCs. The PMIC wrapper is a proprietary
+         hardware to connect the PMIC.
++
++config MTK_SCPSYS
++      bool "MediaTek SCPSYS Support"
++      depends on ARCH_MEDIATEK || COMPILE_TEST
++      select REGMAP
++      select MTK_INFRACFG
++      help
++        Say yes here to add support for the MediaTek SCPSYS power domain
++        driver.
+diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
+index 3fa940f..12998b0 100644
+--- a/drivers/soc/mediatek/Makefile
++++ b/drivers/soc/mediatek/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
++obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
+diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
+new file mode 100644
+index 0000000..b9eed37
+--- /dev/null
++++ b/drivers/soc/mediatek/mtk-scpsys.c
+@@ -0,0 +1,490 @@
++/*
++ * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de>
++ *
++ * 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/io.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/pm_domain.h>
++#include <linux/regmap.h>
++#include <linux/soc/mediatek/infracfg.h>
++#include <dt-bindings/power/mt8173-power.h>
++
++#define SPM_VDE_PWR_CON                       0x0210
++#define SPM_MFG_PWR_CON                       0x0214
++#define SPM_VEN_PWR_CON                       0x0230
++#define SPM_ISP_PWR_CON                       0x0238
++#define SPM_DIS_PWR_CON                       0x023c
++#define SPM_VEN2_PWR_CON              0x0298
++#define SPM_AUDIO_PWR_CON             0x029c
++#define SPM_MFG_2D_PWR_CON            0x02c0
++#define SPM_MFG_ASYNC_PWR_CON         0x02c4
++#define SPM_USB_PWR_CON                       0x02cc
++#define SPM_PWR_STATUS                        0x060c
++#define SPM_PWR_STATUS_2ND            0x0610
++
++#define PWR_RST_B_BIT                 BIT(0)
++#define PWR_ISO_BIT                   BIT(1)
++#define PWR_ON_BIT                    BIT(2)
++#define PWR_ON_2ND_BIT                        BIT(3)
++#define PWR_CLK_DIS_BIT                       BIT(4)
++
++#define PWR_STATUS_DISP                       BIT(3)
++#define PWR_STATUS_MFG                        BIT(4)
++#define PWR_STATUS_ISP                        BIT(5)
++#define PWR_STATUS_VDEC                       BIT(7)
++#define PWR_STATUS_VENC_LT            BIT(20)
++#define PWR_STATUS_VENC                       BIT(21)
++#define PWR_STATUS_MFG_2D             BIT(22)
++#define PWR_STATUS_MFG_ASYNC          BIT(23)
++#define PWR_STATUS_AUDIO              BIT(24)
++#define PWR_STATUS_USB                        BIT(25)
++
++enum clk_id {
++      MT8173_CLK_NONE,
++      MT8173_CLK_MM,
++      MT8173_CLK_MFG,
++      MT8173_CLK_MAX = MT8173_CLK_MFG,
++};
++
++struct scp_domain_data {
++      const char *name;
++      u32 sta_mask;
++      int ctl_offs;
++      u32 sram_pdn_bits;
++      u32 sram_pdn_ack_bits;
++      u32 bus_prot_mask;
++      enum clk_id clk_id;
++};
++
++static const struct scp_domain_data scp_domain_data[] __initconst = {
++      [MT8173_POWER_DOMAIN_VDEC] = {
++              .name = "vdec",
++              .sta_mask = PWR_STATUS_VDEC,
++              .ctl_offs = SPM_VDE_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(12, 12),
++              .clk_id = MT8173_CLK_MM,
++      },
++      [MT8173_POWER_DOMAIN_VENC] = {
++              .name = "venc",
++              .sta_mask = PWR_STATUS_VENC,
++              .ctl_offs = SPM_VEN_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(15, 12),
++              .clk_id = MT8173_CLK_MM,
++      },
++      [MT8173_POWER_DOMAIN_ISP] = {
++              .name = "isp",
++              .sta_mask = PWR_STATUS_ISP,
++              .ctl_offs = SPM_ISP_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(13, 12),
++              .clk_id = MT8173_CLK_MM,
++      },
++      [MT8173_POWER_DOMAIN_MM] = {
++              .name = "mm",
++              .sta_mask = PWR_STATUS_DISP,
++              .ctl_offs = SPM_DIS_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(12, 12),
++              .clk_id = MT8173_CLK_MM,
++              .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
++                      MT8173_TOP_AXI_PROT_EN_MM_M1,
++      },
++      [MT8173_POWER_DOMAIN_VENC_LT] = {
++              .name = "venc_lt",
++              .sta_mask = PWR_STATUS_VENC_LT,
++              .ctl_offs = SPM_VEN2_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(15, 12),
++              .clk_id = MT8173_CLK_MM,
++      },
++      [MT8173_POWER_DOMAIN_AUDIO] = {
++              .name = "audio",
++              .sta_mask = PWR_STATUS_AUDIO,
++              .ctl_offs = SPM_AUDIO_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(15, 12),
++              .clk_id = MT8173_CLK_NONE,
++      },
++      [MT8173_POWER_DOMAIN_USB] = {
++              .name = "usb",
++              .sta_mask = PWR_STATUS_USB,
++              .ctl_offs = SPM_USB_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(15, 12),
++              .clk_id = MT8173_CLK_NONE,
++      },
++      [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
++              .name = "mfg_async",
++              .sta_mask = PWR_STATUS_MFG_ASYNC,
++              .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = 0,
++              .clk_id = MT8173_CLK_MFG,
++      },
++      [MT8173_POWER_DOMAIN_MFG_2D] = {
++              .name = "mfg_2d",
++              .sta_mask = PWR_STATUS_MFG_2D,
++              .ctl_offs = SPM_MFG_2D_PWR_CON,
++              .sram_pdn_bits = GENMASK(11, 8),
++              .sram_pdn_ack_bits = GENMASK(13, 12),
++              .clk_id = MT8173_CLK_NONE,
++      },
++      [MT8173_POWER_DOMAIN_MFG] = {
++              .name = "mfg",
++              .sta_mask = PWR_STATUS_MFG,
++              .ctl_offs = SPM_MFG_PWR_CON,
++              .sram_pdn_bits = GENMASK(13, 8),
++              .sram_pdn_ack_bits = GENMASK(21, 16),
++              .clk_id = MT8173_CLK_NONE,
++              .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
++                      MT8173_TOP_AXI_PROT_EN_MFG_M0 |
++                      MT8173_TOP_AXI_PROT_EN_MFG_M1 |
++                      MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
++      },
++};
++
++#define NUM_DOMAINS   ARRAY_SIZE(scp_domain_data)
++
++struct scp;
++
++struct scp_domain {
++      struct generic_pm_domain genpd;
++      struct scp *scp;
++      struct clk *clk;
++      u32 sta_mask;
++      void __iomem *ctl_addr;
++      u32 sram_pdn_bits;
++      u32 sram_pdn_ack_bits;
++      u32 bus_prot_mask;
++};
++
++struct scp {
++      struct scp_domain domains[NUM_DOMAINS];
++      struct genpd_onecell_data pd_data;
++      struct device *dev;
++      void __iomem *base;
++      struct regmap *infracfg;
++      struct clk *clk[MT8173_CLK_MAX];
++};
++
++static int scpsys_domain_is_on(struct scp_domain *scpd)
++{
++      struct scp *scp = scpd->scp;
++
++      u32 status = readl(scp->base + SPM_PWR_STATUS) & scpd->sta_mask;
++      u32 status2 = readl(scp->base + SPM_PWR_STATUS_2ND) & scpd->sta_mask;
++
++      /*
++       * A domain is on when both status bits are set. If only one is set
++       * return an error. This happens while powering up a domain
++       */
++
++      if (status && status2)
++              return true;
++      if (!status && !status2)
++              return false;
++
++      return -EINVAL;
++}
++
++static int scpsys_power_on(struct generic_pm_domain *genpd)
++{
++      struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
++      struct scp *scp = scpd->scp;
++      unsigned long timeout;
++      bool expired;
++      void __iomem *ctl_addr = scpd->ctl_addr;
++      u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
++      u32 val;
++      int ret;
++
++      if (scpd->clk) {
++              ret = clk_prepare_enable(scpd->clk);
++              if (ret)
++                      return ret;
++      }
++
++      val = readl(ctl_addr);
++      val |= PWR_ON_BIT;
++      writel(val, ctl_addr);
++      val |= PWR_ON_2ND_BIT;
++      writel(val, ctl_addr);
++
++      /* wait until PWR_ACK = 1 */
++      timeout = jiffies + HZ;
++      expired = false;
++      while (1) {
++              ret = scpsys_domain_is_on(scpd);
++              if (ret > 0)
++                      break;
++
++              if (expired) {
++                      ret = -ETIMEDOUT;
++                      goto out;
++              }
++
++              cpu_relax();
++
++              if (time_after(jiffies, timeout))
++                      expired = true;
++      }
++
++      val &= ~PWR_CLK_DIS_BIT;
++      writel(val, ctl_addr);
++
++      val &= ~PWR_ISO_BIT;
++      writel(val, ctl_addr);
++
++      val |= PWR_RST_B_BIT;
++      writel(val, ctl_addr);
++
++      val &= ~scpd->sram_pdn_bits;
++      writel(val, ctl_addr);
++
++      /* wait until SRAM_PDN_ACK all 0 */
++      timeout = jiffies + HZ;
++      expired = false;
++      while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) {
++
++              if (expired) {
++                      ret = -ETIMEDOUT;
++                      goto out;
++              }
++
++              cpu_relax();
++
++              if (time_after(jiffies, timeout))
++                      expired = true;
++      }
++
++      if (scpd->bus_prot_mask) {
++              ret = mtk_infracfg_clear_bus_protection(scp->infracfg,
++                              scpd->bus_prot_mask);
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
++out:
++      dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
++
++      return ret;
++}
++
++static int scpsys_power_off(struct generic_pm_domain *genpd)
++{
++      struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
++      struct scp *scp = scpd->scp;
++      unsigned long timeout;
++      bool expired;
++      void __iomem *ctl_addr = scpd->ctl_addr;
++      u32 pdn_ack = scpd->sram_pdn_ack_bits;
++      u32 val;
++      int ret;
++
++      if (scpd->bus_prot_mask) {
++              ret = mtk_infracfg_set_bus_protection(scp->infracfg,
++                              scpd->bus_prot_mask);
++              if (ret)
++                      return ret;
++      }
++
++      val = readl(ctl_addr);
++      val |= scpd->sram_pdn_bits;
++      writel(val, ctl_addr);
++
++      /* wait until SRAM_PDN_ACK all 1 */
++      timeout = jiffies + HZ;
++      expired = false;
++      while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) {
++              if (expired) {
++                      ret = -ETIMEDOUT;
++                      goto out;
++              }
++
++              cpu_relax();
++
++              if (time_after(jiffies, timeout))
++                      expired = true;
++      }
++
++      val |= PWR_ISO_BIT;
++      writel(val, ctl_addr);
++
++      val &= ~PWR_RST_B_BIT;
++      writel(val, ctl_addr);
++
++      val |= PWR_CLK_DIS_BIT;
++      writel(val, ctl_addr);
++
++      val &= ~PWR_ON_BIT;
++      writel(val, ctl_addr);
++
++      val &= ~PWR_ON_2ND_BIT;
++      writel(val, ctl_addr);
++
++      /* wait until PWR_ACK = 0 */
++      timeout = jiffies + HZ;
++      expired = false;
++      while (1) {
++              ret = scpsys_domain_is_on(scpd);
++              if (ret == 0)
++                      break;
++
++              if (expired) {
++                      ret = -ETIMEDOUT;
++                      goto out;
++              }
++
++              cpu_relax();
++
++              if (time_after(jiffies, timeout))
++                      expired = true;
++      }
++
++      if (scpd->clk)
++              clk_disable_unprepare(scpd->clk);
++
++      return 0;
++
++out:
++      dev_err(scp->dev, "Failed to power off domain %s\n", genpd->name);
++
++      return ret;
++}
++
++static int __init scpsys_probe(struct platform_device *pdev)
++{
++      struct genpd_onecell_data *pd_data;
++      struct resource *res;
++      int i, ret;
++      struct scp *scp;
++
++      scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
++      if (!scp)
++              return -ENOMEM;
++
++      scp->dev = &pdev->dev;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      scp->base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(scp->base))
++              return PTR_ERR(scp->base);
++
++      pd_data = &scp->pd_data;
++
++      pd_data->domains = devm_kzalloc(&pdev->dev,
++                      sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL);
++      if (!pd_data->domains)
++              return -ENOMEM;
++
++      scp->clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm");
++      if (IS_ERR(scp->clk[MT8173_CLK_MM])) {
++              dev_err(&pdev->dev, "Failed to get mm clk: %ld\n",
++                              PTR_ERR(scp->clk[MT8173_CLK_MM]));
++              return PTR_ERR(scp->clk[MT8173_CLK_MM]);
++      }
++
++      scp->clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg");
++      if (IS_ERR(scp->clk[MT8173_CLK_MFG])) {
++              dev_err(&pdev->dev, "Failed to get mfg clk: %ld\n",
++                              PTR_ERR(scp->clk[MT8173_CLK_MFG]));
++              return PTR_ERR(scp->clk[MT8173_CLK_MFG]);
++      }
++
++      scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
++                      "infracfg");
++      if (IS_ERR(scp->infracfg)) {
++              dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
++                              PTR_ERR(scp->infracfg));
++              return PTR_ERR(scp->infracfg);
++      }
++
++      pd_data->num_domains = NUM_DOMAINS;
++
++      for (i = 0; i < NUM_DOMAINS; i++) {
++              struct scp_domain *scpd = &scp->domains[i];
++              struct generic_pm_domain *genpd = &scpd->genpd;
++              const struct scp_domain_data *data = &scp_domain_data[i];
++
++              pd_data->domains[i] = genpd;
++              scpd->scp = scp;
++
++              scpd->sta_mask = data->sta_mask;
++              scpd->ctl_addr = scp->base + data->ctl_offs;
++              scpd->sram_pdn_bits = data->sram_pdn_bits;
++              scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
++              scpd->bus_prot_mask = data->bus_prot_mask;
++              if (data->clk_id != MT8173_CLK_NONE)
++                      scpd->clk = scp->clk[data->clk_id];
++
++              genpd->name = data->name;
++              genpd->power_off = scpsys_power_off;
++              genpd->power_on = scpsys_power_on;
++
++              /*
++               * Initially turn on all domains to make the domains usable
++               * with !CONFIG_PM and to get the hardware in sync with the
++               * software.  The unused domains will be switched off during
++               * late_init time.
++               */
++              genpd->power_on(genpd);
++
++              pm_genpd_init(genpd, NULL, false);
++      }
++
++      /*
++       * We are not allowed to fail here since there is no way to unregister
++       * a power domain. Once registered above we have to keep the domains
++       * valid.
++       */
++
++      ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC],
++              pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]);
++      if (ret && IS_ENABLED(CONFIG_PM))
++              dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
++
++      ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D],
++              pd_data->domains[MT8173_POWER_DOMAIN_MFG]);
++      if (ret && IS_ENABLED(CONFIG_PM))
++              dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
++
++      ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
++      if (ret)
++              dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
++
++      return 0;
++}
++
++static const struct of_device_id of_scpsys_match_tbl[] = {
++      {
++              .compatible = "mediatek,mt8173-scpsys",
++      }, {
++              /* sentinel */
++      }
++};
++
++static struct platform_driver scpsys_drv = {
++      .driver = {
++              .name = "mtk-scpsys",
++              .owner = THIS_MODULE,
++              .of_match_table = of_match_ptr(of_scpsys_match_tbl),
++      },
++};
++
++module_platform_driver_probe(scpsys_drv, scpsys_probe);
+diff --git a/include/dt-bindings/power/mt8173-power.h b/include/dt-bindings/power/mt8173-power.h
+new file mode 100644
+index 0000000..b34cee9
+--- /dev/null
++++ b/include/dt-bindings/power/mt8173-power.h
+@@ -0,0 +1,15 @@
++#ifndef _DT_BINDINGS_POWER_MT8183_POWER_H
++#define _DT_BINDINGS_POWER_MT8183_POWER_H
++
++#define MT8173_POWER_DOMAIN_VDEC      0
++#define MT8173_POWER_DOMAIN_VENC      1
++#define MT8173_POWER_DOMAIN_ISP               2
++#define MT8173_POWER_DOMAIN_MM                3
++#define MT8173_POWER_DOMAIN_VENC_LT   4
++#define MT8173_POWER_DOMAIN_AUDIO     5
++#define MT8173_POWER_DOMAIN_USB               6
++#define MT8173_POWER_DOMAIN_MFG_ASYNC 7
++#define MT8173_POWER_DOMAIN_MFG_2D    8
++#define MT8173_POWER_DOMAIN_MFG               9
++
++#endif /* _DT_BINDINGS_POWER_MT8183_POWER_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0009-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch b/target/linux/mediatek/patches/0009-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch
new file mode 100644 (file)
index 0000000..6d7fd47
--- /dev/null
@@ -0,0 +1,154 @@
+From 87043a64dd5185dc076b3c3ab2e421b3a8c47798 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Thu, 23 Apr 2015 10:35:43 +0200
+Subject: [PATCH 09/76] dt-bindings: ARM: Mediatek: Document devicetree
+ bindings for clock/reset controllers
+
+This adds the binding documentation for the apmixedsys, perisys and
+infracfg controllers found on Mediatek SoCs.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ .../bindings/arm/mediatek/mediatek,apmixedsys.txt  |   23 +++++++++++++++
+ .../bindings/arm/mediatek/mediatek,infracfg.txt    |   30 ++++++++++++++++++++
+ .../bindings/arm/mediatek/mediatek,pericfg.txt     |   30 ++++++++++++++++++++
+ .../bindings/arm/mediatek/mediatek,topckgen.txt    |   23 +++++++++++++++
+ 4 files changed, 106 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+new file mode 100644
+index 0000000..5af6d73
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+@@ -0,0 +1,23 @@
++Mediatek apmixedsys controller
++==============================
++
++The Mediatek apmixedsys controller provides the PLLs to the system.
++
++Required Properties:
++
++- compatible: Should be:
++      - "mediatek,mt8135-apmixedsys"
++      - "mediatek,mt8173-apmixedsys"
++- #clock-cells: Must be 1
++
++The apmixedsys 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:
++
++apmixedsys: apmixedsys@10209000 {
++      compatible = "mediatek,mt8173-apmixedsys";
++      reg = <0 0x10209000 0 0x1000>;
++      #clock-cells = <1>;
++};
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+new file mode 100644
+index 0000000..684da473
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+@@ -0,0 +1,30 @@
++Mediatek infracfg controller
++============================
++
++The Mediatek infracfg controller provides various clocks and reset
++outputs to the system.
++
++Required Properties:
++
++- compatible: Should be:
++      - "mediatek,mt8135-infracfg", "syscon"
++      - "mediatek,mt8173-infracfg", "syscon"
++- #clock-cells: Must be 1
++- #reset-cells: Must be 1
++
++The infracfg 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.
++Also it uses the common reset controller binding from
++Documentation/devicetree/bindings/reset/reset.txt.
++The available reset outputs are defined in
++dt-bindings/reset-controller/mt*-resets.h
++
++Example:
++
++infracfg: infracfg@10001000 {
++      compatible = "mediatek,mt8173-infracfg", "syscon";
++      reg = <0 0x10001000 0 0x1000>;
++      #clock-cells = <1>;
++      #reset-cells = <1>;
++};
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+new file mode 100644
+index 0000000..fdb45c6
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+@@ -0,0 +1,30 @@
++Mediatek pericfg controller
++===========================
++
++The Mediatek pericfg controller provides various clocks and reset
++outputs to the system.
++
++Required Properties:
++
++- compatible: Should be:
++      - "mediatek,mt8135-pericfg", "syscon"
++      - "mediatek,mt8173-pericfg", "syscon"
++- #clock-cells: Must be 1
++- #reset-cells: Must be 1
++
++The pericfg 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.
++Also it uses the common reset controller binding from
++Documentation/devicetree/bindings/reset/reset.txt.
++The available reset outputs are defined in
++dt-bindings/reset-controller/mt*-resets.h
++
++Example:
++
++pericfg: pericfg@10003000 {
++      compatible = "mediatek,mt8173-pericfg", "syscon";
++      reg = <0 0x10003000 0 0x1000>;
++      #clock-cells = <1>;
++      #reset-cells = <1>;
++};
+diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+new file mode 100644
+index 0000000..a425248
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+@@ -0,0 +1,23 @@
++Mediatek topckgen controller
++============================
++
++The Mediatek topckgen controller provides various clocks to the system.
++
++Required Properties:
++
++- compatible: Should be:
++      - "mediatek,mt8135-topckgen"
++      - "mediatek,mt8173-topckgen"
++- #clock-cells: Must be 1
++
++The topckgen 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:
++
++topckgen: topckgen@10000000 {
++      compatible = "mediatek,mt8173-topckgen";
++      reg = <0 0x10000000 0 0x1000>;
++      #clock-cells = <1>;
++};
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0010-thermal-consistently-use-int-for-temperatures.patch b/target/linux/mediatek/patches/0010-thermal-consistently-use-int-for-temperatures.patch
new file mode 100644 (file)
index 0000000..2aa83ab
--- /dev/null
@@ -0,0 +1,1155 @@
+From 29e6031548373b9e7ec0c17e85da6a4cf4fee7f5 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:29 +0200
+Subject: [PATCH 10/76] thermal: consistently use int for temperatures
+
+The thermal code uses int, long and unsigned long for temperatures
+in different places. Using an unsigned type limits the thermal framework
+to positive temperatures without need. 'long' is 64bit on several
+architectures which is not needed. Consistently use a plain 'int'
+for temperatures.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/acpi/thermal.c                             |   12 ++++-----
+ drivers/hwmon/lm75.c                               |    2 +-
+ drivers/hwmon/ntc_thermistor.c                     |    2 +-
+ drivers/hwmon/tmp102.c                             |    2 +-
+ drivers/input/touchscreen/sun4i-ts.c               |    8 +++---
+ drivers/platform/x86/acerhdf.c                     |    9 +++----
+ drivers/power/power_supply_core.c                  |    2 +-
+ drivers/thermal/armada_thermal.c                   |    2 +-
+ drivers/thermal/db8500_thermal.c                   |    7 +++--
+ drivers/thermal/dove_thermal.c                     |    2 +-
+ drivers/thermal/fair_share.c                       |    2 +-
+ drivers/thermal/gov_bang_bang.c                    |    5 ++--
+ drivers/thermal/imx_thermal.c                      |   27 ++++++++++----------
+ .../thermal/int340x_thermal/int340x_thermal_zone.c |   10 ++++----
+ .../thermal/int340x_thermal/int340x_thermal_zone.h |    8 +++---
+ drivers/thermal/intel_soc_dts_thermal.c            |    7 +++--
+ drivers/thermal/of-thermal.c                       |   14 +++++-----
+ drivers/thermal/rcar_thermal.c                     |    7 +++--
+ drivers/thermal/rockchip_thermal.c                 |   10 ++++----
+ drivers/thermal/samsung/exynos_tmu.c               |   19 +++++++-------
+ drivers/thermal/spear_thermal.c                    |    2 +-
+ drivers/thermal/st/st_thermal.c                    |    5 ++--
+ drivers/thermal/step_wise.c                        |    4 +--
+ drivers/thermal/tegra_soctherm.c                   |    4 +--
+ drivers/thermal/thermal_core.c                     |   26 +++++++++----------
+ drivers/thermal/thermal_hwmon.c                    |   10 ++++----
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c |   10 ++++----
+ drivers/thermal/x86_pkg_temp_thermal.c             |   10 ++++----
+ include/linux/thermal.h                            |   26 ++++++++-----------
+ 29 files changed, 120 insertions(+), 134 deletions(-)
+
+diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
+index d24fa19..68bff60 100644
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -529,8 +529,7 @@ static void acpi_thermal_check(void *data)
+ /* sys I/F for generic thermal sysfs support */
+-static int thermal_get_temp(struct thermal_zone_device *thermal,
+-                          unsigned long *temp)
++static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
+ {
+       struct acpi_thermal *tz = thermal->devdata;
+       int result;
+@@ -637,7 +636,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
+ }
+ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+-                               int trip, unsigned long *temp)
++                               int trip, int *temp)
+ {
+       struct acpi_thermal *tz = thermal->devdata;
+       int i;
+@@ -690,7 +689,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+ }
+ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
+-                              unsigned long *temperature) {
++                              int *temperature)
++{
+       struct acpi_thermal *tz = thermal->devdata;
+       if (tz->trips.critical.flags.valid) {
+@@ -713,8 +713,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
+               return -EINVAL;
+       if (type == THERMAL_TRIP_ACTIVE) {
+-              unsigned long trip_temp;
+-              unsigned long temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
++              int trip_temp;
++              int temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
+                                       tz->temperature, tz->kelvin_offset);
+               if (thermal_get_trip_temp(thermal, trip, &trip_temp))
+                       return -EINVAL;
+diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
+index fe41d5a..e4e57bb 100644
+--- a/drivers/hwmon/lm75.c
++++ b/drivers/hwmon/lm75.c
+@@ -104,7 +104,7 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
+ /* sysfs attributes for hwmon */
+-static int lm75_read_temp(void *dev, long *temp)
++static int lm75_read_temp(void *dev, int *temp)
+ {
+       struct lm75_data *data = lm75_update_device(dev);
+diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
+index 6880011..3d9eab9 100644
+--- a/drivers/hwmon/ntc_thermistor.c
++++ b/drivers/hwmon/ntc_thermistor.c
+@@ -439,7 +439,7 @@ static int ntc_thermistor_get_ohm(struct ntc_data *data)
+       return -EINVAL;
+ }
+-static int ntc_read_temp(void *dev, long *temp)
++static int ntc_read_temp(void *dev, int *temp)
+ {
+       struct ntc_data *data = dev_get_drvdata(dev);
+       int ohm;
+diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
+index 9da2735..6548262 100644
+--- a/drivers/hwmon/tmp102.c
++++ b/drivers/hwmon/tmp102.c
+@@ -98,7 +98,7 @@ static struct tmp102 *tmp102_update_device(struct device *dev)
+       return tmp102;
+ }
+-static int tmp102_read_temp(void *dev, long *temp)
++static int tmp102_read_temp(void *dev, int *temp)
+ {
+       struct tmp102 *tmp102 = tmp102_update_device(dev);
+diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
+index c011699..4857943 100644
+--- a/drivers/input/touchscreen/sun4i-ts.c
++++ b/drivers/input/touchscreen/sun4i-ts.c
+@@ -191,7 +191,7 @@ static void sun4i_ts_close(struct input_dev *dev)
+       writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
+ }
+-static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
++static int sun4i_get_temp(const struct sun4i_ts_data *ts, int *temp)
+ {
+       /* No temp_data until the first irq */
+       if (ts->temp_data == -1)
+@@ -202,7 +202,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp)
+       return 0;
+ }
+-static int sun4i_get_tz_temp(void *data, long *temp)
++static int sun4i_get_tz_temp(void *data, int *temp)
+ {
+       return sun4i_get_temp(data, temp);
+ }
+@@ -215,14 +215,14 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+                        char *buf)
+ {
+       struct sun4i_ts_data *ts = dev_get_drvdata(dev);
+-      long temp;
++      int temp;
+       int error;
+       error = sun4i_get_temp(ts, &temp);
+       if (error)
+               return error;
+-      return sprintf(buf, "%ld\n", temp);
++      return sprintf(buf, "%d\n", temp);
+ }
+ static ssize_t show_temp_label(struct device *dev,
+diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
+index 594c918..f2ce63c 100644
+--- a/drivers/platform/x86/acerhdf.c
++++ b/drivers/platform/x86/acerhdf.c
+@@ -346,8 +346,7 @@ static void acerhdf_check_param(struct thermal_zone_device *thermal)
+  * as late as the polling interval is since we can't do that in the respective
+  * accessors of the module parameters.
+  */
+-static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal,
+-                             unsigned long *t)
++static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal, int *t)
+ {
+       int temp, err = 0;
+@@ -452,7 +451,7 @@ static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip,
+ }
+ static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
+-                               unsigned long *temp)
++                               int *temp)
+ {
+       if (trip != 0)
+               return -EINVAL;
+@@ -463,7 +462,7 @@ static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
+ }
+ static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
+-                               unsigned long *temp)
++                               int *temp)
+ {
+       if (trip == 0)
+               *temp = fanon;
+@@ -476,7 +475,7 @@ static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
+ }
+ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
+-                               unsigned long *temperature)
++                               int *temperature)
+ {
+       *temperature = ACERHDF_TEMP_CRIT;
+       return 0;
+diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
+index 2ed4a4a..87e2fd1 100644
+--- a/drivers/power/power_supply_core.c
++++ b/drivers/power/power_supply_core.c
+@@ -492,7 +492,7 @@ EXPORT_SYMBOL_GPL(power_supply_unreg_notifier);
+ #ifdef CONFIG_THERMAL
+ static int power_supply_read_temp(struct thermal_zone_device *tzd,
+-              unsigned long *temp)
++              int *temp)
+ {
+       struct power_supply *psy;
+       union power_supply_propval val;
+diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
+index 01255fd..26b8d32 100644
+--- a/drivers/thermal/armada_thermal.c
++++ b/drivers/thermal/armada_thermal.c
+@@ -155,7 +155,7 @@ static bool armada_is_valid(struct armada_thermal_priv *priv)
+ }
+ static int armada_get_temp(struct thermal_zone_device *thermal,
+-                        unsigned long *temp)
++                        int *temp)
+ {
+       struct armada_thermal_priv *priv = thermal->devdata;
+       unsigned long reg;
+diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
+index 20adfbe..b3eca71 100644
+--- a/drivers/thermal/db8500_thermal.c
++++ b/drivers/thermal/db8500_thermal.c
+@@ -107,8 +107,7 @@ static int db8500_cdev_unbind(struct thermal_zone_device *thermal,
+ }
+ /* Callback to get current temperature */
+-static int db8500_sys_get_temp(struct thermal_zone_device *thermal,
+-              unsigned long *temp)
++static int db8500_sys_get_temp(struct thermal_zone_device *thermal, int *temp)
+ {
+       struct db8500_thermal_zone *pzone = thermal->devdata;
+@@ -180,7 +179,7 @@ static int db8500_sys_get_trip_type(struct thermal_zone_device *thermal,
+ /* Callback to get trip point temperature */
+ static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
+-              int trip, unsigned long *temp)
++              int trip, int *temp)
+ {
+       struct db8500_thermal_zone *pzone = thermal->devdata;
+       struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+@@ -195,7 +194,7 @@ static int db8500_sys_get_trip_temp(struct thermal_zone_device *thermal,
+ /* Callback to get critical trip point temperature */
+ static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
+-              unsigned long *temp)
++              int *temp)
+ {
+       struct db8500_thermal_zone *pzone = thermal->devdata;
+       struct db8500_thsens_platform_data *ptrips = pzone->trip_tab;
+diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
+index 09f6e30..a0bc9de 100644
+--- a/drivers/thermal/dove_thermal.c
++++ b/drivers/thermal/dove_thermal.c
+@@ -93,7 +93,7 @@ static int dove_init_sensor(const struct dove_thermal_priv *priv)
+ }
+ static int dove_get_temp(struct thermal_zone_device *thermal,
+-                        unsigned long *temp)
++                        int *temp)
+ {
+       unsigned long reg;
+       struct dove_thermal_priv *priv = thermal->devdata;
+diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
+index 6e0a3fb..efad70e 100644
+--- a/drivers/thermal/fair_share.c
++++ b/drivers/thermal/fair_share.c
+@@ -34,7 +34,7 @@
+ static int get_trip_level(struct thermal_zone_device *tz)
+ {
+       int count = 0;
+-      unsigned long trip_temp;
++      int trip_temp;
+       enum thermal_trip_type trip_type;
+       if (tz->trips == 0 || !tz->ops->get_trip_temp)
+diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
+index c5dd76b..70836c5 100644
+--- a/drivers/thermal/gov_bang_bang.c
++++ b/drivers/thermal/gov_bang_bang.c
+@@ -25,14 +25,13 @@
+ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+ {
+-      long trip_temp;
+-      unsigned long trip_hyst;
++      int trip_temp, trip_hyst;
+       struct thermal_instance *instance;
+       tz->ops->get_trip_temp(tz, trip, &trip_temp);
+       tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
+-      dev_dbg(&tz->device, "Trip%d[temp=%ld]:temp=%d:hyst=%ld\n",
++      dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
+                               trip, trip_temp, tz->temperature,
+                               trip_hyst);
+diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
+index 2ccbc07..f1424f0 100644
+--- a/drivers/thermal/imx_thermal.c
++++ b/drivers/thermal/imx_thermal.c
+@@ -98,10 +98,10 @@ struct imx_thermal_data {
+       enum thermal_device_mode mode;
+       struct regmap *tempmon;
+       u32 c1, c2; /* See formula in imx_get_sensor_data() */
+-      unsigned long temp_passive;
+-      unsigned long temp_critical;
+-      unsigned long alarm_temp;
+-      unsigned long last_temp;
++      int temp_passive;
++      int temp_critical;
++      int alarm_temp;
++      int last_temp;
+       bool irq_enabled;
+       int irq;
+       struct clk *thermal_clk;
+@@ -109,7 +109,7 @@ struct imx_thermal_data {
+ };
+ static void imx_set_panic_temp(struct imx_thermal_data *data,
+-                             signed long panic_temp)
++                             int panic_temp)
+ {
+       struct regmap *map = data->tempmon;
+       int critical_value;
+@@ -121,7 +121,7 @@ static void imx_set_panic_temp(struct imx_thermal_data *data,
+ }
+ static void imx_set_alarm_temp(struct imx_thermal_data *data,
+-                             signed long alarm_temp)
++                             int alarm_temp)
+ {
+       struct regmap *map = data->tempmon;
+       int alarm_value;
+@@ -133,7 +133,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data,
+                       TEMPSENSE0_ALARM_VALUE_SHIFT);
+ }
+-static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
++static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+       struct imx_thermal_data *data = tz->devdata;
+       struct regmap *map = data->tempmon;
+@@ -189,13 +189,13 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
+               if (data->alarm_temp == data->temp_critical &&
+                       *temp < data->temp_passive) {
+                       imx_set_alarm_temp(data, data->temp_passive);
+-                      dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
++                      dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
+                               data->alarm_temp / 1000);
+               }
+       }
+       if (*temp != data->last_temp) {
+-              dev_dbg(&tz->device, "millicelsius: %ld\n", *temp);
++              dev_dbg(&tz->device, "millicelsius: %d\n", *temp);
+               data->last_temp = *temp;
+       }
+@@ -262,8 +262,7 @@ static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
+       return 0;
+ }
+-static int imx_get_crit_temp(struct thermal_zone_device *tz,
+-                           unsigned long *temp)
++static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
+ {
+       struct imx_thermal_data *data = tz->devdata;
+@@ -272,7 +271,7 @@ static int imx_get_crit_temp(struct thermal_zone_device *tz,
+ }
+ static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
+-                           unsigned long *temp)
++                           int *temp)
+ {
+       struct imx_thermal_data *data = tz->devdata;
+@@ -282,7 +281,7 @@ static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
+ }
+ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
+-                           unsigned long temp)
++                           int temp)
+ {
+       struct imx_thermal_data *data = tz->devdata;
+@@ -433,7 +432,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
+ {
+       struct imx_thermal_data *data = dev;
+-      dev_dbg(&data->tz->device, "THERMAL ALARM: T > %lu\n",
++      dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
+               data->alarm_temp / 1000);
+       thermal_zone_device_update(data->tz);
+diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+index 1e25133..b9b2666 100644
+--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
++++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+@@ -20,7 +20,7 @@
+ #include "int340x_thermal_zone.h"
+ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
+-                                       unsigned long *temp)
++                                       int *temp)
+ {
+       struct int34x_thermal_zone *d = zone->devdata;
+       unsigned long long tmp;
+@@ -49,7 +49,7 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
+ }
+ static int int340x_thermal_get_trip_temp(struct thermal_zone_device *zone,
+-                                       int trip, unsigned long *temp)
++                                       int trip, int *temp)
+ {
+       struct int34x_thermal_zone *d = zone->devdata;
+       int i;
+@@ -114,7 +114,7 @@ static int int340x_thermal_get_trip_type(struct thermal_zone_device *zone,
+ }
+ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
+-                                    int trip, unsigned long temp)
++                                    int trip, int temp)
+ {
+       struct int34x_thermal_zone *d = zone->devdata;
+       acpi_status status;
+@@ -136,7 +136,7 @@ static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
+ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
+-              int trip, unsigned long *temp)
++              int trip, int *temp)
+ {
+       struct int34x_thermal_zone *d = zone->devdata;
+       acpi_status status;
+@@ -163,7 +163,7 @@ static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
+ };
+ static int int340x_thermal_get_trip_config(acpi_handle handle, char *name,
+-                                    unsigned long *temp)
++                                    int *temp)
+ {
+       unsigned long long r;
+       acpi_status status;
+diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+index 9f38ab7..aaadf72 100644
+--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
++++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.h
+@@ -21,7 +21,7 @@
+ #define INT340X_THERMAL_MAX_ACT_TRIP_COUNT    10
+ struct active_trip {
+-      unsigned long temp;
++      int temp;
+       int id;
+       bool valid;
+ };
+@@ -31,11 +31,11 @@ struct int34x_thermal_zone {
+       struct active_trip act_trips[INT340X_THERMAL_MAX_ACT_TRIP_COUNT];
+       unsigned long *aux_trips;
+       int aux_trip_nr;
+-      unsigned long psv_temp;
++      int psv_temp;
+       int psv_trip_id;
+-      unsigned long crt_temp;
++      int crt_temp;
+       int crt_trip_id;
+-      unsigned long hot_temp;
++      int hot_temp;
+       int hot_trip_id;
+       struct thermal_zone_device *zone;
+       struct thermal_zone_device_ops *override_ops;
+diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
+index 9013505..fd550b9 100644
+--- a/drivers/thermal/intel_soc_dts_thermal.c
++++ b/drivers/thermal/intel_soc_dts_thermal.c
+@@ -106,7 +106,7 @@ err_ret:
+ }
+ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+-                                      int trip, unsigned long *temp)
++                                      int trip, int *temp)
+ {
+       int status;
+       u32 out;
+@@ -224,7 +224,7 @@ err_restore_ptps:
+ }
+ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
+-                                                      unsigned long temp)
++                                                      int temp)
+ {
+       struct soc_sensor_entry *aux_entry = tzd->devdata;
+       int status;
+@@ -250,8 +250,7 @@ static int sys_get_trip_type(struct thermal_zone_device *thermal,
+       return 0;
+ }
+-static int sys_get_curr_temp(struct thermal_zone_device *tzd,
+-                                              unsigned long *temp)
++static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+ {
+       int status;
+       u32 out;
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index 668fb1b..03839df 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -87,7 +87,7 @@ struct __thermal_zone {
+ /***   DT thermal zone device callbacks   ***/
+ static int of_thermal_get_temp(struct thermal_zone_device *tz,
+-                             unsigned long *temp)
++                             int *temp)
+ {
+       struct __thermal_zone *data = tz->devdata;
+@@ -173,7 +173,7 @@ EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
+  * Return: zero on success, error code otherwise
+  */
+ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
+-                                  unsigned long temp)
++                                  int temp)
+ {
+       struct __thermal_zone *data = tz->devdata;
+@@ -306,7 +306,7 @@ static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip,
+ }
+ static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
+-                                  unsigned long *temp)
++                                  int *temp)
+ {
+       struct __thermal_zone *data = tz->devdata;
+@@ -319,7 +319,7 @@ static int of_thermal_get_trip_temp(struct thermal_zone_device *tz, int trip,
+ }
+ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
+-                                  unsigned long temp)
++                                  int temp)
+ {
+       struct __thermal_zone *data = tz->devdata;
+@@ -333,7 +333,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip,
+ }
+ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
+-                                  unsigned long *hyst)
++                                  int *hyst)
+ {
+       struct __thermal_zone *data = tz->devdata;
+@@ -346,7 +346,7 @@ static int of_thermal_get_trip_hyst(struct thermal_zone_device *tz, int trip,
+ }
+ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
+-                                  unsigned long hyst)
++                                  int hyst)
+ {
+       struct __thermal_zone *data = tz->devdata;
+@@ -360,7 +360,7 @@ static int of_thermal_set_trip_hyst(struct thermal_zone_device *tz, int trip,
+ }
+ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+-                                  unsigned long *temp)
++                                  int *temp)
+ {
+       struct __thermal_zone *data = tz->devdata;
+       int i;
+diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
+index fe4e767..5d4ae7d 100644
+--- a/drivers/thermal/rcar_thermal.c
++++ b/drivers/thermal/rcar_thermal.c
+@@ -200,8 +200,7 @@ err_out_unlock:
+       return ret;
+ }
+-static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
+-                               unsigned long *temp)
++static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
+ {
+       struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
+@@ -235,7 +234,7 @@ static int rcar_thermal_get_trip_type(struct thermal_zone_device *zone,
+ }
+ static int rcar_thermal_get_trip_temp(struct thermal_zone_device *zone,
+-                                    int trip, unsigned long *temp)
++                                    int trip, int *temp)
+ {
+       struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
+       struct device *dev = rcar_priv_to_dev(priv);
+@@ -299,7 +298,7 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable)
+ static void rcar_thermal_work(struct work_struct *work)
+ {
+       struct rcar_thermal_priv *priv;
+-      unsigned long cctemp, nctemp;
++      int cctemp, nctemp;
+       priv = container_of(work, struct rcar_thermal_priv, work.work);
+diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
+index cd8f5f93..c89ffb2 100644
+--- a/drivers/thermal/rockchip_thermal.c
++++ b/drivers/thermal/rockchip_thermal.c
+@@ -64,7 +64,7 @@ struct rockchip_tsadc_chip {
+       void (*control)(void __iomem *reg, bool on);
+       /* Per-sensor methods */
+-      int (*get_temp)(int chn, void __iomem *reg, long *temp);
++      int (*get_temp)(int chn, void __iomem *reg, int *temp);
+       void (*set_tshut_temp)(int chn, void __iomem *reg, long temp);
+       void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
+ };
+@@ -191,7 +191,7 @@ static u32 rk_tsadcv2_temp_to_code(long temp)
+       return 0;
+ }
+-static long rk_tsadcv2_code_to_temp(u32 code)
++static int rk_tsadcv2_code_to_temp(u32 code)
+ {
+       unsigned int low = 0;
+       unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
+@@ -277,7 +277,7 @@ static void rk_tsadcv2_control(void __iomem *regs, bool enable)
+       writel_relaxed(val, regs + TSADCV2_AUTO_CON);
+ }
+-static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, long *temp)
++static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, int *temp)
+ {
+       u32 val;
+@@ -366,7 +366,7 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
+       return IRQ_HANDLED;
+ }
+-static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
++static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
+ {
+       struct rockchip_thermal_sensor *sensor = _sensor;
+       struct rockchip_thermal_data *thermal = sensor->thermal;
+@@ -374,7 +374,7 @@ static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
+       int retval;
+       retval = tsadc->get_temp(sensor->id, thermal->regs, out_temp);
+-      dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %ld, retval: %d\n",
++      dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
+               sensor->id, *out_temp, retval);
+       return retval;
+diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
+index 1d30b09..29eaf4d 100644
+--- a/drivers/thermal/samsung/exynos_tmu.c
++++ b/drivers/thermal/samsung/exynos_tmu.c
+@@ -181,8 +181,7 @@ struct exynos_tmu_data {
+       int (*tmu_initialize)(struct platform_device *pdev);
+       void (*tmu_control)(struct platform_device *pdev, bool on);
+       int (*tmu_read)(struct exynos_tmu_data *data);
+-      void (*tmu_set_emulation)(struct exynos_tmu_data *data,
+-                                unsigned long temp);
++      void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
+       void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
+ };
+@@ -190,7 +189,7 @@ static void exynos_report_trigger(struct exynos_tmu_data *p)
+ {
+       char data[10], *envp[] = { data, NULL };
+       struct thermal_zone_device *tz = p->tzd;
+-      unsigned long temp;
++      int temp;
+       unsigned int i;
+       if (!tz) {
+@@ -489,7 +488,7 @@ static int exynos5440_tmu_initialize(struct platform_device *pdev)
+       struct exynos_tmu_data *data = platform_get_drvdata(pdev);
+       unsigned int trim_info = 0, con, rising_threshold;
+       int ret = 0, threshold_code;
+-      unsigned long crit_temp = 0;
++      int crit_temp = 0;
+       /*
+        * For exynos5440 soc triminfo value is swapped between TMU0 and
+@@ -542,7 +541,7 @@ static int exynos7_tmu_initialize(struct platform_device *pdev)
+       unsigned int status, trim_info;
+       unsigned int rising_threshold = 0, falling_threshold = 0;
+       int ret = 0, threshold_code, i;
+-      unsigned long temp, temp_hist;
++      int temp, temp_hist;
+       unsigned int reg_off, bit_off;
+       status = readb(data->base + EXYNOS_TMU_REG_STATUS);
+@@ -713,7 +712,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
+       writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
+ }
+-static int exynos_get_temp(void *p, long *temp)
++static int exynos_get_temp(void *p, int *temp)
+ {
+       struct exynos_tmu_data *data = p;
+@@ -733,7 +732,7 @@ static int exynos_get_temp(void *p, long *temp)
+ #ifdef CONFIG_THERMAL_EMULATION
+ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
+-                          unsigned long temp)
++                          int temp)
+ {
+       if (temp) {
+               temp /= MCELSIUS;
+@@ -763,7 +762,7 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
+ }
+ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
+-                                       unsigned long temp)
++                                       int temp)
+ {
+       unsigned int val;
+       u32 emul_con;
+@@ -781,7 +780,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
+ }
+ static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
+-                                       unsigned long temp)
++                                       int temp)
+ {
+       unsigned int val;
+@@ -790,7 +789,7 @@ static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
+       writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG);
+ }
+-static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
++static int exynos_tmu_set_emulation(void *drv_data, int temp)
+ {
+       struct exynos_tmu_data *data = drv_data;
+       int ret = -EINVAL;
+diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
+index bddb717..534dd91 100644
+--- a/drivers/thermal/spear_thermal.c
++++ b/drivers/thermal/spear_thermal.c
+@@ -38,7 +38,7 @@ struct spear_thermal_dev {
+ };
+ static inline int thermal_get_temp(struct thermal_zone_device *thermal,
+-                              unsigned long *temp)
++                              int *temp)
+ {
+       struct spear_thermal_dev *stdev = thermal->devdata;
+diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
+index 76c515d..44cbba9 100644
+--- a/drivers/thermal/st/st_thermal.c
++++ b/drivers/thermal/st/st_thermal.c
+@@ -111,8 +111,7 @@ static int st_thermal_calibration(struct st_thermal_sensor *sensor)
+ }
+ /* Callback to get temperature from HW*/
+-static int st_thermal_get_temp(struct thermal_zone_device *th,
+-              unsigned long *temperature)
++static int st_thermal_get_temp(struct thermal_zone_device *th, int *temperature)
+ {
+       struct st_thermal_sensor *sensor = th->devdata;
+       struct device *dev = sensor->dev;
+@@ -159,7 +158,7 @@ static int st_thermal_get_trip_type(struct thermal_zone_device *th,
+ }
+ static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
+-                                  int trip, unsigned long *temp)
++                                  int trip, int *temp)
+ {
+       struct st_thermal_sensor *sensor = th->devdata;
+       struct device *dev = sensor->dev;
+diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
+index 5a0f12d..2f9f708 100644
+--- a/drivers/thermal/step_wise.c
++++ b/drivers/thermal/step_wise.c
+@@ -113,7 +113,7 @@ static void update_passive_instance(struct thermal_zone_device *tz,
+ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+ {
+-      long trip_temp;
++      int trip_temp;
+       enum thermal_trip_type trip_type;
+       enum thermal_trend trend;
+       struct thermal_instance *instance;
+@@ -135,7 +135,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+               trace_thermal_zone_trip(tz, trip, trip_type);
+       }
+-      dev_dbg(&tz->device, "Trip%d[type=%d,temp=%ld]:trend=%d,throttle=%d\n",
++      dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
+                               trip, trip_type, trip_temp, trend, throttle);
+       mutex_lock(&tz->lock);
+diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c
+index 9197fc0..74ea576 100644
+--- a/drivers/thermal/tegra_soctherm.c
++++ b/drivers/thermal/tegra_soctherm.c
+@@ -293,7 +293,7 @@ static int enable_tsensor(struct tegra_soctherm *tegra,
+  * H denotes an addition of 0.5 Celsius and N denotes negation
+  * of the final value.
+  */
+-static long translate_temp(u16 val)
++static int translate_temp(u16 val)
+ {
+       long t;
+@@ -306,7 +306,7 @@ static long translate_temp(u16 val)
+       return t;
+ }
+-static int tegra_thermctl_get_temp(void *data, long *out_temp)
++static int tegra_thermctl_get_temp(void *data, int *out_temp)
+ {
+       struct tegra_thermctl_zone *zone = data;
+       u32 val;
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 4108db7..62cc82a 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -363,7 +363,7 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz,
+ static void handle_critical_trips(struct thermal_zone_device *tz,
+                               int trip, enum thermal_trip_type trip_type)
+ {
+-      long trip_temp;
++      int trip_temp;
+       tz->ops->get_trip_temp(tz, trip, &trip_temp);
+@@ -411,12 +411,12 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+  *
+  * Return: On success returns 0, an error code otherwise
+  */
+-int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
++int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+       int ret = -EINVAL;
+ #ifdef CONFIG_THERMAL_EMULATION
+       int count;
+-      unsigned long crit_temp = -1UL;
++      int crit_temp = INT_MAX;
+       enum thermal_trip_type type;
+ #endif
+@@ -453,8 +453,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+ static void update_temperature(struct thermal_zone_device *tz)
+ {
+-      long temp;
+-      int ret;
++      int temp, ret;
+       ret = thermal_zone_get_temp(tz, &temp);
+       if (ret) {
+@@ -514,15 +513,14 @@ static ssize_t
+ temp_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+       struct thermal_zone_device *tz = to_thermal_zone(dev);
+-      long temperature;
+-      int ret;
++      int temperature, ret;
+       ret = thermal_zone_get_temp(tz, &temperature);
+       if (ret)
+               return ret;
+-      return sprintf(buf, "%ld\n", temperature);
++      return sprintf(buf, "%d\n", temperature);
+ }
+ static ssize_t
+@@ -626,7 +624,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
+ {
+       struct thermal_zone_device *tz = to_thermal_zone(dev);
+       int trip, ret;
+-      long temperature;
++      int temperature;
+       if (!tz->ops->get_trip_temp)
+               return -EPERM;
+@@ -639,7 +637,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
+       if (ret)
+               return ret;
+-      return sprintf(buf, "%ld\n", temperature);
++      return sprintf(buf, "%d\n", temperature);
+ }
+ static ssize_t
+@@ -648,7 +646,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
+ {
+       struct thermal_zone_device *tz = to_thermal_zone(dev);
+       int trip, ret;
+-      unsigned long temperature;
++      int temperature;
+       if (!tz->ops->set_trip_hyst)
+               return -EPERM;
+@@ -656,7 +654,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
+       if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip))
+               return -EINVAL;
+-      if (kstrtoul(buf, 10, &temperature))
++      if (kstrtoint(buf, 10, &temperature))
+               return -EINVAL;
+       /*
+@@ -675,7 +673,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
+ {
+       struct thermal_zone_device *tz = to_thermal_zone(dev);
+       int trip, ret;
+-      unsigned long temperature;
++      int temperature;
+       if (!tz->ops->get_trip_hyst)
+               return -EPERM;
+@@ -685,7 +683,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
+       ret = tz->ops->get_trip_hyst(tz, trip, &temperature);
+-      return ret ? ret : sprintf(buf, "%ld\n", temperature);
++      return ret ? ret : sprintf(buf, "%d\n", temperature);
+ }
+ static ssize_t
+diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
+index 1967bee..06fd2ed9 100644
+--- a/drivers/thermal/thermal_hwmon.c
++++ b/drivers/thermal/thermal_hwmon.c
+@@ -69,7 +69,7 @@ static DEVICE_ATTR(name, 0444, name_show, NULL);
+ static ssize_t
+ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-      long temperature;
++      int temperature;
+       int ret;
+       struct thermal_hwmon_attr *hwmon_attr
+                       = container_of(attr, struct thermal_hwmon_attr, attr);
+@@ -83,7 +83,7 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+       if (ret)
+               return ret;
+-      return sprintf(buf, "%ld\n", temperature);
++      return sprintf(buf, "%d\n", temperature);
+ }
+ static ssize_t
+@@ -95,14 +95,14 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, char *buf)
+                       = container_of(hwmon_attr, struct thermal_hwmon_temp,
+                                      temp_crit);
+       struct thermal_zone_device *tz = temp->tz;
+-      long temperature;
++      int temperature;
+       int ret;
+       ret = tz->ops->get_trip_temp(tz, 0, &temperature);
+       if (ret)
+               return ret;
+-      return sprintf(buf, "%ld\n", temperature);
++      return sprintf(buf, "%d\n", temperature);
+ }
+@@ -142,7 +142,7 @@ thermal_hwmon_lookup_temp(const struct thermal_hwmon_device *hwmon,
+ static bool thermal_zone_crit_temp_valid(struct thermal_zone_device *tz)
+ {
+-      unsigned long temp;
++      int temp;
+       return tz->ops->get_crit_temp && !tz->ops->get_crit_temp(tz, &temp);
+ }
+diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+index a38c175..d3a42bf 100644
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -76,14 +76,14 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
+ /* thermal zone ops */
+ /* Get temperature callback function for thermal zone*/
+-static inline int __ti_thermal_get_temp(void *devdata, long *temp)
++static inline int __ti_thermal_get_temp(void *devdata, int *temp)
+ {
+       struct thermal_zone_device *pcb_tz = NULL;
+       struct ti_thermal_data *data = devdata;
+       struct ti_bandgap *bgp;
+       const struct ti_temp_sensor *s;
+       int ret, tmp, slope, constant;
+-      unsigned long pcb_temp;
++      int pcb_temp;
+       if (!data)
+               return 0;
+@@ -119,7 +119,7 @@ static inline int __ti_thermal_get_temp(void *devdata, long *temp)
+ }
+ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
+-                                    unsigned long *temp)
++                                    int *temp)
+ {
+       struct ti_thermal_data *data = thermal->devdata;
+@@ -228,7 +228,7 @@ static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
+ /* Get trip temperature callback functions for thermal zone */
+ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
+-                                  int trip, unsigned long *temp)
++                                  int trip, int *temp)
+ {
+       if (!ti_thermal_is_valid_trip(trip))
+               return -EINVAL;
+@@ -279,7 +279,7 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+ /* Get critical temperature callback functions for thermal zone */
+ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
+-                                  unsigned long *temp)
++                                  int *temp)
+ {
+       /* shutdown zone */
+       return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
+diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
+index 9ea3d9d..054c6d45 100644
+--- a/drivers/thermal/x86_pkg_temp_thermal.c
++++ b/drivers/thermal/x86_pkg_temp_thermal.c
+@@ -164,7 +164,7 @@ err_ret:
+       return err;
+ }
+-static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
++static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+ {
+       u32 eax, edx;
+       struct phy_dev_entry *phy_dev_entry;
+@@ -175,7 +175,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem
+       if (eax & 0x80000000) {
+               *temp = phy_dev_entry->tj_max -
+                               ((eax >> 16) & 0x7f) * 1000;
+-              pr_debug("sys_get_curr_temp %ld\n", *temp);
++              pr_debug("sys_get_curr_temp %d\n", *temp);
+               return 0;
+       }
+@@ -183,7 +183,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *tem
+ }
+ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+-              int trip, unsigned long *temp)
++              int trip, int *temp)
+ {
+       u32 eax, edx;
+       struct phy_dev_entry *phy_dev_entry;
+@@ -214,13 +214,13 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+               *temp = phy_dev_entry->tj_max - thres_reg_value * 1000;
+       else
+               *temp = 0;
+-      pr_debug("sys_get_trip_temp %ld\n", *temp);
++      pr_debug("sys_get_trip_temp %d\n", *temp);
+       return 0;
+ }
+ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
+-                                                      unsigned long temp)
++                                                      int temp)
+ {
+       u32 l, h;
+       struct phy_dev_entry *phy_dev_entry;
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index 5eac316..e9f2863 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -86,23 +86,19 @@ struct thermal_zone_device_ops {
+                    struct thermal_cooling_device *);
+       int (*unbind) (struct thermal_zone_device *,
+                      struct thermal_cooling_device *);
+-      int (*get_temp) (struct thermal_zone_device *, unsigned long *);
++      int (*get_temp) (struct thermal_zone_device *, int *);
+       int (*get_mode) (struct thermal_zone_device *,
+                        enum thermal_device_mode *);
+       int (*set_mode) (struct thermal_zone_device *,
+               enum thermal_device_mode);
+       int (*get_trip_type) (struct thermal_zone_device *, int,
+               enum thermal_trip_type *);
+-      int (*get_trip_temp) (struct thermal_zone_device *, int,
+-                            unsigned long *);
+-      int (*set_trip_temp) (struct thermal_zone_device *, int,
+-                            unsigned long);
+-      int (*get_trip_hyst) (struct thermal_zone_device *, int,
+-                            unsigned long *);
+-      int (*set_trip_hyst) (struct thermal_zone_device *, int,
+-                            unsigned long);
+-      int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *);
+-      int (*set_emul_temp) (struct thermal_zone_device *, unsigned long);
++      int (*get_trip_temp) (struct thermal_zone_device *, int, int *);
++      int (*set_trip_temp) (struct thermal_zone_device *, int, int);
++      int (*get_trip_hyst) (struct thermal_zone_device *, int, int *);
++      int (*set_trip_hyst) (struct thermal_zone_device *, int, int);
++      int (*get_crit_temp) (struct thermal_zone_device *, int *);
++      int (*set_emul_temp) (struct thermal_zone_device *, int);
+       int (*get_trend) (struct thermal_zone_device *, int,
+                         enum thermal_trend *);
+       int (*notify) (struct thermal_zone_device *, int,
+@@ -272,9 +268,9 @@ struct thermal_genl_event {
+  *               temperature.
+  */
+ struct thermal_zone_of_device_ops {
+-      int (*get_temp)(void *, long *);
++      int (*get_temp)(void *, int *);
+       int (*get_trend)(void *, long *);
+-      int (*set_emul_temp)(void *, unsigned long);
++      int (*set_emul_temp)(void *, int);
+ };
+ /**
+@@ -335,7 +331,7 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
+                                  const struct thermal_cooling_device_ops *);
+ void thermal_cooling_device_unregister(struct thermal_cooling_device *);
+ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
+-int thermal_zone_get_temp(struct thermal_zone_device *tz, unsigned long *temp);
++int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
+ int get_tz_trend(struct thermal_zone_device *, int);
+ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
+@@ -378,7 +374,7 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
+               const char *name)
+ { return ERR_PTR(-ENODEV); }
+ static inline int thermal_zone_get_temp(
+-              struct thermal_zone_device *tz, unsigned long *temp)
++              struct thermal_zone_device *tz, int *temp)
+ { return -ENODEV; }
+ static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
+ { return -ENODEV; }
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0011-thermal-trivial-fix-typo-in-comment.patch b/target/linux/mediatek/patches/0011-thermal-trivial-fix-typo-in-comment.patch
new file mode 100644 (file)
index 0000000..4b9e0f9
--- /dev/null
@@ -0,0 +1,27 @@
+From a2214b951a1102ad2a2a72b6ae6e71c148f8249f Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:30 +0200
+Subject: [PATCH 11/76] thermal: trivial: fix typo in comment
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Acked-by: Eduardo Valentin <edubezval@gmail.com>
+---
+ drivers/thermal/thermal_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 62cc82a..244784f 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -402,7 +402,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+ }
+ /**
+- * thermal_zone_get_temp() - returns its the temperature of thermal zone
++ * thermal_zone_get_temp() - returns the temperature of a thermal zone
+  * @tz: a valid pointer to a struct thermal_zone_device
+  * @temp: a valid pointer to where to store the resulting temperature.
+  *
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0012-thermal-remove-useless-call-to-thermal_zone_device_s.patch b/target/linux/mediatek/patches/0012-thermal-remove-useless-call-to-thermal_zone_device_s.patch
new file mode 100644 (file)
index 0000000..2d64f49
--- /dev/null
@@ -0,0 +1,34 @@
+From 41adcc8cf217dfb4b70c2da061e70034b3c9add0 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:31 +0200
+Subject: [PATCH 12/76] thermal: remove useless call to
+ thermal_zone_device_set_polling
+
+When the thermal zone has no get_temp callback then thermal_zone_device_register()
+calls thermal_zone_device_set_polling() with a polling delay of 0. This
+only cancels the poll_queue. Since the poll_queue hasn't been scheduled this
+is a no-op. Remove it.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Acked-by: Eduardo Valentin <edubezval@gmail.com>
+---
+ drivers/thermal/thermal_core.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 244784f..1b68d20 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -1571,9 +1571,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+       INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
+-      if (!tz->ops->get_temp)
+-              thermal_zone_device_set_polling(tz, 0);
+-
+       thermal_zone_device_update(tz);
+       return tz;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0013-thermal-Use-IS_ENABLED-instead-of-ifdef.patch b/target/linux/mediatek/patches/0013-thermal-Use-IS_ENABLED-instead-of-ifdef.patch
new file mode 100644 (file)
index 0000000..0b033d6
--- /dev/null
@@ -0,0 +1,106 @@
+From bddcae2b66a23bfb6d381d089b0b862235480a9b Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:32 +0200
+Subject: [PATCH 13/76] thermal: Use IS_ENABLED instead of #ifdef
+
+Use IS_ENABLED(CONFIG_THERMAL_EMULATION) to make the code more readable
+and to get rid of the addtional #ifdef around the variable definitions
+in thermal_zone_get_temp().
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/thermal_core.c |   45 +++++++++++++++++-----------------------
+ 1 file changed, 19 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 1b68d20..3e0fe55 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -414,11 +414,9 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+       int ret = -EINVAL;
+-#ifdef CONFIG_THERMAL_EMULATION
+       int count;
+       int crit_temp = INT_MAX;
+       enum thermal_trip_type type;
+-#endif
+       if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
+               goto exit;
+@@ -426,25 +424,21 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+       mutex_lock(&tz->lock);
+       ret = tz->ops->get_temp(tz, temp);
+-#ifdef CONFIG_THERMAL_EMULATION
+-      if (!tz->emul_temperature)
+-              goto skip_emul;
+-
+-      for (count = 0; count < tz->trips; count++) {
+-              ret = tz->ops->get_trip_type(tz, count, &type);
+-              if (!ret && type == THERMAL_TRIP_CRITICAL) {
+-                      ret = tz->ops->get_trip_temp(tz, count, &crit_temp);
+-                      break;
+-              }
+-      }
+-      if (ret)
+-              goto skip_emul;
++      if (IS_ENABLED(CONFIG_THERMAL_EMULATION) && tz->emul_temperature) {
++              for (count = 0; count < tz->trips; count++) {
++                      ret = tz->ops->get_trip_type(tz, count, &type);
++                      if (!ret && type == THERMAL_TRIP_CRITICAL) {
++                              ret = tz->ops->get_trip_temp(tz, count,
++                                              &crit_temp);
++                              break;
++                      }
++              }
+-      if (*temp < crit_temp)
+-              *temp = tz->emul_temperature;
+-skip_emul:
+-#endif
++              if (!ret && *temp < crit_temp)
++                      *temp = tz->emul_temperature;
++      }
++ 
+       mutex_unlock(&tz->lock);
+ exit:
+       return ret;
+@@ -780,7 +774,6 @@ policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
+       return sprintf(buf, "%s\n", tz->governor->name);
+ }
+-#ifdef CONFIG_THERMAL_EMULATION
+ static ssize_t
+ emul_temp_store(struct device *dev, struct device_attribute *attr,
+                    const char *buf, size_t count)
+@@ -806,7 +799,6 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
+       return ret ? ret : count;
+ }
+ static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
+-#endif/*CONFIG_THERMAL_EMULATION*/
+ static DEVICE_ATTR(type, 0444, type_show, NULL);
+ static DEVICE_ATTR(temp, 0444, temp_show, NULL);
+@@ -1536,11 +1528,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+                       goto unregister;
+       }
+-#ifdef CONFIG_THERMAL_EMULATION
+-      result = device_create_file(&tz->device, &dev_attr_emul_temp);
+-      if (result)
+-              goto unregister;
+-#endif
++      if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
++              result = device_create_file(&tz->device, &dev_attr_emul_temp);
++              if (result)
++                      goto unregister;
++      }
++
+       /* Create policy attribute */
+       result = device_create_file(&tz->device, &dev_attr_policy);
+       if (result)
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0014-thermal-Add-comment-explaining-test-for-critical-tem.patch b/target/linux/mediatek/patches/0014-thermal-Add-comment-explaining-test-for-critical-tem.patch
new file mode 100644 (file)
index 0000000..56d3e4f
--- /dev/null
@@ -0,0 +1,34 @@
+From 18f50eae474edc716b01959fad6898c8553b131c Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:33 +0200
+Subject: [PATCH 14/76] thermal: Add comment explaining test for critical
+ temperature
+
+The code testing if a temperature should be emulated or not is
+not obvious. Add a comment explaining why this test is done.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
+---
+ drivers/thermal/thermal_core.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 3e0fe55..e204deb 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -435,6 +435,11 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+                       }
+               }
++              /*
++               * Only allow emulating a temperature when the real temperature
++               * is below the critical temperature so that the emulation code
++               * cannot hide critical conditions.
++               */
+               if (!ret && *temp < crit_temp)
+                       *temp = tz->emul_temperature;
+       }
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0015-thermal-inline-only-once-used-function.patch b/target/linux/mediatek/patches/0015-thermal-inline-only-once-used-function.patch
new file mode 100644 (file)
index 0000000..e050ae7
--- /dev/null
@@ -0,0 +1,53 @@
+From 0b729a98127ef045096edf20dfe5c4eadac21d44 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:34 +0200
+Subject: [PATCH 15/76] thermal: inline only once used function
+
+Inline update_temperature into its only caller to make the code
+more readable.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
+---
+ drivers/thermal/thermal_core.c |   17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index e204deb..19da022 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -450,9 +450,12 @@ exit:
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+-static void update_temperature(struct thermal_zone_device *tz)
++void thermal_zone_device_update(struct thermal_zone_device *tz)
+ {
+-      int temp, ret;
++      int temp, ret, count;
++
++      if (!tz->ops->get_temp)
++              return;
+       ret = thermal_zone_get_temp(tz, &temp);
+       if (ret) {
+@@ -471,16 +474,6 @@ static void update_temperature(struct thermal_zone_device *tz)
+       trace_thermal_temperature(tz);
+       dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
+                               tz->last_temperature, tz->temperature);
+-}
+-
+-void thermal_zone_device_update(struct thermal_zone_device *tz)
+-{
+-      int count;
+-
+-      if (!tz->ops->get_temp)
+-              return;
+-
+-      update_temperature(tz);
+       for (count = 0; count < tz->trips; count++)
+               handle_thermal_trip(tz, count);
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0016-thermal-streamline-get_trend-callbacks.patch b/target/linux/mediatek/patches/0016-thermal-streamline-get_trend-callbacks.patch
new file mode 100644 (file)
index 0000000..99d490f
--- /dev/null
@@ -0,0 +1,123 @@
+From 5da86f6a2b4c2c318e153649dc8fd34fe73f8292 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:35 +0200
+Subject: [PATCH 16/76] thermal: streamline get_trend callbacks
+
+The .get_trend callback in struct thermal_zone_device_ops has the prototype:
+
+       int (*get_trend) (struct thermal_zone_device *, int,
+                         enum thermal_trend *);
+
+whereas the .get_trend callback in struct thermal_zone_of_device_ops has:
+
+       int (*get_trend)(void *, long *);
+
+Streamline both prototypes and add the trip argument to the OF callback
+aswell and use enum thermal_trend * instead of an integer pointer.
+
+While the OF prototype may be the better one, this should be decided at
+framework level and not on OF level.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/of-thermal.c                       |   11 +--------
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c |   25 +++++++-------------
+ include/linux/thermal.h                            |    2 +-
+ 3 files changed, 10 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index 03839df..c84404d 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -187,24 +187,15 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
+                               enum thermal_trend *trend)
+ {
+       struct __thermal_zone *data = tz->devdata;
+-      long dev_trend;
+       int r;
+       if (!data->ops->get_trend)
+               return -EINVAL;
+-      r = data->ops->get_trend(data->sensor_data, &dev_trend);
++      r = data->ops->get_trend(data->sensor_data, trip, trend);
+       if (r)
+               return r;
+-      /* TODO: These intervals might have some thresholds, but in core code */
+-      if (dev_trend > 0)
+-              *trend = THERMAL_TREND_RAISING;
+-      else if (dev_trend < 0)
+-              *trend = THERMAL_TREND_DROPPING;
+-      else
+-              *trend = THERMAL_TREND_STABLE;
+-
+       return 0;
+ }
+diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+index d3a42bf..ade78eb 100644
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -238,7 +238,7 @@ static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
+       return 0;
+ }
+-static int __ti_thermal_get_trend(void *p, long *trend)
++static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
+ {
+       struct ti_thermal_data *data = p;
+       struct ti_bandgap *bgp;
+@@ -251,22 +251,6 @@ static int __ti_thermal_get_trend(void *p, long *trend)
+       if (ret)
+               return ret;
+-      *trend = tr;
+-
+-      return 0;
+-}
+-
+-/* Get the temperature trend callback functions for thermal zone */
+-static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+-                              int trip, enum thermal_trend *trend)
+-{
+-      int ret;
+-      long tr;
+-
+-      ret = __ti_thermal_get_trend(thermal->devdata, &tr);
+-      if (ret)
+-              return ret;
+-
+       if (tr > 0)
+               *trend = THERMAL_TREND_RAISING;
+       else if (tr < 0)
+@@ -277,6 +261,13 @@ static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
+       return 0;
+ }
++/* Get the temperature trend callback functions for thermal zone */
++static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
++                              int trip, enum thermal_trend *trend)
++{
++      return __ti_thermal_get_trend(thermal->devdata, trip, trend);
++}
++
+ /* Get critical temperature callback functions for thermal zone */
+ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
+                                   int *temp)
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index e9f2863..5c6a589 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -269,7 +269,7 @@ struct thermal_genl_event {
+  */
+ struct thermal_zone_of_device_ops {
+       int (*get_temp)(void *, int *);
+-      int (*get_trend)(void *, long *);
++      int (*get_trend)(void *, int, enum thermal_trend *);
+       int (*set_emul_temp)(void *, int);
+ };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0017-thermal-Allow-sensor-ops-to-fail-with-ENOSYS.patch b/target/linux/mediatek/patches/0017-thermal-Allow-sensor-ops-to-fail-with-ENOSYS.patch
new file mode 100644 (file)
index 0000000..f533a88
--- /dev/null
@@ -0,0 +1,90 @@
+From 5b622cb2d6ff44b1fb0750beee61f93f2c00548a Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:36 +0200
+Subject: [PATCH 17/76] thermal: Allow sensor ops to fail with -ENOSYS
+
+The thermal core uses the existence of the .get_temp, .get_trend and
+.set_emul_temp to detect whether this operation exists and should be
+used or whether it should be emulated in software. This makes problems
+for of-thermal which has to modify the struct thermal_zone_device_ops
+during runtime whenever a sensor is registered or unregistered.
+
+Let the core test for -ENOSYS from these callbacks and treat it like
+if the callbacks were not present.
+
+This allows of-thermal to always set the sensor related callbacks and
+to make struct thermal_zone_device_ops const again.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/thermal_core.c |   24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 19da022..3d8f9f9 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -413,13 +413,16 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
+  */
+ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+-      int ret = -EINVAL;
++      int ret;
+       int count;
+       int crit_temp = INT_MAX;
+       enum thermal_trip_type type;
+-      if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
+-              goto exit;
++      if (!tz || IS_ERR(tz))
++              return -EINVAL;
++
++      if (!tz->ops->get_temp)
++              return -ENOSYS;
+       mutex_lock(&tz->lock);
+@@ -445,7 +448,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+       }
+  
+       mutex_unlock(&tz->lock);
+-exit:
++
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
+@@ -454,10 +457,11 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
+ {
+       int temp, ret, count;
+-      if (!tz->ops->get_temp)
++      ret = thermal_zone_get_temp(tz, &temp);
++
++      if (ret == -ENOSYS)
+               return;
+-      ret = thermal_zone_get_temp(tz, &temp);
+       if (ret) {
+               if (ret != -EAGAIN)
+                       dev_warn(&tz->device,
+@@ -783,10 +787,16 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
+       if (kstrtoul(buf, 10, &temperature))
+               return -EINVAL;
+-      if (!tz->ops->set_emul_temp) {
++      if (tz->ops->set_emul_temp)
++              ret = tz->ops->set_emul_temp(tz, temperature);
++      else
++              ret = -ENOSYS;
++
++      if (ret == -ENOSYS) {
+               mutex_lock(&tz->lock);
+               tz->emul_temperature = temperature;
+               mutex_unlock(&tz->lock);
++              ret = 0;
+       } else {
+               ret = tz->ops->set_emul_temp(tz, temperature);
+       }
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0018-thermal-of-always-set-sensor-related-callbacks.patch b/target/linux/mediatek/patches/0018-thermal-of-always-set-sensor-related-callbacks.patch
new file mode 100644 (file)
index 0000000..e47e8a2
--- /dev/null
@@ -0,0 +1,129 @@
+From 8c9c4ed500e92c10dc4965dcd00692b3102a328a Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:37 +0200
+Subject: [PATCH 18/76] thermal: of: always set sensor related callbacks
+
+Now that the thermal core treats -ENOSYS like the callbacks were
+not present at all we no longer have to overwrite the ops during
+runtime but instead can always set them and return -ENOSYS if no
+sensor is registered.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/of-thermal.c |   33 +++++++++++++--------------------
+ 1 file changed, 13 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index c84404d..b9c35bd 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -91,7 +91,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
+ {
+       struct __thermal_zone *data = tz->devdata;
+-      if (!data->ops->get_temp)
++      if (!data->ops)
+               return -EINVAL;
+       return data->ops->get_temp(data->sensor_data, temp);
+@@ -178,7 +178,7 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
+       struct __thermal_zone *data = tz->devdata;
+       if (!data->ops || !data->ops->set_emul_temp)
+-              return -EINVAL;
++              return -ENOSYS;
+       return data->ops->set_emul_temp(data->sensor_data, temp);
+ }
+@@ -189,8 +189,8 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
+       struct __thermal_zone *data = tz->devdata;
+       int r;
+-      if (!data->ops->get_trend)
+-              return -EINVAL;
++      if (!data->ops || !data->ops->get_trend)
++              return -ENOSYS;
+       r = data->ops->get_trend(data->sensor_data, trip, trend);
+       if (r)
+@@ -366,6 +366,10 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+ }
+ static struct thermal_zone_device_ops of_thermal_ops = {
++      .get_temp = of_thermal_get_temp,
++      .get_trend = of_thermal_get_trend,
++      .set_emul_temp = of_thermal_set_emul_temp,
++
+       .get_mode = of_thermal_get_mode,
+       .set_mode = of_thermal_set_mode,
+@@ -399,13 +403,13 @@ thermal_zone_of_add_sensor(struct device_node *zone,
+       if (!ops)
+               return ERR_PTR(-EINVAL);
++      if (!ops->get_temp)
++              return ERR_PTR(-EINVAL);
++
+       mutex_lock(&tzd->lock);
+       tz->ops = ops;
+       tz->sensor_data = data;
+-      tzd->ops->get_temp = of_thermal_get_temp;
+-      tzd->ops->get_trend = of_thermal_get_trend;
+-      tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
+       mutex_unlock(&tzd->lock);
+       return tzd;
+@@ -535,9 +539,6 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
+               return;
+       mutex_lock(&tzd->lock);
+-      tzd->ops->get_temp = NULL;
+-      tzd->ops->get_trend = NULL;
+-      tzd->ops->set_emul_temp = NULL;
+       tz->ops = NULL;
+       tz->sensor_data = NULL;
+@@ -845,7 +846,6 @@ int __init of_parse_thermal_zones(void)
+ {
+       struct device_node *np, *child;
+       struct __thermal_zone *tz;
+-      struct thermal_zone_device_ops *ops;
+       np = of_find_node_by_name(NULL, "thermal-zones");
+       if (!np) {
+@@ -869,29 +869,22 @@ int __init of_parse_thermal_zones(void)
+                       continue;
+               }
+-              ops = kmemdup(&of_thermal_ops, sizeof(*ops), GFP_KERNEL);
+-              if (!ops)
+-                      goto exit_free;
+-
+               tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
+-              if (!tzp) {
+-                      kfree(ops);
++              if (!tzp)
+                       goto exit_free;
+-              }
+               /* No hwmon because there might be hwmon drivers registering */
+               tzp->no_hwmon = true;
+               zone = thermal_zone_device_register(child->name, tz->ntrips,
+                                                   0, tz,
+-                                                  ops, tzp,
++                                                  &of_thermal_ops, tzp,
+                                                   tz->passive_delay,
+                                                   tz->polling_delay);
+               if (IS_ERR(zone)) {
+                       pr_err("Failed to build %s zone %ld\n", child->name,
+                              PTR_ERR(zone));
+                       kfree(tzp);
+-                      kfree(ops);
+                       of_thermal_free_zone(tz);
+                       /* attempting to build remaining zones still */
+               }
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0019-thermal-Make-struct-thermal_zone_device_ops-const.patch b/target/linux/mediatek/patches/0019-thermal-Make-struct-thermal_zone_device_ops-const.patch
new file mode 100644 (file)
index 0000000..1ca9ab8
--- /dev/null
@@ -0,0 +1,327 @@
+From 7cbee588bc6eee59c025f89cf9324943fda98934 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:38 +0200
+Subject: [PATCH 19/76] thermal: Make struct thermal_zone_device_ops const
+
+Now that the of thermal support no longer changes the
+thermal_zone_device_ops it can be const again.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ Documentation/thermal/sysfs-api.txt                    |    2 +-
+ drivers/acpi/thermal.c                                 |    2 +-
+ drivers/platform/x86/acerhdf.c                         |    2 +-
+ drivers/platform/x86/intel_mid_thermal.c               |    2 +-
+ drivers/power/power_supply_core.c                      |    2 +-
+ drivers/thermal/armada_thermal.c                       |    2 +-
+ drivers/thermal/db8500_thermal.c                       |    2 +-
+ drivers/thermal/dove_thermal.c                         |    2 +-
+ drivers/thermal/imx_thermal.c                          |    2 +-
+ drivers/thermal/int340x_thermal/int3400_thermal.c      |    2 +-
+ drivers/thermal/int340x_thermal/int340x_thermal_zone.c |    2 +-
+ drivers/thermal/intel_soc_dts_thermal.c                |    2 +-
+ drivers/thermal/kirkwood_thermal.c                     |    2 +-
+ drivers/thermal/of-thermal.c                           |    2 +-
+ drivers/thermal/rcar_thermal.c                         |    2 +-
+ drivers/thermal/spear_thermal.c                        |    2 +-
+ drivers/thermal/st/st_thermal.c                        |    2 +-
+ drivers/thermal/thermal_core.c                         |    2 +-
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c     |    2 +-
+ drivers/thermal/x86_pkg_temp_thermal.c                 |    2 +-
+ include/linux/thermal.h                                |    6 +++---
+ 21 files changed, 23 insertions(+), 23 deletions(-)
+
+diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
+index 87519cb..bb346a2 100644
+--- a/Documentation/thermal/sysfs-api.txt
++++ b/Documentation/thermal/sysfs-api.txt
+@@ -33,7 +33,7 @@ temperature) and throttle appropriate devices.
+ 1.1 thermal zone device interface
+ 1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *type,
+               int trips, int mask, void *devdata,
+-              struct thermal_zone_device_ops *ops,
++              const struct thermal_zone_device_ops *ops,
+               const struct thermal_zone_params *tzp,
+               int passive_delay, int polling_delay))
+diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
+index 68bff60..6b11462 100644
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -869,7 +869,7 @@ acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
+       return acpi_thermal_cooling_device_cb(thermal, cdev, false);
+ }
+-static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
++static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
+       .bind = acpi_thermal_bind_cooling_device,
+       .unbind = acpi_thermal_unbind_cooling_device,
+       .get_temp = thermal_get_temp,
+diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
+index f2ce63c..bae9ca0 100644
+--- a/drivers/platform/x86/acerhdf.c
++++ b/drivers/platform/x86/acerhdf.c
+@@ -482,7 +482,7 @@ static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
+ }
+ /* bind callback functions to thermalzone */
+-static struct thermal_zone_device_ops acerhdf_dev_ops = {
++static const struct thermal_zone_device_ops acerhdf_dev_ops = {
+       .bind = acerhdf_bind,
+       .unbind = acerhdf_unbind,
+       .get_temp = acerhdf_get_ec_temp,
+diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c
+index 0944e83..069d36b 100644
+--- a/drivers/platform/x86/intel_mid_thermal.c
++++ b/drivers/platform/x86/intel_mid_thermal.c
+@@ -460,7 +460,7 @@ static int read_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+ }
+ /* Can't be const */
+-static struct thermal_zone_device_ops tzd_ops = {
++static const struct thermal_zone_device_ops tzd_ops = {
+       .get_temp = read_curr_temp,
+ };
+diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
+index 87e2fd1..878cb4e 100644
+--- a/drivers/power/power_supply_core.c
++++ b/drivers/power/power_supply_core.c
+@@ -509,7 +509,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
+       return ret;
+ }
+-static struct thermal_zone_device_ops psy_tzd_ops = {
++static const struct thermal_zone_device_ops psy_tzd_ops = {
+       .get_temp = power_supply_read_temp,
+ };
+diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
+index 26b8d32..3f59c8b 100644
+--- a/drivers/thermal/armada_thermal.c
++++ b/drivers/thermal/armada_thermal.c
+@@ -183,7 +183,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal,
+       return 0;
+ }
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+       .get_temp = armada_get_temp,
+ };
+diff --git a/drivers/thermal/db8500_thermal.c b/drivers/thermal/db8500_thermal.c
+index b3eca71..38d6aab9 100644
+--- a/drivers/thermal/db8500_thermal.c
++++ b/drivers/thermal/db8500_thermal.c
+@@ -210,7 +210,7 @@ static int db8500_sys_get_crit_temp(struct thermal_zone_device *thermal,
+       return -EINVAL;
+ }
+-static struct thermal_zone_device_ops thdev_ops = {
++static const struct thermal_zone_device_ops thdev_ops = {
+       .bind = db8500_cdev_bind,
+       .unbind = db8500_cdev_unbind,
+       .get_temp = db8500_sys_get_temp,
+diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
+index a0bc9de..e8fd627 100644
+--- a/drivers/thermal/dove_thermal.c
++++ b/drivers/thermal/dove_thermal.c
+@@ -118,7 +118,7 @@ static int dove_get_temp(struct thermal_zone_device *thermal,
+       return 0;
+ }
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+       .get_temp = dove_get_temp,
+ };
+diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
+index f1424f0..8a3cfed 100644
+--- a/drivers/thermal/imx_thermal.c
++++ b/drivers/thermal/imx_thermal.c
+@@ -332,7 +332,7 @@ static int imx_unbind(struct thermal_zone_device *tz,
+       return 0;
+ }
+-static struct thermal_zone_device_ops imx_tz_ops = {
++static const struct thermal_zone_device_ops imx_tz_ops = {
+       .bind = imx_bind,
+       .unbind = imx_unbind,
+       .get_temp = imx_get_temp,
+diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
+index 031018e..96bdf8a 100644
+--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
++++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
+@@ -231,7 +231,7 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
+       return result;
+ }
+-static struct thermal_zone_device_ops int3400_thermal_ops = {
++static const struct thermal_zone_device_ops int3400_thermal_ops = {
+       .get_temp = int3400_thermal_get_temp,
+ };
+diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+index b9b2666..bd9f9e8 100644
+--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
++++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+@@ -154,7 +154,7 @@ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
+       return 0;
+ }
+-static struct thermal_zone_device_ops int340x_thermal_zone_ops = {
++static const struct thermal_zone_device_ops int340x_thermal_zone_ops = {
+       .get_temp       = int340x_thermal_get_zone_temp,
+       .get_trip_temp  = int340x_thermal_get_trip_temp,
+       .get_trip_type  = int340x_thermal_get_trip_type,
+diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
+index fd550b9..625ba6f 100644
+--- a/drivers/thermal/intel_soc_dts_thermal.c
++++ b/drivers/thermal/intel_soc_dts_thermal.c
+@@ -270,7 +270,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+       return 0;
+ }
+-static struct thermal_zone_device_ops tzone_ops = {
++static const struct thermal_zone_device_ops tzone_ops = {
+       .get_temp = sys_get_curr_temp,
+       .get_trip_temp = sys_get_trip_temp,
+       .get_trip_type = sys_get_trip_type,
+diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c
+index 11041fe..abba3e2 100644
+--- a/drivers/thermal/kirkwood_thermal.c
++++ b/drivers/thermal/kirkwood_thermal.c
+@@ -60,7 +60,7 @@ static int kirkwood_get_temp(struct thermal_zone_device *thermal,
+       return 0;
+ }
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+       .get_temp = kirkwood_get_temp,
+ };
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index b9c35bd..bd3185e 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -365,7 +365,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+       return -EINVAL;
+ }
+-static struct thermal_zone_device_ops of_thermal_ops = {
++static const struct thermal_zone_device_ops of_thermal_ops = {
+       .get_temp = of_thermal_get_temp,
+       .get_trend = of_thermal_get_trend,
+       .set_emul_temp = of_thermal_set_emul_temp,
+diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
+index 5d4ae7d..320ceac 100644
+--- a/drivers/thermal/rcar_thermal.c
++++ b/drivers/thermal/rcar_thermal.c
+@@ -270,7 +270,7 @@ static int rcar_thermal_notify(struct thermal_zone_device *zone,
+       return 0;
+ }
+-static struct thermal_zone_device_ops rcar_thermal_zone_ops = {
++static const struct thermal_zone_device_ops rcar_thermal_zone_ops = {
+       .get_temp       = rcar_thermal_get_temp,
+       .get_trip_type  = rcar_thermal_get_trip_type,
+       .get_trip_temp  = rcar_thermal_get_trip_temp,
+diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
+index 534dd91..ec07743 100644
+--- a/drivers/thermal/spear_thermal.c
++++ b/drivers/thermal/spear_thermal.c
+@@ -50,7 +50,7 @@ static inline int thermal_get_temp(struct thermal_zone_device *thermal,
+       return 0;
+ }
+-static struct thermal_zone_device_ops ops = {
++static const struct thermal_zone_device_ops ops = {
+       .get_temp = thermal_get_temp,
+ };
+diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c
+index 44cbba9..0cb5c19 100644
+--- a/drivers/thermal/st/st_thermal.c
++++ b/drivers/thermal/st/st_thermal.c
+@@ -175,7 +175,7 @@ static int st_thermal_get_trip_temp(struct thermal_zone_device *th,
+       return 0;
+ }
+-static struct thermal_zone_device_ops st_tz_ops = {
++static const struct thermal_zone_device_ops st_tz_ops = {
+       .get_temp       = st_thermal_get_temp,
+       .get_trip_type  = st_thermal_get_trip_type,
+       .get_trip_temp  = st_thermal_get_trip_temp,
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 3d8f9f9..6bbf61f 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -1451,7 +1451,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
+  */
+ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+       int trips, int mask, void *devdata,
+-      struct thermal_zone_device_ops *ops,
++      const struct thermal_zone_device_ops *ops,
+       const struct thermal_zone_params *tzp,
+       int passive_delay, int polling_delay)
+ {
+diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+index ade78eb..e9c82fc 100644
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -281,7 +281,7 @@ static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
+       .get_trend = __ti_thermal_get_trend,
+ };
+-static struct thermal_zone_device_ops ti_thermal_ops = {
++static const struct thermal_zone_device_ops ti_thermal_ops = {
+       .get_temp = ti_thermal_get_temp,
+       .get_trend = ti_thermal_get_trend,
+       .bind = ti_thermal_bind,
+diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
+index 054c6d45..bb2b975 100644
+--- a/drivers/thermal/x86_pkg_temp_thermal.c
++++ b/drivers/thermal/x86_pkg_temp_thermal.c
+@@ -274,7 +274,7 @@ static int sys_get_trip_type(struct thermal_zone_device *thermal,
+ }
+ /* Thermal zone callback registry */
+-static struct thermal_zone_device_ops tzone_ops = {
++static const struct thermal_zone_device_ops tzone_ops = {
+       .get_temp = sys_get_curr_temp,
+       .get_trip_temp = sys_get_trip_temp,
+       .get_trip_type = sys_get_trip_type,
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index 5c6a589..07bd5e8 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -181,7 +181,7 @@ struct thermal_zone_device {
+       int emul_temperature;
+       int passive;
+       unsigned int forced_passive;
+-      struct thermal_zone_device_ops *ops;
++      const struct thermal_zone_device_ops *ops;
+       const struct thermal_zone_params *tzp;
+       struct thermal_governor *governor;
+       struct list_head thermal_instances;
+@@ -313,7 +313,7 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
+ #if IS_ENABLED(CONFIG_THERMAL)
+ struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
+-              void *, struct thermal_zone_device_ops *,
++              void *, const struct thermal_zone_device_ops *,
+               const struct thermal_zone_params *, int, int);
+ void thermal_zone_device_unregister(struct thermal_zone_device *);
+@@ -341,7 +341,7 @@ void thermal_notify_framework(struct thermal_zone_device *, int);
+ #else
+ static inline struct thermal_zone_device *thermal_zone_device_register(
+       const char *type, int trips, int mask, void *devdata,
+-      struct thermal_zone_device_ops *ops,
++      const struct thermal_zone_device_ops *ops,
+       const struct thermal_zone_params *tzp,
+       int passive_delay, int polling_delay)
+ { return ERR_PTR(-ENODEV); }
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0020-thermal-thermal-Add-support-for-hardware-tracked-tri.patch b/target/linux/mediatek/patches/0020-thermal-thermal-Add-support-for-hardware-tracked-tri.patch
new file mode 100644 (file)
index 0000000..6a48350
--- /dev/null
@@ -0,0 +1,124 @@
+From 346632bc00fe71c269709702fecb474bb22e933e Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:39 +0200
+Subject: [PATCH 20/76] thermal: thermal: Add support for hardware-tracked
+ trip points
+
+This adds support for hardware-tracked trip points to the device tree
+thermal sensor framework.
+
+The framework supports an arbitrary number of trip points. Whenever
+the current temperature is updated, the trip points immediately
+below and above the current temperature are found. A .set_trips
+callback is then called with the temperatures. If there is no trip
+point above or below the current temperature, the passed trip
+temperature will be -INT_MAX or INT_MAX respectively. In this callback,
+the driver should program the hardware such that it is notified
+when either of these trip points are triggered. When a trip point
+is triggered, the driver should call `thermal_zone_device_update'
+for the respective thermal zone. This will cause the trip points
+to be updated again.
+
+If .set_trips is not implemented, the framework behaves as before.
+
+This patch is based on an earlier version from Mikko Perttunen
+<mikko.perttunen@kapsi.fi>
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/thermal_core.c |   43 ++++++++++++++++++++++++++++++++++++++++
+ include/linux/thermal.h        |    3 +++
+ 2 files changed, 46 insertions(+)
+
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index 6bbf61f..3ae1795 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -453,6 +453,45 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
++static void thermal_zone_set_trips(struct thermal_zone_device *tz)
++{
++      int low = -INT_MAX;
++      int high = INT_MAX;
++      int trip_temp, hysteresis;
++      int temp = tz->temperature;
++      int i;
++
++      if (!tz->ops->set_trips)
++              return;
++
++      /* No need to change trip points */
++      if (temp > tz->prev_low_trip && temp < tz->prev_high_trip)
++              return;
++
++      for (i = 0; i < tz->trips; i++) {
++              int trip_low;
++
++              tz->ops->get_trip_temp(tz, i, &trip_temp);
++              tz->ops->get_trip_hyst(tz, i, &hysteresis);
++
++              trip_low = trip_temp - hysteresis;
++
++              if (trip_low < temp && trip_low > low)
++                      low = trip_low;
++
++              if (trip_temp > temp && trip_temp < high)
++                      high = trip_temp;
++      }
++
++      tz->prev_low_trip = low;
++      tz->prev_high_trip = high;
++
++      dev_dbg(&tz->device, "new temperature boundaries: %d < x < %d\n",
++                      low, high);
++
++      tz->ops->set_trips(tz, low, high);
++}
++
+ void thermal_zone_device_update(struct thermal_zone_device *tz)
+ {
+       int temp, ret, count;
+@@ -479,6 +518,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
+       dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
+                               tz->last_temperature, tz->temperature);
++      thermal_zone_set_trips(tz);
++
+       for (count = 0; count < tz->trips; count++)
+               handle_thermal_trip(tz, count);
+ }
+@@ -1494,6 +1535,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
+       tz->trips = trips;
+       tz->passive_delay = passive_delay;
+       tz->polling_delay = polling_delay;
++      tz->prev_low_trip = INT_MAX;
++      tz->prev_high_trip = -INT_MAX;
+       dev_set_name(&tz->device, "thermal_zone%d", tz->id);
+       result = device_register(&tz->device);
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index 07bd5e8..aef6e13 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -87,6 +87,7 @@ struct thermal_zone_device_ops {
+       int (*unbind) (struct thermal_zone_device *,
+                      struct thermal_cooling_device *);
+       int (*get_temp) (struct thermal_zone_device *, int *);
++      int (*set_trips) (struct thermal_zone_device *, int, int);
+       int (*get_mode) (struct thermal_zone_device *,
+                        enum thermal_device_mode *);
+       int (*set_mode) (struct thermal_zone_device *,
+@@ -180,6 +181,8 @@ struct thermal_zone_device {
+       int last_temperature;
+       int emul_temperature;
+       int passive;
++      int prev_low_trip;
++      int prev_high_trip;
+       unsigned int forced_passive;
+       const struct thermal_zone_device_ops *ops;
+       const struct thermal_zone_params *tzp;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0021-thermal-of-implement-.set_trips-for-device-tree-ther.patch b/target/linux/mediatek/patches/0021-thermal-of-implement-.set_trips-for-device-tree-ther.patch
new file mode 100644 (file)
index 0000000..81b5043
--- /dev/null
@@ -0,0 +1,65 @@
+From 525f68bb9d9f6334dbcd2b5ec99f9d797ff53618 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:40 +0200
+Subject: [PATCH 21/76] thermal: of: implement .set_trips for device tree
+ thermal zones
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/of-thermal.c |   12 ++++++++++++
+ include/linux/thermal.h      |    3 +++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
+index bd3185e..f8dd847 100644
+--- a/drivers/thermal/of-thermal.c
++++ b/drivers/thermal/of-thermal.c
+@@ -97,6 +97,17 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
+       return data->ops->get_temp(data->sensor_data, temp);
+ }
++static int of_thermal_set_trips(struct thermal_zone_device *tz,
++                             int low, int high)
++{
++      struct __thermal_zone *data = tz->devdata;
++
++      if (!data->ops || !data->ops->set_trips)
++              return -ENOSYS;
++
++      return data->ops->set_trips(data->sensor_data, low, high);
++}
++
+ /**
+  * of_thermal_get_ntrips - function to export number of available trip
+  *                       points.
+@@ -367,6 +378,7 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz,
+ static const struct thermal_zone_device_ops of_thermal_ops = {
+       .get_temp = of_thermal_get_temp,
++      .set_trips = of_thermal_set_trips,
+       .get_trend = of_thermal_get_trend,
+       .set_emul_temp = of_thermal_set_emul_temp,
+diff --git a/include/linux/thermal.h b/include/linux/thermal.h
+index aef6e13..b751f6b 100644
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -267,12 +267,15 @@ struct thermal_genl_event {
+  *
+  * Optional:
+  * @get_trend: a pointer to a function that reads the sensor temperature trend.
++ * @set_trips: a pointer to a function that sets a temperature window which shall
++ *             trigger an interrupt when it is left.
+  * @set_emul_temp: a pointer to a function that sets sensor emulated
+  *               temperature.
+  */
+ struct thermal_zone_of_device_ops {
+       int (*get_temp)(void *, int *);
+       int (*get_trend)(void *, int, enum thermal_trend *);
++      int (*set_trips)(void *, int, int);
+       int (*set_emul_temp)(void *, int);
+ };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0022-dt-bindings-thermal-Add-binding-document-for-Mediate.patch b/target/linux/mediatek/patches/0022-dt-bindings-thermal-Add-binding-document-for-Mediate.patch
new file mode 100644 (file)
index 0000000..c556ac0
--- /dev/null
@@ -0,0 +1,57 @@
+From 9b799b8a4ecbf560f8fb996e8e5147a8f7b9a1b3 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:41 +0200
+Subject: [PATCH 22/76] dt-bindings: thermal: Add binding document for
+ Mediatek thermal controller
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ .../bindings/thermal/mediatek-thermal.txt          |   36 ++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+
+diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+new file mode 100644
+index 0000000..adf5d2c
+--- /dev/null
++++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+@@ -0,0 +1,36 @@
++* Mediatek Thermal
++
++This describes the device tree binding for the Mediatek thermal controller
++which measures the on-SoC temperatures. This device does not have its own ADC,
++instead it directly controls the AUXADC via AHB bus accesses. For this reason
++this device needs phandles to the AUXADC.
++
++Required properties:
++- compatible: "mediatek,mt8173-thermal"
++- reg: Address range of the thermal controller
++- interrupts: IRQ for the thermal controller
++- clocks, clock-names: Clocks needed for the thermal controller. required
++                       clocks are:
++              "therm":        Main clock needed for register access
++              "auxadc":       The AUXADC clock
++- resets, reset-names: Reference to the reset controller controlling the thermal
++                       controller. Required reset-names:
++              "therm":        The main reset line
++- auxadc: A phandle to the AUXADC which the thermal controller uses
++- apmixedsys: A phandle to the APMIXEDSYS controller.
++- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
++
++Example:
++
++      thermal: thermal@1100b000 {
++              #thermal-sensor-cells = <1>;
++              compatible = "mediatek,mt8173-thermal";
++              reg = <0 0x1100b000 0 0x1000>;
++              interrupts = <0 70 IRQ_TYPE_LEVEL_LOW>;
++              clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
++              clock-names = "therm", "auxadc";
++              resets = <&pericfg MT8173_PERI_THERM_SW_RST>;
++              reset-names = "therm";
++              auxadc = <&auxadc>;
++              apmixedsys = <&apmixedsys>;
++      };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0023-thermal-Add-Mediatek-thermal-controller-support.patch b/target/linux/mediatek/patches/0023-thermal-Add-Mediatek-thermal-controller-support.patch
new file mode 100644 (file)
index 0000000..827d721
--- /dev/null
@@ -0,0 +1,785 @@
+From 014330a304100782a26bc7df02778c8c386b2857 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:42 +0200
+Subject: [PATCH 23/76] thermal: Add Mediatek thermal controller support
+
+This adds support for the Mediatek thermal controller found on MT8173
+and likely other SoCs.
+The controller is a bit special. It does not have its own ADC, instead
+it controls the on-SoC AUXADC via AHB bus accesses. For this reason
+we need the physical address of the AUXADC. Also it controls a mux
+using AHB bus accesses, so we need the APMIXEDSYS physical address aswell.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ drivers/thermal/Kconfig       |    8 +
+ drivers/thermal/Makefile      |    1 +
+ drivers/thermal/mtk_thermal.c |  728 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 737 insertions(+)
+ create mode 100644 drivers/thermal/mtk_thermal.c
+
+diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
+index af40db0..3aa5500 100644
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -285,6 +285,14 @@ config ACPI_THERMAL_REL
+       tristate
+       depends on ACPI
++config MTK_THERMAL
++      tristate "Temperature sensor driver for mediatek SoCs"
++      depends on ARCH_MEDIATEK || COMPILE_TEST
++      default y
++      help
++        Enable this option if you want to have support for thermal management
++        controller present in Mediatek SoCs
++
+ menu "Texas Instruments thermal drivers"
+ source "drivers/thermal/ti-soc-thermal/Kconfig"
+ endmenu
+diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
+index fa0dc48..51cfab7 100644
+--- a/drivers/thermal/Makefile
++++ b/drivers/thermal/Makefile
+@@ -39,3 +39,4 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
+ obj-$(CONFIG_INT340X_THERMAL)  += int340x_thermal/
+ obj-$(CONFIG_ST_THERMAL)      += st/
+ obj-$(CONFIG_TEGRA_SOCTHERM)  += tegra_soctherm.o
++obj-$(CONFIG_MTK_THERMAL)     += mtk_thermal.o
+diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
+new file mode 100644
+index 0000000..27aab12
+--- /dev/null
++++ b/drivers/thermal/mtk_thermal.c
+@@ -0,0 +1,728 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Hanyi.Wu <hanyi.wu@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/kernel.h>
++#include <linux/module.h>
++#include <linux/dmi.h>
++#include <linux/thermal.h>
++#include <linux/platform_device.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/clk.h>
++#include <linux/time.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/interrupt.h>
++#include <linux/reset.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)        (1 << (x))
++
++/* Thermal Controller Registers */
++#define TEMPMONCTL0           0x000
++#define TEMPMONCTL1           0x004
++#define TEMPMONCTL2           0x008
++#define TEMPMONINT            0x00c
++#define TEMPMONINTSTS         0x010
++#define TEMPMONIDET0          0x014
++#define TEMPMONIDET1          0x018
++#define TEMPMONIDET2          0x01c
++#define TEMPH2NTHRE           0x024
++#define TEMPHTHRE             0x028
++#define TEMPCTHRE             0x02c
++#define TEMPOFFSETH           0x030
++#define TEMPOFFSETL           0x034
++#define TEMPMSRCTL0           0x038
++#define TEMPMSRCTL1           0x03c
++#define TEMPAHBPOLL           0x040
++#define TEMPAHBTO             0x044
++#define TEMPADCPNP0           0x048
++#define TEMPADCPNP1           0x04c
++#define TEMPADCPNP2           0x050
++#define TEMPADCPNP3           0x0b4
++
++#define TEMPADCMUX            0x054
++#define TEMPADCEXT            0x058
++#define TEMPADCEXT1           0x05c
++#define TEMPADCEN             0x060
++#define TEMPPNPMUXADDR                0x064
++#define TEMPADCMUXADDR                0x068
++#define TEMPADCEXTADDR                0x06c
++#define TEMPADCEXT1ADDR               0x070
++#define TEMPADCENADDR         0x074
++#define TEMPADCVALIDADDR      0x078
++#define TEMPADCVOLTADDR               0x07c
++#define TEMPRDCTRL            0x080
++#define TEMPADCVALIDMASK      0x084
++#define TEMPADCVOLTAGESHIFT   0x088
++#define TEMPADCWRITECTRL      0x08c
++#define TEMPMSR0              0x090
++#define TEMPMSR1              0x094
++#define TEMPMSR2              0x098
++#define TEMPMSR3              0x0B8
++
++#define TEMPIMMD0             0x0a0
++#define TEMPIMMD1             0x0a4
++#define TEMPIMMD2             0x0a8
++
++#define TEMPPROTCTL           0x0c0
++#define TEMPPROTTA            0x0c4
++#define TEMPPROTTB            0x0c8
++#define TEMPPROTTC            0x0cc
++
++#define TEMPSPARE0            0x0f0
++#define TEMPSPARE1            0x0f4
++#define TEMPSPARE2            0x0f8
++#define TEMPSPARE3            0x0fc
++
++#define PTPCORESEL            0x400
++#define THERMINTST            0x404
++#define PTPODINTST            0x408
++#define THSTAGE0ST            0x40c
++#define THSTAGE1ST            0x410
++#define THSTAGE2ST            0x414
++#define THAHBST0              0x418
++#define THAHBST1              0x41c   /* Only for DE debug */
++#define PTPSPARE0             0x420
++#define PTPSPARE1             0x424
++#define PTPSPARE2             0x428
++#define PTPSPARE3             0x42c
++#define THSLPEVEB             0x430
++
++#define TEMPMONINT_COLD(sp)                   ((1 << 0) << ((sp) * 5))
++#define TEMPMONINT_HOT(sp)                    ((1 << 1) << ((sp) * 5))
++#define TEMPMONINT_LOW_OFS(sp)                        ((1 << 2) << ((sp) * 5))
++#define TEMPMONINT_HIGH_OFS(sp)                       ((1 << 3) << ((sp) * 5))
++#define TEMPMONINT_HOT_TO_NORM(sp)            ((1 << 4) << ((sp) * 5))
++#define TEMPMONINT_TIMEOUT                    (1 << 15)
++#define TEMPMONINT_IMMEDIATE_SENSE(sp)                (1 << (16 + (sp)))
++#define TEMPMONINT_FILTER_SENSE(sp)           (1 << (19 + (sp)))
++
++#define TEMPADCWRITECTRL_ADC_PNP_WRITE                (1 << 0)
++#define TEMPADCWRITECTRL_ADC_MUX_WRITE                (1 << 1)
++#define TEMPADCWRITECTRL_ADC_EXTRA_WRITE      (1 << 2)
++#define TEMPADCWRITECTRL_ADC_EXTRA1_WRITE     (1 << 3)
++
++#define TEMPADCVALIDMASK_VALID_HIGH           (1 << 5)
++#define TEMPADCVALIDMASK_VALID_POS(bit)               (bit)
++
++#define TEMPPROTCTL_AVERAGE                   (0 << 16)
++#define TEMPPROTCTL_MAXIMUM                   (1 << 16)
++#define TEMPPROTCTL_SELECTED                  (2 << 16)
++
++#define MT8173_THERMAL_ZONE_CA57              0
++#define MT8173_THERMAL_ZONE_CA53              1
++#define MT8173_THERMAL_ZONE_GPU                       2
++#define MT8173_THERMAL_ZONE_CORE              3
++
++#define MT8173_TS1    0
++#define MT8173_TS2    1
++#define MT8173_TS3    2
++#define MT8173_TS4    3
++#define MT8173_TSABB  4
++
++/* AUXADC channel 11 is used for the temperature sensors */
++#define MT8173_TEMP_AUXADC_CHANNEL    11
++
++/* The total number of temperature sensors in the MT8173 */
++#define MT8173_NUM_SENSORS            5
++
++/* The number of banks in the MT8173 */
++#define MT8173_NUM_BANKS              4
++
++/* The number of sensing points per bank */
++#define MT8173_NUM_SENSING_POINTS     4
++
++#define THERMAL_NAME    "mtk-thermal"
++
++struct mtk_thermal;
++
++struct mtk_thermal_bank {
++      struct mtk_thermal *mt;
++      struct thermal_zone_device *tz;
++      int id;
++};
++
++struct mtk_thermal {
++      struct device *dev;
++      void __iomem *thermal_base;
++      void __iomem *auxadc_base;
++
++      u64 auxadc_phys_base;
++      u64 apmixed_phys_base;
++      struct reset_control *reset;
++      struct clk *clk_peri_therm;
++      struct clk *clk_auxadc;
++
++      struct mtk_thermal_bank banks[MT8173_NUM_BANKS];
++
++      struct mutex lock;
++
++      /* Calibration values */
++      s32 adc_ge;
++      s32 adc_oe;
++      s32 degc_cali;
++      s32 o_slope;
++      s32 vts;
++};
++
++struct mtk_thermal_bank_cfg {
++      unsigned int enable_mask;
++      unsigned int sensors[4];
++};
++
++static int sensor_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
++
++/*
++ * The MT8173 thermal controller has four banks. Each bank can read up to
++ * four temperature sensors simultaneously. The MT8173 has a total of 5
++ * temperature sensors. We use each bank to measure a certain area of the
++ * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple
++ * areas, hence is used in different banks.
++ */
++static struct mtk_thermal_bank_cfg bank_data[] = {
++      {
++              .enable_mask = 3,
++              .sensors = { MT8173_TS2, MT8173_TS3 },
++      }, {
++              .enable_mask = 3,
++              .sensors = { MT8173_TS2, MT8173_TS4 },
++      }, {
++              .enable_mask = 7,
++              .sensors = { MT8173_TS1, MT8173_TS2, MT8173_TSABB },
++      }, {
++              .enable_mask = 1,
++              .sensors = { MT8173_TS2 },
++      },
++};
++
++static int tempmsr_ofs[MT8173_NUM_SENSING_POINTS] = {
++      TEMPMSR0, TEMPMSR1, TEMPMSR2, TEMPMSR3
++};
++
++static int tempadcpnp_ofs[MT8173_NUM_SENSING_POINTS] = {
++      TEMPADCPNP0, TEMPADCPNP1, TEMPADCPNP2, TEMPADCPNP3
++};
++
++/**
++ * raw_to_mcelsius - convert a raw ADC value to mcelsius
++ * @mt:               The thermal controller
++ * @raw:      raw ADC value
++ *
++ * This converts the raw ADC value to mcelsius using the SoC specific
++ * calibration constants
++ */
++static int raw_to_mcelsius(struct mtk_thermal *mt, u32 raw)
++{
++      s32 format_1, format_2, format_3, format_4;
++      s32 xtoomt;
++      s32 gain;
++
++      raw &= 0xfff;
++
++      gain = (10000 + mt->adc_ge);
++
++      xtoomt = ((((mt->vts + 3350 - mt->adc_oe) * 10000) / 4096) * 10000) /
++              gain;
++
++      format_1 = ((mt->degc_cali * 10) >> 1);
++      format_2 = (raw - mt->adc_oe);
++      format_3 = (((((format_2) * 10000) >> 12) * 10000) / gain) - xtoomt;
++      format_3 = format_3 * 15 / 18;
++      format_4 = ((format_3 * 100) / (165 + mt->o_slope));
++      format_4 = format_4 - (format_4 << 1);
++
++      return (format_1 + format_4) * 100;
++}
++
++/**
++ * mcelsius_to_raw - convert mcelsius to raw ADC value
++ * @mt:               The thermal controller
++ * @temp:     The temperature in mcelsius
++ *
++ * This converts a temperature in mcelsius to a raw ADC value, needed to
++ * calculate the trigger values for interrupt generation.
++ */
++static u32 mcelsius_to_raw(struct mtk_thermal *mt, int temp)
++{
++      s32 format_1, format_2, format_3, format_4;
++      s32 xtoomt;
++      s32 gain;
++
++      gain = (10000 + mt->adc_ge);
++
++      xtoomt = ((((mt->vts + 3350 - mt->adc_oe) * 10000) / 4096) * 10000) /
++              gain;
++
++      format_1 = temp - (mt->degc_cali * 1000 / 2);
++      format_2 = format_1 * (165 + mt->o_slope) * 18 / 15;
++      format_2 = format_2 - 2 * format_2;
++      format_3 = format_2 / 1000 + xtoomt * 10;
++      format_4 = (format_3 * 4096 / 10000 * gain) / 100000 + mt->adc_oe;
++
++      return format_4;
++}
++
++/**
++ * mtk_thermal_get_bank - get bank
++ * @bank:     The bank
++ *
++ * The bank registers are banked, we have to select a bank in the
++ * PTPCORESEL register to access it.
++ */
++static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++      u32 val;
++
++      mutex_lock(&mt->lock);
++
++      val = readl(mt->thermal_base + PTPCORESEL);
++      val &= ~0xf;
++      val |= bank->id;
++      writel(val, mt->thermal_base + PTPCORESEL);
++}
++
++/**
++ * mtk_thermal_put_bank - release bank
++ * @bank:     The bank
++ *
++ * release a bank previously taken with mtk_thermal_get_bank,
++ */
++static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++
++      mutex_unlock(&mt->lock);
++}
++
++/**
++ * mtk_thermal_bank_temperature - get the temperature of a bank
++ * @bank:     The bank
++ *
++ * The temperature of a bank is considered the maximum temperature of
++ * the sensors associated to the bank.
++ */
++static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++      int temp, i, max;
++      u32 raw;
++
++      temp = max = -INT_MAX;
++
++      for (i = 0; i < 4; i++) {
++              int sensno;
++
++              if (!(bank_data[bank->id].enable_mask & (1 << i)))
++                      continue;
++
++              raw = readl(mt->thermal_base + tempmsr_ofs[i]);
++
++              sensno = bank_data[bank->id].sensors[i];
++              temp = raw_to_mcelsius(mt, raw);
++
++              if (temp > max)
++                      max = temp;
++      }
++
++      return max;
++}
++
++static void mtk_thermal_irq_bank(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++      int sp;
++      u32 irqstat;
++      bool update = false;
++
++      mtk_thermal_get_bank(bank);
++
++      irqstat = readl(mt->thermal_base + TEMPMONINTSTS);
++
++      mtk_thermal_put_bank(bank);
++
++      for (sp = 0; sp < 3; sp++) {
++              if (irqstat & TEMPMONINT_LOW_OFS(sp)) {
++                      update = true;
++                      dev_vdbg(mt->dev, "bank %d sensor %d low offset interrupt\n",
++                                      bank->id, sp);
++              }
++
++              if (irqstat & TEMPMONINT_HIGH_OFS(sp)) {
++                      update = true;
++                      dev_vdbg(mt->dev, "bank %d sensor %d high offset interrupt\n",
++                                      bank->id, sp);
++              }
++      }
++
++      if (update)
++              thermal_zone_device_update(bank->tz);
++}
++
++static irqreturn_t mtk_thermal_irq(int irq, void *dev_id)
++{
++      struct mtk_thermal *mt = dev_id;
++      u32 irqstat = 0;
++      int i;
++
++      irqstat = readl(mt->thermal_base + THERMINTST);
++
++      dev_vdbg(mt->dev, "thermal_interrupt_handler : THERMINTST = 0x%x\n",
++                      irqstat);
++
++      for (i = 0; i < MT8173_NUM_BANKS; i++) {
++              if (!(irqstat & (1 << i)))
++                      mtk_thermal_irq_bank(&mt->banks[i]);
++      }
++
++      return IRQ_HANDLED;
++}
++
++static int mtk_read_temp(void *data, int *temp)
++{
++      struct mtk_thermal_bank *bank = data;
++
++      mtk_thermal_get_bank(bank);
++
++      *temp = mtk_thermal_bank_temperature(bank);
++
++      mtk_thermal_put_bank(bank);
++
++      return 0;
++}
++
++static int mtk_set_trips(void *data, int low, int high)
++{
++      struct mtk_thermal_bank *bank = data;
++      struct mtk_thermal *mt = bank->mt;
++      int i;
++      u32 val, enable_mask;
++      u32 raw_low, raw_high;
++
++      raw_low = mcelsius_to_raw(mt, low);
++      raw_high = mcelsius_to_raw(mt, high);
++
++      mtk_thermal_get_bank(bank);
++
++      writel(0x0, mt->thermal_base + TEMPMONINT);
++
++      writel(TEMPPROTCTL_SELECTED, mt->thermal_base + TEMPPROTCTL);
++
++      writel(raw_low, mt->thermal_base + TEMPOFFSETL);
++      writel(raw_high, mt->thermal_base + TEMPOFFSETH);
++
++      enable_mask = readl(mt->thermal_base + TEMPMONCTL0);
++
++      val = 0;
++      for (i = 0; i < MT8173_NUM_SENSING_POINTS; i++)
++              if (enable_mask & (1 << i))
++                      val |=  TEMPMONINT_LOW_OFS(i) | TEMPMONINT_HIGH_OFS(i);
++
++      writel(val, mt->thermal_base + TEMPMONINT);
++
++      mtk_thermal_put_bank(bank);
++
++      dev_dbg(mt->dev, "new boundaries: %d (0x%04x) < x < %d (0x%04x)\n",
++                      low, mcelsius_to_raw(mt, low),
++                      high, mcelsius_to_raw(mt, high));
++
++      return 0;
++}
++
++static const struct thermal_zone_of_device_ops mtk_thermal_ops = {
++      .get_temp = mtk_read_temp,
++      .set_trips = mtk_set_trips,
++};
++
++static void mtk_thermal_init_bank(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++      struct mtk_thermal_bank_cfg *cfg = &bank_data[bank->id];
++      int i;
++
++      mtk_thermal_get_bank(bank);
++
++      /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
++      writel(0x0000000c, mt->thermal_base + TEMPMONCTL1);
++
++      /*
++       * filt interval is 1 * 46.540us = 46.54us,
++       * sen interval is 429 * 46.540us = 19.96ms
++       */
++      writel(0x000101ad, mt->thermal_base + TEMPMONCTL2);
++
++      /* poll is set to 10u */
++      writel(0x00000300, mt->thermal_base + TEMPAHBPOLL);
++
++      /* temperature sampling control, 1 sample */
++      writel(0x00000000, mt->thermal_base + TEMPMSRCTL0);
++
++      /* exceed this polling time, IRQ would be inserted */
++      writel(0xffffffff, mt->thermal_base + TEMPAHBTO);
++
++      /* number of interrupts per event, 1 is enough */
++      writel(0x0, mt->thermal_base + TEMPMONIDET0);
++      writel(0x0, mt->thermal_base + TEMPMONIDET1);
++
++      /*
++       * The MT8173 thermal controller does not have its own ADC. Instead it
++       * uses AHB bus accesses to control the AUXADC. To do this the thermal
++       * controller has to be programmed with the physical addresses of the
++       * AUXADC registers and with the various bit positions in the AUXADC.
++       * Also the thermal controller controls a mux in the APMIXEDSYS register
++       * space.
++       */
++
++      /*
++       * this value will be stored to TEMPPNPMUXADDR (TEMPSPARE0)
++       * automatically by hw
++       */
++      writel(1 << MT8173_TEMP_AUXADC_CHANNEL, mt->thermal_base + TEMPADCMUX);
++
++      /* AHB address for auxadc mux selection */
++      writel(mt->auxadc_phys_base + 0x00c,
++                      mt->thermal_base + TEMPADCMUXADDR);
++
++      /* AHB address for pnp sensor mux selection */
++      writel(mt->apmixed_phys_base + 0x0604,
++                      mt->thermal_base + TEMPPNPMUXADDR);
++
++      /* AHB value for auxadc enable */
++      writel(1 << MT8173_TEMP_AUXADC_CHANNEL, mt->thermal_base + TEMPADCEN);
++
++      /* AHB address for auxadc enable (channel 0 immediate mode selected) */
++      writel(mt->auxadc_phys_base + AUXADC_CON1_SET_V,
++                      mt->thermal_base + TEMPADCENADDR);
++
++      /* AHB address for auxadc valid bit */
++      writel(mt->auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL),
++                      mt->thermal_base + TEMPADCVALIDADDR);
++
++      /* AHB address for auxadc voltage output */
++      writel(mt->auxadc_phys_base + AUXADC_DATA(MT8173_TEMP_AUXADC_CHANNEL),
++                      mt->thermal_base + TEMPADCVOLTADDR);
++
++      /* read valid & voltage are at the same register */
++      writel(0x0, mt->thermal_base + TEMPRDCTRL);
++
++      /* indicate where the valid bit is */
++      writel(TEMPADCVALIDMASK_VALID_HIGH | TEMPADCVALIDMASK_VALID_POS(12),
++                      mt->thermal_base + TEMPADCVALIDMASK);
++
++      /* no shift */
++      writel(0x0, mt->thermal_base + TEMPADCVOLTAGESHIFT);
++
++      /* enable auxadc mux write transaction */
++      writel(TEMPADCWRITECTRL_ADC_MUX_WRITE,
++                      mt->thermal_base + TEMPADCWRITECTRL);
++
++      for (i = 0; i < MT8173_NUM_SENSING_POINTS; i++)
++              writel(sensor_mux_values[cfg->sensors[i]],
++                              mt->thermal_base + tempadcpnp_ofs[i]);
++
++      writel(cfg->enable_mask, mt->thermal_base + TEMPMONCTL0);
++
++      writel(TEMPADCWRITECTRL_ADC_PNP_WRITE | TEMPADCWRITECTRL_ADC_MUX_WRITE,
++                      mt->thermal_base + TEMPADCWRITECTRL);
++
++      mtk_thermal_put_bank(bank);
++}
++
++static u64 of_get_phys_base(struct device_node *np)
++{
++      u64 size64;
++      const __be32 *regaddr_p;
++
++      regaddr_p = of_get_address(np, 0, &size64, NULL);
++      if (!regaddr_p)
++              return OF_BAD_ADDR;
++
++      return of_translate_address(np, regaddr_p);
++}
++
++static int mtk_thermal_probe(struct platform_device *pdev)
++{
++      int ret, i;
++      struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
++      int irq;
++      struct mtk_thermal *mt;
++      struct resource *res;
++
++      mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
++      if (!mt)
++              return -ENOMEM;
++
++      mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
++      if (IS_ERR(mt->clk_peri_therm))
++              return PTR_ERR(mt->clk_peri_therm);
++
++      mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc");
++      if (IS_ERR(mt->clk_auxadc))
++              return PTR_ERR(mt->clk_auxadc);
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      mt->thermal_base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(mt->thermal_base))
++              return PTR_ERR(mt->thermal_base);
++
++      mt->reset = devm_reset_control_get(&pdev->dev, "therm");
++      if (IS_ERR(mt->reset)) {
++              ret = PTR_ERR(mt->reset);
++              dev_err(&pdev->dev, "cannot get reset: %d\n", ret);
++              return ret;
++      }
++
++      mutex_init(&mt->lock);
++
++      mt->dev = &pdev->dev;
++
++      auxadc = of_parse_phandle(np, "auxadc", 0);
++      if (!auxadc) {
++              dev_err(&pdev->dev, "missing auxadc node\n");
++              return -ENODEV;
++      }
++
++      mt->auxadc_phys_base = of_get_phys_base(auxadc);
++      if (mt->auxadc_phys_base == OF_BAD_ADDR) {
++              dev_err(&pdev->dev, "Can't get auxadc phys address\n");
++              return -EINVAL;
++      }
++
++      apmixedsys = of_parse_phandle(np, "apmixedsys", 0);
++      if (!apmixedsys) {
++              dev_err(&pdev->dev, "missing apmixedsys node\n");
++              return -ENODEV;
++      }
++
++      mt->apmixed_phys_base = of_get_phys_base(apmixedsys);
++      if (mt->apmixed_phys_base == OF_BAD_ADDR) {
++              dev_err(&pdev->dev, "Can't get auxadc phys address\n");
++              return -EINVAL;
++      }
++
++      irq = platform_get_irq(pdev, 0);
++      if (!irq) {
++              dev_err(&pdev->dev, "Can't find irq\n");
++              return -EINVAL;
++      }
++
++      ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, mtk_thermal_irq,
++                      IRQF_ONESHOT, THERMAL_NAME, mt);
++      if (ret) {
++              dev_err(&pdev->dev, "Can't request irq %d: %d\n", irq, ret);
++              return ret;
++      }
++
++      ret = clk_prepare_enable(mt->clk_auxadc);
++      if (ret) {
++              dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
++              return ret;
++      }
++
++      reset_control_reset(mt->reset);
++
++      ret = clk_prepare_enable(mt->clk_peri_therm);
++      if (ret) {
++              dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
++              goto err_enable_clk;
++      }
++
++      /*
++       * These calibration values should finally be provided by the
++       * firmware or fuses. For now use default values.
++       */
++      mt->adc_ge = ((512 - 512) * 10000) / 4096;
++      mt->adc_oe = 512 - 512;
++      mt->degc_cali = 40;
++      mt->o_slope = 0;
++      mt->vts = 260;
++
++      for (i = 0; i < MT8173_NUM_BANKS; i++) {
++              struct mtk_thermal_bank *bank = &mt->banks[i];
++
++              bank->id = i;
++              bank->mt = mt;
++              mtk_thermal_init_bank(&mt->banks[i]);
++      }
++
++      platform_set_drvdata(pdev, mt);
++
++      /*
++       * This is needed after initialising the banks because otherwise
++       * the first temperature read contains bogus high temperatures which
++       * immediately cause a system shutdown.
++       */
++      msleep(100);
++
++      for (i = 0; i < MT8173_NUM_BANKS; i++) {
++              struct mtk_thermal_bank *bank = &mt->banks[i];
++
++              bank->tz = thermal_zone_of_sensor_register(&pdev->dev, i, bank,
++                              &mtk_thermal_ops);
++      }
++
++      return 0;
++
++err_enable_clk:
++      clk_disable_unprepare(mt->clk_peri_therm);
++
++      return ret;
++}
++
++static int mtk_thermal_remove(struct platform_device *pdev)
++{
++      struct mtk_thermal *mt = platform_get_drvdata(pdev);
++      int i;
++
++      for (i = 0; i < MT8173_NUM_BANKS; i++) {
++              struct mtk_thermal_bank *bank = &mt->banks[i];
++
++              if (!IS_ERR(bank))
++                      thermal_zone_of_sensor_unregister(&pdev->dev, bank->tz);
++      }
++
++      clk_disable_unprepare(mt->clk_peri_therm);
++      clk_disable_unprepare(mt->clk_auxadc);
++
++      return 0;
++}
++
++static const struct of_device_id mtk_thermal_of_match[] = {
++      {
++              .compatible = "mediatek,mt8173-thermal",
++      }, {
++      },
++};
++
++static struct platform_driver mtk_thermal_driver = {
++      .probe = mtk_thermal_probe,
++      .remove = mtk_thermal_remove,
++      .driver = {
++              .name = THERMAL_NAME,
++              .of_match_table = mtk_thermal_of_match,
++      },
++};
++
++module_platform_driver(mtk_thermal_driver);
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0024-ARM64-dts-mt8173-Add-thermal-auxadc-device-nodes.patch b/target/linux/mediatek/patches/0024-ARM64-dts-mt8173-Add-thermal-auxadc-device-nodes.patch
new file mode 100644 (file)
index 0000000..ef80497
--- /dev/null
@@ -0,0 +1,49 @@
+From 720e25e5c821336f7fa0c5fb564475c791c00340 Mon Sep 17 00:00:00 2001
+From: Sascha Hauer <s.hauer@pengutronix.de>
+Date: Wed, 13 May 2015 10:52:43 +0200
+Subject: [PATCH 24/76] ARM64: dts: mt8173: Add thermal/auxadc device nodes
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+---
+ arch/arm64/boot/dts/mediatek/mt8173.dtsi |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+index 924fdb6..50d424f 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+@@ -147,6 +147,11 @@
+                               (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               };
++              auxadc: auxadc@11001000 {
++                      compatible = "mediatek,mt8173-auxadc";
++                      reg = <0 0x11001000 0 0x1000>;
++              };
++
+               uart0: serial@11002000 {
+                       compatible = "mediatek,mt8173-uart",
+                                       "mediatek,mt6577-uart";
+@@ -182,6 +187,19 @@
+                       clocks = <&uart_clk>;
+                       status = "disabled";
+               };
++
++              thermal: thermal@1100b000 {
++                      #thermal-sensor-cells = <1>;
++                      compatible = "mediatek,mt8173-thermal";
++                      reg = <0 0x1100b000 0 0x1000>;
++                      interrupts = <0 70 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
++                      clock-names = "therm", "auxadc";
++                      resets = <&pericfg MT8173_PERI_THERM_SW_RST>;
++                      reset-names = "therm";
++                      auxadc = <&auxadc>;
++                      apmixedsys = <&apmixedsys>;
++              };
+       };
+ };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0025-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch b/target/linux/mediatek/patches/0025-dt-bindings-ARM-Mediatek-Document-devicetree-binding.patch
new file mode 100644 (file)
index 0000000..ab8f2d5
--- /dev/null
@@ -0,0 +1,53 @@
+From a6de66d3cf5add25f2b8913332117f3334db506e Mon Sep 17 00:00:00 2001
+From: Leilk Liu <leilk.liu@mediatek.com>
+Date: Fri, 8 May 2015 16:55:41 +0800
+Subject: [PATCH 25/76] dt-bindings: ARM: Mediatek: Document devicetree
+ bindings for spi bus
+
+Signed-off-by: Leilk Liu <leilk.liu@mediatek.com>
+---
+ .../devicetree/bindings/spi/spi-mt65xx.txt         |   32 ++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-mt65xx.txt
+
+diff --git a/Documentation/devicetree/bindings/spi/spi-mt65xx.txt b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
+new file mode 100644
+index 0000000..04c28fd
+--- /dev/null
++++ b/Documentation/devicetree/bindings/spi/spi-mt65xx.txt
+@@ -0,0 +1,32 @@
++MTK SPI device
++
++Required properties:
++- compatible: should be one of the following.
++    - mediatek,mt8173-spi: for mt8173 platforms
++    - mediatek,mt8135-spi: for mt8135 platforms
++    - mediatek,mt6589-spi: for mt6589 platforms
++
++- reg: Address and length of the register set for the device
++
++- interrupts: Should contain spi interrupt
++
++- clock-names: tuple listing input clock names.
++      Required elements: "main"
++
++- clocks: phandles to input clocks.
++
++- pad-select: should specify spi pad used, only required for MT8173.
++      This value should be 0~3.
++
++Example:
++
++- SoC Specific Portion:
++spi: spi@1100a000 {
++      compatible = "mediatek,mt8173-spi";
++      reg = <0 0x1100a000 0 0x1000>;
++      interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
++      clocks = <&pericfg PERI_SPI0>;
++      clock-names = "main";
++      pad-select = <1>;
++      status = "disabled";
++};
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0026-spi-mediatek-Add-spi-bus-for-Mediatek-MT8173.patch b/target/linux/mediatek/patches/0026-spi-mediatek-Add-spi-bus-for-Mediatek-MT8173.patch
new file mode 100644 (file)
index 0000000..3466581
--- /dev/null
@@ -0,0 +1,679 @@
+From 047222cfefe97ef8706f03117bc8deada4cb4ddd Mon Sep 17 00:00:00 2001
+From: Leilk Liu <leilk.liu@mediatek.com>
+Date: Fri, 8 May 2015 16:55:42 +0800
+Subject: [PATCH 26/76] spi: mediatek: Add spi bus for Mediatek MT8173
+
+This patch adds basic spi bus for MT8173.
+
+Signed-off-by: Leilk Liu <leilk.liu@mediatek.com>
+---
+ drivers/spi/Kconfig      |   10 +
+ drivers/spi/Makefile     |    1 +
+ drivers/spi/spi-mt65xx.c |  622 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 633 insertions(+)
+ create mode 100644 drivers/spi/spi-mt65xx.c
+
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 72b0590..53dbea3 100644
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -325,6 +325,16 @@ config SPI_MESON_SPIFC
+         This enables master mode support for the SPIFC (SPI flash
+         controller) available in Amlogic Meson SoCs.
++config SPI_MT65XX
++      tristate "MediaTek SPI controller"
++      depends on ARCH_MEDIATEK || COMPILE_TEST
++      select SPI_BITBANG
++      help
++        This selects the MediaTek(R) SPI bus driver.
++        If you want to use MediaTek(R) SPI interface,
++        say Y or M here.If you are not sure, say N.
++        SPI drivers for Mediatek mt65XX series ARM SoCs.
++
+ config SPI_OC_TINY
+       tristate "OpenCores tiny SPI"
+       depends on GPIOLIB
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index d8cbf65..ab332ef 100644
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_MESON_SPIFC)                += spi-meson-spifc.o
+ obj-$(CONFIG_SPI_MPC512x_PSC)         += spi-mpc512x-psc.o
+ obj-$(CONFIG_SPI_MPC52xx_PSC)         += spi-mpc52xx-psc.o
+ obj-$(CONFIG_SPI_MPC52xx)             += spi-mpc52xx.o
++obj-$(CONFIG_SPI_MT65XX)                += spi-mt65xx.o
+ obj-$(CONFIG_SPI_MXS)                 += spi-mxs.o
+ obj-$(CONFIG_SPI_NUC900)              += spi-nuc900.o
+ obj-$(CONFIG_SPI_OC_TINY)             += spi-oc-tiny.o
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+new file mode 100644
+index 0000000..92c119d
+--- /dev/null
++++ b/drivers/spi/spi-mt65xx.c
+@@ -0,0 +1,622 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Leilk Liu <leilk.liu@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/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/ioport.h>
++#include <linux/errno.h>
++#include <linux/spi/spi.h>
++#include <linux/workqueue.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/irqreturn.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/sched.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/kernel.h>
++#include <linux/spi/spi_bitbang.h>
++#include <linux/gpio.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++
++#define SPI_CFG0_REG                      0x0000
++#define SPI_CFG1_REG                      0x0004
++#define SPI_TX_SRC_REG                    0x0008
++#define SPI_RX_DST_REG                    0x000c
++#define SPI_CMD_REG                       0x0018
++#define SPI_STATUS0_REG                   0x001c
++#define SPI_PAD_SEL_REG                   0x0024
++
++#define SPI_CFG0_SCK_HIGH_OFFSET          0
++#define SPI_CFG0_SCK_LOW_OFFSET           8
++#define SPI_CFG0_CS_HOLD_OFFSET           16
++#define SPI_CFG0_CS_SETUP_OFFSET          24
++
++#define SPI_CFG0_SCK_HIGH_MASK            0xff
++#define SPI_CFG0_SCK_LOW_MASK             0xff00
++#define SPI_CFG0_CS_HOLD_MASK             0xff0000
++#define SPI_CFG0_CS_SETUP_MASK            0xff000000
++
++#define SPI_CFG1_CS_IDLE_OFFSET           0
++#define SPI_CFG1_PACKET_LOOP_OFFSET       8
++#define SPI_CFG1_PACKET_LENGTH_OFFSET     16
++#define SPI_CFG1_GET_TICK_DLY_OFFSET      30
++
++#define SPI_CFG1_CS_IDLE_MASK             0xff
++#define SPI_CFG1_PACKET_LOOP_MASK         0xff00
++#define SPI_CFG1_PACKET_LENGTH_MASK       0x3ff0000
++#define SPI_CFG1_GET_TICK_DLY_MASK        0xc0000000
++
++#define SPI_CMD_ACT_OFFSET                0
++#define SPI_CMD_RESUME_OFFSET             1
++#define SPI_CMD_RST_OFFSET                2
++#define SPI_CMD_PAUSE_EN_OFFSET           4
++#define SPI_CMD_DEASSERT_OFFSET           5
++#define SPI_CMD_CPHA_OFFSET               8
++#define SPI_CMD_CPOL_OFFSET               9
++#define SPI_CMD_RX_DMA_OFFSET             10
++#define SPI_CMD_TX_DMA_OFFSET             11
++#define SPI_CMD_TXMSBF_OFFSET             12
++#define SPI_CMD_RXMSBF_OFFSET             13
++#define SPI_CMD_RX_ENDIAN_OFFSET          14
++#define SPI_CMD_TX_ENDIAN_OFFSET          15
++#define SPI_CMD_FINISH_IE_OFFSET          16
++#define SPI_CMD_PAUSE_IE_OFFSET           17
++
++#define SPI_CMD_RESUME_MASK               0x2
++#define SPI_CMD_RST_MASK                  0x4
++#define SPI_CMD_PAUSE_EN_MASK             0x10
++#define SPI_CMD_DEASSERT_MASK             0x20
++#define SPI_CMD_CPHA_MASK                 0x100
++#define SPI_CMD_CPOL_MASK                 0x200
++#define SPI_CMD_RX_DMA_MASK               0x400
++#define SPI_CMD_TX_DMA_MASK               0x800
++#define SPI_CMD_TXMSBF_MASK               0x1000
++#define SPI_CMD_RXMSBF_MASK               0x2000
++#define SPI_CMD_RX_ENDIAN_MASK            0x4000
++#define SPI_CMD_TX_ENDIAN_MASK            0x8000
++#define SPI_CMD_FINISH_IE_MASK            0x10000
++
++#define COMPAT_MT6589                 (0x1 << 0)
++#define COMPAT_MT8173                 (0x1 << 1)
++
++#define MT8173_MAX_PAD_SEL 3
++
++#define IDLE 0
++#define INPROGRESS 1
++#define PAUSED 2
++
++#define PACKET_SIZE 1024
++
++struct mtk_chip_config {
++      u32 setuptime;
++      u32 holdtime;
++      u32 high_time;
++      u32 low_time;
++      u32 cs_idletime;
++      u32 tx_mlsb;
++      u32 rx_mlsb;
++      u32 tx_endian;
++      u32 rx_endian;
++      u32 pause;
++      u32 finish_intr;
++      u32 deassert;
++      u32 tckdly;
++};
++
++struct mtk_spi_ddata {
++      struct spi_bitbang bitbang;
++      void __iomem *base;
++      u32 irq;
++      u32 state;
++      u32 platform_compat;
++      u32 pad_sel;
++      struct clk *clk;
++
++      const u8 *tx_buf;
++      u8 *rx_buf;
++      u32 tx_len, rx_len;
++      struct completion done;
++};
++
++/*
++ * A piece of default chip info unless the platform
++ * supplies it.
++ */
++static const struct mtk_chip_config mtk_default_chip_info = {
++      .setuptime = 10,
++      .holdtime = 12,
++      .high_time = 6,
++      .low_time = 6,
++      .cs_idletime = 12,
++      .rx_mlsb = 1,
++      .tx_mlsb = 1,
++      .tx_endian = 0,
++      .rx_endian = 0,
++      .pause = 0,
++      .finish_intr = 1,
++      .deassert = 0,
++      .tckdly = 0,
++};
++
++static const struct of_device_id mtk_spi_of_match[] = {
++      { .compatible = "mediatek,mt6589-spi", .data = (void *)COMPAT_MT6589},
++      { .compatible = "mediatek,mt8173-spi", .data = (void *)COMPAT_MT8173},
++      {}
++};
++MODULE_DEVICE_TABLE(of, mtk_spi_of_match);
++
++static void mtk_spi_reset(struct mtk_spi_ddata *mdata)
++{
++      u32 reg_val;
++
++      /*set the software reset bit in SPI_CMD_REG.*/
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~SPI_CMD_RST_MASK;
++      reg_val |= 1 << SPI_CMD_RST_OFFSET;
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~SPI_CMD_RST_MASK;
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static void mtk_set_pause_bit(struct mtk_spi_ddata *mdata)
++{
++      u32 reg_val;
++
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val |= 1 << SPI_CMD_PAUSE_EN_OFFSET;
++      reg_val |= 1 << SPI_CMD_PAUSE_IE_OFFSET;
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static void mtk_clear_pause_bit(struct mtk_spi_ddata *mdata)
++{
++      u32 reg_val;
++
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~SPI_CMD_PAUSE_EN_MASK;
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static int mtk_spi_config(struct mtk_spi_ddata *mdata,
++                        struct mtk_chip_config *chip_config)
++{
++      u32 reg_val;
++
++      /* set the timing */
++      reg_val = readl(mdata->base + SPI_CFG0_REG);
++      reg_val &= ~(SPI_CFG0_SCK_HIGH_MASK | SPI_CFG0_SCK_LOW_MASK);
++      reg_val &= ~(SPI_CFG0_CS_HOLD_MASK | SPI_CFG0_CS_SETUP_MASK);
++      reg_val |= ((chip_config->high_time - 1) << SPI_CFG0_SCK_HIGH_OFFSET);
++      reg_val |= ((chip_config->low_time - 1) << SPI_CFG0_SCK_LOW_OFFSET);
++      reg_val |= ((chip_config->holdtime - 1) << SPI_CFG0_CS_HOLD_OFFSET);
++      reg_val |= ((chip_config->setuptime - 1) << SPI_CFG0_CS_SETUP_OFFSET);
++      writel(reg_val, mdata->base + SPI_CFG0_REG);
++
++      reg_val = readl(mdata->base + SPI_CFG1_REG);
++      reg_val &= ~SPI_CFG1_CS_IDLE_MASK;
++      reg_val |= ((chip_config->cs_idletime - 1) << SPI_CFG1_CS_IDLE_OFFSET);
++      reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK;
++      reg_val |= ((chip_config->tckdly) << SPI_CFG1_GET_TICK_DLY_OFFSET);
++      writel(reg_val, mdata->base + SPI_CFG1_REG);
++
++      /* set the mlsbx and mlsbtx */
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~(SPI_CMD_TX_ENDIAN_MASK | SPI_CMD_RX_ENDIAN_MASK);
++      reg_val &= ~(SPI_CMD_TXMSBF_MASK | SPI_CMD_RXMSBF_MASK);
++      reg_val |= (chip_config->tx_mlsb << SPI_CMD_TXMSBF_OFFSET);
++      reg_val |= (chip_config->rx_mlsb << SPI_CMD_RXMSBF_OFFSET);
++      reg_val |= (chip_config->tx_endian << SPI_CMD_TX_ENDIAN_OFFSET);
++      reg_val |= (chip_config->rx_endian << SPI_CMD_RX_ENDIAN_OFFSET);
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++
++      /* set finish and pause interrupt always enable */
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~SPI_CMD_FINISH_IE_MASK;
++      reg_val |= (chip_config->finish_intr << SPI_CMD_FINISH_IE_OFFSET);
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val |= 1 << SPI_CMD_TX_DMA_OFFSET;
++      reg_val |= 1 << SPI_CMD_RX_DMA_OFFSET;
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++
++      /* set deassert mode */
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~SPI_CMD_DEASSERT_MASK;
++      reg_val |= (chip_config->deassert << SPI_CMD_DEASSERT_OFFSET);
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++
++      /* pad select */
++      if (mdata->platform_compat & COMPAT_MT8173)
++              writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG);
++
++      return 0;
++}
++
++static int mtk_spi_setup_transfer(struct spi_device *spi,
++                                struct spi_transfer *t)
++{
++      u32 reg_val;
++      struct spi_master *master = spi->master;
++      struct mtk_spi_ddata *mdata = spi_master_get_devdata(master);
++      struct spi_message *m = master->cur_msg;
++      struct mtk_chip_config *chip_config;
++
++      u8 cpha = spi->mode & SPI_CPHA ? 1 : 0;
++      u8 cpol = spi->mode & SPI_CPOL ? 1 : 0;
++
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~(SPI_CMD_CPHA_MASK | SPI_CMD_CPOL_MASK);
++      reg_val |= (cpha << SPI_CMD_CPHA_OFFSET);
++      reg_val |= (cpol << SPI_CMD_CPOL_OFFSET);
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++
++      if (t->cs_change) {
++              if (!(list_is_last(&t->transfer_list, &m->transfers)))
++                      mdata->state = IDLE;
++      } else {
++              mdata->state = IDLE;
++              mtk_spi_reset(mdata);
++      }
++
++      chip_config = (struct mtk_chip_config *)spi->controller_data;
++      if (!chip_config) {
++              chip_config = (void *)&mtk_default_chip_info;
++              spi->controller_data = chip_config;
++              mdata->state = IDLE;
++      }
++
++      mtk_spi_config(mdata, chip_config);
++
++      return 0;
++}
++
++static void mtk_spi_chipselect(struct spi_device *spi, int is_on)
++{
++      struct mtk_spi_ddata *mdata = spi_master_get_devdata(spi->master);
++
++      switch (is_on) {
++      case BITBANG_CS_ACTIVE:
++              mtk_set_pause_bit(mdata);
++              break;
++      case BITBANG_CS_INACTIVE:
++              mtk_clear_pause_bit(mdata);
++              break;
++      }
++}
++
++static void mtk_spi_start_transfer(struct mtk_spi_ddata *mdata)
++{
++      u32 reg_val;
++
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val |= 1 << SPI_CMD_ACT_OFFSET;
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static void mtk_spi_resume_transfer(struct mtk_spi_ddata *mdata)
++{
++      u32 reg_val;
++
++      reg_val = readl(mdata->base + SPI_CMD_REG);
++      reg_val &= ~SPI_CMD_RESUME_MASK;
++      reg_val |= 1 << SPI_CMD_RESUME_OFFSET;
++      writel(reg_val, mdata->base + SPI_CMD_REG);
++}
++
++static int mtk_spi_setup_packet(struct mtk_spi_ddata *mdata,
++                              struct spi_transfer *xfer)
++{
++      struct device *dev = &mdata->bitbang.master->dev;
++      u32 packet_size, packet_loop, reg_val;
++
++      packet_size = min_t(unsigned, xfer->len, PACKET_SIZE);
++
++      /* mtk hw has the restriction that xfer len must be a multiple of 1024,
++       * when it is greater than 1024bytes.
++       */
++      if (xfer->len % packet_size) {
++              dev_err(dev, "ERROR!The lens must be a multiple of %d, your len %d\n",
++                      PACKET_SIZE, xfer->len);
++              return -EINVAL;
++      }
++
++      packet_loop = xfer->len / packet_size;
++
++      reg_val = readl(mdata->base + SPI_CFG1_REG);
++      reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK + SPI_CFG1_PACKET_LOOP_MASK);
++      reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET;
++      reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;
++      writel(reg_val, mdata->base + SPI_CFG1_REG);
++
++      return 0;
++}
++
++static int mtk_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *xfer)
++{
++      struct spi_master *master = spi->master;
++      struct mtk_spi_ddata *mdata = spi_master_get_devdata(master);
++      struct device *dev = &mdata->bitbang.master->dev;
++      int cmd, ret;
++
++      /* mtk spi hw tx/rx have 4bytes aligned restriction,
++       * so kmalloc tx/rx buffer to workaround here.
++       */
++      mdata->tx_buf = NULL;
++      mdata->rx_buf = NULL;
++      if (xfer->tx_buf) {
++              mdata->tx_buf = kmalloc(xfer->len, GFP_KERNEL);
++              if (!mdata->tx_buf) {
++                      dev_err(dev, "malloc tx_buf failed.\n");
++                      ret = -ENOMEM;
++                      goto err_free;
++              }
++              memcpy((void *)mdata->tx_buf, xfer->tx_buf, xfer->len);
++      }
++      if (xfer->rx_buf) {
++              mdata->rx_buf = kmalloc(xfer->len, GFP_KERNEL);
++              if (!mdata->rx_buf) {
++                      dev_err(dev, "malloc rx_buf failed.\n");
++                      ret = -ENOMEM;
++                      goto err_free;
++              }
++      }
++
++      reinit_completion(&mdata->done);
++
++      xfer->tx_dma = DMA_ERROR_CODE;
++      xfer->rx_dma = DMA_ERROR_CODE;
++      if (xfer->tx_buf) {
++              xfer->tx_dma = dma_map_single(dev, (void *)mdata->tx_buf,
++                                            xfer->len, DMA_TO_DEVICE);
++              if (dma_mapping_error(dev, xfer->tx_dma)) {
++                      dev_err(dev, "dma mapping tx_buf error.\n");
++                      ret = -ENOMEM;
++                      goto err_free;
++              }
++      }
++      if (xfer->rx_buf) {
++              xfer->rx_dma = dma_map_single(dev, mdata->rx_buf,
++                                            xfer->len, DMA_FROM_DEVICE);
++              if (dma_mapping_error(dev, xfer->rx_dma)) {
++                      if (xfer->tx_buf)
++                              dma_unmap_single(dev, xfer->tx_dma,
++                                               xfer->len, DMA_TO_DEVICE);
++                      dev_err(dev, "dma mapping rx_buf error.\n");
++                      ret = -ENOMEM;
++                      goto err_free;
++              }
++      }
++
++      ret = mtk_spi_setup_packet(mdata, xfer);
++      if (ret != 0)
++              goto err_free;
++
++      /* Here is mt8173 HW issue: RX must enable TX, then TX transfer
++       * dummy data; TX don't need to enable RX. so enable TX dma for
++       * RX to workaround.
++       */
++      cmd = readl(mdata->base + SPI_CMD_REG);
++      if (xfer->tx_buf || (mdata->platform_compat & COMPAT_MT8173))
++              cmd |= 1 << SPI_CMD_TX_DMA_OFFSET;
++      if (xfer->rx_buf)
++              cmd |= 1 << SPI_CMD_RX_DMA_OFFSET;
++      writel(cmd, mdata->base + SPI_CMD_REG);
++
++      /* set up the DMA bus address */
++      if (xfer->tx_dma != DMA_ERROR_CODE)
++              writel(cpu_to_le32(xfer->tx_dma), mdata->base + SPI_TX_SRC_REG);
++      if (xfer->rx_dma != DMA_ERROR_CODE)
++              writel(cpu_to_le32(xfer->rx_dma), mdata->base + SPI_RX_DST_REG);
++
++      if (mdata->state == IDLE)
++              mtk_spi_start_transfer(mdata);
++      else if (mdata->state == PAUSED)
++              mtk_spi_resume_transfer(mdata);
++      else
++              mdata->state = INPROGRESS;
++
++      wait_for_completion(&mdata->done);
++
++      if (xfer->tx_dma != DMA_ERROR_CODE) {
++              dma_unmap_single(dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE);
++              xfer->tx_dma = DMA_ERROR_CODE;
++      }
++      if (xfer->rx_dma != DMA_ERROR_CODE) {
++              dma_unmap_single(dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE);
++              xfer->rx_dma = DMA_ERROR_CODE;
++      }
++
++      /* spi disable dma */
++      cmd = readl(mdata->base + SPI_CMD_REG);
++      cmd &= ~SPI_CMD_TX_DMA_MASK;
++      cmd &= ~SPI_CMD_RX_DMA_MASK;
++      writel(cmd, mdata->base + SPI_CMD_REG);
++
++      if (xfer->rx_buf)
++              memcpy(xfer->rx_buf, mdata->rx_buf, xfer->len);
++
++      ret = xfer->len;
++
++err_free:
++      kfree(mdata->tx_buf);
++      kfree(mdata->rx_buf);
++      return ret;
++}
++
++static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
++{
++      struct mtk_spi_ddata *mdata = dev_id;
++      u32 reg_val;
++
++      reg_val = readl(mdata->base + SPI_STATUS0_REG);
++      if (reg_val & 0x2)
++              mdata->state = PAUSED;
++      else
++              mdata->state = IDLE;
++      complete(&mdata->done);
++
++      return IRQ_HANDLED;
++}
++
++static unsigned long mtk_get_device_prop(struct platform_device *pdev)
++{
++      const struct of_device_id *match;
++
++      match = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
++      return (unsigned long)match->data;
++}
++
++static int mtk_spi_probe(struct platform_device *pdev)
++{
++      struct spi_master *master;
++      struct mtk_spi_ddata *mdata;
++      struct resource *res;
++      int     ret;
++
++      master = spi_alloc_master(&pdev->dev, sizeof(struct mtk_spi_ddata));
++      if (!master) {
++              dev_err(&pdev->dev, "failed to alloc spi master\n");
++              return -ENOMEM;
++      }
++
++      platform_set_drvdata(pdev, master);
++
++      master->dev.of_node = pdev->dev.of_node;
++      master->bus_num = pdev->id;
++      master->num_chipselect = 1;
++      master->mode_bits = SPI_CPOL | SPI_CPHA;
++
++      mdata = spi_master_get_devdata(master);
++
++      mdata->bitbang.master = master;
++      mdata->bitbang.chipselect = mtk_spi_chipselect;
++      mdata->bitbang.setup_transfer = mtk_spi_setup_transfer;
++      mdata->bitbang.txrx_bufs = mtk_spi_txrx_bufs;
++      mdata->platform_compat = mtk_get_device_prop(pdev);
++
++      if (mdata->platform_compat & COMPAT_MT8173) {
++              ret = of_property_read_u32(pdev->dev.of_node, "pad-select",
++                                         &mdata->pad_sel);
++              if (ret) {
++                      dev_err(&pdev->dev, "failed to read pad select: %d\n",
++                              ret);
++                      goto err;
++              }
++
++              if (mdata->pad_sel > MT8173_MAX_PAD_SEL) {
++                      dev_err(&pdev->dev, "wrong pad-select: %u\n",
++                              mdata->pad_sel);
++                      goto err;
++              }
++      }
++
++      init_completion(&mdata->done);
++
++      mdata->clk = devm_clk_get(&pdev->dev, "main");
++      if (IS_ERR(mdata->clk)) {
++              ret = PTR_ERR(mdata->clk);
++              dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
++              goto err;
++      }
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!res) {
++              ret = -ENODEV;
++              dev_err(&pdev->dev, "failed to determine base address\n");
++              goto err;
++      }
++
++      mdata->base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(mdata->base)) {
++              ret = PTR_ERR(mdata->base);
++              goto err;
++      }
++
++      ret = platform_get_irq(pdev, 0);
++      if (ret < 0) {
++              dev_err(&pdev->dev, "failed to get irq (%d)\n", ret);
++              goto err;
++      }
++
++      mdata->irq = ret;
++
++      if (!pdev->dev.dma_mask)
++              pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
++
++      mdata->bitbang.master->dev.dma_mask = pdev->dev.dma_mask;
++
++      ret = clk_prepare_enable(mdata->clk);
++      if (ret < 0) {
++              dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret);
++              goto err;
++      }
++
++      ret = devm_request_irq(&pdev->dev, mdata->irq, mtk_spi_interrupt,
++                             IRQF_TRIGGER_NONE, dev_name(&pdev->dev), mdata);
++      if (ret) {
++              dev_err(&pdev->dev, "failed to register irq (%d)\n", ret);
++              goto err_disable_clk;
++      }
++
++      ret = spi_bitbang_start(&mdata->bitbang);
++      if (ret) {
++              dev_err(&pdev->dev, "spi_bitbang_start failed (%d)\n", ret);
++err_disable_clk:
++              clk_disable_unprepare(mdata->clk);
++err:
++              spi_master_put(master);
++      }
++
++      return ret;
++}
++
++static int mtk_spi_remove(struct platform_device *pdev)
++{
++      struct spi_master *master = platform_get_drvdata(pdev);
++      struct mtk_spi_ddata *mdata = spi_master_get_devdata(master);
++
++      spi_bitbang_stop(&mdata->bitbang);
++      mtk_spi_reset(mdata);
++      clk_disable_unprepare(mdata->clk);
++      spi_master_put(master);
++
++      return 0;
++}
++
++struct platform_driver mtk_spi_driver = {
++      .driver = {
++              .name = "mtk-spi",
++              .of_match_table = mtk_spi_of_match,
++      },
++      .probe = mtk_spi_probe,
++      .remove = mtk_spi_remove,
++};
++
++module_platform_driver(mtk_spi_driver);
++
++MODULE_DESCRIPTION("MTK SPI Controller driver");
++MODULE_AUTHOR("Leilk Liu <leilk.liu@mediatek.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform: mtk_spi");
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0027-dt-bindings-pwm-add-Mediatek-display-PWM-bindings.patch b/target/linux/mediatek/patches/0027-dt-bindings-pwm-add-Mediatek-display-PWM-bindings.patch
new file mode 100644 (file)
index 0000000..1236a96
--- /dev/null
@@ -0,0 +1,47 @@
+From 908a87b47af8303c9aa8fb6aa183ca9f8b544d78 Mon Sep 17 00:00:00 2001
+From: YH Huang <yh.huang@mediatek.com>
+Date: Mon, 11 May 2015 17:26:21 +0800
+Subject: [PATCH 27/76] dt-bindings: pwm: add Mediatek display PWM bindings
+
+Document the device-tree binding of Mediatek display PWM.
+
+Signed-off-by: YH Huang <yh.huang@mediatek.com>
+---
+ .../devicetree/bindings/pwm/pwm-disp-mediatek.txt  |   25 ++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt
+
+diff --git a/Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt b/Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt
+new file mode 100644
+index 0000000..ef54e9d
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pwm/pwm-disp-mediatek.txt
+@@ -0,0 +1,25 @@
++Mediatek display PWM controller
++
++Required properties:
++ - compatible: should be "mediatek,<name>-disp-pwm"
++   - "mediatek,mt8173-disp-pwm": found on mt8173 SoC
++   - "mediatek,mt6595-disp-pwm": found on mt6595 SoC
++ - reg: physical base address and length of the controller's registers
++ - #pwm-cells: must be 2. See pwm.txt in this directory
++   for a description of the cell format
++ - clocks: phandle and clock specifier of the PWM reference clock
++ - clock-names: must contain the following
++   - "main": clock used to generate PWM signals
++   - "mm": sync signals from the modules of mmsys
++
++Example:
++      pwm0: pwm@1401e000 {
++              compatible = "mediatek,mt8173-disp-pwm",
++                           "mediatek,mt6595-disp-pwm";
++              reg = <0 0x1401e000 0 0x1000>;
++              #pwm-cells = <2>;
++              clocks = <&mmsys MM_DISP_PWM026M>,
++                       <&mmsys MM_DISP_PWM0MM>;
++              clock-names = "main",
++                            "mm";
++      };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0028-pwm-add-Mediatek-display-PWM-driver-support.patch b/target/linux/mediatek/patches/0028-pwm-add-Mediatek-display-PWM-driver-support.patch
new file mode 100644 (file)
index 0000000..dbcca3e
--- /dev/null
@@ -0,0 +1,281 @@
+From 77e664940f6daa86965d16a2047188519341a31a Mon Sep 17 00:00:00 2001
+From: YH Huang <yh.huang@mediatek.com>
+Date: Mon, 11 May 2015 17:26:22 +0800
+Subject: [PATCH 28/76] pwm: add Mediatek display PWM driver support
+
+Add display PWM driver support to modify backlight for MT8173/MT6595.
+
+Signed-off-by: YH Huang <yh.huang@mediatek.com>
+---
+ drivers/pwm/Kconfig             |    9 ++
+ drivers/pwm/Makefile            |    1 +
+ drivers/pwm/pwm-disp-mediatek.c |  225 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 235 insertions(+)
+ create mode 100644 drivers/pwm/pwm-disp-mediatek.c
+
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index b1541f4..9edbb5a 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -111,6 +111,15 @@ config PWM_CLPS711X
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-clps711x.
++config PWM_DISP_MEDIATEK
++      tristate "MEDIATEK display PWM driver"
++      depends on OF
++      help
++        Generic PWM framework driver for mediatek disp-pwm device.
++
++        To compile this driver as a module, choose M here: the module
++        will be called pwm-disp-mediatek.
++
+ config PWM_EP93XX
+       tristate "Cirrus Logic EP93xx PWM support"
+       depends on ARCH_EP93XX
+diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
+index ec50eb5..c5ff72a 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_PWM_BCM_KONA)     += pwm-bcm-kona.o
+ obj-$(CONFIG_PWM_BCM2835)     += pwm-bcm2835.o
+ obj-$(CONFIG_PWM_BFIN)                += pwm-bfin.o
+ obj-$(CONFIG_PWM_CLPS711X)    += pwm-clps711x.o
++obj-$(CONFIG_PWM_DISP_MEDIATEK)       += pwm-disp-mediatek.o
+ obj-$(CONFIG_PWM_EP93XX)      += pwm-ep93xx.o
+ obj-$(CONFIG_PWM_FSL_FTM)     += pwm-fsl-ftm.o
+ obj-$(CONFIG_PWM_IMG)         += pwm-img.o
+diff --git a/drivers/pwm/pwm-disp-mediatek.c b/drivers/pwm/pwm-disp-mediatek.c
+new file mode 100644
+index 0000000..38293af
+--- /dev/null
++++ b/drivers/pwm/pwm-disp-mediatek.c
+@@ -0,0 +1,225 @@
++/*
++ * Mediatek display pulse-width-modulation controller driver.
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: YH Huang <yh.huang@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/err.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/pwm.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#define DISP_PWM_EN_OFF                       (0x0)
++#define PWM_ENABLE_SHIFT              (0x0)
++#define PWM_ENABLE_MASK                       (0x1 << PWM_ENABLE_SHIFT)
++
++#define DISP_PWM_COMMIT_OFF           (0x08)
++#define PWM_COMMIT_SHIFT              (0x0)
++#define PWM_COMMIT_MASK                       (0x1 << PWM_COMMIT_SHIFT)
++
++#define DISP_PWM_CON_0_OFF            (0x10)
++#define PWM_CLKDIV_SHIFT              (0x10)
++#define PWM_CLKDIV_MASK                       (0x3ff << PWM_CLKDIV_SHIFT)
++#define PWM_CLKDIV_MAX                        (0x000003ff)
++
++#define DISP_PWM_CON_1_OFF            (0x14)
++#define PWM_PERIOD_SHIFT              (0x0)
++#define PWM_PERIOD_MASK                       (0xfff << PWM_PERIOD_SHIFT)
++#define PWM_PERIOD_MAX                        (0x00000fff)
++/* Shift log2(PWM_PERIOD_MAX + 1) as divisor */
++#define PWM_PERIOD_BIT_SHIFT          12
++
++#define PWM_HIGH_WIDTH_SHIFT          (0x10)
++#define PWM_HIGH_WIDTH_MASK           (0x1fff << PWM_HIGH_WIDTH_SHIFT)
++
++#define NUM_PWM 1
++
++struct mtk_disp_pwm_chip {
++      struct pwm_chip chip;
++      struct device   *dev;
++      struct clk      *clk_main;
++      struct clk      *clk_mm;
++      void __iomem    *mmio_base;
++};
++
++static void mtk_disp_pwm_setting(void __iomem *address, u32 value, u32 mask)
++{
++      u32 val;
++
++      val = readl(address);
++      val &= ~mask;
++      val |= value;
++      writel(val, address);
++}
++
++static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
++                             int duty_ns, int period_ns)
++{
++      struct mtk_disp_pwm_chip *mpc;
++      u64 div, rate;
++      u32 clk_div, period, high_width, rem;
++
++      /*
++       * Find period, high_width and clk_div to suit duty_ns and period_ns.
++       * Calculate proper div value to keep period value in the bound.
++       *
++       * period_ns = 10^9 * (clk_div + 1) * (period +1) / PWM_CLK_RATE
++       * duty_ns = 10^9 * (clk_div + 1) * (high_width + 1) / PWM_CLK_RATE
++       *
++       * period = (PWM_CLK_RATE * period_ns) / (10^9 * (clk_div + 1)) - 1
++       * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1)) - 1
++       */
++      mpc = container_of(chip, struct mtk_disp_pwm_chip, chip);
++      rate = clk_get_rate(mpc->clk_main);
++      clk_div = div_u64_rem(rate * period_ns, NSEC_PER_SEC, &rem) >>
++                              PWM_PERIOD_BIT_SHIFT;
++      if (clk_div > PWM_CLKDIV_MAX)
++              return -EINVAL;
++
++      div = clk_div + 1;
++      period = div64_u64(rate * period_ns, NSEC_PER_SEC * div);
++      if (period > 0)
++              period--;
++      high_width = div64_u64(rate * duty_ns, NSEC_PER_SEC * div);
++      if (high_width > 0)
++              high_width--;
++
++      mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_CON_0_OFF,
++                           clk_div << PWM_CLKDIV_SHIFT, PWM_CLKDIV_MASK);
++      mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_CON_1_OFF,
++                           (period << PWM_PERIOD_SHIFT) |
++                      (high_width << PWM_HIGH_WIDTH_SHIFT),
++                      PWM_PERIOD_MASK | PWM_HIGH_WIDTH_MASK);
++
++      mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_COMMIT_OFF,
++                           1 << PWM_COMMIT_SHIFT, PWM_COMMIT_MASK);
++      mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_COMMIT_OFF,
++                           0 << PWM_COMMIT_SHIFT, PWM_COMMIT_MASK);
++
++      return 0;
++}
++
++static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++      struct mtk_disp_pwm_chip *mpc;
++
++      mpc = container_of(chip, struct mtk_disp_pwm_chip, chip);
++      mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_EN_OFF,
++                           1 << PWM_ENABLE_SHIFT, PWM_ENABLE_MASK);
++
++      return 0;
++}
++
++static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++      struct mtk_disp_pwm_chip *mpc;
++
++      mpc = container_of(chip, struct mtk_disp_pwm_chip, chip);
++      mtk_disp_pwm_setting(mpc->mmio_base + DISP_PWM_EN_OFF,
++                           0 << PWM_ENABLE_SHIFT, PWM_ENABLE_MASK);
++}
++
++static const struct pwm_ops mtk_disp_pwm_ops = {
++      .config = mtk_disp_pwm_config,
++      .enable = mtk_disp_pwm_enable,
++      .disable = mtk_disp_pwm_disable,
++      .owner = THIS_MODULE,
++};
++
++static int mtk_disp_pwm_probe(struct platform_device *pdev)
++{
++      struct mtk_disp_pwm_chip *pwm;
++      struct resource *r;
++      int ret;
++
++      pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
++      if (!pwm)
++              return -ENOMEM;
++
++      pwm->dev = &pdev->dev;
++
++      r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);
++      if (IS_ERR(pwm->mmio_base))
++              return PTR_ERR(pwm->mmio_base);
++
++      pwm->clk_main = devm_clk_get(&pdev->dev, "main");
++      if (IS_ERR(pwm->clk_main))
++              return PTR_ERR(pwm->clk_main);
++      pwm->clk_mm = devm_clk_get(&pdev->dev, "mm");
++      if (IS_ERR(pwm->clk_mm))
++              return PTR_ERR(pwm->clk_mm);
++
++      ret = clk_prepare_enable(pwm->clk_main);
++      if (ret < 0)
++              return ret;
++      ret = clk_prepare_enable(pwm->clk_mm);
++      if (ret < 0) {
++              clk_disable_unprepare(pwm->clk_main);
++              return ret;
++      }
++
++      platform_set_drvdata(pdev, pwm);
++
++      pwm->chip.dev = &pdev->dev;
++      pwm->chip.ops = &mtk_disp_pwm_ops;
++      pwm->chip.base = -1;
++      pwm->chip.npwm = NUM_PWM;
++
++      ret = pwmchip_add(&pwm->chip);
++      if (ret < 0) {
++              dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
++              return ret;
++      }
++
++      return 0;
++}
++
++static int mtk_disp_pwm_remove(struct platform_device *pdev)
++{
++      struct mtk_disp_pwm_chip *pc = platform_get_drvdata(pdev);
++
++      if (WARN_ON(!pc))
++              return -ENODEV;
++
++      clk_disable_unprepare(pc->clk_main);
++      clk_disable_unprepare(pc->clk_mm);
++
++      return pwmchip_remove(&pc->chip);
++}
++
++static const struct of_device_id mtk_disp_pwm_of_match[] = {
++      { .compatible = "mediatek,mt6595-disp-pwm" },
++      { }
++};
++
++MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match);
++
++static struct platform_driver mtk_disp_pwm_driver = {
++      .driver = {
++              .name = "mediatek-disp-pwm",
++              .owner = THIS_MODULE,
++              .of_match_table = mtk_disp_pwm_of_match,
++      },
++      .probe = mtk_disp_pwm_probe,
++      .remove = mtk_disp_pwm_remove,
++};
++
++module_platform_driver(mtk_disp_pwm_driver);
++
++MODULE_AUTHOR("YH Huang <yh.huang@mediatek.com>");
++MODULE_DESCRIPTION("MediaTek SoC display PWM driver");
++MODULE_LICENSE("GPL v2");
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0029-dt-bindings-Add-I2C-bindings-for-mt65xx-mt81xx.patch b/target/linux/mediatek/patches/0029-dt-bindings-Add-I2C-bindings-for-mt65xx-mt81xx.patch
new file mode 100644 (file)
index 0000000..03f03fb
--- /dev/null
@@ -0,0 +1,64 @@
+From d1447a6815913823ef5e75d70efc6f08f288ee40 Mon Sep 17 00:00:00 2001
+From: Xudong Chen <xudong.chen@mediatek.com>
+Date: Wed, 6 May 2015 16:37:05 +0800
+Subject: [PATCH 29/76] dt-bindings: Add I2C bindings for mt65xx/mt81xx.
+
+Add devicetree bindings for Mediatek Soc I2C driver.
+
+Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ .../devicetree/bindings/i2c/i2c-mt6577.txt         |   41 ++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
+new file mode 100644
+index 0000000..0ce6fa3
+--- /dev/null
++++ b/Documentation/devicetree/bindings/i2c/i2c-mt6577.txt
+@@ -0,0 +1,41 @@
++* Mediatek's I2C controller
++
++The Mediatek's I2C controller is used to interface with I2C devices.
++
++Required properties:
++  - compatible: value should be either of the following.
++      (a) "mediatek,mt6577-i2c", for i2c compatible with mt6577 i2c.
++      (b) "mediatek,mt6589-i2c", for i2c compatible with mt6589 i2c.
++      (c) "mediatek,mt8127-i2c", for i2c compatible with mt8127 i2c.
++      (d) "mediatek,mt8135-i2c", for i2c compatible with mt8135 i2c.
++      (e) "mediatek,mt8173-i2c", for i2c compatible with mt8173 i2c.
++  - reg: physical base address of the controller and dma base, length of memory
++    mapped region.
++  - interrupts: interrupt number to the cpu.
++  - clock-div: the fixed value for frequency divider of clock source in i2c
++    module. Each IC may be different.
++  - clocks: clock name from clock manager
++  - clock-names: Must include "main" and "dma", if enable have-pmic need include
++    "pmic" extra.
++
++Optional properties:
++  - clock-frequency: Frequency in Hz of the bus when transfer, the default value
++    is 100000.
++  - mediatek,have-pmic: platform can control i2c form special pmic side.
++    Only mt6589 and mt8135 support this feature.
++  - mediatek,use-push-pull: IO config use push-pull mode.
++
++Example:
++
++      i2c0: i2c@1100d000 {
++                      compatible = "mediatek,mt6577-i2c";
++                      reg = <0x1100d000 0x70>,
++                            <0x11000300 0x80>;
++                      interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_LOW>;
++                      clock-frequency = <400000>;
++                      mediatek,have-pmic;
++                      clock-div = <16>;
++                      clocks = <&i2c0_ck>, <&ap_dma_ck>;
++                      clock-names = "main", "dma";
++      };
++
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0030-I2C-mediatek-Add-driver-for-MediaTek-I2C-controller.patch b/target/linux/mediatek/patches/0030-I2C-mediatek-Add-driver-for-MediaTek-I2C-controller.patch
new file mode 100644 (file)
index 0000000..df22f08
--- /dev/null
@@ -0,0 +1,760 @@
+From 2471bc43c6079ab956a04f29ffd1ab8371b7bd73 Mon Sep 17 00:00:00 2001
+From: Xudong Chen <xudong.chen@mediatek.com>
+Date: Wed, 6 May 2015 16:37:06 +0800
+Subject: [PATCH 30/76] I2C: mediatek: Add driver for MediaTek I2C controller
+
+The mediatek SoCs have I2C controller that handle I2C transfer.
+This patch include common I2C bus driver.
+This driver is compatible with I2C controller on mt65xx/mt81xx.
+
+Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
+Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ drivers/i2c/busses/Kconfig      |    9 +
+ drivers/i2c/busses/Makefile     |    1 +
+ drivers/i2c/busses/i2c-mt65xx.c |  700 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 710 insertions(+)
+ create mode 100644 drivers/i2c/busses/i2c-mt65xx.c
+
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 2255af2..14c7266 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -620,6 +620,15 @@ config I2C_MPC
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mpc.
++config I2C_MT65XX
++      tristate "MediaTek I2C adapter"
++      depends on ARCH_MEDIATEK || COMPILE_TEST
++      help
++        This selects the MediaTek(R) Integrated Inter Circuit bus driver
++        for MT65xx and MT81xx.
++        If you want to use MediaTek(R) I2C interface, say Y or M here.
++        If unsure, say N.
++
+ config I2C_MV64XXX
+       tristate "Marvell mv64xxx I2C Controller"
+       depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index cdf941d..abbf422 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -60,6 +60,7 @@ obj-$(CONFIG_I2C_JZ4780)     += i2c-jz4780.o
+ obj-$(CONFIG_I2C_KEMPLD)      += i2c-kempld.o
+ obj-$(CONFIG_I2C_MESON)               += i2c-meson.o
+ obj-$(CONFIG_I2C_MPC)         += i2c-mpc.o
++obj-$(CONFIG_I2C_MT65XX)      += i2c-mt65xx.o
+ obj-$(CONFIG_I2C_MV64XXX)     += i2c-mv64xxx.o
+ obj-$(CONFIG_I2C_MXS)         += i2c-mxs.o
+ obj-$(CONFIG_I2C_NOMADIK)     += i2c-nomadik.o
+diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
+new file mode 100644
+index 0000000..faecf7e
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -0,0 +1,700 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Xudong.chen <xudong.chen@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/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/mm.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++#include <linux/io.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/clk.h>
++#include <linux/completion.h>
++
++#define I2C_HS_NACKERR                        (1 << 2)
++#define I2C_ACKERR                    (1 << 1)
++#define I2C_TRANSAC_COMP              (1 << 0)
++#define I2C_TRANSAC_START             (1 << 0)
++#define I2C_TIMING_STEP_DIV_MASK      (0x3f << 0)
++#define I2C_TIMING_SAMPLE_COUNT_MASK  (0x7 << 0)
++#define I2C_TIMING_SAMPLE_DIV_MASK    (0x7 << 8)
++#define I2C_TIMING_DATA_READ_MASK     (0x7 << 12)
++#define I2C_DCM_DISABLE                       0x0000
++#define I2C_IO_CONFIG_OPEN_DRAIN      0x0003
++#define I2C_IO_CONFIG_PUSH_PULL               0x0000
++#define I2C_SOFT_RST                  0x0001
++#define I2C_FIFO_ADDR_CLR             0x0001
++#define I2C_DELAY_LEN                 0x0002
++#define I2C_ST_START_CON              0x8001
++#define I2C_FS_START_CON              0x1800
++#define I2C_TIME_CLR_VALUE            0x0000
++#define I2C_TIME_DEFAULT_VALUE                0x0003
++#define I2C_FS_TIME_INIT_VALUE                0x1303
++#define I2C_WRRD_TRANAC_VALUE         0x0002
++#define I2C_RD_TRANAC_VALUE           0x0001
++
++#define I2C_DMA_CON_TX                        0x0000
++#define I2C_DMA_CON_RX                        0x0001
++#define I2C_DMA_START_EN              0x0001
++#define I2C_DMA_INT_FLAG_NONE         0x0000
++#define I2C_DMA_CLR_FLAG              0x0000
++
++#define I2C_DEFAUT_SPEED              100000  /* hz */
++#define MAX_FS_MODE_SPEED             400000
++#define MAX_HS_MODE_SPEED             3400000
++#define MAX_MSG_NUM_MT6577            1
++#define MAX_DMA_TRANS_SIZE_MT6577     255
++#define MAX_WRRD_TRANS_SIZE_MT6577    31
++#define MAX_SAMPLE_CNT_DIV            8
++#define MAX_STEP_CNT_DIV              64
++#define MAX_HS_STEP_CNT_DIV           8
++
++#define I2C_CONTROL_RS                  (0x1 << 1)
++#define I2C_CONTROL_DMA_EN              (0x1 << 2)
++#define I2C_CONTROL_CLK_EXT_EN          (0x1 << 3)
++#define I2C_CONTROL_DIR_CHANGE          (0x1 << 4)
++#define I2C_CONTROL_ACKERR_DET_EN       (0x1 << 5)
++#define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
++#define I2C_CONTROL_WRAPPER             (0x1 << 0)
++
++#define I2C_DRV_NAME          "mt-i2c"
++
++enum DMA_REGS_OFFSET {
++      OFFSET_INT_FLAG = 0x0,
++      OFFSET_INT_EN = 0x04,
++      OFFSET_EN = 0x08,
++      OFFSET_CON = 0x18,
++      OFFSET_TX_MEM_ADDR = 0x1c,
++      OFFSET_RX_MEM_ADDR = 0x20,
++      OFFSET_TX_LEN = 0x24,
++      OFFSET_RX_LEN = 0x28,
++};
++
++enum i2c_trans_st_rs {
++      I2C_TRANS_STOP = 0,
++      I2C_TRANS_REPEATED_START,
++};
++
++enum mtk_trans_op {
++      I2C_MASTER_WR = 1,
++      I2C_MASTER_RD,
++      I2C_MASTER_WRRD,
++};
++
++enum I2C_REGS_OFFSET {
++      OFFSET_DATA_PORT = 0x0,
++      OFFSET_SLAVE_ADDR = 0x04,
++      OFFSET_INTR_MASK = 0x08,
++      OFFSET_INTR_STAT = 0x0c,
++      OFFSET_CONTROL = 0x10,
++      OFFSET_TRANSFER_LEN = 0x14,
++      OFFSET_TRANSAC_LEN = 0x18,
++      OFFSET_DELAY_LEN = 0x1c,
++      OFFSET_TIMING = 0x20,
++      OFFSET_START = 0x24,
++      OFFSET_EXT_CONF = 0x28,
++      OFFSET_FIFO_STAT = 0x30,
++      OFFSET_FIFO_THRESH = 0x34,
++      OFFSET_FIFO_ADDR_CLR = 0x38,
++      OFFSET_IO_CONFIG = 0x40,
++      OFFSET_RSV_DEBUG = 0x44,
++      OFFSET_HS = 0x48,
++      OFFSET_SOFTRESET = 0x50,
++      OFFSET_DCM_EN = 0x54,
++      OFFSET_PATH_DIR = 0x60,
++      OFFSET_DEBUGSTAT = 0x64,
++      OFFSET_DEBUGCTRL = 0x68,
++      OFFSET_TRANSFER_LEN_AUX = 0x6c,
++};
++
++struct mtk_i2c_data {
++      unsigned int clk_frequency;     /* bus speed in Hz */
++      unsigned int flags;
++      unsigned int clk_src_div;
++};
++
++struct mtk_i2c_compatible {
++      const struct i2c_adapter_quirks *quirks;
++      unsigned char pmic_i2c;
++      unsigned char dcm;
++};
++
++struct mtk_i2c {
++      struct i2c_adapter adap;        /* i2c host adapter */
++      struct device *dev;
++      struct completion msg_complete;
++
++      /* set in i2c probe */
++      void __iomem *base;             /* i2c base addr */
++      void __iomem *pdmabase;         /* dma base address*/
++      struct clk *clk_main;           /* main clock for i2c bus */
++      struct clk *clk_dma;            /* DMA clock for i2c via DMA */
++      struct clk *clk_pmic;           /* PMIC clock for i2c from PMIC */
++      bool have_pmic;                 /* can use i2c pins from PMIC */
++      bool use_push_pull;             /* IO config push-pull mode */
++
++      u16 irq_stat;                   /* interrupt status */
++      unsigned int speed_hz;          /* The speed in transfer */
++      enum mtk_trans_op op;
++      u16 timing_reg;
++      u16 high_speed_reg;
++      const struct mtk_i2c_compatible *dev_comp;
++};
++
++static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
++      .flags = I2C_AQ_COMB_WRITE_THEN_READ,
++      .max_num_msgs = MAX_MSG_NUM_MT6577,
++      .max_write_len = MAX_DMA_TRANS_SIZE_MT6577,
++      .max_read_len = MAX_DMA_TRANS_SIZE_MT6577,
++      .max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT6577,
++      .max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
++};
++
++static const struct mtk_i2c_compatible mt6577_compat = {
++      .quirks = &mt6577_i2c_quirks,
++      .pmic_i2c = 0,
++      .dcm = 1,
++};
++
++static const struct mtk_i2c_compatible mt6589_compat = {
++      .quirks = &mt6577_i2c_quirks,
++      .pmic_i2c = 1,
++      .dcm = 0,
++};
++
++static const struct of_device_id mtk_i2c_of_match[] = {
++      { .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
++      { .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
++      {}
++};
++MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
++
++static inline void mtk_i2c_writew(u16 value, struct mtk_i2c *i2c, u8 offset)
++{
++      writew(value, i2c->base + offset);
++}
++
++static inline u16 mtk_i2c_readw(struct mtk_i2c *i2c, u8 offset)
++{
++      return readw(i2c->base + offset);
++}
++
++static inline void mtk_i2c_writel_dma(u32 value, struct mtk_i2c *i2c, u8 offset)
++{
++      writel(value, i2c->pdmabase + offset);
++}
++
++static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
++{
++      int ret;
++
++      ret = clk_prepare_enable(i2c->clk_dma);
++      if (ret)
++              return ret;
++
++      ret = clk_prepare_enable(i2c->clk_main);
++      if (ret)
++              goto err_main;
++
++      if (i2c->have_pmic) {
++              ret = clk_prepare_enable(i2c->clk_pmic);
++              if (ret)
++                      goto err_pmic;
++      }
++      return 0;
++
++err_pmic:
++      clk_disable_unprepare(i2c->clk_main);
++err_main:
++      clk_disable_unprepare(i2c->clk_dma);
++
++      return ret;
++}
++
++static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
++{
++      if (i2c->have_pmic)
++              clk_disable_unprepare(i2c->clk_pmic);
++
++      clk_disable_unprepare(i2c->clk_main);
++      clk_disable_unprepare(i2c->clk_dma);
++}
++
++static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
++{
++      u16 control_reg;
++
++      mtk_i2c_writew(I2C_SOFT_RST, i2c, OFFSET_SOFTRESET);
++      /* Set ioconfig */
++      if (i2c->use_push_pull)
++              mtk_i2c_writew(I2C_IO_CONFIG_PUSH_PULL, i2c, OFFSET_IO_CONFIG);
++      else
++              mtk_i2c_writew(I2C_IO_CONFIG_OPEN_DRAIN, i2c, OFFSET_IO_CONFIG);
++
++      if (i2c->dev_comp->dcm)
++              mtk_i2c_writew(I2C_DCM_DISABLE, i2c, OFFSET_DCM_EN);
++
++      mtk_i2c_writew(i2c->timing_reg, i2c, OFFSET_TIMING);
++      mtk_i2c_writew(i2c->high_speed_reg, i2c, OFFSET_HS);
++
++      /* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
++      if (i2c->have_pmic)
++              mtk_i2c_writew(I2C_CONTROL_WRAPPER, i2c, OFFSET_PATH_DIR);
++
++      control_reg = I2C_CONTROL_ACKERR_DET_EN |
++              I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
++      mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
++      mtk_i2c_writew(I2C_DELAY_LEN, i2c, OFFSET_DELAY_LEN);
++}
++
++/* calculate i2c port speed */
++static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
++{
++      unsigned int khz;
++      unsigned int step_cnt;
++      unsigned int sample_cnt;
++      unsigned int sclk;
++      unsigned int hclk;
++      unsigned int max_step_cnt;
++      unsigned int sample_div = MAX_SAMPLE_CNT_DIV;
++      unsigned int step_div;
++      unsigned int min_div;
++      unsigned int best_mul;
++      unsigned int cnt_mul;
++
++      if (i2c->speed_hz > MAX_HS_MODE_SPEED)
++              return -EINVAL;
++      else if (i2c->speed_hz > MAX_FS_MODE_SPEED)
++              max_step_cnt = MAX_HS_STEP_CNT_DIV;
++      else
++              max_step_cnt = MAX_STEP_CNT_DIV;
++
++      step_div = max_step_cnt;
++      /* Find the best combination */
++      khz = i2c->speed_hz / 1000;
++      hclk = clk_src_in_hz / 1000;
++      min_div = ((hclk >> 1) + khz - 1) / khz;
++      best_mul = MAX_SAMPLE_CNT_DIV * max_step_cnt;
++
++      for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
++              step_cnt = (min_div + sample_cnt - 1) / sample_cnt;
++              cnt_mul = step_cnt * sample_cnt;
++              if (step_cnt > max_step_cnt)
++                      continue;
++
++              if (cnt_mul < best_mul) {
++                      best_mul = cnt_mul;
++                      sample_div = sample_cnt;
++                      step_div = step_cnt;
++                      if (best_mul == min_div)
++                              break;
++              }
++      }
++
++      sample_cnt = sample_div;
++      step_cnt = step_div;
++      sclk = hclk / (2 * sample_cnt * step_cnt);
++      if (sclk > khz) {
++              dev_dbg(i2c->dev, "%s mode: unsupported speed (%ldkhz)\n",
++                      (i2c->speed_hz > MAX_HS_MODE_SPEED) ? "HS" : "ST/FT",
++                      (long int)khz);
++              return -ENOTSUPP;
++      }
++
++      step_cnt--;
++      sample_cnt--;
++
++      if (i2c->speed_hz > MAX_FS_MODE_SPEED) {
++              /* Set the hign speed mode register */
++              i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
++              i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
++                      (sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 12 |
++                      (step_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8;
++      } else {
++              i2c->timing_reg =
++                      (sample_cnt & I2C_TIMING_SAMPLE_COUNT_MASK) << 8 |
++                      (step_cnt & I2C_TIMING_STEP_DIV_MASK) << 0;
++              /* Disable the high speed transaction */
++              i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
++      }
++
++      return 0;
++}
++
++static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
++{
++      u16 addr_reg;
++      u16 control_reg;
++      dma_addr_t rpaddr = 0;
++      dma_addr_t wpaddr = 0;
++      int ret;
++
++      i2c->irq_stat = 0;
++
++      reinit_completion(&i2c->msg_complete);
++
++      control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
++                      ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
++      if (i2c->speed_hz > 400000)
++              control_reg |= I2C_CONTROL_RS;
++      if (i2c->op == I2C_MASTER_WRRD)
++              control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
++      mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
++
++      /* set start condition */
++      if (i2c->speed_hz <= 100000)
++              mtk_i2c_writew(I2C_ST_START_CON, i2c, OFFSET_EXT_CONF);
++      else
++              mtk_i2c_writew(I2C_FS_START_CON, i2c, OFFSET_EXT_CONF);
++
++      addr_reg = msgs->addr << 1;
++      if (i2c->op == I2C_MASTER_RD)
++              addr_reg |= 0x1;
++      mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
++
++      /* Clear interrupt status */
++      mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
++              i2c, OFFSET_INTR_STAT);
++      mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
++
++      /* Enable interrupt */
++      mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
++              i2c, OFFSET_INTR_MASK);
++
++      /* Set transfer and transaction len */
++      if (i2c->op == I2C_MASTER_WRRD) {
++              mtk_i2c_writew(msgs->len | ((msgs + 1)->len) << 8,
++                      i2c, OFFSET_TRANSFER_LEN);
++              mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
++      } else {
++              mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
++              mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
++      }
++
++      /* Prepare buffer data to start transfer */
++      if (i2c->op == I2C_MASTER_RD) {
++              mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
++              mtk_i2c_writel_dma(I2C_DMA_CON_RX, i2c, OFFSET_CON);
++              rpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
++                                              msgs->len, DMA_FROM_DEVICE);
++              if (dma_mapping_error(i2c->adap.dev.parent, rpaddr))
++                      return -ENOMEM;
++              mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
++              mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_RX_LEN);
++      } else if (i2c->op == I2C_MASTER_WR) {
++              mtk_i2c_writel_dma(I2C_DMA_INT_FLAG_NONE, i2c, OFFSET_INT_FLAG);
++              mtk_i2c_writel_dma(I2C_DMA_CON_TX, i2c, OFFSET_CON);
++              wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
++                                              msgs->len, DMA_TO_DEVICE);
++              if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
++                      return -ENOMEM;
++              mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
++              mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
++      } else {
++              mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_INT_FLAG);
++              mtk_i2c_writel_dma(I2C_DMA_CLR_FLAG, i2c, OFFSET_CON);
++              wpaddr = dma_map_single(i2c->adap.dev.parent, msgs->buf,
++                                              msgs->len, DMA_TO_DEVICE);
++              if (dma_mapping_error(i2c->adap.dev.parent, wpaddr))
++                      return -ENOMEM;
++              rpaddr = dma_map_single(i2c->adap.dev.parent, (msgs + 1)->buf,
++                                              (msgs + 1)->len,
++                                              DMA_FROM_DEVICE);
++              if (dma_mapping_error(i2c->adap.dev.parent, rpaddr)) {
++                      dma_unmap_single(i2c->adap.dev.parent, wpaddr,
++                                              msgs->len, DMA_TO_DEVICE);
++                      return -ENOMEM;
++              }
++              mtk_i2c_writel_dma((u32)wpaddr, i2c, OFFSET_TX_MEM_ADDR);
++              mtk_i2c_writel_dma((u32)rpaddr, i2c, OFFSET_RX_MEM_ADDR);
++              mtk_i2c_writel_dma(msgs->len, i2c, OFFSET_TX_LEN);
++              mtk_i2c_writel_dma((msgs + 1)->len, i2c, OFFSET_RX_LEN);
++      }
++
++      /* flush before sending start */
++      mb();
++      mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
++      mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
++
++      ret = wait_for_completion_timeout(&i2c->msg_complete,
++                              i2c->adap.timeout);
++
++      /* Clear interrupt mask */
++      mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
++                      | I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
++
++      if (i2c->op == I2C_MASTER_WR) {
++              dma_unmap_single(i2c->adap.dev.parent, wpaddr,
++                                      msgs->len, DMA_TO_DEVICE);
++      } else if (i2c->op == I2C_MASTER_RD) {
++              dma_unmap_single(i2c->adap.dev.parent, rpaddr,
++                                      msgs->len, DMA_FROM_DEVICE);
++      } else {
++              dma_unmap_single(i2c->adap.dev.parent, wpaddr, msgs->len,
++                                      DMA_TO_DEVICE);
++              dma_unmap_single(i2c->adap.dev.parent, rpaddr, (msgs + 1)->len,
++                                      DMA_FROM_DEVICE);
++      }
++
++      if (ret == 0) {
++              dev_dbg(i2c->dev, "addr: %x, transfer timeout\n", msgs->addr);
++              mtk_i2c_init_hw(i2c);
++              return -ETIMEDOUT;
++      }
++
++      completion_done(&i2c->msg_complete);
++
++      if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {
++              dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);
++              mtk_i2c_init_hw(i2c);
++              return -EREMOTEIO;
++      }
++
++      return 0;
++}
++
++static int mtk_i2c_transfer(struct i2c_adapter *adap,
++      struct i2c_msg msgs[], int num)
++{
++      int ret;
++      int left_num = num;
++      struct mtk_i2c *i2c = i2c_get_adapdata(adap);
++
++      ret = mtk_i2c_clock_enable(i2c);
++      if (ret)
++              return ret;
++
++      if (msgs->buf == NULL) {
++              dev_dbg(i2c->dev, "data buffer is NULL.\n");
++              ret = -EINVAL;
++              goto err_exit;
++      }
++
++      if (msgs->flags & I2C_M_RD)
++              i2c->op = I2C_MASTER_RD;
++      else
++              i2c->op = I2C_MASTER_WR;
++
++      if (num > 1) {
++              /* combined two messages into one transaction */
++              i2c->op = I2C_MASTER_WRRD;
++              left_num--;
++      }
++
++      /* always use DMA mode. */
++      ret = mtk_i2c_do_transfer(i2c, msgs);
++      if (ret < 0)
++              goto err_exit;
++
++      /* the return value is number of executed messages */
++      ret = num;
++
++err_exit:
++      mtk_i2c_clock_disable(i2c);
++      return ret;
++}
++
++static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
++{
++      struct mtk_i2c *i2c = dev_id;
++
++      i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
++      mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
++                      | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
++
++      complete(&i2c->msg_complete);
++
++      return IRQ_HANDLED;
++}
++
++static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
++{
++      return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
++}
++
++static const struct i2c_algorithm mtk_i2c_algorithm = {
++      .master_xfer = mtk_i2c_transfer,
++      .functionality = mtk_i2c_functionality,
++};
++
++static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
++      unsigned int *clk_src_div)
++{
++      int ret;
++
++      ret = of_property_read_u32(np, "clock-frequency", &i2c->speed_hz);
++      if (ret < 0)
++              i2c->speed_hz = I2C_DEFAUT_SPEED;
++
++      ret = of_property_read_u32(np, "clock-div", clk_src_div);
++      if (ret < 0)
++              return ret;
++
++      if (*clk_src_div == 0)
++              return -EINVAL;
++
++      i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
++      i2c->use_push_pull =
++              of_property_read_bool(np, "mediatek,use-push-pull");
++
++      return 0;
++}
++
++static int mtk_i2c_probe(struct platform_device *pdev)
++{
++      const struct of_device_id *of_id;
++      int ret = 0;
++      struct mtk_i2c *i2c;
++      struct clk *clk;
++      unsigned int clk_src_in_hz;
++      unsigned int clk_src_div;
++      struct resource *res;
++      int irq;
++
++      i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
++      if (i2c == NULL)
++              return -ENOMEM;
++
++      ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div);
++      if (ret)
++              return -EINVAL;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      i2c->base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(i2c->base))
++              return PTR_ERR(i2c->base);
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++      i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(i2c->pdmabase))
++              return PTR_ERR(i2c->pdmabase);
++
++      irq = platform_get_irq(pdev, 0);
++      if (irq <= 0)
++              return irq;
++
++      init_completion(&i2c->msg_complete);
++
++      of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
++      if (!of_id)
++              return -EINVAL;
++
++      i2c->dev_comp = of_id->data;
++      i2c->adap.dev.of_node = pdev->dev.of_node;
++      i2c->dev = &i2c->adap.dev;
++      i2c->adap.dev.parent = &pdev->dev;
++      i2c->adap.owner = THIS_MODULE;
++      i2c->adap.algo = &mtk_i2c_algorithm;
++      i2c->adap.quirks = i2c->dev_comp->quirks;
++      i2c->adap.timeout = 2 * HZ;
++      i2c->adap.retries = 1;
++
++      if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c)
++              return -EINVAL;
++
++      i2c->clk_main = devm_clk_get(&pdev->dev, "main");
++      if (IS_ERR(i2c->clk_main)) {
++              dev_err(&pdev->dev, "cannot get main clock\n");
++              return PTR_ERR(i2c->clk_main);
++      }
++
++      i2c->clk_dma = devm_clk_get(&pdev->dev, "dma");
++      if (IS_ERR(i2c->clk_dma)) {
++              dev_err(&pdev->dev, "cannot get dma clock\n");
++              return PTR_ERR(i2c->clk_dma);
++      }
++
++      clk = i2c->clk_main;
++      if (i2c->have_pmic) {
++              i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
++              if (IS_ERR(i2c->clk_pmic)) {
++                      dev_err(&pdev->dev, "cannot get pmic clock\n");
++                      return PTR_ERR(i2c->clk_pmic);
++              }
++              clk = i2c->clk_pmic;
++      }
++      clk_src_in_hz = clk_get_rate(clk) / clk_src_div;
++
++      dev_dbg(&pdev->dev, "clock source %p,clock src frequency %d\n",
++              i2c->clk_main, clk_src_in_hz);
++      strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
++
++      ret = mtk_i2c_set_speed(i2c, clk_src_in_hz);
++      if (ret) {
++              dev_err(&pdev->dev, "Failed to set the speed.\n");
++              return -EINVAL;
++      }
++
++      ret = mtk_i2c_clock_enable(i2c);
++      if (ret) {
++              dev_err(&pdev->dev, "clock enable failed!\n");
++              return ret;
++      }
++      mtk_i2c_init_hw(i2c);
++      mtk_i2c_clock_disable(i2c);
++
++      ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
++              IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
++      if (ret < 0) {
++              dev_err(&pdev->dev,
++                      "Request I2C IRQ %d fail\n", irq);
++              return ret;
++      }
++
++      i2c_set_adapdata(&i2c->adap, i2c);
++      ret = i2c_add_adapter(&i2c->adap);
++      if (ret) {
++              dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
++              return ret;
++      }
++
++      platform_set_drvdata(pdev, i2c);
++
++      return 0;
++}
++
++static int mtk_i2c_remove(struct platform_device *pdev)
++{
++      struct mtk_i2c *i2c = platform_get_drvdata(pdev);
++
++      i2c_del_adapter(&i2c->adap);
++
++      return 0;
++}
++
++static struct platform_driver mtk_i2c_driver = {
++      .probe = mtk_i2c_probe,
++      .remove = mtk_i2c_remove,
++      .driver = {
++              .name = I2C_DRV_NAME,
++              .of_match_table = of_match_ptr(mtk_i2c_of_match),
++      },
++};
++
++module_platform_driver(mtk_i2c_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek I2C Bus Driver");
++MODULE_AUTHOR("Xudong Chen <xudong.chen@mediatek.com>");
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0031-I2C-mediatek-Add-driver-for-MediaTek-MT8173-I2C-cont.patch b/target/linux/mediatek/patches/0031-I2C-mediatek-Add-driver-for-MediaTek-MT8173-I2C-cont.patch
new file mode 100644 (file)
index 0000000..25ea23e
--- /dev/null
@@ -0,0 +1,244 @@
+From 5f33206ebe4fb4a2cc8634f29c3e3c9bc01e3416 Mon Sep 17 00:00:00 2001
+From: Eddie Huang <eddie.huang@mediatek.com>
+Date: Wed, 6 May 2015 16:37:07 +0800
+Subject: [PATCH 31/76] I2C: mediatek: Add driver for MediaTek MT8173 I2C
+ controller
+
+Add mediatek MT8173 I2C controller driver. Compare to I2C controller
+of earlier mediatek SoC, MT8173 fix write-then-read limitation, and
+also increase message size to 64kb.
+
+Signed-off-by: Xudong Chen <xudong.chen@mediatek.com>
+Signed-off-by: Liguo Zhang <liguo.zhang@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ drivers/i2c/busses/i2c-mt65xx.c |  104 ++++++++++++++++++++++++++++-----------
+ 1 file changed, 76 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
+index faecf7e..c501421 100644
+--- a/drivers/i2c/busses/i2c-mt65xx.c
++++ b/drivers/i2c/busses/i2c-mt65xx.c
+@@ -33,10 +33,13 @@
+ #include <linux/clk.h>
+ #include <linux/completion.h>
++#define I2C_RS_TRANSFER                       (1 << 4)
+ #define I2C_HS_NACKERR                        (1 << 2)
+ #define I2C_ACKERR                    (1 << 1)
+ #define I2C_TRANSAC_COMP              (1 << 0)
+ #define I2C_TRANSAC_START             (1 << 0)
++#define I2C_RS_MUL_CNFG                       (1 << 15)
++#define I2C_RS_MUL_TRIG                       (1 << 14)
+ #define I2C_TIMING_STEP_DIV_MASK      (0x3f << 0)
+ #define I2C_TIMING_SAMPLE_COUNT_MASK  (0x7 << 0)
+ #define I2C_TIMING_SAMPLE_DIV_MASK    (0x7 << 8)
+@@ -67,6 +70,9 @@
+ #define MAX_MSG_NUM_MT6577            1
+ #define MAX_DMA_TRANS_SIZE_MT6577     255
+ #define MAX_WRRD_TRANS_SIZE_MT6577    31
++#define MAX_MSG_NUM_MT8173            65535
++#define MAX_DMA_TRANS_SIZE_MT8173     65535
++#define MAX_WRRD_TRANS_SIZE_MT8173    65535
+ #define MAX_SAMPLE_CNT_DIV            8
+ #define MAX_STEP_CNT_DIV              64
+ #define MAX_HS_STEP_CNT_DIV           8
+@@ -139,6 +145,7 @@ struct mtk_i2c_compatible {
+       const struct i2c_adapter_quirks *quirks;
+       unsigned char pmic_i2c;
+       unsigned char dcm;
++      unsigned char auto_restart;
+ };
+ struct mtk_i2c {
+@@ -172,21 +179,39 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
+       .max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT6577,
+ };
++static const struct i2c_adapter_quirks mt8173_i2c_quirks = {
++      .max_num_msgs = MAX_MSG_NUM_MT8173,
++      .max_write_len = MAX_DMA_TRANS_SIZE_MT8173,
++      .max_read_len = MAX_DMA_TRANS_SIZE_MT8173,
++      .max_comb_1st_msg_len = MAX_DMA_TRANS_SIZE_MT8173,
++      .max_comb_2nd_msg_len = MAX_WRRD_TRANS_SIZE_MT8173,
++};
++
+ static const struct mtk_i2c_compatible mt6577_compat = {
+       .quirks = &mt6577_i2c_quirks,
+       .pmic_i2c = 0,
+       .dcm = 1,
++      .auto_restart = 0,
+ };
+ static const struct mtk_i2c_compatible mt6589_compat = {
+       .quirks = &mt6577_i2c_quirks,
+       .pmic_i2c = 1,
+       .dcm = 0,
++      .auto_restart = 0,
++};
++
++static const struct mtk_i2c_compatible mt8173_compat = {
++      .quirks = &mt8173_i2c_quirks,
++      .pmic_i2c = 0,
++      .dcm = 1,
++      .auto_restart = 1,
+ };
+ static const struct of_device_id mtk_i2c_of_match[] = {
+       { .compatible = "mediatek,mt6577-i2c", .data = (void *)&mt6577_compat },
+       { .compatible = "mediatek,mt6589-i2c", .data = (void *)&mt6589_compat },
++      { .compatible = "mediatek,mt8173-i2c", .data = (void *)&mt8173_compat },
+       {}
+ };
+ MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
+@@ -343,9 +368,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int clk_src_in_hz)
+       return 0;
+ }
+-static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
++static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
++                                      int num, int left_num)
+ {
+       u16 addr_reg;
++      u16 start_reg;
+       u16 control_reg;
+       dma_addr_t rpaddr = 0;
+       dma_addr_t wpaddr = 0;
+@@ -361,6 +388,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+               control_reg |= I2C_CONTROL_RS;
+       if (i2c->op == I2C_MASTER_WRRD)
+               control_reg |= I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS;
++      if (left_num >= 1)
++              control_reg |= I2C_CONTROL_RS;
+       mtk_i2c_writew(control_reg, i2c, OFFSET_CONTROL);
+       /* set start condition */
+@@ -375,13 +404,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+       mtk_i2c_writew(addr_reg, i2c, OFFSET_SLAVE_ADDR);
+       /* Clear interrupt status */
+-      mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+-              i2c, OFFSET_INTR_STAT);
++      mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
++                      | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+       mtk_i2c_writew(I2C_FIFO_ADDR_CLR, i2c, OFFSET_FIFO_ADDR_CLR);
+       /* Enable interrupt */
+-      mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR | I2C_TRANSAC_COMP,
+-              i2c, OFFSET_INTR_MASK);
++      mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
++                      | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_MASK);
+       /* Set transfer and transaction len */
+       if (i2c->op == I2C_MASTER_WRRD) {
+@@ -390,7 +419,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+               mtk_i2c_writew(I2C_WRRD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
+       } else {
+               mtk_i2c_writew(msgs->len, i2c, OFFSET_TRANSFER_LEN);
+-              mtk_i2c_writew(I2C_RD_TRANAC_VALUE, i2c, OFFSET_TRANSAC_LEN);
++              mtk_i2c_writew(num, i2c, OFFSET_TRANSAC_LEN);
+       }
+       /* Prepare buffer data to start transfer */
+@@ -436,13 +465,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+       /* flush before sending start */
+       mb();
+       mtk_i2c_writel_dma(I2C_DMA_START_EN, i2c, OFFSET_EN);
+-      mtk_i2c_writew(I2C_TRANSAC_START, i2c, OFFSET_START);
++
++      if (!i2c->dev_comp->auto_restart) {
++              start_reg = I2C_TRANSAC_START;
++      } else {
++              if (left_num >= 1)
++                      start_reg = I2C_TRANSAC_START | I2C_RS_MUL_CNFG
++                                      | I2C_RS_MUL_TRIG;
++              else
++                      start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
++      }
++      mtk_i2c_writew(start_reg, i2c, OFFSET_START);
+       ret = wait_for_completion_timeout(&i2c->msg_complete,
+                               i2c->adap.timeout);
+       /* Clear interrupt mask */
+-      mtk_i2c_writew(~(I2C_HS_NACKERR | I2C_ACKERR
++      mtk_i2c_writew(~(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+                       | I2C_TRANSAC_COMP), i2c, OFFSET_INTR_MASK);
+       if (i2c->op == I2C_MASTER_WR) {
+@@ -472,6 +511,10 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs)
+               return -EREMOTEIO;
+       }
++      if (i2c->irq_stat & I2C_RS_TRANSFER)
++              dev_dbg(i2c->dev, "addr: %x, restart transfer interrupt.\n",
++                              msgs->addr);
++
+       return 0;
+ }
+@@ -486,28 +529,33 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
+       if (ret)
+               return ret;
+-      if (msgs->buf == NULL) {
+-              dev_dbg(i2c->dev, "data buffer is NULL.\n");
+-              ret = -EINVAL;
+-              goto err_exit;
+-      }
+-
+-      if (msgs->flags & I2C_M_RD)
+-              i2c->op = I2C_MASTER_RD;
+-      else
+-              i2c->op = I2C_MASTER_WR;
++      while (left_num--) {
++              if (msgs->buf == NULL) {
++                      dev_dbg(i2c->dev, "data buffer is NULL.\n");
++                      ret = -EINVAL;
++                      goto err_exit;
++              }
+-      if (num > 1) {
+-              /* combined two messages into one transaction */
+-              i2c->op = I2C_MASTER_WRRD;
+-              left_num--;
+-      }
++              if (msgs->flags & I2C_M_RD)
++                      i2c->op = I2C_MASTER_RD;
++              else
++                      i2c->op = I2C_MASTER_WR;
++
++              if (!i2c->dev_comp->auto_restart) {
++                      if (num > 1) {
++                              /* combined two messages into one transaction */
++                              i2c->op = I2C_MASTER_WRRD;
++                              left_num--;
++                      }
++              }
+-      /* always use DMA mode. */
+-      ret = mtk_i2c_do_transfer(i2c, msgs);
+-      if (ret < 0)
+-              goto err_exit;
++              /* always use DMA mode. */
++              ret = mtk_i2c_do_transfer(i2c, msgs, num, left_num);
++              if (ret < 0)
++                      goto err_exit;
++              msgs++;
++      }
+       /* the return value is number of executed messages */
+       ret = num;
+@@ -521,7 +569,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
+       struct mtk_i2c *i2c = dev_id;
+       i2c->irq_stat = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
+-      mtk_i2c_writew(I2C_HS_NACKERR | I2C_ACKERR
++      mtk_i2c_writew(I2C_RS_TRANSFER | I2C_HS_NACKERR | I2C_ACKERR
+                       | I2C_TRANSAC_COMP, i2c, OFFSET_INTR_STAT);
+       complete(&i2c->msg_complete);
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0032-dt-bindings-mediatek-Add-MT8173-cpufreq-driver-bindi.patch b/target/linux/mediatek/patches/0032-dt-bindings-mediatek-Add-MT8173-cpufreq-driver-bindi.patch
new file mode 100644 (file)
index 0000000..7f3b249
--- /dev/null
@@ -0,0 +1,150 @@
+From d83532fe7eb9cc7b8cc39dd9f2bbd9873d4e390b Mon Sep 17 00:00:00 2001
+From: "pi-cheng.chen" <pi-cheng.chen@linaro.org>
+Date: Mon, 8 Jun 2015 20:29:20 +0800
+Subject: [PATCH 32/76] dt-bindings: mediatek: Add MT8173 cpufreq driver
+ binding
+
+This patch adds device tree binding document for MT8173 cpufreq driver.
+
+Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+---
+ .../devicetree/bindings/cpufreq/cpufreq-mt8173.txt |  127 ++++++++++++++++++++
+ 1 file changed, 127 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt
+
+diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt
+new file mode 100644
+index 0000000..7708a65
+--- /dev/null
++++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mt8173.txt
+@@ -0,0 +1,127 @@
++
++Mediatek MT8173 cpufreq driver
++-------------------
++
++Mediatek MT8173 cpufreq driver for CPU frequency scaling.
++
++Required properties:
++- clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock names.
++- clock-names: Should contain the following:
++      "cpu"           - The multiplexer for clock input of CPU cluster.
++      "intermediate"  - A parent of "cpu" clock which is used as "intermediate" clock
++                        source (usually MAINPLL) when the original CPU PLL is under
++                        transition and not stable yet.
++- operating-points: Table of frequencies and voltage CPU could be transitioned into,
++                  Frequency should be in KHz units and voltage should be in microvolts.
++- proc-supply: Regulator for Vproc of CPU cluster.
++
++Optional properties:
++- sram-supply: Regulator for Vsram of CPU cluster. When present, the cpufreq driver
++             needs to do "voltage trace" to step by step scale up/down Vproc and
++             Vsram to fit SoC specific needs. When absent, the voltage scaling
++             flow is handled by hardware, hence no software "voltage trace" is
++             needed.
++
++Example:
++--------
++      cpu0: cpu@0 {
++              device_type = "cpu";
++              compatible = "arm,cortex-a53";
++              reg = <0x000>;
++              enable-method = "psci";
++              cpu-idle-states = <&CPU_SLEEP_0>;
++              clocks = <&infracfg CLK_INFRA_CA53SEL>,
++                       <&apmixedsys CLK_APMIXED_MAINPLL>;
++              clock-names = "cpu", "intermediate";
++              operating-points = <
++                      507000  859000
++                      702000  908000
++                      1001000 983000
++                      1105000 1009000
++                      1183000 1028000
++                      1404000 1083000
++                      1508000 1109000
++                      1573000 1125000
++              >;
++      };
++
++      cpu1: cpu@1 {
++              device_type = "cpu";
++              compatible = "arm,cortex-a53";
++              reg = <0x001>;
++              enable-method = "psci";
++              cpu-idle-states = <&CPU_SLEEP_0>;
++              clocks = <&infracfg CLK_INFRA_CA53SEL>,
++                       <&apmixedsys CLK_APMIXED_MAINPLL>;
++              clock-names = "cpu", "intermediate";
++              operating-points = <
++                      507000  859000
++                      702000  908000
++                      1001000 983000
++                      1105000 1009000
++                      1183000 1028000
++                      1404000 1083000
++                      1508000 1109000
++                      1573000 1125000
++              >;
++      };
++
++      cpu2: cpu@100 {
++              device_type = "cpu";
++              compatible = "arm,cortex-a57";
++              reg = <0x100>;
++              enable-method = "psci";
++              cpu-idle-states = <&CPU_SLEEP_0>;
++              clocks = <&infracfg CLK_INFRA_CA57SEL>,
++                       <&apmixedsys CLK_APMIXED_MAINPLL>;
++              clock-names = "cpu", "intermediate";
++              operating-points = <
++                      507000  828000
++                      702000  867000
++                      1001000 927000
++                      1209000 968000
++                      1404000 1007000
++                      1612000 1049000
++                      1807000 1089000
++                      1989000 1125000
++              >;
++      };
++
++      cpu3: cpu@101 {
++              device_type = "cpu";
++              compatible = "arm,cortex-a57";
++              reg = <0x101>;
++              enable-method = "psci";
++              cpu-idle-states = <&CPU_SLEEP_0>;
++              clocks = <&infracfg CLK_INFRA_CA57SEL>,
++                       <&apmixedsys CLK_APMIXED_MAINPLL>;
++              clock-names = "cpu", "intermediate";
++              operating-points = <
++                      507000  828000
++                      702000  867000
++                      1001000 927000
++                      1209000 968000
++                      1404000 1007000
++                      1612000 1049000
++                      1807000 1089000
++                      1989000 1125000
++              >;
++      };
++
++      &cpu0 {
++              proc-supply = <&mt6397_vpca15_reg>;
++      };
++
++      &cpu1 {
++              proc-supply = <&mt6397_vpca15_reg>;
++      };
++
++      &cpu2 {
++              proc-supply = <&da9211_vcpu_reg>;
++              sram-supply = <&mt6397_vsramca7_reg>;
++      };
++
++      &cpu3 {
++              proc-supply = <&da9211_vcpu_reg>;
++              sram-supply = <&mt6397_vsramca7_reg>;
++      };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0033-cpufreq-mediatek-Add-MT8173-cpufreq-driver.patch b/target/linux/mediatek/patches/0033-cpufreq-mediatek-Add-MT8173-cpufreq-driver.patch
new file mode 100644 (file)
index 0000000..81ae4f8
--- /dev/null
@@ -0,0 +1,604 @@
+From 2028cb37c941014f6a817d27a867ee1d37ccf2b6 Mon Sep 17 00:00:00 2001
+From: "pi-cheng.chen" <pi-cheng.chen@linaro.org>
+Date: Mon, 8 Jun 2015 20:29:21 +0800
+Subject: [PATCH 33/76] cpufreq: mediatek: Add MT8173 cpufreq driver
+
+This patch implements MT8173 cpufreq driver.
+
+Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+---
+ drivers/cpufreq/Kconfig.arm      |    7 +
+ drivers/cpufreq/Makefile         |    1 +
+ drivers/cpufreq/mt8173-cpufreq.c |  550 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 558 insertions(+)
+ create mode 100644 drivers/cpufreq/mt8173-cpufreq.c
+
+diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
+index 4f3dbc8..350752b 100644
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -141,6 +141,13 @@ config ARM_KIRKWOOD_CPUFREQ
+         This adds the CPUFreq driver for Marvell Kirkwood
+         SoCs.
++config ARM_MT8173_CPUFREQ
++      bool "Mediatek MT8173 CPUFreq support"
++      depends on ARCH_MEDIATEK && REGULATOR
++      select PM_OPP
++      help
++        This adds the CPUFreq driver support for Mediatek MT8173 SoC.
++
+ config ARM_OMAP2PLUS_CPUFREQ
+       bool "TI OMAP2+"
+       depends on ARCH_OMAP2PLUS
+diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
+index cdce92a..97f9a9b 100644
+--- a/drivers/cpufreq/Makefile
++++ b/drivers/cpufreq/Makefile
+@@ -63,6 +63,7 @@ obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ)  += hisi-acpu-cpufreq.o
+ obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)               += imx6q-cpufreq.o
+ obj-$(CONFIG_ARM_INTEGRATOR)          += integrator-cpufreq.o
+ obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)    += kirkwood-cpufreq.o
++obj-$(CONFIG_ARM_MT8173_CPUFREQ)      += mt8173-cpufreq.o
+ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)   += omap-cpufreq.o
+ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)      += pxa2xx-cpufreq.o
+ obj-$(CONFIG_PXA3xx)                  += pxa3xx-cpufreq.o
+diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
+new file mode 100644
+index 0000000..d539e7b
+--- /dev/null
++++ b/drivers/cpufreq/mt8173-cpufreq.c
+@@ -0,0 +1,550 @@
++/*
++ * Copyright (c) 2015 Linaro Ltd.
++ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
++ *
++ * 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/cpu.h>
++#include <linux/cpufreq.h>
++#include <linux/cpumask.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/pm_opp.h>
++#include <linux/regulator/consumer.h>
++#include <linux/slab.h>
++
++#define MIN_VOLT_SHIFT                (100000)
++#define MAX_VOLT_SHIFT                (200000)
++#define MAX_VOLT_LIMIT                (1150000)
++#define VOLT_TOL              (10000)
++
++/*
++ * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS
++ * on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in
++ * Mediatek SoCs has two voltage inputs, Vproc and Vsram. In some cases the two
++ * voltage inputs need to be controlled under a hardware limitation:
++ * 100mV < Vsram - Vproc < 200mV
++ *
++ * When scaling the clock frequency of a CPU clock domain, the clock source
++ * needs to be switched to another stable PLL clock temporarily until
++ * the original PLL becomes stable at target frequency.
++ */
++struct mtk_cpu_dvfs_info {
++      struct list_head node;
++      cpumask_var_t cpus;
++      struct cpufreq_frequency_table *freq_table;
++      struct device *cpu_dev;
++      struct regulator *proc_reg;
++      struct regulator *sram_reg;
++      struct clk *cpu_clk;
++      struct clk *inter_clk;
++      int intermediate_voltage;
++      bool need_voltage_trace;
++};
++
++static LIST_HEAD(cpu_dvfs_info_list);
++
++static inline struct mtk_cpu_dvfs_info *to_mtk_cpu_dvfs_info(
++                      struct list_head *list)
++{
++      return list_entry(list, struct mtk_cpu_dvfs_info, node);
++}
++
++static inline void mtk_cpu_dvfs_info_add(struct mtk_cpu_dvfs_info *info)
++{
++      list_add(&info->node, &cpu_dvfs_info_list);
++}
++
++static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_get(int cpu)
++{
++      struct mtk_cpu_dvfs_info *info;
++      struct list_head *list;
++
++      list_for_each(list, &cpu_dvfs_info_list) {
++              info = to_mtk_cpu_dvfs_info(list);
++
++              if (cpumask_test_cpu(cpu, info->cpus))
++                      return info;
++      }
++
++      return NULL;
++}
++
++static void mtk_cpu_dvfs_info_release(void)
++{
++      struct list_head *list, *tmp;
++      struct mtk_cpu_dvfs_info *info;
++
++      list_for_each_safe(list, tmp, &cpu_dvfs_info_list) {
++              info = to_mtk_cpu_dvfs_info(list);
++
++              dev_pm_opp_free_cpufreq_table(info->cpu_dev,
++                                            &info->freq_table);
++
++              if (!IS_ERR(info->proc_reg))
++                      regulator_put(info->proc_reg);
++              if (!IS_ERR(info->sram_reg))
++                      regulator_put(info->sram_reg);
++              if (!IS_ERR(info->cpu_clk))
++                      clk_put(info->cpu_clk);
++              if (!IS_ERR(info->inter_clk))
++                      clk_put(info->inter_clk);
++
++              of_free_opp_table(info->cpu_dev);
++
++              list_del(list);
++              kfree(info);
++      }
++}
++
++#define MIN(a, b) ((a) < (b) ? (a) : (b))
++#define MAX(a, b) ((a) > (b) ? (a) : (b))
++
++static int mtk_cpufreq_voltage_trace(struct mtk_cpu_dvfs_info *info,
++                                   int new_vproc)
++{
++      struct regulator *proc_reg = info->proc_reg;
++      struct regulator *sram_reg = info->sram_reg;
++      int old_vproc, old_vsram, new_vsram, vsram, vproc, ret;
++
++      old_vproc = regulator_get_voltage(proc_reg);
++      old_vsram = regulator_get_voltage(sram_reg);
++      /* Vsram should not exceed the maximum allowed voltage of SoC. */
++      new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
++
++      if (old_vproc < new_vproc) {
++              /*
++               * When scaling up voltages, Vsram and Vproc scale up step
++               * by step. At each step, set Vsram to (Vproc + 200mV) first,
++               * then set Vproc to (Vsram - 100mV).
++               * Keep doing it until Vsram and Vproc hit target voltages.
++               */
++              do {
++                      old_vsram = regulator_get_voltage(sram_reg);
++                      old_vproc = regulator_get_voltage(proc_reg);
++
++                      vsram = MIN(new_vsram, old_vproc + MAX_VOLT_SHIFT);
++
++                      if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
++                              vsram = MAX_VOLT_LIMIT;
++
++                              /*
++                               * If the target Vsram hits the maximum voltage,
++                               * try to set the exact voltage value first.
++                               */
++                              ret = regulator_set_voltage(sram_reg, vsram,
++                                                          vsram);
++                              if (ret)
++                                      ret = regulator_set_voltage(sram_reg,
++                                                      vsram - VOLT_TOL,
++                                                      vsram);
++
++                              vproc = new_vproc;
++                      } else {
++                              ret = regulator_set_voltage(sram_reg, vsram,
++                                                          vsram + VOLT_TOL);
++
++                              vproc = vsram - MIN_VOLT_SHIFT;
++                      }
++                      if (ret)
++                              return ret;
++
++                      ret = regulator_set_voltage(proc_reg, vproc,
++                                                  vproc + VOLT_TOL);
++                      if (ret) {
++                              regulator_set_voltage(sram_reg, old_vsram,
++                                                    old_vsram);
++                              return ret;
++                      }
++              } while (vproc < new_vproc || vsram < new_vsram);
++      } else if (old_vproc > new_vproc) {
++              /*
++               * When scaling down voltages, Vsram and Vproc scale down step
++               * by step. At each step, set Vproc to (Vsram - 200mV) first,
++               * then set Vproc to (Vproc + 100mV).
++               * Keep doing it until Vsram and Vproc hit target voltages.
++               */
++              do {
++                      old_vproc = regulator_get_voltage(proc_reg);
++                      old_vsram = regulator_get_voltage(sram_reg);
++
++                      vproc = MAX(new_vproc, old_vsram - MAX_VOLT_SHIFT);
++                      ret = regulator_set_voltage(proc_reg, vproc,
++                                                  vproc + VOLT_TOL);
++                      if (ret)
++                              return ret;
++
++                      if (vproc == new_vproc)
++                              vsram = new_vsram;
++                      else
++                              vsram = MAX(new_vsram, vproc + MIN_VOLT_SHIFT);
++
++                      if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
++                              vsram = MAX_VOLT_LIMIT;
++
++                              /*
++                               * If the target Vsram hits the maximum voltage,
++                               * try to set the exact voltage value first.
++                               */
++                              ret = regulator_set_voltage(sram_reg, vsram,
++                                                          vsram);
++                              if (ret)
++                                      ret = regulator_set_voltage(sram_reg,
++                                                      vsram - VOLT_TOL,
++                                                      vsram);
++                      } else {
++                              ret = regulator_set_voltage(sram_reg, vsram,
++                                                          vsram + VOLT_TOL);
++                      }
++
++                      if (ret) {
++                              regulator_set_voltage(proc_reg, old_vproc,
++                                                    old_vproc);
++                              return ret;
++                      }
++              } while (vproc > new_vproc + VOLT_TOL ||
++                       vsram > new_vsram + VOLT_TOL);
++      }
++
++      return 0;
++}
++
++static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
++{
++      if (info->need_voltage_trace)
++              return mtk_cpufreq_voltage_trace(info, vproc);
++      else
++              return regulator_set_voltage(info->proc_reg, vproc,
++                                           vproc + VOLT_TOL);
++}
++
++static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
++                                unsigned int index)
++{
++      struct cpufreq_frequency_table *freq_table = policy->freq_table;
++      struct clk *cpu_clk = policy->clk;
++      struct clk *armpll = clk_get_parent(cpu_clk);
++      struct mtk_cpu_dvfs_info *info = policy->driver_data;
++      struct device *cpu_dev = info->cpu_dev;
++      struct dev_pm_opp *opp;
++      long freq_hz, old_freq_hz;
++      int vproc, old_vproc, inter_vproc, target_vproc, ret;
++
++      inter_vproc = info->intermediate_voltage;
++
++      old_freq_hz = clk_get_rate(cpu_clk);
++      old_vproc = regulator_get_voltage(info->proc_reg);
++
++      freq_hz = freq_table[index].frequency * 1000;
++      rcu_read_lock();
++      opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
++      if (IS_ERR(opp)) {
++              rcu_read_unlock();
++              pr_err("cpu%d: failed to find OPP for %ld\n",
++                     policy->cpu, freq_hz);
++              return PTR_ERR(opp);
++      }
++      vproc = dev_pm_opp_get_voltage(opp);
++      rcu_read_unlock();
++
++      /*
++       * If the new voltage or the intermediate voltage is higher than the
++       * current voltage, scale up voltage first.
++       */
++      target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc;
++      if (old_vproc < target_vproc) {
++              ret = mtk_cpufreq_set_voltage(info, target_vproc);
++              if (ret) {
++                      pr_err("cpu%d: failed to scale up voltage!\n",
++                             policy->cpu);
++                      mtk_cpufreq_set_voltage(info, old_vproc);
++                      return ret;
++              }
++      }
++
++      /* Reparent the CPU clock to intermediate clock. */
++      ret = clk_set_parent(cpu_clk, info->inter_clk);
++      if (ret) {
++              pr_err("cpu%d: failed to re-parent cpu clock!\n",
++                     policy->cpu);
++              mtk_cpufreq_set_voltage(info, old_vproc);
++              WARN_ON(1);
++              return ret;
++      }
++
++      /* Set the original PLL to target rate. */
++      ret = clk_set_rate(armpll, freq_hz);
++      if (ret) {
++              pr_err("cpu%d: failed to scale cpu clock rate!\n",
++                     policy->cpu);
++              clk_set_parent(cpu_clk, armpll);
++              mtk_cpufreq_set_voltage(info, old_vproc);
++              return ret;
++      }
++
++      /* Set parent of CPU clock back to the original PLL. */
++      ret = clk_set_parent(cpu_clk, armpll);
++      if (ret) {
++              pr_err("cpu%d: failed to re-parent cpu clock!\n",
++                     policy->cpu);
++              mtk_cpufreq_set_voltage(info, inter_vproc);
++              WARN_ON(1);
++              return ret;
++      }
++
++      /*
++       * If the new voltage is lower than the intermediate voltage or the
++       * original voltage, scale down to the new voltage.
++       */
++      if (vproc < inter_vproc || vproc < old_vproc) {
++              ret = mtk_cpufreq_set_voltage(info, vproc);
++              if (ret) {
++                      pr_err("cpu%d: failed to scale down voltage!\n",
++                             policy->cpu);
++                      clk_set_parent(cpu_clk, info->inter_clk);
++                      clk_set_rate(armpll, old_freq_hz);
++                      clk_set_parent(cpu_clk, armpll);
++                      return ret;
++              }
++      }
++
++      return 0;
++}
++
++static int mtk_cpufreq_init(struct cpufreq_policy *policy)
++{
++      struct mtk_cpu_dvfs_info *info;
++      int ret;
++
++      info = mtk_cpu_dvfs_info_get(policy->cpu);
++      if (!info) {
++              pr_err("%s: mtk cpu dvfs info for cpu%d is not initialized\n",
++                     __func__, policy->cpu);
++              return -ENODEV;
++      }
++
++      ret = cpufreq_table_validate_and_show(policy, info->freq_table);
++      if (ret) {
++              pr_err("%s: invalid frequency table: %d\n", __func__, ret);
++              return ret;
++      }
++
++      cpumask_copy(policy->cpus, info->cpus);
++      policy->driver_data = info;
++      policy->clk = info->cpu_clk;
++
++      return 0;
++}
++
++static struct cpufreq_driver mt8173_cpufreq_driver = {
++      .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
++      .verify = cpufreq_generic_frequency_table_verify,
++      .target_index = mtk_cpufreq_set_target,
++      .get = cpufreq_generic_get,
++      .init = mtk_cpufreq_init,
++      .name = "mtk-cpufreq",
++      .attr = cpufreq_generic_attr,
++};
++
++static int mtk_cpu_dvfs_info_init(int cpu)
++{
++      struct device *cpu_dev;
++      struct regulator *proc_reg = ERR_PTR(-ENODEV);
++      struct regulator *sram_reg = ERR_PTR(-ENODEV);
++      struct clk *cpu_clk = ERR_PTR(-ENODEV);
++      struct clk *inter_clk = ERR_PTR(-ENODEV);
++      struct mtk_cpu_dvfs_info *info;
++      struct cpufreq_frequency_table *freq_table;
++      struct dev_pm_opp *opp;
++      unsigned long rate;
++      int ret;
++
++      cpu_dev = get_cpu_device(cpu);
++      if (!cpu_dev) {
++              pr_err("failed to get cpu%d device\n", cpu);
++              return -ENODEV;
++      }
++
++      ret = of_init_opp_table(cpu_dev);
++      if (ret) {
++              pr_warn("no OPP table for cpu%d\n", cpu);
++              return ret;
++      }
++
++      cpu_clk = clk_get(cpu_dev, "cpu");
++      if (IS_ERR(cpu_clk)) {
++              if (PTR_ERR(cpu_clk) == -EPROBE_DEFER)
++                      pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu);
++              else
++                      pr_err("failed to get cpu clk for cpu%d\n", cpu);
++
++              ret = PTR_ERR(cpu_clk);
++              goto out_free_opp_table;
++      }
++
++      inter_clk = clk_get(cpu_dev, "intermediate");
++      if (IS_ERR(inter_clk)) {
++              if (PTR_ERR(inter_clk) == -EPROBE_DEFER)
++                      pr_warn("intermediate clk for cpu%d not ready, retry.\n",
++                              cpu);
++              else
++                      pr_err("failed to get intermediate clk for cpu%d\n",
++                             cpu);
++
++              ret = PTR_ERR(cpu_clk);
++              goto out_free_resources;
++      }
++
++      proc_reg = regulator_get_exclusive(cpu_dev, "proc");
++      if (IS_ERR(proc_reg)) {
++              if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
++                      pr_warn("proc regulator for cpu%d not ready, retry.\n",
++                              cpu);
++              else
++                      pr_err("failed to get proc regulator for cpu%d\n",
++                             cpu);
++
++              ret = PTR_ERR(proc_reg);
++              goto out_free_resources;
++      }
++
++      /* Both presence and absence of sram regulator are valid cases. */
++      sram_reg = regulator_get_exclusive(cpu_dev, "sram");
++
++      info = kzalloc(sizeof(*info), GFP_KERNEL);
++      if (!info) {
++              ret = -ENOMEM;
++              goto out_free_resources;
++      }
++
++      ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
++      if (ret) {
++              pr_err("failed to init cpufreq table for cpu%d: %d\n",
++                     cpu, ret);
++              goto out_free_mtk_cpu_dvfs_info;
++      }
++
++      if (!alloc_cpumask_var(&info->cpus, GFP_KERNEL))
++              goto out_free_cpufreq_table;
++
++      /* Search a safe voltage for intermediate frequency. */
++      rate = clk_get_rate(inter_clk);
++      rcu_read_lock();
++      opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
++      if (IS_ERR(opp)) {
++              pr_err("failed to get intermediate opp for cpu%d\n", cpu);
++              ret = PTR_ERR(opp);
++              goto out_free_cpumask;
++      }
++      info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
++      rcu_read_unlock();
++
++      /* CPUs in the same cluster share a clock and power domain. */
++      cpumask_copy(info->cpus, &cpu_topology[cpu].core_sibling);
++
++      info->cpu_dev = cpu_dev;
++      info->proc_reg = proc_reg;
++      info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
++      info->cpu_clk = cpu_clk;
++      info->inter_clk = inter_clk;
++      info->freq_table = freq_table;
++
++      /*
++       * If SRAM regulator is present, software "voltage trace" is needed
++       * for this CPU power domain.
++       */
++      info->need_voltage_trace = !IS_ERR(sram_reg);
++
++      mtk_cpu_dvfs_info_add(info);
++
++      return 0;
++
++out_free_cpumask:
++      free_cpumask_var(info->cpus);
++
++out_free_cpufreq_table:
++      dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
++
++out_free_mtk_cpu_dvfs_info:
++      kfree(info);
++
++out_free_resources:
++      if (!IS_ERR(proc_reg))
++              regulator_put(proc_reg);
++      if (!IS_ERR(sram_reg))
++              regulator_put(sram_reg);
++      if (!IS_ERR(cpu_clk))
++              clk_put(cpu_clk);
++      if (!IS_ERR(inter_clk))
++              clk_put(inter_clk);
++
++out_free_opp_table:
++      of_free_opp_table(cpu_dev);
++
++      return ret;
++}
++
++static int mt8173_cpufreq_probe(struct platform_device *pdev)
++{
++      int cpu, ret;
++
++      for_each_possible_cpu(cpu) {
++              /*
++               * If the struct mtk_cpu_dvfs_info for the cpu power domain
++               * is already initialized, skip this CPU.
++               */
++              if (!mtk_cpu_dvfs_info_get(cpu)) {
++                      ret = mtk_cpu_dvfs_info_init(cpu);
++                      if (ret) {
++                              if (ret != -EPROBE_DEFER)
++                                      pr_err("%s probe fail\n", __func__);
++
++                              mtk_cpu_dvfs_info_release();
++                              return ret;
++                      }
++              }
++      }
++
++      ret = cpufreq_register_driver(&mt8173_cpufreq_driver);
++      if (ret) {
++              pr_err("failed to register mtk cpufreq driver\n");
++              mtk_cpu_dvfs_info_release();
++      }
++
++      return ret;
++}
++
++static struct platform_driver mt8173_cpufreq_platdrv = {
++      .driver = {
++              .name   = "mt8173-cpufreq",
++      },
++      .probe          = mt8173_cpufreq_probe,
++};
++module_platform_driver(mt8173_cpufreq_platdrv);
++
++static int mt8173_cpufreq_driver_init(void)
++{
++      struct platform_device *pdev;
++
++      if (!of_machine_is_compatible("mediatek,mt8173"))
++              return -ENODEV;
++
++      pdev = platform_device_register_simple("mt8173-cpufreq", -1, NULL, 0);
++      if (IS_ERR(pdev)) {
++              pr_err("failed to register mtk-cpufreq platform device\n");
++              return PTR_ERR(pdev);
++      }
++
++      return 0;
++}
++module_init(mt8173_cpufreq_driver_init);
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0034-mmc-dt-bindings-add-Mediatek-MMC-bindings.patch b/target/linux/mediatek/patches/0034-mmc-dt-bindings-add-Mediatek-MMC-bindings.patch
new file mode 100644 (file)
index 0000000..02a153d
--- /dev/null
@@ -0,0 +1,54 @@
+From fe43da8836dbf8e48377d208000877a17e465f3f Mon Sep 17 00:00:00 2001
+From: Chaotian Jing <chaotian.jing@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:47 +0800
+Subject: [PATCH 34/76] mmc: dt-bindings: add Mediatek MMC bindings
+
+Document the device-tree binding of Mediatek MMC host
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ Documentation/devicetree/bindings/mmc/mtk-sd.txt |   32 ++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt
+
+diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+new file mode 100644
+index 0000000..a1adfa4
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+@@ -0,0 +1,32 @@
++* MTK MMC controller
++
++The MTK  MSDC can act as a MMC controller
++to support MMC, SD, and SDIO types of memory cards.
++
++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"
++- interrupts: Should contain MSDC interrupt number
++- clocks: MSDC source clock, HCLK
++- clock-names: "source", "hclk"
++- pinctrl-names: should be "default", "state_uhs"
++- pinctrl-0: should contain default/high speed pin ctrl
++- pinctrl-1: should contain uhs mode pin ctrl
++- vmmc-supply: power to the Core
++- vqmmc-supply: power to the IO
++
++Examples:
++mmc0: mmc@11230000 {
++      compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc";
++      reg = <0 0x11230000 0 0x108>;
++      interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
++      vmmc-supply = <&mt6397_vemc_3v3_reg>;
++      vqmmc-supply = <&mt6397_vio18_reg>;
++      clocks = <&pericfg CLK_PERI_MSDC30_0>, <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
++      clock-names = "source", "hclk";
++      pinctrl-names = "default", "state_uhs";
++      pinctrl-0 = <&mmc0_pins_default>;
++      pinctrl-1 = <&mmc0_pins_uhs>;
++};
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0035-mmc-mediatek-Add-Mediatek-MMC-driver.patch b/target/linux/mediatek/patches/0035-mmc-mediatek-Add-Mediatek-MMC-driver.patch
new file mode 100644 (file)
index 0000000..d135ad0
--- /dev/null
@@ -0,0 +1,1422 @@
+From 0b71d2f1ee40313f58a3c6e9ed95add6f5a8192d Mon Sep 17 00:00:00 2001
+From: Chaotian Jing <chaotian.jing@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:48 +0800
+Subject: [PATCH 35/76] mmc: mediatek: Add Mediatek MMC driver
+
+Add Mediatek MMC driver code
+Support eMMC/SD/SDIO
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ drivers/mmc/host/Kconfig  |    8 +
+ drivers/mmc/host/Makefile |    1 +
+ drivers/mmc/host/mtk-sd.c | 1378 +++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/mmc/core.h  |    1 +
+ 4 files changed, 1388 insertions(+)
+ create mode 100644 drivers/mmc/host/mtk-sd.c
+
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -800,3 +800,11 @@
+       tristate "Toshiba Type A SD/MMC Card Interface Driver"
+       depends on PCI
+       help
++
++config MMC_MTK
++      tristate "MediaTek SD/MMC Card Interface support"
++      help
++        This selects the MediaTek(R) Secure digital and Multimedia card Interface.
++        If you have a machine with a integrated SD/MMC card reader, say Y or M here.
++        This is needed if support for any SD/SDIO/MMC devices is required.
++        If unsure, say N.
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -20,6 +20,7 @@
+ obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
+ obj-$(CONFIG_MMC_WBSD)                += wbsd.o
+ obj-$(CONFIG_MMC_AU1X)                += au1xmmc.o
++obj-$(CONFIG_MMC_MTK)           += mtk-sd.o
+ obj-$(CONFIG_MMC_OMAP)                += omap.o
+ obj-$(CONFIG_MMC_OMAP_HS)     += omap_hsmmc.o
+ obj-$(CONFIG_MMC_ATMELMCI)    += atmel-mci.o
+--- /dev/null
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -0,0 +1,1378 @@
++/*
++ * Copyright (c) 2014-2015 MediaTek Inc.
++ * Author: Chaotian.Jing <chaotian.jing@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/dma-mapping.h>
++#include <linux/ioport.h>
++#include <linux/irq.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/spinlock.h>
++
++#include <linux/mmc/card.h>
++#include <linux/mmc/core.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/sd.h>
++#include <linux/mmc/sdio.h>
++
++#define MAX_BD_NUM          1024
++
++/*--------------------------------------------------------------------------*/
++/* Common Definition                                                        */
++/*--------------------------------------------------------------------------*/
++#define MSDC_BUS_1BITS          0x0
++#define MSDC_BUS_4BITS          0x1
++#define MSDC_BUS_8BITS          0x2
++
++#define MSDC_BURST_64B          0x6
++
++/*--------------------------------------------------------------------------*/
++/* Register Offset                                                          */
++/*--------------------------------------------------------------------------*/
++#define MSDC_CFG         0x0
++#define MSDC_IOCON       0x04
++#define MSDC_PS          0x08
++#define MSDC_INT         0x0c
++#define MSDC_INTEN       0x10
++#define MSDC_FIFOCS      0x14
++#define SDC_CFG          0x30
++#define SDC_CMD          0x34
++#define SDC_ARG          0x38
++#define SDC_STS          0x3c
++#define SDC_RESP0        0x40
++#define SDC_RESP1        0x44
++#define SDC_RESP2        0x48
++#define SDC_RESP3        0x4c
++#define SDC_BLK_NUM      0x50
++#define SDC_ACMD_RESP    0x80
++#define MSDC_DMA_SA      0x90
++#define MSDC_DMA_CTRL    0x98
++#define MSDC_DMA_CFG     0x9c
++#define MSDC_PATCH_BIT   0xb0
++#define MSDC_PATCH_BIT1  0xb4
++#define MSDC_PAD_TUNE    0xec
++
++/*--------------------------------------------------------------------------*/
++/* Register Mask                                                            */
++/*--------------------------------------------------------------------------*/
++
++/* MSDC_CFG mask */
++#define MSDC_CFG_MODE           (0x1 << 0)    /* RW */
++#define MSDC_CFG_CKPDN          (0x1 << 1)    /* RW */
++#define MSDC_CFG_RST            (0x1 << 2)    /* RW */
++#define MSDC_CFG_PIO            (0x1 << 3)    /* RW */
++#define MSDC_CFG_CKDRVEN        (0x1 << 4)    /* RW */
++#define MSDC_CFG_BV18SDT        (0x1 << 5)    /* RW */
++#define MSDC_CFG_BV18PSS        (0x1 << 6)    /* R  */
++#define MSDC_CFG_CKSTB          (0x1 << 7)    /* R  */
++#define MSDC_CFG_CKDIV          (0xff << 8)   /* RW */
++#define MSDC_CFG_CKMOD          (0x3 << 16)   /* RW */
++
++/* MSDC_IOCON mask */
++#define MSDC_IOCON_SDR104CKS    (0x1 << 0)    /* RW */
++#define MSDC_IOCON_RSPL         (0x1 << 1)    /* RW */
++#define MSDC_IOCON_DSPL         (0x1 << 2)    /* RW */
++#define MSDC_IOCON_DDLSEL       (0x1 << 3)    /* RW */
++#define MSDC_IOCON_DDR50CKD     (0x1 << 4)    /* RW */
++#define MSDC_IOCON_DSPLSEL      (0x1 << 5)    /* RW */
++#define MSDC_IOCON_W_DSPL       (0x1 << 8)    /* RW */
++#define MSDC_IOCON_D0SPL        (0x1 << 16)   /* RW */
++#define MSDC_IOCON_D1SPL        (0x1 << 17)   /* RW */
++#define MSDC_IOCON_D2SPL        (0x1 << 18)   /* RW */
++#define MSDC_IOCON_D3SPL        (0x1 << 19)   /* RW */
++#define MSDC_IOCON_D4SPL        (0x1 << 20)   /* RW */
++#define MSDC_IOCON_D5SPL        (0x1 << 21)   /* RW */
++#define MSDC_IOCON_D6SPL        (0x1 << 22)   /* RW */
++#define MSDC_IOCON_D7SPL        (0x1 << 23)   /* RW */
++#define MSDC_IOCON_RISCSZ       (0x3 << 24)   /* RW */
++
++/* MSDC_PS mask */
++#define MSDC_PS_CDEN            (0x1 << 0)    /* RW */
++#define MSDC_PS_CDSTS           (0x1 << 1)    /* R  */
++#define MSDC_PS_CDDEBOUNCE      (0xf << 12)   /* RW */
++#define MSDC_PS_DAT             (0xff << 16)  /* R  */
++#define MSDC_PS_CMD             (0x1 << 24)   /* R  */
++#define MSDC_PS_WP              (0x1 << 31)   /* R  */
++
++/* MSDC_INT mask */
++#define MSDC_INT_MMCIRQ         (0x1 << 0)    /* W1C */
++#define MSDC_INT_CDSC           (0x1 << 1)    /* W1C */
++#define MSDC_INT_ACMDRDY        (0x1 << 3)    /* W1C */
++#define MSDC_INT_ACMDTMO        (0x1 << 4)    /* W1C */
++#define MSDC_INT_ACMDCRCERR     (0x1 << 5)    /* W1C */
++#define MSDC_INT_DMAQ_EMPTY     (0x1 << 6)    /* W1C */
++#define MSDC_INT_SDIOIRQ        (0x1 << 7)    /* W1C */
++#define MSDC_INT_CMDRDY         (0x1 << 8)    /* W1C */
++#define MSDC_INT_CMDTMO         (0x1 << 9)    /* W1C */
++#define MSDC_INT_RSPCRCERR      (0x1 << 10)   /* W1C */
++#define MSDC_INT_CSTA           (0x1 << 11)   /* R */
++#define MSDC_INT_XFER_COMPL     (0x1 << 12)   /* W1C */
++#define MSDC_INT_DXFER_DONE     (0x1 << 13)   /* W1C */
++#define MSDC_INT_DATTMO         (0x1 << 14)   /* W1C */
++#define MSDC_INT_DATCRCERR      (0x1 << 15)   /* W1C */
++#define MSDC_INT_ACMD19_DONE    (0x1 << 16)   /* W1C */
++#define MSDC_INT_DMA_BDCSERR    (0x1 << 17)   /* W1C */
++#define MSDC_INT_DMA_GPDCSERR   (0x1 << 18)   /* W1C */
++#define MSDC_INT_DMA_PROTECT    (0x1 << 19)   /* W1C */
++
++/* MSDC_INTEN mask */
++#define MSDC_INTEN_MMCIRQ       (0x1 << 0)    /* RW */
++#define MSDC_INTEN_CDSC         (0x1 << 1)    /* RW */
++#define MSDC_INTEN_ACMDRDY      (0x1 << 3)    /* RW */
++#define MSDC_INTEN_ACMDTMO      (0x1 << 4)    /* RW */
++#define MSDC_INTEN_ACMDCRCERR   (0x1 << 5)    /* RW */
++#define MSDC_INTEN_DMAQ_EMPTY   (0x1 << 6)    /* RW */
++#define MSDC_INTEN_SDIOIRQ      (0x1 << 7)    /* RW */
++#define MSDC_INTEN_CMDRDY       (0x1 << 8)    /* RW */
++#define MSDC_INTEN_CMDTMO       (0x1 << 9)    /* RW */
++#define MSDC_INTEN_RSPCRCERR    (0x1 << 10)   /* RW */
++#define MSDC_INTEN_CSTA         (0x1 << 11)   /* RW */
++#define MSDC_INTEN_XFER_COMPL   (0x1 << 12)   /* RW */
++#define MSDC_INTEN_DXFER_DONE   (0x1 << 13)   /* RW */
++#define MSDC_INTEN_DATTMO       (0x1 << 14)   /* RW */
++#define MSDC_INTEN_DATCRCERR    (0x1 << 15)   /* RW */
++#define MSDC_INTEN_ACMD19_DONE  (0x1 << 16)   /* RW */
++#define MSDC_INTEN_DMA_BDCSERR  (0x1 << 17)   /* RW */
++#define MSDC_INTEN_DMA_GPDCSERR (0x1 << 18)   /* RW */
++#define MSDC_INTEN_DMA_PROTECT  (0x1 << 19)   /* RW */
++
++/* MSDC_FIFOCS mask */
++#define MSDC_FIFOCS_RXCNT       (0xff << 0)   /* R */
++#define MSDC_FIFOCS_TXCNT       (0xff << 16)  /* R */
++#define MSDC_FIFOCS_CLR         (0x1 << 31)   /* RW */
++
++/* SDC_CFG mask */
++#define SDC_CFG_SDIOINTWKUP     (0x1 << 0)    /* RW */
++#define SDC_CFG_INSWKUP         (0x1 << 1)    /* RW */
++#define SDC_CFG_BUSWIDTH        (0x3 << 16)   /* RW */
++#define SDC_CFG_SDIO            (0x1 << 19)   /* RW */
++#define SDC_CFG_SDIOIDE         (0x1 << 20)   /* RW */
++#define SDC_CFG_INTATGAP        (0x1 << 21)   /* RW */
++#define SDC_CFG_DTOC            (0xff << 24)  /* RW */
++
++/* SDC_STS mask */
++#define SDC_STS_SDCBUSY         (0x1 << 0)    /* RW */
++#define SDC_STS_CMDBUSY         (0x1 << 1)    /* RW */
++#define SDC_STS_SWR_COMPL       (0x1 << 31)   /* RW */
++
++/* MSDC_DMA_CTRL mask */
++#define MSDC_DMA_CTRL_START     (0x1 << 0)    /* W */
++#define MSDC_DMA_CTRL_STOP      (0x1 << 1)    /* W */
++#define MSDC_DMA_CTRL_RESUME    (0x1 << 2)    /* W */
++#define MSDC_DMA_CTRL_MODE      (0x1 << 8)    /* RW */
++#define MSDC_DMA_CTRL_LASTBUF   (0x1 << 10)   /* RW */
++#define MSDC_DMA_CTRL_BRUSTSZ   (0x7 << 12)   /* RW */
++
++/* MSDC_DMA_CFG mask */
++#define MSDC_DMA_CFG_STS        (0x1 << 0)    /* R */
++#define MSDC_DMA_CFG_DECSEN     (0x1 << 1)    /* RW */
++#define MSDC_DMA_CFG_AHBHPROT2  (0x2 << 8)    /* RW */
++#define MSDC_DMA_CFG_ACTIVEEN   (0x2 << 12)   /* RW */
++#define MSDC_DMA_CFG_CS12B16B   (0x1 << 16)   /* RW */
++
++/* MSDC_PATCH_BIT mask */
++#define MSDC_PATCH_BIT_ODDSUPP    (0x1 <<  1) /* RW */
++#define MSDC_INT_DAT_LATCH_CK_SEL (0x7 <<  7)
++#define MSDC_CKGEN_MSDC_DLY_SEL   (0x1f << 10)
++#define MSDC_PATCH_BIT_IODSSEL    (0x1 << 16) /* RW */
++#define MSDC_PATCH_BIT_IOINTSEL   (0x1 << 17) /* RW */
++#define MSDC_PATCH_BIT_BUSYDLY    (0xf << 18) /* RW */
++#define MSDC_PATCH_BIT_WDOD       (0xf << 22) /* RW */
++#define MSDC_PATCH_BIT_IDRTSEL    (0x1 << 26) /* RW */
++#define MSDC_PATCH_BIT_CMDFSEL    (0x1 << 27) /* RW */
++#define MSDC_PATCH_BIT_INTDLSEL   (0x1 << 28) /* RW */
++#define MSDC_PATCH_BIT_SPCPUSH    (0x1 << 29) /* RW */
++#define MSDC_PATCH_BIT_DECRCTMO   (0x1 << 30) /* RW */
++
++#define REQ_CMD_EIO  (0x1 << 0)
++#define REQ_CMD_TMO  (0x1 << 1)
++#define REQ_DAT_ERR  (0x1 << 2)
++#define REQ_STOP_EIO (0x1 << 3)
++#define REQ_STOP_TMO (0x1 << 4)
++#define REQ_CMD_BUSY (0x1 << 5)
++
++#define MSDC_PREPARE_FLAG (0x1 << 0)
++#define MSDC_ASYNC_FLAG (0x1 << 1)
++#define MSDC_MMAP_FLAG (0x1 << 2)
++
++#define CMD_TIMEOUT         (HZ/10 * 5)       /* 100ms x5 */
++#define DAT_TIMEOUT         (HZ    * 5)       /* 1000ms x5 */
++
++/*--------------------------------------------------------------------------*/
++/* Descriptor Structure                                                     */
++/*--------------------------------------------------------------------------*/
++struct mt_gpdma_desc {
++      u32 gpd_info;
++#define GPDMA_DESC_HWO                (0x1 << 0)
++#define GPDMA_DESC_BDP                (0x1 << 1)
++#define GPDMA_DESC_CHECKSUM   (0xff << 8) /* bit8 ~ bit15 */
++#define GPDMA_DESC_INT                (0x1 << 16)
++      u32 next;
++      u32 ptr;
++      u32 gpd_data_len;
++#define GPDMA_DESC_BUFLEN     (0xffff) /* bit0 ~ bit15 */
++#define GPDMA_DESC_EXTLEN     (0xff << 16) /* bit16 ~ bit23 */
++      u32 arg;
++      u32 blknum;
++      u32 cmd;
++};
++
++struct mt_bdma_desc {
++      u32 bd_info;
++#define BDMA_DESC_EOL         (0x1 << 0)
++#define BDMA_DESC_CHECKSUM    (0xff << 8) /* bit8 ~ bit15 */
++#define BDMA_DESC_BLKPAD      (0x1 << 17)
++#define BDMA_DESC_DWPAD               (0x1 << 18)
++      u32 next;
++      u32 ptr;
++      u32 bd_data_len;
++#define BDMA_DESC_BUFLEN      (0xffff) /* bit0 ~ bit15 */
++};
++
++struct msdc_dma {
++      struct scatterlist *sg; /* I/O scatter list */
++      struct mt_gpdma_desc *gpd;              /* pointer to gpd array */
++      struct mt_bdma_desc *bd;                /* pointer to bd array */
++      dma_addr_t gpd_addr;    /* the physical address of gpd array */
++      dma_addr_t bd_addr;     /* the physical address of bd array */
++};
++
++struct msdc_host {
++      struct device *dev;
++      struct mmc_host *mmc;   /* mmc structure */
++      int cmd_rsp;
++
++      spinlock_t lock;
++      struct mmc_request *mrq;
++      struct mmc_command *cmd;
++      struct mmc_data *data;
++      int error;
++
++      void __iomem *base;             /* host base address */
++
++      struct msdc_dma dma;    /* dma channel */
++      u64 dma_mask;
++
++      u32 timeout_ns;         /* data timeout ns */
++      u32 timeout_clks;       /* data timeout clks */
++
++      struct pinctrl *pinctrl;
++      struct pinctrl_state *pins_default;
++      struct pinctrl_state *pins_uhs;
++      struct delayed_work req_timeout;
++      int irq;                /* host interrupt */
++
++      struct clk *src_clk;    /* msdc source clock */
++      struct clk *h_clk;      /* msdc h_clk */
++      u32 mclk;               /* mmc subsystem clock frequency */
++      u32 src_clk_freq;       /* source clock frequency */
++      u32 sclk;               /* SD/MS bus clock frequency */
++      bool ddr;
++      bool vqmmc_enabled;
++};
++
++static void sdr_set_bits(void __iomem *reg, u32 bs)
++{
++      u32 val = readl(reg);
++
++      val |= bs;
++      writel(val, reg);
++}
++
++static void sdr_clr_bits(void __iomem *reg, u32 bs)
++{
++      u32 val = readl(reg);
++
++      val &= ~bs;
++      writel(val, reg);
++}
++
++static void sdr_set_field(void __iomem *reg, u32 field, u32 val)
++{
++      unsigned int tv = readl(reg);
++
++      tv &= ~field;
++      tv |= ((val) << (ffs((unsigned int)field) - 1));
++      writel(tv, reg);
++}
++
++static void sdr_get_field(void __iomem *reg, u32 field, u32 *val)
++{
++      unsigned int tv = readl(reg);
++
++      *val = ((tv & field) >> (ffs((unsigned int)field) - 1));
++}
++
++static void msdc_reset_hw(struct msdc_host *host)
++{
++      u32 val;
++
++      sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST);
++      while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST)
++              cpu_relax();
++
++      sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
++      while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR)
++              cpu_relax();
++
++      val = readl(host->base + MSDC_INT);
++      writel(val, host->base + MSDC_INT);
++}
++
++static void msdc_cmd_next(struct msdc_host *host,
++              struct mmc_request *mrq, struct mmc_command *cmd);
++
++static u32 data_ints_mask = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO |
++                      MSDC_INTEN_DATCRCERR | MSDC_INTEN_DMA_BDCSERR |
++                      MSDC_INTEN_DMA_GPDCSERR | MSDC_INTEN_DMA_PROTECT;
++
++static u8 msdc_dma_calcs(u8 *buf, u32 len)
++{
++      u32 i, sum = 0;
++
++      for (i = 0; i < len; i++)
++              sum += buf[i];
++      return 0xff - (u8) sum;
++}
++
++static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma,
++              struct mmc_data *data)
++{
++      unsigned int j, dma_len;
++      dma_addr_t dma_address;
++      u32 dma_ctrl;
++      struct scatterlist *sg;
++      struct mt_gpdma_desc *gpd;
++      struct mt_bdma_desc *bd;
++
++      sg = data->sg;
++
++      gpd = dma->gpd;
++      bd = dma->bd;
++
++      /* modify gpd */
++      gpd->gpd_info |= GPDMA_DESC_HWO;
++      gpd->gpd_info |= GPDMA_DESC_BDP;
++      /* need to clear first. use these bits to calc checksum */
++      gpd->gpd_info &= ~GPDMA_DESC_CHECKSUM;
++      gpd->gpd_info |= msdc_dma_calcs((u8 *) gpd, 16) << 8;
++
++      /* modify bd */
++      for_each_sg(data->sg, sg, data->sg_count, j) {
++              dma_address = sg_dma_address(sg);
++              dma_len = sg_dma_len(sg);
++
++              /* init bd */
++              bd[j].bd_info &= ~BDMA_DESC_BLKPAD;
++              bd[j].bd_info &= ~BDMA_DESC_DWPAD;
++              bd[j].ptr = (u32)dma_address;
++              bd[j].bd_data_len &= ~BDMA_DESC_BUFLEN;
++              bd[j].bd_data_len |= (dma_len & BDMA_DESC_BUFLEN);
++
++              if (j == data->sg_count - 1) /* the last bd */
++                      bd[j].bd_info |= BDMA_DESC_EOL;
++              else
++                      bd[j].bd_info &= ~BDMA_DESC_EOL;
++
++              /* checksume need to clear first */
++              bd[j].bd_info &= ~BDMA_DESC_CHECKSUM;
++              bd[j].bd_info |= msdc_dma_calcs((u8 *)(&bd[j]), 16) << 8;
++      }
++
++      sdr_set_field(host->base + MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, 1);
++      dma_ctrl = readl_relaxed(host->base + MSDC_DMA_CTRL);
++      dma_ctrl &= ~(MSDC_DMA_CTRL_BRUSTSZ | MSDC_DMA_CTRL_MODE);
++      dma_ctrl |= (MSDC_BURST_64B << 12 | 1 << 8);
++      writel_relaxed(dma_ctrl, host->base + MSDC_DMA_CTRL);
++      writel((u32)dma->gpd_addr, host->base + MSDC_DMA_SA);
++}
++
++static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq)
++{
++      struct mmc_data *data = mrq->data;
++
++      if (!(data->host_cookie & MSDC_PREPARE_FLAG)) {
++              bool read = (data->flags & MMC_DATA_READ) != 0;
++
++              data->host_cookie |= MSDC_PREPARE_FLAG;
++              data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len,
++                                         read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++      }
++}
++
++static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq)
++{
++      struct mmc_data *data = mrq->data;
++
++      if (data->host_cookie & MSDC_ASYNC_FLAG)
++              return;
++
++      if (data->host_cookie & MSDC_PREPARE_FLAG) {
++              bool read = (data->flags & MMC_DATA_READ) != 0;
++
++              dma_unmap_sg(host->dev, data->sg, data->sg_len,
++                           read ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
++              data->host_cookie &= ~MSDC_PREPARE_FLAG;
++      }
++}
++
++/* clock control primitives */
++static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
++{
++      u32 timeout, clk_ns;
++      u32 mode = 0;
++
++      host->timeout_ns = ns;
++      host->timeout_clks = clks;
++      if (host->sclk == 0) {
++              timeout = 0;
++      } else {
++              clk_ns  = 1000000000UL / host->sclk;
++              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);
++              /*DDR mode will double the clk cycles for data timeout */
++              timeout = mode >= 2 ? timeout * 2 : timeout;
++              timeout = timeout > 1 ? timeout - 1 : 0;
++              timeout = timeout > 255 ? 255 : timeout;
++      }
++      sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
++}
++
++static void msdc_gate_clock(struct msdc_host *host)
++{
++      clk_disable_unprepare(host->src_clk);
++      clk_disable_unprepare(host->h_clk);
++}
++
++static void msdc_ungate_clock(struct msdc_host *host)
++{
++      clk_prepare_enable(host->h_clk);
++      clk_prepare_enable(host->src_clk);
++      while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
++              cpu_relax();
++}
++
++static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
++{
++      u32 mode;
++      u32 flags;
++      u32 div;
++      u32 sclk;
++
++      if (!hz) {
++              dev_dbg(host->dev, "set mclk to 0\n");
++              host->mclk = 0;
++              sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
++              return;
++      }
++
++      flags = readl(host->base + MSDC_INTEN);
++      sdr_clr_bits(host->base + MSDC_INTEN, flags);
++      if (ddr) { /* may need to modify later */
++              mode = 0x2; /* ddr mode and use divisor */
++              if (hz >= (host->src_clk_freq >> 2)) {
++                      div = 0; /* mean div = 1/4 */
++                      sclk = host->src_clk_freq >> 2; /* sclk = clk / 4 */
++              } else {
++                      div = (host->src_clk_freq + ((hz << 2) - 1)) / (hz << 2);
++                      sclk = (host->src_clk_freq >> 2) / div;
++                      div = (div >> 1);
++              }
++      } else if (hz >= host->src_clk_freq) {
++              mode = 0x1; /* no divisor */
++              div = 0;
++              sclk = host->src_clk_freq;
++      } else {
++              mode = 0x0; /* use divisor */
++              if (hz >= (host->src_clk_freq >> 1)) {
++                      div = 0; /* mean div = 1/2 */
++                      sclk = host->src_clk_freq >> 1; /* sclk = clk / 2 */
++              } else {
++                      div = (host->src_clk_freq + ((hz << 2) - 1)) / (hz << 2);
++                      sclk = (host->src_clk_freq >> 2) / div;
++              }
++      }
++      sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD | MSDC_CFG_CKDIV,
++                      (mode << 8) | (div % 0xff));
++      sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN);
++      while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB))
++              cpu_relax();
++      host->sclk = sclk;
++      host->mclk = hz;
++      host->ddr = ddr;
++      /* need because clk changed. */
++      msdc_set_timeout(host, host->timeout_ns, host->timeout_clks);
++      sdr_set_bits(host->base + MSDC_INTEN, flags);
++
++      dev_dbg(host->dev, "sclk: %d, ddr: %d\n", host->sclk, ddr);
++}
++
++static inline u32 msdc_cmd_find_resp(struct msdc_host *host,
++              struct mmc_request *mrq, struct mmc_command *cmd)
++{
++      u32 resp;
++
++      switch (mmc_resp_type(cmd)) {
++              /* Actually, R1, R5, R6, R7 are the same */
++      case MMC_RSP_R1:
++              resp = 0x1;
++              break;
++      case MMC_RSP_R1B:
++              resp = 0x7;
++              break;
++      case MMC_RSP_R2:
++              resp = 0x2;
++              break;
++      case MMC_RSP_R3:
++              resp = 0x3;
++              break;
++      case MMC_RSP_NONE:
++      default:
++              resp = 0x0;
++              break;
++      }
++
++      return resp;
++}
++
++static inline u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host,
++              struct mmc_request *mrq, struct mmc_command *cmd)
++{
++      /* rawcmd :
++       * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 |
++       * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode
++       */
++      u32 opcode = cmd->opcode;
++      u32 resp = msdc_cmd_find_resp(host, mrq, cmd);
++      u32 rawcmd = (opcode & 0x3f) | ((resp & 0x7) << 7);
++
++      host->cmd_rsp = resp;
++
++      if ((opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int) -1) ||
++          opcode == MMC_STOP_TRANSMISSION)
++              rawcmd |= (0x1 << 14);
++      else if (opcode == SD_SWITCH_VOLTAGE)
++              rawcmd |= (0x1 << 30);
++      else if (opcode == SD_APP_SEND_SCR ||
++               opcode == SD_APP_SEND_NUM_WR_BLKS ||
++               (opcode == SD_SWITCH && mmc_cmd_type(cmd) == MMC_CMD_ADTC) ||
++               (opcode == SD_APP_SD_STATUS && mmc_cmd_type(cmd) == MMC_CMD_ADTC) ||
++               (opcode == MMC_SEND_EXT_CSD && mmc_cmd_type(cmd) == MMC_CMD_ADTC))
++              rawcmd |= (0x1 << 11);
++
++      if (cmd->data) {
++              struct mmc_data *data = cmd->data;
++
++              if (mmc_op_multi(opcode)) {
++                      if (mmc_card_mmc(host->mmc->card) && mrq->sbc &&
++                          !(mrq->sbc->arg & 0xFFFF0000))
++                              rawcmd |= 0x2 << 28; /* AutoCMD23 */
++              }
++
++              rawcmd |= ((data->blksz & 0xFFF) << 16);
++              if (data->flags & MMC_DATA_WRITE)
++                      rawcmd |= (0x1 << 13);
++              if (data->blocks > 1)
++                      rawcmd |= (0x2 << 11);
++              else
++                      rawcmd |= (0x1 << 11);
++              /* Always use dma mode */
++              sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_PIO);
++
++              if (host->timeout_ns != data->timeout_ns ||
++                  host->timeout_clks != data->timeout_clks)
++                      msdc_set_timeout(host, data->timeout_ns,
++                                      data->timeout_clks);
++
++              writel(data->blocks, host->base + SDC_BLK_NUM);
++      }
++      return rawcmd;
++}
++
++static void msdc_start_data(struct msdc_host *host, struct mmc_request *mrq,
++                          struct mmc_command *cmd, struct mmc_data *data)
++{
++      bool read;
++
++      WARN_ON(host->data);
++      host->data = data;
++      read = data->flags & MMC_DATA_READ;
++
++      mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
++      msdc_dma_setup(host, &host->dma, data);
++      sdr_set_bits(host->base + MSDC_INTEN, data_ints_mask);
++      sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1);
++      dev_dbg(host->dev, "DMA start\n");
++      dev_dbg(host->dev, "%s: cmd=%d DMA data: %d blocks; read=%d\n",
++                      __func__, cmd->opcode, data->blocks, read);
++}
++
++static int msdc_auto_cmd_done(struct msdc_host *host, int events,
++              struct mmc_command *cmd)
++{
++      u32 *rsp = cmd->resp;
++
++      rsp[0] = readl(host->base + SDC_ACMD_RESP);
++
++      if (events & MSDC_INT_ACMDRDY) {
++              cmd->error = 0;
++      } else {
++              msdc_reset_hw(host);
++              if (events & MSDC_INT_ACMDCRCERR) {
++                      cmd->error = -EILSEQ;
++                      host->error |= REQ_STOP_EIO;
++              } else if (events & MSDC_INT_ACMDTMO) {
++                      cmd->error = -ETIMEDOUT;
++                      host->error |= REQ_STOP_TMO;
++              }
++              dev_err(host->dev,
++                      "%s: AUTO_CMD%d arg=%08X; rsp %08X; cmd_error=%d\n",
++                      __func__, cmd->opcode, cmd->arg, rsp[0], cmd->error);
++      }
++      return cmd->error;
++}
++
++static void msdc_track_cmd_data(struct msdc_host *host,
++                              struct mmc_command *cmd, struct mmc_data *data)
++{
++      if (host->error)
++              dev_dbg(host->dev, "%s: cmd=%d arg=%08X; host->error=0x%08X\n",
++                      __func__, cmd->opcode, cmd->arg, host->error);
++}
++
++static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
++{
++      unsigned long flags;
++      bool ret;
++
++      ret = cancel_delayed_work(&host->req_timeout);
++      if (!ret) {
++              /* delay work already running */
++              return;
++      }
++      spin_lock_irqsave(&host->lock, flags);
++      host->mrq = NULL;
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      msdc_track_cmd_data(host, mrq->cmd, mrq->data);
++      if (mrq->data)
++              msdc_unprepare_data(host, mrq);
++      mmc_request_done(host->mmc, mrq);
++}
++
++/* returns true if command is fully handled; returns false otherwise */
++static bool msdc_cmd_done(struct msdc_host *host, int events,
++                        struct mmc_request *mrq, struct mmc_command *cmd)
++{
++      bool done = false;
++      bool sbc_error;
++      unsigned long flags;
++      u32 *rsp = cmd->resp;
++
++      if (mrq->sbc && cmd == mrq->cmd &&
++          (events & (MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR
++                                 | MSDC_INT_ACMDTMO)))
++              msdc_auto_cmd_done(host, events, mrq->sbc);
++
++      sbc_error = mrq->sbc && mrq->sbc->error;
++
++      if (!sbc_error && !(events & (MSDC_INT_CMDRDY
++                                      | MSDC_INT_RSPCRCERR
++                                      | MSDC_INT_CMDTMO)))
++              return done;
++
++      spin_lock_irqsave(&host->lock, flags);
++      done = !host->cmd;
++      host->cmd = NULL;
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (done)
++              return true;
++
++      sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
++                      MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
++                      MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
++                      MSDC_INTEN_ACMDTMO);
++      writel(cmd->arg, host->base + SDC_ARG);
++
++      if (cmd->flags & MMC_RSP_PRESENT) {
++              if (cmd->flags & MMC_RSP_136) {
++                      rsp[0] = readl(host->base + SDC_RESP3);
++                      rsp[1] = readl(host->base + SDC_RESP2);
++                      rsp[2] = readl(host->base + SDC_RESP1);
++                      rsp[3] = readl(host->base + SDC_RESP0);
++              } else {
++                      rsp[0] = readl(host->base + SDC_RESP0);
++              }
++      }
++
++      if (!sbc_error && !(events & MSDC_INT_CMDRDY)) {
++              msdc_reset_hw(host);
++              if (events & MSDC_INT_RSPCRCERR) {
++                      cmd->error = -EILSEQ;
++                      host->error |= REQ_CMD_EIO;
++              } else if (events & MSDC_INT_CMDTMO) {
++                      cmd->error = -ETIMEDOUT;
++                      host->error |= REQ_CMD_TMO;
++              }
++      }
++      if (cmd->error)
++              dev_dbg(host->dev,
++                              "%s: cmd=%d arg=%08X; rsp %08X; cmd_error=%d\n",
++                              __func__, cmd->opcode, cmd->arg, rsp[0],
++                              cmd->error);
++
++      msdc_cmd_next(host, mrq, cmd);
++      return true;
++}
++
++/* It is the core layer's responsibility to ensure card status
++ * is correct before issue a request. but host design do below
++ * checks recommended.
++ */
++static inline bool msdc_cmd_is_ready(struct msdc_host *host,
++              struct mmc_request *mrq, struct mmc_command *cmd)
++{
++      /* The max busy time we can endure is 20ms */
++      unsigned long tmo = jiffies + msecs_to_jiffies(20);
++
++      while ((readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) &&
++                      time_before(jiffies, tmo))
++              cpu_relax();
++      if (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) {
++              dev_err(host->dev, "CMD bus busy detected\n");
++              host->error |= REQ_CMD_BUSY;
++              msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
++              return false;
++      }
++
++      if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) {
++              tmo = jiffies + msecs_to_jiffies(20);
++              /* R1B or with data, should check SDCBUSY */
++              while ((readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) &&
++                              time_before(jiffies, tmo))
++                      cpu_relax();
++              if (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) {
++                      dev_err(host->dev, "Controller busy detected\n");
++                      host->error |= REQ_CMD_BUSY;
++                      msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd);
++                      return false;
++              }
++      }
++      return true;
++}
++
++static void msdc_start_command(struct msdc_host *host,
++              struct mmc_request *mrq, struct mmc_command *cmd)
++{
++      u32 rawcmd;
++
++      WARN_ON(host->cmd);
++      host->cmd = cmd;
++
++      if (!msdc_cmd_is_ready(host, mrq, cmd))
++              return;
++
++      if ((readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16 ||
++          readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) {
++              dev_err(host->dev, "TX/RX FIFO non-empty before start of IO. Reset\n");
++              msdc_reset_hw(host);
++      }
++
++      cmd->error = 0;
++      rawcmd = msdc_cmd_prepare_raw_cmd(host, mrq, cmd);
++      mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT);
++
++      sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_CMDRDY |
++                      MSDC_INTEN_RSPCRCERR | MSDC_INTEN_CMDTMO |
++                      MSDC_INTEN_ACMDRDY | MSDC_INTEN_ACMDCRCERR |
++                      MSDC_INTEN_ACMDTMO);
++      writel(cmd->arg, host->base + SDC_ARG);
++      writel(rawcmd, host->base + SDC_CMD);
++}
++
++static void msdc_cmd_next(struct msdc_host *host,
++              struct mmc_request *mrq, struct mmc_command *cmd)
++{
++      if (cmd->error || (mrq->sbc && mrq->sbc->error))
++              msdc_request_done(host, mrq);
++      else if (cmd == mrq->sbc)
++              msdc_start_command(host, mrq, mrq->cmd);
++      else if (!cmd->data)
++              msdc_request_done(host, mrq);
++      else
++              msdc_start_data(host, mrq, cmd, cmd->data);
++}
++
++static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++      struct msdc_host *host = mmc_priv(mmc);
++
++      host->error = 0;
++      WARN_ON(host->mrq);
++      host->mrq = mrq;
++
++      if (mrq->data)
++              msdc_prepare_data(host, mrq);
++
++      /* if SBC is required, we have HW option and SW option.
++       * if HW option is enabled, and SBC does not have "special" flags,
++       * use HW option,  otherwise use SW option
++       */
++      if (mrq->sbc && (!mmc_card_mmc(mmc->card) ||
++          (mrq->sbc->arg & 0xFFFF0000)))
++              msdc_start_command(host, mrq, mrq->sbc);
++      else
++              msdc_start_command(host, mrq, mrq->cmd);
++}
++
++static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
++              bool is_first_req)
++{
++      struct msdc_host *host = mmc_priv(mmc);
++      struct mmc_data *data = mrq->data;
++
++      if (!data)
++              return;
++
++      msdc_prepare_data(host, mrq);
++      data->host_cookie |= MSDC_ASYNC_FLAG;
++}
++
++static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
++              int err)
++{
++      struct msdc_host *host = mmc_priv(mmc);
++      struct mmc_data *data;
++
++      data = mrq->data;
++      if (!data)
++              return;
++      if (data->host_cookie) {
++              data->host_cookie &= ~MSDC_ASYNC_FLAG;
++              msdc_unprepare_data(host, mrq);
++      }
++}
++
++static void msdc_data_xfer_next(struct msdc_host *host,
++                              struct mmc_request *mrq, struct mmc_data *data)
++{
++      if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error &&
++          (!data->bytes_xfered || !mrq->sbc))
++              msdc_start_command(host, mrq, mrq->stop);
++      else
++              msdc_request_done(host, mrq);
++}
++
++static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
++                              struct mmc_request *mrq, struct mmc_data *data)
++{
++      struct mmc_command *stop = data->stop;
++      unsigned long flags;
++      bool done;
++      unsigned int check_data = events &
++          (MSDC_INT_XFER_COMPL | MSDC_INT_DATCRCERR | MSDC_INT_DATTMO
++           | MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR
++           | MSDC_INT_DMA_PROTECT);
++
++      spin_lock_irqsave(&host->lock, flags);
++      done = !host->data;
++      if (check_data)
++              host->data = NULL;
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (done)
++              return true;
++
++      if (check_data || (stop && stop->error)) {
++              dev_dbg(host->dev, "DMA status: 0x%8X\n",
++                              readl(host->base + MSDC_DMA_CFG));
++              sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP,
++                              1);
++              while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS)
++                      cpu_relax();
++              sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask);
++              dev_dbg(host->dev, "DMA stop\n");
++
++              if ((events & MSDC_INT_XFER_COMPL) && (!stop || !stop->error)) {
++                      data->bytes_xfered = data->blocks * data->blksz;
++              } else {
++                      dev_err(host->dev, "interrupt events: %x\n", events);
++                      msdc_reset_hw(host);
++                      host->error |= REQ_DAT_ERR;
++                      data->bytes_xfered = 0;
++
++                      if (events & MSDC_INT_DATTMO)
++                              data->error = -ETIMEDOUT;
++
++                      dev_err(host->dev, "%s: cmd=%d; blocks=%d",
++                              __func__, mrq->cmd->opcode, data->blocks);
++                      dev_err(host->dev, "data_error=%d xfer_size=%d\n",
++                                      (int)data->error, data->bytes_xfered);
++              }
++
++              msdc_data_xfer_next(host, mrq, data);
++              done = true;
++      }
++      return done;
++}
++
++static void msdc_set_buswidth(struct msdc_host *host, u32 width)
++{
++      u32 val = readl(host->base + SDC_CFG);
++
++      val &= ~SDC_CFG_BUSWIDTH;
++
++      switch (width) {
++      default:
++      case MMC_BUS_WIDTH_1:
++              val |= (MSDC_BUS_1BITS << 16);
++              break;
++      case MMC_BUS_WIDTH_4:
++              val |= (MSDC_BUS_4BITS << 16);
++              break;
++      case MMC_BUS_WIDTH_8:
++              val |= (MSDC_BUS_8BITS << 16);
++              break;
++      }
++
++      writel(val, host->base + SDC_CFG);
++      dev_dbg(host->dev, "Bus Width = %d", width);
++}
++
++static int msdc_ops_switch_volt(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++      struct msdc_host *host = mmc_priv(mmc);
++      int min_uv, max_uv;
++      int ret = 0;
++
++      if (!IS_ERR(mmc->supply.vqmmc)) {
++              if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
++                      min_uv = 3300000;
++                      max_uv = 3300000;
++              } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
++                      min_uv = 1800000;
++                      max_uv = 1800000;
++              } else {
++                      dev_err(host->dev, "Unsupported signal voltage!\n");
++                      return -EINVAL;
++              }
++
++              ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv);
++              if (ret) {
++                      dev_err(host->dev,
++                                      "Regulator set error %d: %d - %d\n",
++                                      ret, min_uv, max_uv);
++              } else {
++                      /* Apply different pinctrl settings for different signal voltage */
++                      if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
++                              pinctrl_select_state(host->pinctrl, host->pins_uhs);
++                      else
++                              pinctrl_select_state(host->pinctrl, host->pins_default);
++              }
++      }
++      return ret;
++}
++
++static int msdc_card_busy(struct mmc_host *mmc)
++{
++      struct msdc_host *host = mmc_priv(mmc);
++      u32 status = readl(host->base + MSDC_PS);
++
++      /* check if any pin between dat[0:3] is low */
++      if (((status >> 16) & 0xf) != 0xf)
++              return 1;
++
++      return 0;
++}
++
++static void msdc_request_timeout(struct work_struct *work)
++{
++      struct msdc_host *host = container_of(work, struct msdc_host,
++                      req_timeout.work);
++
++      /* simulate HW timeout status */
++      dev_err(host->dev, "%s: aborting cmd/data/mrq\n", __func__);
++      if (host->mrq) {
++              dev_err(host->dev, "%s: aborting mrq=%p cmd=%d\n", __func__,
++                              host->mrq, host->mrq->cmd->opcode);
++              if (host->cmd) {
++                      dev_err(host->dev, "%s: aborting cmd=%d\n",
++                                      __func__, host->cmd->opcode);
++                      msdc_cmd_done(host, MSDC_INT_CMDTMO, host->mrq,
++                                      host->cmd);
++              } else if (host->data) {
++                      dev_err(host->dev, "%s: abort data: cmd%d; %d blocks\n",
++                                      __func__, host->mrq->cmd->opcode,
++                                      host->data->blocks);
++                      msdc_data_xfer_done(host, MSDC_INT_DATTMO, host->mrq,
++                                      host->data);
++              }
++      }
++}
++
++static irqreturn_t msdc_irq(int irq, void *dev_id)
++{
++      struct msdc_host *host = (struct msdc_host *) dev_id;
++
++      while (true) {
++              unsigned long flags;
++              struct mmc_request *mrq;
++              struct mmc_command *cmd;
++              struct mmc_data *data;
++              u32 events, event_mask;
++
++              spin_lock_irqsave(&host->lock, flags);
++              events = readl(host->base + MSDC_INT);
++              event_mask = readl(host->base + MSDC_INTEN);
++              /* clear interrupts */
++              writel(events & event_mask, host->base + MSDC_INT);
++
++              mrq = host->mrq;
++              cmd = host->cmd;
++              data = host->data;
++              spin_unlock_irqrestore(&host->lock, flags);
++
++              if (!(events & event_mask))
++                      break;
++
++              if (!mrq) {
++                      dev_err(host->dev,
++                              "%s: MRQ=NULL; events=%08X; event_mask=%08X\n",
++                              __func__, events, event_mask);
++                      WARN_ON(1);
++                      break;
++              }
++
++              dev_dbg(host->dev, "%s: events=%08X\n", __func__, events);
++
++              if (cmd)
++                      msdc_cmd_done(host, events, mrq, cmd);
++              else if (data)
++                      msdc_data_xfer_done(host, events, mrq, data);
++      }
++
++      return IRQ_HANDLED;
++}
++
++static void msdc_init_hw(struct msdc_host *host)
++{
++      u32 val;
++
++      /* Configure to MMC/SD mode, clock free running */
++      sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN);
++
++      /* Reset */
++      msdc_reset_hw(host);
++
++      /* Disable card detection */
++      sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN);
++
++      /* Disable and clear all interrupts */
++      writel(0, host->base + MSDC_INTEN);
++      val = readl(host->base + MSDC_INT);
++      writel(val, host->base + MSDC_INT);
++
++      writel(0, host->base + MSDC_PAD_TUNE);
++      writel(0, host->base + MSDC_IOCON);
++      sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
++      writel(0x403c004f, 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);
++      /* Configure to enable SDIO mode.
++       * it's must otherwise sdio cmd5 failed
++       */
++      sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
++
++      /* disable detect SDIO device interrupt function */
++      sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
++
++      /* Configure to default data timeout */
++      sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
++
++      dev_dbg(host->dev, "init hardware done!");
++}
++
++static void msdc_deinit_hw(struct msdc_host *host)
++{
++      u32 val;
++      /* Disable and clear all interrupts */
++      writel(0, host->base + MSDC_INTEN);
++
++      val = readl(host->base + MSDC_INT);
++      writel(val, host->base + MSDC_INT);
++}
++
++/* init gpd and bd list in msdc_drv_probe */
++static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma)
++{
++      struct mt_gpdma_desc *gpd = dma->gpd;
++      struct mt_bdma_desc *bd = dma->bd;
++      int i;
++
++      memset(gpd, 0, sizeof(struct mt_gpdma_desc));
++
++      gpd->gpd_info = GPDMA_DESC_BDP; /* hwo, cs, bd pointer */
++      gpd->ptr = (u32)dma->bd_addr; /* physical address */
++
++      memset(bd, 0, sizeof(struct mt_bdma_desc) * MAX_BD_NUM);
++      for (i = 0; i < (MAX_BD_NUM - 1); i++)
++              bd[i].next = (u32)dma->bd_addr + sizeof(*bd) * (i + 1);
++}
++
++static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++      struct msdc_host *host = mmc_priv(mmc);
++      int ret;
++      u32 ddr = 0;
++
++      if (ios->timing == MMC_TIMING_UHS_DDR50 ||
++          ios->timing == MMC_TIMING_MMC_DDR52)
++              ddr = 1;
++
++      msdc_set_buswidth(host, ios->bus_width);
++
++      /* Suspend/Resume will do power off/on */
++      switch (ios->power_mode) {
++      case MMC_POWER_UP:
++              if (!IS_ERR(mmc->supply.vmmc)) {
++                      ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
++                                      ios->vdd);
++                      if (ret) {
++                              dev_err(host->dev, "Failed to set vmmc power!\n");
++                              return;
++                      }
++              }
++              break;
++      case MMC_POWER_ON:
++              if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
++                      ret = regulator_enable(mmc->supply.vqmmc);
++                      if (ret)
++                              dev_err(host->dev, "Failed to set vqmmc power!\n");
++                      else
++                              host->vqmmc_enabled = true;
++              }
++              break;
++      case MMC_POWER_OFF:
++              if (!IS_ERR(mmc->supply.vmmc))
++                      mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
++
++              if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
++                      regulator_disable(mmc->supply.vqmmc);
++                      host->vqmmc_enabled = false;
++              }
++              break;
++      default:
++              break;
++      }
++
++      if (host->mclk != ios->clock || host->ddr != ddr)
++              msdc_set_mclk(host, ddr, ios->clock);
++}
++
++static struct mmc_host_ops mt_msdc_ops = {
++      .post_req = msdc_post_req,
++      .pre_req = msdc_pre_req,
++      .request = msdc_ops_request,
++      .set_ios = msdc_ops_set_ios,
++      .start_signal_voltage_switch = msdc_ops_switch_volt,
++      .card_busy = msdc_card_busy,
++};
++
++static int msdc_drv_probe(struct platform_device *pdev)
++{
++      struct mmc_host *mmc;
++      struct msdc_host *host;
++      struct resource *res;
++      int ret;
++
++      if (!pdev->dev.of_node) {
++              dev_err(&pdev->dev, "No DT found\n");
++              return -EINVAL;
++      }
++      /* Allocate MMC host for this device */
++      mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
++      if (!mmc)
++              return -ENOMEM;
++
++      host = mmc_priv(mmc);
++      ret = mmc_of_parse(mmc);
++      if (ret)
++              goto host_free;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      host->base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(host->base)) {
++              ret = PTR_ERR(host->base);
++              goto host_free;
++      }
++
++      ret = mmc_regulator_get_supply(mmc);
++      if (ret == -EPROBE_DEFER)
++              goto host_free;
++
++      host->src_clk = devm_clk_get(&pdev->dev, "source");
++      if (IS_ERR(host->src_clk)) {
++              ret = PTR_ERR(host->src_clk);
++              goto host_free;
++      }
++
++      host->h_clk = devm_clk_get(&pdev->dev, "hclk");
++      if (IS_ERR(host->h_clk)) {
++              ret = PTR_ERR(host->h_clk);
++              goto host_free;
++      }
++
++      host->irq = platform_get_irq(pdev, 0);
++      if (host->irq < 0) {
++              ret = -EINVAL;
++              goto host_free;
++      }
++
++      host->pinctrl = devm_pinctrl_get(&pdev->dev);
++      if (IS_ERR(host->pinctrl)) {
++              ret = PTR_ERR(host->pinctrl);
++              dev_err(&pdev->dev, "Cannot find pinctrl!\n");
++              goto host_free;
++      }
++
++      host->pins_default = pinctrl_lookup_state(host->pinctrl, "default");
++      if (IS_ERR(host->pins_default)) {
++              ret = PTR_ERR(host->pins_default);
++              dev_err(&pdev->dev, "Cannot find pinctrl default!\n");
++              goto host_free;
++      }
++
++      host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs");
++      if (IS_ERR(host->pins_uhs)) {
++              ret = PTR_ERR(host->pins_uhs);
++              dev_err(&pdev->dev, "Cannot find pinctrl uhs!\n");
++              goto host_free;
++      }
++
++      host->dev = &pdev->dev;
++      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 = host->src_clk_freq / (4 * 255);
++
++      mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
++      /* MMC core transfer sizes tunable parameters */
++      mmc->max_segs = MAX_BD_NUM;
++      mmc->max_seg_size = BDMA_DESC_BUFLEN;
++      mmc->max_blk_size = 2048;
++      mmc->max_req_size = 512 * 1024;
++      mmc->max_blk_count = mmc->max_req_size / 512;
++      host->dma_mask = DMA_BIT_MASK(32);
++      mmc_dev(mmc)->dma_mask = &host->dma_mask;
++
++      host->timeout_clks = 3 * 1048576;
++      host->dma.gpd = dma_alloc_coherent(&pdev->dev,
++                              sizeof(struct mt_gpdma_desc),
++                              &host->dma.gpd_addr, GFP_KERNEL);
++      host->dma.bd = dma_alloc_coherent(&pdev->dev,
++                              MAX_BD_NUM * sizeof(struct mt_bdma_desc),
++                              &host->dma.bd_addr, GFP_KERNEL);
++      if (!host->dma.gpd || !host->dma.bd) {
++              ret = -ENOMEM;
++              goto release_mem;
++      }
++      msdc_init_gpd_bd(host, &host->dma);
++      INIT_DELAYED_WORK(&host->req_timeout, msdc_request_timeout);
++      spin_lock_init(&host->lock);
++
++      platform_set_drvdata(pdev, mmc);
++      msdc_ungate_clock(host);
++      msdc_init_hw(host);
++
++      ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
++              IRQF_TRIGGER_LOW | IRQF_ONESHOT, pdev->name, host);
++      if (ret)
++              goto release;
++
++      ret = mmc_add_host(mmc);
++      if (ret)
++              goto release;
++
++      return 0;
++
++release:
++      platform_set_drvdata(pdev, NULL);
++      msdc_deinit_hw(host);
++      msdc_gate_clock(host);
++release_mem:
++      if (host->dma.gpd)
++              dma_free_coherent(&pdev->dev,
++                      sizeof(struct mt_gpdma_desc),
++                      host->dma.gpd, host->dma.gpd_addr);
++      if (host->dma.bd)
++              dma_free_coherent(&pdev->dev,
++                      MAX_BD_NUM * sizeof(struct mt_bdma_desc),
++                      host->dma.bd, host->dma.bd_addr);
++host_free:
++      mmc_free_host(mmc);
++
++      return ret;
++}
++
++static int msdc_drv_remove(struct platform_device *pdev)
++{
++      struct mmc_host *mmc;
++      struct msdc_host *host;
++
++      mmc = platform_get_drvdata(pdev);
++      host = mmc_priv(mmc);
++
++      platform_set_drvdata(pdev, NULL);
++      mmc_remove_host(host->mmc);
++      msdc_deinit_hw(host);
++      msdc_gate_clock(host);
++
++      dma_free_coherent(&pdev->dev,
++                      sizeof(struct mt_gpdma_desc),
++                      host->dma.gpd, host->dma.gpd_addr);
++      dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
++                      host->dma.bd, host->dma.bd_addr);
++
++      mmc_free_host(host->mmc);
++
++      return 0;
++}
++
++static const struct of_device_id msdc_of_ids[] = {
++      {   .compatible = "mediatek,mt8135-mmc", },
++      {}
++};
++
++static struct platform_driver mt_msdc_driver = {
++      .probe = msdc_drv_probe,
++      .remove = msdc_drv_remove,
++      .driver = {
++              .name = "mtk-msdc",
++              .of_match_table = msdc_of_ids,
++      },
++};
++
++module_platform_driver(mt_msdc_driver);
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek SD/MMC Card Driver");
diff --git a/target/linux/mediatek/patches/0036-mmc-mediatek-Add-PM-support-for-MMC-driver.patch b/target/linux/mediatek/patches/0036-mmc-mediatek-Add-PM-support-for-MMC-driver.patch
new file mode 100644 (file)
index 0000000..e9ba31d
--- /dev/null
@@ -0,0 +1,209 @@
+From 4ca0e8a959569852b520b607d39ce6ceeeb0f518 Mon Sep 17 00:00:00 2001
+From: Chaotian Jing <chaotian.jing@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:49 +0800
+Subject: [PATCH 36/76] mmc: mediatek: Add PM support for MMC driver
+
+Add PM support for Mediatek MMC driver
+Save/restore registers when PM
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ drivers/mmc/host/mtk-sd.c |   89 +++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 86 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 952be2e..7c20f28 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -22,6 +22,8 @@
+ #include <linux/of_gpio.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/spinlock.h>
+@@ -212,6 +214,7 @@
+ #define MSDC_ASYNC_FLAG (0x1 << 1)
+ #define MSDC_MMAP_FLAG (0x1 << 2)
++#define MTK_MMC_AUTOSUSPEND_DELAY     50
+ #define CMD_TIMEOUT         (HZ/10 * 5)       /* 100ms x5 */
+ #define DAT_TIMEOUT         (HZ    * 5)       /* 1000ms x5 */
+@@ -254,6 +257,15 @@ struct msdc_dma {
+       dma_addr_t bd_addr;     /* the physical address of bd array */
+ };
++struct msdc_save_para {
++      u32 msdc_cfg;
++      u32 iocon;
++      u32 sdc_cfg;
++      u32 pad_tune;
++      u32 patch_bit0;
++      u32 patch_bit1;
++};
++
+ struct msdc_host {
+       struct device *dev;
+       struct mmc_host *mmc;   /* mmc structure */
+@@ -286,6 +298,7 @@ struct msdc_host {
+       u32 sclk;               /* SD/MS bus clock frequency */
+       bool ddr;
+       bool vqmmc_enabled;
++      struct msdc_save_para save_para; /* used when gate HCLK */
+ };
+ static void sdr_set_bits(void __iomem *reg, u32 bs)
+@@ -677,6 +690,9 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
+       if (mrq->data)
+               msdc_unprepare_data(host, mrq);
+       mmc_request_done(host->mmc, mrq);
++
++      pm_runtime_mark_last_busy(host->dev);
++      pm_runtime_put_autosuspend(host->dev);
+ }
+ /* returns true if command is fully handled; returns false otherwise */
+@@ -831,6 +847,8 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
+       WARN_ON(host->mrq);
+       host->mrq = mrq;
++      pm_runtime_get_sync(host->dev);
++
+       if (mrq->data)
+               msdc_prepare_data(host, mrq);
+@@ -1145,6 +1163,8 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+       int ret;
+       u32 ddr = 0;
++      pm_runtime_get_sync(host->dev);
++
+       if (ios->timing == MMC_TIMING_UHS_DDR50 ||
+           ios->timing == MMC_TIMING_MMC_DDR52)
+               ddr = 1;
+@@ -1159,7 +1179,7 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+                                       ios->vdd);
+                       if (ret) {
+                               dev_err(host->dev, "Failed to set vmmc power!\n");
+-                              return;
++                              goto end;
+                       }
+               }
+               break;
+@@ -1187,6 +1207,10 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+       if (host->mclk != ios->clock || host->ddr != ddr)
+               msdc_set_mclk(host, ddr, ios->clock);
++
++end:
++      pm_runtime_mark_last_busy(host->dev);
++      pm_runtime_put_autosuspend(host->dev);
+ }
+ static struct mmc_host_ops mt_msdc_ops = {
+@@ -1310,12 +1334,18 @@ static int msdc_drv_probe(struct platform_device *pdev)
+       if (ret)
+               goto release;
++      pm_runtime_set_active(host->dev);
++      pm_runtime_set_autosuspend_delay(host->dev, MTK_MMC_AUTOSUSPEND_DELAY);
++      pm_runtime_use_autosuspend(host->dev);
++      pm_runtime_enable(host->dev);
+       ret = mmc_add_host(mmc);
++
+       if (ret)
+-              goto release;
++              goto end;
+       return 0;
+-
++end:
++      pm_runtime_disable(host->dev);
+ release:
+       platform_set_drvdata(pdev, NULL);
+       msdc_deinit_hw(host);
+@@ -1343,11 +1373,15 @@ static int msdc_drv_remove(struct platform_device *pdev)
+       mmc = platform_get_drvdata(pdev);
+       host = mmc_priv(mmc);
++      pm_runtime_get_sync(host->dev);
++
+       platform_set_drvdata(pdev, NULL);
+       mmc_remove_host(host->mmc);
+       msdc_deinit_hw(host);
+       msdc_gate_clock(host);
++      pm_runtime_disable(host->dev);
++      pm_runtime_put_noidle(host->dev);
+       dma_free_coherent(&pdev->dev,
+                       sizeof(struct mt_gpdma_desc),
+                       host->dma.gpd, host->dma.gpd_addr);
+@@ -1359,6 +1393,54 @@ static int msdc_drv_remove(struct platform_device *pdev)
+       return 0;
+ }
++#ifdef CONFIG_PM
++static void msdc_save_reg(struct msdc_host *host)
++{
++      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.patch_bit0 = readl(host->base + MSDC_PATCH_BIT);
++      host->save_para.patch_bit1 = readl(host->base + MSDC_PATCH_BIT1);
++}
++
++static void msdc_restore_reg(struct msdc_host *host)
++{
++      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.patch_bit0, host->base + MSDC_PATCH_BIT);
++      writel(host->save_para.patch_bit1, host->base + MSDC_PATCH_BIT1);
++}
++
++static int msdc_runtime_suspend(struct device *dev)
++{
++      struct mmc_host *mmc = dev_get_drvdata(dev);
++      struct msdc_host *host = mmc_priv(mmc);
++
++      msdc_save_reg(host);
++      msdc_gate_clock(host);
++      return 0;
++}
++
++static int msdc_runtime_resume(struct device *dev)
++{
++      struct mmc_host *mmc = dev_get_drvdata(dev);
++      struct msdc_host *host = mmc_priv(mmc);
++
++      msdc_ungate_clock(host);
++      msdc_restore_reg(host);
++      return 0;
++}
++#endif
++
++static const struct dev_pm_ops msdc_dev_pm_ops = {
++      SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
++                              pm_runtime_force_resume)
++      SET_RUNTIME_PM_OPS(msdc_runtime_suspend, msdc_runtime_resume, NULL)
++};
++
+ static const struct of_device_id msdc_of_ids[] = {
+       {   .compatible = "mediatek,mt8135-mmc", },
+       {}
+@@ -1370,6 +1452,7 @@ static struct platform_driver mt_msdc_driver = {
+       .driver = {
+               .name = "mtk-msdc",
+               .of_match_table = msdc_of_ids,
++              .pm = &msdc_dev_pm_ops,
+       },
+ };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0037-arm64-mediatek-Add-Mediatek-MMC-support-in-defconfig.patch b/target/linux/mediatek/patches/0037-arm64-mediatek-Add-Mediatek-MMC-support-in-defconfig.patch
new file mode 100644 (file)
index 0000000..7d9143f
--- /dev/null
@@ -0,0 +1,28 @@
+From 0435517df474d830711b7e1dc56e2d47ae5083b5 Mon Sep 17 00:00:00 2001
+From: Eddie Huang <eddie.huang@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:52 +0800
+Subject: [PATCH 37/76] arm64: mediatek: Add Mediatek MMC support in defconfig
+
+Add CONFIG_MMC_MTK=y in defconfig
+
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+Signed-off-by: Eddie Huang <eddie.huang@mediatek.com>
+---
+ arch/arm64/configs/defconfig |    1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
+index 2ed7449..e03288a 100644
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -138,6 +138,7 @@ CONFIG_MMC_ARMMMCI=y
+ CONFIG_MMC_SDHCI=y
+ CONFIG_MMC_SDHCI_PLTFM=y
+ CONFIG_MMC_SPI=y
++CONFIG_MMC_MTK=y
+ CONFIG_RTC_CLASS=y
+ CONFIG_RTC_DRV_EFI=y
+ CONFIG_RTC_DRV_XGENE=y
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0038-ARM-multi_v7_defconfig-Enable-Mediatek-MMC-support-m.patch b/target/linux/mediatek/patches/0038-ARM-multi_v7_defconfig-Enable-Mediatek-MMC-support-m.patch
new file mode 100644 (file)
index 0000000..35dc99f
--- /dev/null
@@ -0,0 +1,29 @@
+From 3069c2bfe0da7c6c13a61b0e1d457fd0e021e27b Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 15 Jun 2015 19:20:53 +0800
+Subject: [PATCH 38/76] ARM: multi_v7_defconfig: Enable Mediatek MMC support
+ multi-v7
+
+Add CONFIG_MMC_MTK=y in defconfig
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
+---
+ arch/arm/configs/multi_v7_defconfig |    1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
+index fbbb191..bfa09ab 100644
+--- a/arch/arm/configs/multi_v7_defconfig
++++ b/arch/arm/configs/multi_v7_defconfig
+@@ -477,6 +477,7 @@ CONFIG_MMC_DW_EXYNOS=y
+ CONFIG_MMC_DW_ROCKCHIP=y
+ CONFIG_MMC_SH_MMCIF=y
+ CONFIG_MMC_SUNXI=y
++CONFIG_MMC_MTK=y
+ CONFIG_NEW_LEDS=y
+ CONFIG_LEDS_CLASS=y
+ CONFIG_LEDS_GPIO=y
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0039-clocksource-mediatek-Don-t-run-event_handler-if-it-i.patch b/target/linux/mediatek/patches/0039-clocksource-mediatek-Don-t-run-event_handler-if-it-i.patch
new file mode 100644 (file)
index 0000000..aabe849
--- /dev/null
@@ -0,0 +1,32 @@
+From 9d4cba66a74cbdf25f43a7a8cc360370214ba5fc Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:24 +0800
+Subject: [PATCH 39/76] clocksource: mediatek: Don't run event_handler if it
+ is NULL
+
+Spurious timer interrupt is noticed in mtk timer and cause kernel
+crash. In mtk_timer_interrupt(), only run event_handler if it is
+not NULL.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ drivers/clocksource/mtk_timer.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
+index 68ab423..85e0ab5 100644
+--- a/drivers/clocksource/mtk_timer.c
++++ b/drivers/clocksource/mtk_timer.c
+@@ -143,7 +143,8 @@ static irqreturn_t mtk_timer_interrupt(int irq, void *dev_id)
+       /* Acknowledge timer0 irq */
+       writel(GPT_IRQ_ACK(GPT_CLK_EVT), evt->gpt_base + GPT_IRQ_ACK_REG);
+-      evt->dev.event_handler(&evt->dev);
++      if (evt->dev.event_handler)
++              evt->dev.event_handler(&evt->dev);
+       return IRQ_HANDLED;
+ }
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0040-clocksource-mediatek-Use-GPT-as-sched-clock-source.patch b/target/linux/mediatek/patches/0040-clocksource-mediatek-Use-GPT-as-sched-clock-source.patch
new file mode 100644 (file)
index 0000000..c6b66af
--- /dev/null
@@ -0,0 +1,51 @@
+From 3b3c2406dd9797bc806e0ce756142a33d209c4e8 Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:25 +0800
+Subject: [PATCH 40/76] clocksource: mediatek: Use GPT as sched clock source
+
+When cpu is in deep idle, arch timer will stop counting. Setup GPT as
+sched clock source so it can keep counting in idle.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ drivers/clocksource/mtk_timer.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
+index 85e0ab5..9a90c7b 100644
+--- a/drivers/clocksource/mtk_timer.c
++++ b/drivers/clocksource/mtk_timer.c
+@@ -24,6 +24,7 @@
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/of_irq.h>
++#include <linux/sched_clock.h>
+ #include <linux/slab.h>
+ #define GPT_IRQ_EN_REG                0x00
+@@ -59,6 +60,13 @@ struct mtk_clock_event_device {
+       struct clock_event_device dev;
+ };
++static void __iomem *gpt_base __read_mostly;
++
++static u64 notrace mtk_read_sched_clock(void)
++{
++      return readl_relaxed(gpt_base + TIMER_CNT_REG(GPT_CLK_SRC));
++}
++
+ static inline struct mtk_clock_event_device *to_mtk_clk(
+                               struct clock_event_device *c)
+ {
+@@ -239,6 +247,8 @@ static void __init mtk_timer_init(struct device_node *node)
+       mtk_timer_setup(evt, GPT_CLK_SRC, TIMER_CTRL_OP_FREERUN);
+       clocksource_mmio_init(evt->gpt_base + TIMER_CNT_REG(GPT_CLK_SRC),
+                       node->name, rate, 300, 32, clocksource_mmio_readl_up);
++      gpt_base = evt->gpt_base;
++      sched_clock_register(mtk_read_sched_clock, 32, rate);
+       /* Configure clock event */
+       mtk_timer_setup(evt, GPT_CLK_EVT, TIMER_CTRL_OP_REPEAT);
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0041-arm-mediatek-enable-gpt6-on-boot-up-to-make-arch-tim.patch b/target/linux/mediatek/patches/0041-arm-mediatek-enable-gpt6-on-boot-up-to-make-arch-tim.patch
new file mode 100644 (file)
index 0000000..728792c
--- /dev/null
@@ -0,0 +1,63 @@
+From eec99287ace37015ed313b4fc27ba205a158b66c Mon Sep 17 00:00:00 2001
+From: Matthias Brugger <matthias.bgg@gmail.com>
+Date: Fri, 1 May 2015 15:43:26 +0800
+Subject: [PATCH 41/76] arm: mediatek: enable gpt6 on boot up to make arch
+ timer working
+
+We enable GTP6 which ungates the arch timer clock.
+In the future this should be done in the bootloader.
+
+Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ arch/arm/mach-mediatek/mediatek.c |   29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c
+index a954900..6b38d67 100644
+--- a/arch/arm/mach-mediatek/mediatek.c
++++ b/arch/arm/mach-mediatek/mediatek.c
+@@ -16,6 +16,34 @@
+  */
+ #include <linux/init.h>
+ #include <asm/mach/arch.h>
++#include <linux/of.h>
++#include <linux/clk-provider.h>
++#include <linux/clocksource.h>
++
++
++#define GPT6_CON_MT65xx 0x10008060
++#define GPT_ENABLE      0x31
++
++static void __init mediatek_timer_init(void)
++{
++      void __iomem *gpt_base = 0;
++
++      if (of_machine_is_compatible("mediatek,mt6589") ||
++          of_machine_is_compatible("mediatek,mt8135") ||
++          of_machine_is_compatible("mediatek,mt8127")) {
++              /* turn on GPT6 which ungates arch timer clocks */
++              gpt_base = ioremap(GPT6_CON_MT65xx, 0x04);
++      }
++
++      /* enabel clock and set to free-run */
++      if (gpt_base) {
++              writel(GPT_ENABLE, gpt_base);
++              iounmap(gpt_base);
++      }
++
++      of_clk_init(NULL);
++      clocksource_of_init();
++};
+ static const char * const mediatek_board_dt_compat[] = {
+       "mediatek,mt6589",
+@@ -27,4 +55,5 @@ static const char * const mediatek_board_dt_compat[] = {
+ DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
+       .dt_compat      = mediatek_board_dt_compat,
++      .init_time      = mediatek_timer_init,
+ MACHINE_END
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0042-ARM-mediatek-add-smp-bringup-code.patch b/target/linux/mediatek/patches/0042-ARM-mediatek-add-smp-bringup-code.patch
new file mode 100644 (file)
index 0000000..8910532
--- /dev/null
@@ -0,0 +1,178 @@
+From daa2c1f9202f08628d4f91a1cf4dafb44c9bcafe Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:28 +0800
+Subject: [PATCH 42/76] ARM: mediatek: add smp bringup code
+
+Add support for booting secondary CPUs on mt6589, mt8127
+and mt8135.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ arch/arm/mach-mediatek/Makefile  |    3 +
+ arch/arm/mach-mediatek/platsmp.c |  145 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 148 insertions(+)
+ create mode 100644 arch/arm/mach-mediatek/platsmp.c
+
+diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
+index 43e619f..2116460 100644
+--- a/arch/arm/mach-mediatek/Makefile
++++ b/arch/arm/mach-mediatek/Makefile
+@@ -1 +1,4 @@
++ifeq ($(CONFIG_SMP),y)
++obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
++endif
+ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
+diff --git a/arch/arm/mach-mediatek/platsmp.c b/arch/arm/mach-mediatek/platsmp.c
+new file mode 100644
+index 0000000..e266b3d
+--- /dev/null
++++ b/arch/arm/mach-mediatek/platsmp.c
+@@ -0,0 +1,145 @@
++/*
++ * arch/arm/mach-mediatek/platsmp.c
++ *
++ * Copyright (c) 2014 Mediatek Inc.
++ * Author: Shunli Wang <shunli.wang@mediatek.com>
++ *         Yingjoe Chen <yingjoe.chen@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/io.h>
++#include <linux/memblock.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/string.h>
++#include <linux/threads.h>
++
++#define MTK_MAX_CPU           8
++#define MTK_SMP_REG_SIZE      0x1000
++
++struct mtk_smp_boot_info {
++      unsigned long smp_base;
++      unsigned int jump_reg;
++      unsigned int boot_reg;
++      unsigned int core_keys[MTK_MAX_CPU - 1];
++      unsigned int core_regs[MTK_MAX_CPU - 1];
++};
++
++static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = {
++      0x80002000, 1020, 1012,
++      { 0x534c4131, 0x4c415332, 0x41534c33 },
++      { 1016, 1016, 1016},
++};
++
++static const struct mtk_smp_boot_info mtk_mt6589_boot = {
++      0x10002000, 0x34, 0x30,
++      { 0x534c4131, 0x4c415332, 0x41534c33 },
++      { 0x38, 0x3c, 0x40 },
++};
++
++static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
++      { .compatible   = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
++      { .compatible   = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
++};
++
++static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
++      { .compatible   = "mediatek,mt6589", .data = &mtk_mt6589_boot },
++};
++
++static void __iomem *mtk_smp_base;
++static const struct mtk_smp_boot_info *mtk_smp_info;
++
++static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle)
++{
++      if (!mtk_smp_base)
++              return -EINVAL;
++
++      if (!mtk_smp_info->core_keys[cpu-1])
++              return -EINVAL;
++
++      writel_relaxed(mtk_smp_info->core_keys[cpu-1],
++              mtk_smp_base + mtk_smp_info->core_regs[cpu-1]);
++
++      arch_send_wakeup_ipi_mask(cpumask_of(cpu));
++
++      return 0;
++}
++
++static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone)
++{
++      int i, num;
++      const struct of_device_id *infos;
++
++      if (trustzone) {
++              num = ARRAY_SIZE(mtk_tz_smp_boot_infos);
++              infos = mtk_tz_smp_boot_infos;
++      } else {
++              num = ARRAY_SIZE(mtk_smp_boot_infos);
++              infos = mtk_smp_boot_infos;
++      }
++
++      /* Find smp boot info for this SoC */
++      for (i = 0; i < num; i++) {
++              if (of_machine_is_compatible(infos[i].compatible)) {
++                      mtk_smp_info = infos[i].data;
++                      break;
++              }
++      }
++
++      if (!mtk_smp_info) {
++              pr_err("%s: Device is not supported\n", __func__);
++              return;
++      }
++
++      if (trustzone) {
++              if (memblock_reserve(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE)) {
++                      pr_err("%s: Can't reserve smp memory\n", __func__);
++                      return;
++              }
++              mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base);
++      } else {
++              mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE);
++              if (!mtk_smp_base) {
++                      pr_err("%s: Can't remap %lx\n", __func__,
++                              mtk_smp_info->smp_base);
++                      return;
++              }
++      }
++
++      /*
++       * write the address of slave startup address into the system-wide
++       * jump register
++       */
++      writel_relaxed(virt_to_phys(secondary_startup),
++                      mtk_smp_base + mtk_smp_info->jump_reg);
++}
++
++static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus)
++{
++      __mtk_smp_prepare_cpus(max_cpus, 1);
++}
++
++static void __init mtk_smp_prepare_cpus(unsigned int max_cpus)
++{
++      __mtk_smp_prepare_cpus(max_cpus, 0);
++}
++
++static struct smp_operations mt81xx_tz_smp_ops __initdata = {
++      .smp_prepare_cpus = mtk_tz_smp_prepare_cpus,
++      .smp_boot_secondary = mtk_boot_secondary,
++};
++CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops);
++
++static struct smp_operations mt65xx_smp_ops __initdata = {
++      .smp_prepare_cpus = mtk_smp_prepare_cpus,
++      .smp_boot_secondary = mtk_boot_secondary,
++};
++CPU_METHOD_OF_DECLARE(mt65xx_smp, "mediatek,mt65xx-smp", &mt65xx_smp_ops);
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0043-ARM-dts-mt8127-enable-basic-SMP-bringup-for-mt8127.patch b/target/linux/mediatek/patches/0043-ARM-dts-mt8127-enable-basic-SMP-bringup-for-mt8127.patch
new file mode 100644 (file)
index 0000000..60990c3
--- /dev/null
@@ -0,0 +1,53 @@
+From e75f8b666c976aff2aa30b967f74df021d800993 Mon Sep 17 00:00:00 2001
+From: "Joe.C" <yingjoe.chen@mediatek.com>
+Date: Fri, 1 May 2015 15:43:30 +0800
+Subject: [PATCH 43/76] ARM: dts: mt8127: enable basic SMP bringup for mt8127
+
+Add arch timer node to enable arch-timer support. MT8127 firmware
+doesn't correctly setup arch-timer frequency and CNTVOFF, add
+properties to workaround this.
+
+This also set cpu enable-method to enable SMP.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+---
+ arch/arm/boot/dts/mt8127.dtsi |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi
+index aaa7862..7c2090d 100644
+--- a/arch/arm/boot/dts/mt8127.dtsi
++++ b/arch/arm/boot/dts/mt8127.dtsi
+@@ -23,6 +23,7 @@
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
++              enable-method = "mediatek,mt81xx-tz-smp";
+               cpu@0 {
+                       device_type = "cpu";
+@@ -72,6 +73,21 @@
+                 };
+       };
++      timer {
++              compatible = "arm,armv7-timer";
++              interrupt-parent = <&gic>;
++              interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>;
++              clock-frequency = <13000000>;
++              arm,cpu-registers-not-fw-configured;
++      };
++
+       soc {
+               #address-cells = <2>;
+               #size-cells = <2>;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0044-dt-bindings-Add-usb3.0-phy-binding-for-MT65xx-SoCs.patch b/target/linux/mediatek/patches/0044-dt-bindings-Add-usb3.0-phy-binding-for-MT65xx-SoCs.patch
new file mode 100644 (file)
index 0000000..1783e08
--- /dev/null
@@ -0,0 +1,60 @@
+From 8d61eb953496aba51b94dac07c31c7e069c784bd Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:47:58 +0800
+Subject: [PATCH 44/76] dt-bindings: Add usb3.0 phy binding for MT65xx SoCs
+
+add a DT binding documentation of usb3.0 phy for MT65xx
+SoCs from Mediatek.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ .../devicetree/bindings/usb/mt65xx-u3phy.txt       |   37 ++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt
+
+diff --git a/Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt b/Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt
+new file mode 100644
+index 0000000..b0b91b0
+--- /dev/null
++++ b/Documentation/devicetree/bindings/usb/mt65xx-u3phy.txt
+@@ -0,0 +1,37 @@
++MT65xx U3PHY
++
++The device node for Mediatek SOC usb3.0 phy
++
++Required properties:
++ - compatible : Should be "mediatek,mt8173-u3phy"
++ - reg        : Offset and length of registers, the first is for mac domain,
++      another for phy domain
++ - power-domains: to enable usb's mtcmos
++ - reg-vusb33-supply:  regulator of usb avdd3.3v
++ - clocks     : must support all clocks that phy need
++ - clock-names: should be "wakeup_deb_p0", "wakeup_deb_p1" for wakeup
++      debounce control clocks, "sys_mac" for sys and mac clocks and
++      "u3phya_ref" for u3phya reference clock.
++
++Optional properties:
++ - disable-usb2-p1 : disable port1 of usb2.0 which has two ports.
++ - reg-p1-vbus-supply : regulator of port1's vbus;
++
++Example:
++
++u3phy: usb-phy@11271000 {
++      compatible = "mediatek,mt8173-u3phy";
++      reg = <0 0x11271000 0 0x3000>,
++            <0 0x11280000 0 0x20000>;
++      power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
++      reg-vusb33-supply = <&mt6397_usb_reg>;
++      clocks = <&perisys PERI_USB0>,
++               <&perisys PERI_USB1>,
++               <&topckgen CLK_TOP_USB30_SEL>,
++               <&apmixedsys CLK_APMIXED_REF2USB_TX>;
++      clock-names = "wakeup_deb_p0",
++                    "wakeup_deb_p1",
++                    "sys_mac",
++                    "u3phya_ref";
++      disable-usb2-p1;
++};
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0045-dt-bindings-Add-a-binding-for-Mediatek-xHCI-host-con.patch b/target/linux/mediatek/patches/0045-dt-bindings-Add-a-binding-for-Mediatek-xHCI-host-con.patch
new file mode 100644 (file)
index 0000000..6c1d7b3
--- /dev/null
@@ -0,0 +1,43 @@
+From 8629bcb28208ef5b9f5eeb6d4b669651c9521b30 Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:47:59 +0800
+Subject: [PATCH 45/76] dt-bindings: Add a binding for Mediatek xHCI host
+ controller
+
+add a DT binding documentation of xHCI host controller for
+the MT8173 SoC from Mediatek.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ .../devicetree/bindings/usb/mt8173-xhci.txt         |   19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+
+diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+new file mode 100644
+index 0000000..da28570
+--- /dev/null
++++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+@@ -0,0 +1,19 @@
++MT65XX xhci
++
++The device node for Mediatek SOC usb3.0 host controller
++
++Required properties:
++ - compatible : supports "mediatek,mt8173-xhci", "generic-xhci"
++ - reg        : Offset and length of registers
++ - interrupts : Interrupt; mode, number and trigger
++ - usb-phy : the phy that xhci will bind
++ - usb3-lpm-capable: suppots USB3 LPM
++
++Example:
++usb: usb30@11270000 {
++      compatible = "mediatek,mt8173-xhci", "generic-xhci";
++      reg = <0 0x11270000 0 0x1000>;
++      interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
++      usb-phy = <&u3phy>;
++      usb3-lpm-capable;
++};
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch b/target/linux/mediatek/patches/0046-usb-phy-add-usb3.0-phy-driver-for-mt65xx-SoCs.patch
new file mode 100644 (file)
index 0000000..40ba24d
--- /dev/null
@@ -0,0 +1,779 @@
+From cee7c5a343bdecf407c876289327c567bfd34fd4 Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:48:01 +0800
+Subject: [PATCH 46/76] usb: phy: add usb3.0 phy driver for mt65xx SoCs
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ drivers/usb/phy/Kconfig           |   10 +
+ drivers/usb/phy/Makefile          |    1 +
+ drivers/usb/phy/phy-mt65xx-usb3.c |  724 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 735 insertions(+)
+ create mode 100644 drivers/usb/phy/phy-mt65xx-usb3.c
+
+diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
+index 2175678..dfca566 100644
+--- a/drivers/usb/phy/Kconfig
++++ b/drivers/usb/phy/Kconfig
+@@ -151,6 +151,16 @@ config USB_MSM_OTG
+         This driver is not supported on boards like trout which
+         has an external PHY.
++config USB_MT65XX_USB3_PHY
++      tristate "Mediatek USB3.0 PHY controller Driver"
++      depends on ARCH_MEDIATEK || COMPILE_TEST
++      select USB_PHY
++      help
++        Say 'Y' here to add support for Mediatek USB3.0 PHY driver
++        for mt65xx SoCs. it supports two usb2.0 ports and
++        one usb3.0 port.
++        To compile this driver as a module, choose M here
++
+ config USB_MV_OTG
+       tristate "Marvell USB OTG support"
+       depends on USB_EHCI_MV && USB_MV_UDC && PM
+diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
+index 75f2bba..d6113a4 100644
+--- a/drivers/usb/phy/Makefile
++++ b/drivers/usb/phy/Makefile
+@@ -20,6 +20,7 @@ obj-$(CONFIG_USB_EHCI_TEGRA)         += phy-tegra-usb.o
+ obj-$(CONFIG_USB_GPIO_VBUS)           += phy-gpio-vbus-usb.o
+ obj-$(CONFIG_USB_ISP1301)             += phy-isp1301.o
+ obj-$(CONFIG_USB_MSM_OTG)             += phy-msm-usb.o
++obj-$(CONFIG_USB_MT65XX_USB3_PHY)     += phy-mt65xx-usb3.o
+ obj-$(CONFIG_USB_MV_OTG)              += phy-mv-usb.o
+ obj-$(CONFIG_USB_MXS_PHY)             += phy-mxs-usb.o
+ obj-$(CONFIG_USB_RCAR_PHY)            += phy-rcar-usb.o
+diff --git a/drivers/usb/phy/phy-mt65xx-usb3.c b/drivers/usb/phy/phy-mt65xx-usb3.c
+new file mode 100644
+index 0000000..ec5cf24
+--- /dev/null
++++ b/drivers/usb/phy/phy-mt65xx-usb3.c
+@@ -0,0 +1,724 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Chunfeng.Yun <chunfeng.yun@mediatek.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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/resource.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/export.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/pm_runtime.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/of_address.h>
++#include <linux/usb/otg.h>
++#include <linux/usb/of.h>
++#include <linux/usb/phy.h>
++#include <linux/clk.h>
++#include <linux/iopoll.h>
++
++/*
++ * relative to MAC base address
++ */
++#define SSUSB_USB3_MAC_CSR_BASE       (0x1400)
++#define SSUSB_USB3_SYS_CSR_BASE       (0x1400)
++#define SSUSB_USB2_CSR_BASE           (0x2400)
++
++/*
++ * for sifslv1 register
++ * relative to USB3_SIF_BASE base address
++ */
++#define SSUSB_SIFSLV_IPPC_BASE                (0x700)
++
++/*
++ * for sifslv2 register
++ * relative to USB3_SIF_BASE base address
++ */
++#define SSUSB_SIFSLV_U2PHY_COM_BASE   (0x10800)
++#define SSUSB_SIFSLV_U3PHYD_BASE      (0x10900)
++#define SSUSB_SIFSLV_U2FREQ_BASE      (0x10f00)
++#define SSUSB_USB30_PHYA_SIV_B_BASE           (0x10b00)
++#define SSUSB_SIFSLV_U3PHYA_DA_BASE           (0x10c00)
++#define SSUSB_SIFSLV_SPLLC            (0x10000)
++
++/*port1 refs. +0x800(refer to port0)*/
++#define U3P_PORT_OFFSET (0x800)       /*based on port0 */
++#define U3P_PHY_BASE(index) ((U3P_PORT_OFFSET) * (index))
++
++#define U3P_IP_PW_CTRL0       (SSUSB_SIFSLV_IPPC_BASE+0x0000)
++#define CTRL0_IP_SW_RST                       (0x1<<0)
++
++#define U3P_IP_PW_CTRL1       (SSUSB_SIFSLV_IPPC_BASE+0x0004)
++#define CTRL1_IP_HOST_PDN             (0x1<<0)
++
++#define U3P_IP_PW_STS1                (SSUSB_SIFSLV_IPPC_BASE+0x0010)
++#define STS1_U3_MAC_RST               (0x1 << 16)
++#define STS1_SYS125_RST               (0x1 << 10)
++#define STS1_REF_RST          (0x1 << 8)
++#define STS1_SYSPLL_STABLE    (0x1 << 0)
++
++#define U3P_IP_PW_STS2        (SSUSB_SIFSLV_IPPC_BASE+0x0014)
++#define STS2_U2_MAC_RST       (0x1 << 0)
++
++#define U3P_IP_XHCI_CAP       (SSUSB_SIFSLV_IPPC_BASE + 0x24)
++#define CAP_U3_PORT_NUM(p)    ((p) & 0xff)
++#define CAP_U2_PORT_NUM(p)    (((p) >> 8) & 0xff)
++
++#define U3P_U3_CTRL_0P        (SSUSB_SIFSLV_IPPC_BASE+0x0030)
++#define CTRL_U3_PORT_HOST_SEL (0x1<<2)
++#define CTRL_U3_PORT_PDN              (0x1<<1)
++#define CTRL_U3_PORT_DIS              (0x1<<0)
++
++#define U3P_U2_CTRL_0P        (SSUSB_SIFSLV_IPPC_BASE+0x0050)
++#define CTRL_U2_PORT_HOST_SEL (0x1<<2)
++#define CTRL_U2_PORT_PDN              (0x1<<1)
++#define CTRL_U2_PORT_DIS              (0x1<<0)
++
++#define U3P_U3_CTRL(p)        (U3P_U3_CTRL_0P + ((p) * 0x08))
++#define U3P_U2_CTRL(p)        (U3P_U2_CTRL_0P + ((p) * 0x08))
++
++#define U3P_USBPHYACR5      (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0014)
++#define PA5_RG_U2_HSTX_SRCTRL                 (0x7<<12)
++#define PA5_RG_U2_HSTX_SRCTRL_VAL(x)  ((0x7 & (x)) << 12)
++#define PA5_RG_U2_HS_100U_U3_EN                       (0x1<<11)
++
++#define U3P_USBPHYACR6      (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0018)
++#define PA6_RG_U2_ISO_EN                      (0x1<<31)
++#define PA6_RG_U2_BC11_SW_EN          (0x1<<23)
++#define PA6_RG_U2_OTG_VBUSCMP_EN      (0x1<<20)
++
++#define U3P_U2PHYACR4       (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0020)
++#define P2C_RG_USB20_GPIO_CTL (0x1<<9)
++#define P2C_USB20_GPIO_MODE           (0x1<<8)
++#define P2C_U2_GPIO_CTR_MSK  (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
++
++#define U3P_U2PHYDTM0       (SSUSB_SIFSLV_U2PHY_COM_BASE+0x0068)
++#define P2C_FORCE_UART_EN             (0x1<<26)
++#define P2C_FORCE_DATAIN              (0x1<<23)
++#define P2C_FORCE_DM_PULLDOWN (0x1<<21)
++#define P2C_FORCE_DP_PULLDOWN (0x1<<20)
++#define P2C_FORCE_XCVRSEL             (0x1<<19)
++#define P2C_FORCE_SUSPENDM            (0x1<<18)
++#define P2C_FORCE_TERMSEL             (0x1<<17)
++#define P2C_RG_DATAIN                 (0xf<<10)
++#define P2C_RG_DATAIN_VAL(x)  ((0xf & (x)) << 10)
++#define P2C_RG_DMPULLDOWN             (0x1<<7)
++#define P2C_RG_DPPULLDOWN             (0x1<<6)
++#define P2C_RG_XCVRSEL                        (0x3<<4)
++#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4)
++#define P2C_RG_SUSPENDM                       (0x1<<3)
++#define P2C_RG_TERMSEL                        (0x1<<2)
++#define P2C_DTM0_PART_MASK \
++              (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \
++              P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \
++              P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \
++              P2C_RG_TERMSEL)
++
++#define U3P_U2PHYDTM1       (SSUSB_SIFSLV_U2PHY_COM_BASE+0x006C)
++#define P2C_RG_UART_EN                (0x1<<16)
++#define P2C_RG_VBUSVALID      (0x1<<5)
++#define P2C_RG_SESSEND                (0x1<<4)
++#define P2C_RG_AVALID         (0x1<<2)
++
++#define U3P_U3_PHYA_REG0      (SSUSB_USB30_PHYA_SIV_B_BASE+0x0000)
++#define P3A_RG_U3_VUSB10_ON                   (1<<5)
++
++#define U3P_U3_PHYA_REG6      (SSUSB_USB30_PHYA_SIV_B_BASE+0x0018)
++#define P3A_RG_TX_EIDLE_CM                    (0xf<<28)
++#define P3A_RG_TX_EIDLE_CM_VAL(x)     ((0xf & (x)) << 28)
++
++#define U3P_U3_PHYA_REG9      (SSUSB_USB30_PHYA_SIV_B_BASE+0x0024)
++#define P3A_RG_RX_DAC_MUX                     (0x1f<<1)
++#define P3A_RG_RX_DAC_MUX_VAL(x)      ((0x1f & (x)) << 1)
++
++#define U3P_U3PHYA_DA_REG0    (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0)
++#define P3A_RG_XTAL_EXT_EN_U3                 (0x3<<10)
++#define P3A_RG_XTAL_EXT_EN_U3_VAL(x)  ((0x3 & (x)) << 10)
++
++#define U3P_PHYD_CDR1         (SSUSB_SIFSLV_U3PHYD_BASE+0x5c)
++#define P3D_RG_CDR_BIR_LTD1                           (0x1f<<24)
++#define P3D_RG_CDR_BIR_LTD1_VAL(x)            ((0x1f & (x)) << 24)
++#define P3D_RG_CDR_BIR_LTD0                           (0x1f<<8)
++#define P3D_RG_CDR_BIR_LTD0_VAL(x)            ((0x1f & (x)) << 8)
++
++#define U3P_XTALCTL3          (SSUSB_SIFSLV_SPLLC + 0x18)
++#define XC3_RG_U3_XTAL_RX_PWD                 (0x1<<9)
++#define XC3_RG_U3_FRC_XTAL_RX_PWD             (0x1<<8)
++
++#define U3P_UX_EXIT_LFPS_PARAM        (SSUSB_USB3_MAC_CSR_BASE+0x00A0)
++#define RX_UX_EXIT_REF                (0xff<<8)
++#define RX_UX_EXIT_REF_VAL    (0x3 << 8)
++
++#define U3P_REF_CLK_PARAM     (SSUSB_USB3_MAC_CSR_BASE+0x00B0)
++#define REF_CLK_1000NS                (0xff << 0)
++#define REF_CLK_VAL_DEF               (0xa << 0)
++
++#define U3P_LINK_PM_TIMER                     (SSUSB_USB3_SYS_CSR_BASE+0x0208)
++#define PM_LC_TIMEOUT                 (0xf<<0)
++#define PM_LC_TIMEOUT_VAL             (0x3 << 0)
++
++#define U3P_TIMING_PULSE_CTRL (SSUSB_USB3_SYS_CSR_BASE+0x02B4)
++#define U3T_CNT_1US                   (0xff << 0)
++#define U3T_CNT_1US_VAL               (0x3f << 0)     /* 62.5MHz: 63 */
++
++#define U3P_U2_TIMING_PARAM           (SSUSB_USB2_CSR_BASE+0x0040)
++#define U2T_VAL_1US                   (0xff<<0)
++#define U2T_VAL_1US_VAL               (0x3f << 0)     /* 62.5MHz: 63 */
++
++
++struct mt65xx_u3phy {
++      struct usb_phy phy;
++      struct device *dev;
++      struct regulator *vusb33;
++      struct regulator *p1_vbus;
++      void __iomem *mac_base; /* only device-mac regs, exclude xhci's */
++      void __iomem *sif_base; /* include sif & sif2 */
++      struct clk *wk_deb_p0;  /* port0's wakeup debounce clock */
++      struct clk *wk_deb_p1;
++      struct clk *sys_mac;    /* sys and mac clock */
++      struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
++      bool enable_usb2_p1;
++};
++
++
++static void u3p_writel(void __iomem *base, u32 offset, u32 data)
++{
++      writel(data, base + offset);
++}
++
++static u32 u3p_readl(void __iomem *base, u32 offset)
++{
++      return readl(base + offset);
++}
++
++static void u3p_setmsk(void __iomem *base, u32 offset, u32 msk)
++{
++      void __iomem *addr = base + offset;
++
++      writel((readl(addr) | msk), addr);
++}
++
++static void u3p_clrmsk(void __iomem *base, u32 offset, u32 msk)
++{
++      void __iomem *addr = base + offset;
++
++      writel((readl(addr) & ~msk), addr);
++}
++
++static void u3p_setval(void __iomem *base, u32 offset,
++      u32 mask, u32 value)
++{
++      void __iomem *addr = base + offset;
++      unsigned int new_value;
++
++      new_value = (readl(addr) & ~mask) | value;
++      writel(new_value, addr);
++}
++
++static void phy_index_power_on(struct mt65xx_u3phy *u3phy, int index)
++{
++      void __iomem *sif_base = u3phy->sif_base + U3P_PHY_BASE(index);
++
++      if (!index) {
++              /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
++              u3p_setmsk(sif_base, U3P_U3_PHYA_REG0, P3A_RG_U3_VUSB10_ON);
++              /* power domain iso disable */
++              u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_ISO_EN);
++      }
++
++      /* switch to USB function. (system register, force ip into usb mode) */
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_UART_EN);
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_UART_EN);
++      if (!index)
++              u3p_clrmsk(sif_base, U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
++
++      /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM);
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM0,
++                      P2C_RG_XCVRSEL | P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
++
++      /* DP/DM BC1.1 path Disable */
++      u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
++      /* OTG Enable */
++      u3p_setmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
++      u3p_setval(sif_base, U3P_U3PHYA_DA_REG0, P3A_RG_XTAL_EXT_EN_U3,
++                      P3A_RG_XTAL_EXT_EN_U3_VAL(2));
++      u3p_setval(sif_base, U3P_U3_PHYA_REG9, P3A_RG_RX_DAC_MUX,
++                      P3A_RG_RX_DAC_MUX_VAL(4));
++
++      if (!index) {
++              u3p_setmsk(sif_base, U3P_XTALCTL3, XC3_RG_U3_XTAL_RX_PWD);
++              u3p_setmsk(sif_base, U3P_XTALCTL3, XC3_RG_U3_FRC_XTAL_RX_PWD);
++              /* [mt8173]disable Change 100uA current from SSUSB */
++              u3p_clrmsk(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HS_100U_U3_EN);
++      }
++      u3p_setval(sif_base, U3P_U3_PHYA_REG6, P3A_RG_TX_EIDLE_CM,
++                      P3A_RG_TX_EIDLE_CM_VAL(0xe));
++      u3p_setval(sif_base, U3P_PHYD_CDR1, P3D_RG_CDR_BIR_LTD0,
++                      P3D_RG_CDR_BIR_LTD0_VAL(0xc));
++      u3p_setval(sif_base, U3P_PHYD_CDR1, P3D_RG_CDR_BIR_LTD1,
++                      P3D_RG_CDR_BIR_LTD1_VAL(0x3));
++
++      udelay(800);
++      u3p_setmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_VBUSVALID | P2C_RG_AVALID);
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_SESSEND);
++
++      /* USB 2.0 slew rate calibration */
++      u3p_setval(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCTRL,
++                      PA5_RG_U2_HSTX_SRCTRL_VAL(4));
++
++      dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
++}
++
++
++static void phy_index_power_off(struct mt65xx_u3phy *u3phy, int index)
++{
++      void __iomem *sif_base = u3phy->sif_base + U3P_PHY_BASE(index);
++
++      /* switch to USB function. (system register, force ip into usb mode) */
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_UART_EN);
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_UART_EN);
++      if (!index)
++              u3p_clrmsk(sif_base, U3P_U2PHYACR4, P2C_U2_GPIO_CTR_MSK);
++
++      u3p_setmsk(sif_base, U3P_U2PHYDTM0, P2C_FORCE_SUSPENDM);
++      u3p_setval(sif_base, U3P_U2PHYDTM0,
++                      P2C_RG_XCVRSEL, P2C_RG_XCVRSEL_VAL(1));
++      u3p_setval(sif_base, U3P_U2PHYDTM0,
++                      P2C_RG_DATAIN, P2C_RG_DATAIN_VAL(0));
++      u3p_setmsk(sif_base, U3P_U2PHYDTM0, P2C_DTM0_PART_MASK);
++      /* DP/DM BC1.1 path Disable */
++      u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
++      /* OTG Disable */
++      u3p_clrmsk(sif_base, U3P_USBPHYACR6, PA6_RG_U2_OTG_VBUSCMP_EN);
++      if (!index) {
++              /* Change 100uA current switch to USB2.0 */
++              u3p_clrmsk(sif_base, U3P_USBPHYACR5, PA5_RG_U2_HS_100U_U3_EN);
++      }
++      udelay(800);
++
++      /* let suspendm=0, set utmi into analog power down */
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM0, P2C_RG_SUSPENDM);
++      udelay(1);
++
++      u3p_clrmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_VBUSVALID | P2C_RG_AVALID);
++      u3p_setmsk(sif_base, U3P_U2PHYDTM1, P2C_RG_SESSEND);
++      if (!index) {
++              /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
++              u3p_clrmsk(sif_base, U3P_U3_PHYA_REG0, P3A_RG_U3_VUSB10_ON);
++      }
++      dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
++}
++
++
++static int check_ip_clk_status(struct mt65xx_u3phy *u3phy)
++{
++      int ret;
++      int u3_port_num;
++      int u2_port_num;
++      u32 xhci_cap;
++      u32 val;
++      void __iomem *sif_base = u3phy->sif_base;
++
++      xhci_cap = u3p_readl(sif_base, U3P_IP_XHCI_CAP);
++      u3_port_num = CAP_U3_PORT_NUM(xhci_cap);
++      u2_port_num = CAP_U2_PORT_NUM(xhci_cap);
++
++      ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++                        (val & STS1_SYSPLL_STABLE), 100, 10000);
++      if (ret) {
++              dev_err(u3phy->dev, "sypll is not stable!!!\n");
++              return ret;
++      }
++
++      ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++                        (val & STS1_REF_RST), 100, 10000);
++      if (ret) {
++              dev_err(u3phy->dev, "ref_clk is still active!!!\n");
++              return ret;
++      }
++
++      ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++                         (val & STS1_SYS125_RST), 100, 10000);
++      if (ret) {
++              dev_err(u3phy->dev, "sys125_ck is still active!!!\n");
++              return ret;
++      }
++
++      if (u3_port_num) {
++              ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS1, val,
++                                 (val & STS1_U3_MAC_RST), 100, 10000);
++              if (ret) {
++                      dev_err(u3phy->dev, "mac3_mac_ck is still active!!!\n");
++                      return ret;
++              }
++      }
++
++      if (u2_port_num) {
++              ret = readl_poll_timeout(sif_base + U3P_IP_PW_STS2, val,
++                                 (val & STS2_U2_MAC_RST), 100, 10000);
++              if (ret) {
++                      dev_err(u3phy->dev, "mac2_sys_ck is still active!!!\n");
++                      return ret;
++              }
++      }
++
++      return 0;
++}
++
++static int u3phy_ports_enable(struct mt65xx_u3phy *u3phy)
++{
++      int i;
++      u32 temp;
++      int u3_port_num;
++      int u2_port_num;
++      void __iomem *sif_base = u3phy->sif_base;
++
++      temp = u3p_readl(sif_base, U3P_IP_XHCI_CAP);
++      u3_port_num = CAP_U3_PORT_NUM(temp);
++      u2_port_num = CAP_U2_PORT_NUM(temp);
++      dev_dbg(u3phy->dev, "%s u2p:%d, u3p:%d\n",
++              __func__, u2_port_num, u3_port_num);
++
++      /* power on host ip */
++      u3p_clrmsk(sif_base, U3P_IP_PW_CTRL1, CTRL1_IP_HOST_PDN);
++
++      /* power on and enable all u3 ports */
++      for (i = 0; i < u3_port_num; i++) {
++              temp = u3p_readl(sif_base, U3P_U3_CTRL(i));
++              temp &= ~(CTRL_U3_PORT_PDN | CTRL_U3_PORT_DIS);
++              temp |= CTRL_U3_PORT_HOST_SEL;
++              u3p_writel(sif_base, U3P_U3_CTRL(i), temp);
++      }
++
++      /* power on and enable all u2 ports */
++      for (i = 0; i < u2_port_num; i++) {
++              temp = u3p_readl(sif_base, U3P_U2_CTRL(i));
++              temp &= ~(CTRL_U2_PORT_PDN | CTRL_U2_PORT_DIS);
++              temp |= CTRL_U2_PORT_HOST_SEL;
++              u3p_writel(sif_base, U3P_U2_CTRL(i), temp);
++      }
++      return check_ip_clk_status(u3phy);
++}
++
++
++static void u3phy_timing_init(struct mt65xx_u3phy *u3phy)
++{
++      void __iomem *mbase = u3phy->mac_base;
++      int u3_port_num;
++      u32 temp;
++
++      temp = u3p_readl(u3phy->sif_base, U3P_IP_XHCI_CAP);
++      u3_port_num = CAP_U3_PORT_NUM(temp);
++
++      if (u3_port_num) {
++              /* set MAC reference clock speed */
++              u3p_setval(mbase, U3P_UX_EXIT_LFPS_PARAM,
++                              RX_UX_EXIT_REF, RX_UX_EXIT_REF_VAL);
++              /* set REF_CLK */
++              u3p_setval(mbase, U3P_REF_CLK_PARAM,
++                              REF_CLK_1000NS, REF_CLK_VAL_DEF);
++              /* set SYS_CLK */
++              u3p_setval(mbase, U3P_TIMING_PULSE_CTRL,
++                              U3T_CNT_1US, U3T_CNT_1US_VAL);
++              /* set LINK_PM_TIMER=3 */
++              u3p_setval(mbase, U3P_LINK_PM_TIMER,
++                              PM_LC_TIMEOUT, PM_LC_TIMEOUT_VAL);
++      }
++      u3p_setval(mbase, U3P_U2_TIMING_PARAM, U2T_VAL_1US, U2T_VAL_1US_VAL);
++}
++
++
++static int u3phy_clks_enable(struct mt65xx_u3phy *u3phy)
++{
++      int ret;
++
++      ret = clk_prepare_enable(u3phy->sys_mac);
++      if (ret) {
++              dev_err(u3phy->dev, "failed to enable sys_mac\n");
++              goto sys_mac_err;
++      }
++
++      ret = clk_prepare_enable(u3phy->u3phya_ref);
++      if (ret) {
++              dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
++              goto u3phya_ref_err;
++      }
++      ret = clk_prepare_enable(u3phy->wk_deb_p0);
++      if (ret) {
++              dev_err(u3phy->dev, "failed to enable wk_deb_p0\n");
++              goto usb_p0_err;
++      }
++      if (u3phy->enable_usb2_p1) {
++              ret = clk_prepare_enable(u3phy->wk_deb_p1);
++              if (ret) {
++                      dev_err(u3phy->dev, "failed to enable wk_deb_p1\n");
++                      goto usb_p1_err;
++              }
++      }
++      udelay(50);
++
++      return 0;
++
++usb_p1_err:
++      clk_disable_unprepare(u3phy->wk_deb_p0);
++usb_p0_err:
++      clk_disable_unprepare(u3phy->u3phya_ref);
++u3phya_ref_err:
++      clk_disable_unprepare(u3phy->sys_mac);
++sys_mac_err:
++      return -EINVAL;
++}
++
++static void u3phy_clks_disable(struct mt65xx_u3phy *u3phy)
++{
++      if (u3phy->enable_usb2_p1)
++              clk_disable_unprepare(u3phy->wk_deb_p1);
++      clk_disable_unprepare(u3phy->wk_deb_p0);
++      clk_disable_unprepare(u3phy->u3phya_ref);
++      clk_disable_unprepare(u3phy->sys_mac);
++}
++
++
++static int mt65xx_u3phy_init(struct usb_phy *phy)
++{
++      struct mt65xx_u3phy *u3phy;
++      int ret;
++
++      u3phy = container_of(phy, struct mt65xx_u3phy, phy);
++      dev_dbg(u3phy->dev, "%s+\n", __func__);
++
++      if (u3phy->enable_usb2_p1) {
++              ret = regulator_enable(u3phy->p1_vbus);
++              if (ret) {
++                      dev_err(u3phy->dev, "failed to enable p1-vbus\n");
++                      goto reg_p1_err;
++              }
++      }
++
++      ret = regulator_enable(u3phy->vusb33);
++      if (ret) {
++              dev_err(u3phy->dev, "failed to enable vusb33\n");
++              goto reg_err;
++      }
++
++      ret = pm_runtime_get_sync(u3phy->dev);
++      if (ret < 0)
++              goto pm_err;
++
++      ret = u3phy_clks_enable(u3phy);
++      if (ret) {
++              dev_err(u3phy->dev, "failed to enable clks\n");
++              goto clks_err;
++      }
++
++      /* reset whole ip */
++      u3p_setmsk(u3phy->sif_base, U3P_IP_PW_CTRL0, CTRL0_IP_SW_RST);
++      u3p_clrmsk(u3phy->sif_base, U3P_IP_PW_CTRL0, CTRL0_IP_SW_RST);
++
++      ret = u3phy_ports_enable(u3phy);
++      if (ret) {
++              dev_err(u3phy->dev, "failed to enable ports\n");
++              goto port_err;
++      }
++      u3phy_timing_init(u3phy);
++      phy_index_power_on(u3phy, 0);
++      if (u3phy->enable_usb2_p1)
++              phy_index_power_on(u3phy, 1);
++
++      return 0;
++
++port_err:
++      u3phy_clks_disable(u3phy);
++clks_err:
++      pm_runtime_put_sync(u3phy->dev);
++pm_err:
++      regulator_disable(u3phy->vusb33);
++reg_err:
++      if (u3phy->enable_usb2_p1)
++              regulator_disable(u3phy->p1_vbus);
++reg_p1_err:
++      return ret;
++}
++
++
++static void mt65xx_u3phy_shutdown(struct usb_phy *phy)
++{
++      struct mt65xx_u3phy *u3phy;
++
++      u3phy = container_of(phy, struct mt65xx_u3phy, phy);
++      dev_dbg(u3phy->dev, "%s+\n", __func__);
++
++      phy_index_power_off(u3phy, 0);
++      if (u3phy->enable_usb2_p1) {
++              phy_index_power_off(u3phy, 1);
++              regulator_disable(u3phy->p1_vbus);
++      }
++      u3phy_clks_disable(u3phy);
++      pm_runtime_put_sync(u3phy->dev);
++      regulator_disable(u3phy->vusb33);
++}
++
++
++static int mt65xx_u3phy_suspend(struct usb_phy *x, int suspend)
++{
++      struct mt65xx_u3phy *u3phy = container_of(x, struct mt65xx_u3phy, phy);
++
++      if (suspend) {
++              mt65xx_u3phy_shutdown(&u3phy->phy);
++              return 0;
++      } else {
++              return mt65xx_u3phy_init(&u3phy->phy);
++      }
++}
++
++
++static const struct of_device_id mt65xx_u3phy_id_table[] = {
++      { .compatible = "mediatek,mt8173-u3phy",},
++      { },
++};
++MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
++
++
++static int mt65xx_u3phy_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct device_node *np = dev->of_node;
++      struct resource *mac_res;
++      struct resource *sif_res;
++      struct mt65xx_u3phy *u3phy;
++      int retval = -ENOMEM;
++
++      u3phy = devm_kzalloc(&pdev->dev, sizeof(*u3phy), GFP_KERNEL);
++      if (!u3phy)
++              goto err;
++
++      u3phy->dev = &pdev->dev;
++
++      mac_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      u3phy->mac_base = devm_ioremap_resource(dev, mac_res);
++      if (IS_ERR(u3phy->mac_base)) {
++              dev_err(dev, "failed to remap mac regs\n");
++              retval = PTR_ERR(u3phy->mac_base);
++              goto err;
++      }
++
++      sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++      u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
++      if (IS_ERR(u3phy->sif_base)) {
++              dev_err(dev, "failed to remap sif regs\n");
++              retval = PTR_ERR(u3phy->sif_base);
++              goto err;
++      }
++
++      u3phy->enable_usb2_p1 = !of_property_read_bool(np, "disable-usb2-p1");
++      dev_dbg(dev, "enable_usb2_p1 - %d\n", u3phy->enable_usb2_p1);
++
++      u3phy->sys_mac = devm_clk_get(u3phy->dev, "sys_mac");
++      if (IS_ERR(u3phy->sys_mac)) {
++              dev_err(dev, "error to get sys_mac\n");
++              retval = PTR_ERR(u3phy->sys_mac);
++              goto err;
++      }
++
++      u3phy->u3phya_ref = devm_clk_get(u3phy->dev, "u3phya_ref");
++      if (IS_ERR(u3phy->u3phya_ref)) {
++              dev_err(dev, "error to get u3phya_ref\n");
++              retval = PTR_ERR(u3phy->u3phya_ref);
++              goto err;
++      }
++
++      u3phy->wk_deb_p0 = devm_clk_get(u3phy->dev, "wakeup_deb_p0");
++      if (IS_ERR(u3phy->wk_deb_p0)) {
++              dev_err(dev, "error to get wakeup_deb_p0\n");
++              retval = PTR_ERR(u3phy->wk_deb_p0);
++              goto err;
++      }
++
++      if (u3phy->enable_usb2_p1) {
++              u3phy->wk_deb_p1 = devm_clk_get(u3phy->dev, "wakeup_deb_p1");
++              if (IS_ERR(u3phy->wk_deb_p1)) {
++                      dev_err(dev, "error to get wakeup_deb_p1\n");
++                      retval = PTR_ERR(u3phy->wk_deb_p1);
++                      goto err;
++              }
++
++              u3phy->p1_vbus = devm_regulator_get(u3phy->dev, "reg-p1-vbus");
++              if (IS_ERR_OR_NULL(u3phy->p1_vbus)) {
++                      dev_err(dev, "fail to get p1-vbus\n");
++                      retval = PTR_ERR(u3phy->p1_vbus);
++                      goto err;
++              }
++      }
++
++      u3phy->vusb33 = devm_regulator_get(u3phy->dev, "reg-vusb33");
++      if (IS_ERR_OR_NULL(u3phy->vusb33)) {
++              dev_err(dev, "fail to get vusb33\n");
++              retval = PTR_ERR(u3phy->vusb33);
++              goto err;
++      }
++
++      pm_runtime_enable(dev);
++      u3phy->phy.dev = u3phy->dev;
++      u3phy->phy.label = "mt65xx-usb3phy";
++      u3phy->phy.type = USB_PHY_TYPE_USB3;
++      u3phy->phy.init = mt65xx_u3phy_init;
++      u3phy->phy.shutdown = mt65xx_u3phy_shutdown;
++      u3phy->phy.set_suspend = mt65xx_u3phy_suspend;
++
++      platform_set_drvdata(pdev, u3phy);
++      retval = usb_add_phy_dev(&u3phy->phy);
++      if (retval) {
++              dev_err(dev, "failed to add phy\n");
++              goto add_phy_err;
++      }
++
++      return 0;
++
++add_phy_err:
++      pm_runtime_disable(dev);
++err:
++      return retval;
++}
++
++static int mt65xx_u3phy_remove(struct platform_device *pdev)
++{
++      struct mt65xx_u3phy *u3phy = platform_get_drvdata(pdev);
++
++      mt65xx_u3phy_shutdown(&u3phy->phy);
++      pm_runtime_disable(&pdev->dev);
++      usb_remove_phy(&u3phy->phy);
++
++      return 0;
++}
++
++static struct platform_driver mt65xx_u3phy_driver = {
++      .probe          = mt65xx_u3phy_probe,
++      .remove         = mt65xx_u3phy_remove,
++      .driver         = {
++              .name   = "mt65xx-u3phy",
++              .of_match_table = mt65xx_u3phy_id_table,
++      },
++};
++
++module_platform_driver(mt65xx_u3phy_driver);
++
++MODULE_DESCRIPTION("Mt65xx USB PHY driver");
++MODULE_LICENSE("GPL v2");
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0047-xhci-mediatek-support-MTK-xHCI-host-controller.patch b/target/linux/mediatek/patches/0047-xhci-mediatek-support-MTK-xHCI-host-controller.patch
new file mode 100644 (file)
index 0000000..ea3289e
--- /dev/null
@@ -0,0 +1,832 @@
+From e604b6c864f2e3b6fe0706c4bef886533d92f67a Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Wed, 27 May 2015 19:48:02 +0800
+Subject: [PATCH 47/76] xhci: mediatek: support MTK xHCI host controller
+
+MTK xhci host controller defines some extra SW scheduling
+parameters for HW to minimize the scheduling effort for
+synchronous and interrupt endpoints. The parameters are
+put into reseved DWs of slot context and endpoint context.
+
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+---
+ drivers/usb/host/Kconfig     |    9 +
+ drivers/usb/host/Makefile    |    3 +
+ drivers/usb/host/xhci-mtk.c  |  470 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/xhci-mtk.h  |  119 +++++++++++
+ drivers/usb/host/xhci-plat.c |   22 +-
+ drivers/usb/host/xhci-ring.c |   35 +++-
+ drivers/usb/host/xhci.c      |   16 +-
+ drivers/usb/host/xhci.h      |    1 +
+ 8 files changed, 667 insertions(+), 8 deletions(-)
+ create mode 100644 drivers/usb/host/xhci-mtk.c
+ create mode 100644 drivers/usb/host/xhci-mtk.h
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -41,6 +41,15 @@
+         If unsure, say N.
++config USB_XHCI_MTK
++      tristate "xHCI support for Mediatek MT65xx"
++      select USB_XHCI_PLATFORM
++      depends on ARCH_MEDIATEK || COMPILE_TEST
++      ---help---
++        Say 'Y' to enable the support for the xHCI host controller
++        found in Mediatek MT65xx SoCs.
++        If unsure, say N.
++
+ config USB_XHCI_MVEBU
+       tristate "xHCI support for Marvell Armada 375/38x"
+       select USB_XHCI_PLATFORM
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -15,6 +15,9 @@
+ xhci-hcd-y += xhci-trace.o
+ xhci-plat-hcd-y := xhci-plat.o
++ifneq ($(CONFIG_USB_XHCI_MTK), )
++      xhci-plat-hcd-y         += xhci-mtk.o
++endif
+ ifneq ($(CONFIG_USB_XHCI_MVEBU), )
+       xhci-plat-hcd-y         += xhci-mvebu.o
+ endif
+--- /dev/null
++++ b/drivers/usb/host/xhci-mtk.c
+@@ -0,0 +1,470 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author:
++ *  Zhigang.Wei <zhigang.wei@mediatek.com>
++ *  Chunfeng.Yun <chunfeng.yun@mediatek.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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/kernel.h>
++#include <linux/slab.h>
++#include "xhci-mtk.h"
++
++
++#define SS_BW_BOUNDARY        51000
++/* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
++#define HS_BW_BOUNDARY        6144
++/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
++#define FS_PAYLOAD_MAX 188
++
++/* mtk scheduler bitmasks */
++#define EP_BPKTS(p)   ((p) & 0x3f)
++#define EP_BCSCOUNT(p)        (((p) & 0x7) << 8)
++#define EP_BBM(p)     ((p) << 11)
++#define EP_BOFFSET(p) ((p) & 0x3fff)
++#define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
++
++static int is_fs_or_ls(enum usb_device_speed speed)
++{
++      return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
++}
++
++static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev,
++      struct usb_host_endpoint *ep)
++{
++      int bw_index;
++      int port_id;
++      struct xhci_virt_device *virt_dev;
++
++      virt_dev = xhci->devs[udev->slot_id];
++      port_id = virt_dev->real_port;
++
++      if (udev->speed == USB_SPEED_SUPER) {
++              if (usb_endpoint_dir_out(&ep->desc))
++                      bw_index = (port_id - 1) * 2;
++              else
++                      bw_index = (port_id - 1) * 2 + 1;
++      } else {
++              bw_index = port_id + xhci->num_usb3_ports - 1;
++      }
++
++      return bw_index;
++}
++
++
++static void setup_sch_info(struct usb_device *udev,
++              struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)
++{
++      u32 ep_type;
++      u32 ep_interval;
++      u32 max_packet_size;
++      u32 max_burst;
++      u32 mult;
++      u32 esit_pkts;
++
++      ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
++      ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
++      max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
++      max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
++      mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
++      pr_debug("%s: max_burst = %d, mult = %d\n", __func__, max_burst, mult);
++
++      sch_ep->ep_type = ep_type;
++      sch_ep->max_packet_size = max_packet_size;
++      sch_ep->esit = 1 << ep_interval;
++      sch_ep->offset = 0;
++      sch_ep->burst_mode = 0;
++
++      if (udev->speed == USB_SPEED_HIGH) {
++              sch_ep->cs_count = 0;
++              /*
++               * usb_20 spec section5.9
++               * a single microframe is enough for HS synchromous endpoints
++               * in a interval
++               */
++              sch_ep->num_budget_microframes = 1;
++              sch_ep->repeat = 0;
++              /*
++               * xHCI spec section6.2.3.4
++               * @max_busrt is the number of additional transactions opportunities
++               * per microframe
++               */
++              sch_ep->pkts = max_burst + 1;
++              sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts;
++      } else if (udev->speed == USB_SPEED_SUPER) {
++              /* usb3_r1 spec section4.4.7 & 4.4.8 */
++              sch_ep->cs_count = 0;
++              esit_pkts = (mult + 1) * (max_burst + 1);
++              if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
++                      sch_ep->pkts = esit_pkts;
++                      sch_ep->num_budget_microframes = 1;
++                      sch_ep->repeat = 0;
++              }
++
++              if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
++                      if (esit_pkts <= sch_ep->esit)
++                              sch_ep->pkts = 1;
++                      else
++                              sch_ep->pkts = roundup_pow_of_two(esit_pkts)
++                                      / sch_ep->esit;
++
++                      sch_ep->num_budget_microframes =
++                              DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
++
++                      if (sch_ep->num_budget_microframes > 1)
++                              sch_ep->repeat = 1;
++                      else
++                              sch_ep->repeat = 0;
++              }
++              sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts;
++      } else if (is_fs_or_ls(udev->speed)) {
++              /*
++               * usb_20 spec section11.18.4
++               * assume worst cases
++               */
++              sch_ep->repeat = 0;
++              sch_ep->pkts = 1; /* at most one packet for each microframe */
++              if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
++                      sch_ep->cs_count = 3; /* at most need 3 CS*/
++                      /* one for SS and one for budgeted transaction */
++                      sch_ep->num_budget_microframes = sch_ep->cs_count + 2;
++                      sch_ep->bw_cost_per_microframe = max_packet_size;
++              }
++              if (ep_type == ISOC_OUT_EP) {
++                      /* must never schedule a cs ISOC OUT ep */
++                      sch_ep->cs_count = 0;
++                      /*
++                       * the best case FS budget assumes that 188 FS bytes
++                       * occur in each microframe
++                       */
++                      sch_ep->num_budget_microframes = DIV_ROUND_UP(
++                              sch_ep->max_packet_size, FS_PAYLOAD_MAX);
++                      sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX;
++              }
++              if (ep_type == ISOC_IN_EP) {
++                      /* at most need additional two CS. */
++                      sch_ep->cs_count = DIV_ROUND_UP(
++                              sch_ep->max_packet_size, FS_PAYLOAD_MAX) + 2;
++                      sch_ep->num_budget_microframes = sch_ep->cs_count + 2;
++                      sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX;
++              }
++      }
++}
++
++/* Get maximum bandwidth when we schedule at offset slot. */
++static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
++      struct mu3h_sch_ep_info *sch_ep, u32 offset)
++{
++      u32 num_esit;
++      u32 max_bw = 0;
++      int i;
++      int j;
++
++      num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
++      for (i = 0; i < num_esit; i++) {
++              u32 base = offset + i * sch_ep->esit;
++
++              for (j = 0; j < sch_ep->num_budget_microframes; j++) {
++                      if (sch_bw->bus_bw[base + j] > max_bw)
++                              max_bw = sch_bw->bus_bw[base + j];
++              }
++      }
++      return max_bw;
++}
++
++static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
++      struct mu3h_sch_ep_info *sch_ep, int bw_cost)
++{
++      u32 num_esit;
++      u32 base;
++      int i;
++      int j;
++
++      num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
++      for (i = 0; i < num_esit; i++) {
++              base = sch_ep->offset + i * sch_ep->esit;
++              for (j = 0; j < sch_ep->num_budget_microframes; j++)
++                      sch_bw->bus_bw[base + j] += bw_cost;
++      }
++
++}
++
++static void debug_sch_ep(struct mu3h_sch_ep_info *sch_ep)
++{
++      pr_debug("sch_ep->ep_type = %d\n", sch_ep->ep_type);
++      pr_debug("sch_ep->max_packet_size = %d\n", sch_ep->max_packet_size);
++      pr_debug("sch_ep->esit = %d\n", sch_ep->esit);
++      pr_debug("sch_ep->num_budget_microframes = %d\n",
++                      sch_ep->num_budget_microframes);
++      pr_debug("sch_ep->bw_cost_per_microframe = %d\n",
++                      sch_ep->bw_cost_per_microframe);
++      pr_debug("sch_ep->ep = %p\n", sch_ep->ep);
++      pr_debug("sch_ep->offset = %d\n", sch_ep->offset);
++      pr_debug("sch_ep->repeat = %d\n", sch_ep->repeat);
++      pr_debug("sch_ep->pkts = %d\n", sch_ep->pkts);
++      pr_debug("sch_ep->cs_count = %d\n", sch_ep->cs_count);
++}
++
++static int check_sch_bw(struct usb_device *udev,
++      struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
++{
++      u32 offset;
++      u32 esit;
++      u32 num_budget_microframes;
++      u32 min_bw;
++      u32 min_index;
++      u32 worst_bw;
++      u32 bw_boundary;
++
++      if (sch_ep->esit > XHCI_MTK_MAX_ESIT)
++              sch_ep->esit = XHCI_MTK_MAX_ESIT;
++
++      esit = sch_ep->esit;
++      num_budget_microframes = sch_ep->num_budget_microframes;
++
++      /*
++       * Search through all possible schedule microframes.
++       * and find a microframe where its worst bandwidth is minimum.
++       */
++      min_bw = ~0;
++      min_index = 0;
++      for (offset = 0; offset < esit; offset++) {
++              if ((offset + num_budget_microframes) > sch_ep->esit)
++                      break;
++              /*
++               * usb_20 spec section11.18:
++               * must never schedule Start-Split in Y6
++               */
++              if (is_fs_or_ls(udev->speed) && (offset % 8 == 6))
++                      continue;
++
++              worst_bw = get_max_bw(sch_bw, sch_ep, offset);
++              if (min_bw > worst_bw) {
++                      min_bw = worst_bw;
++                      min_index = offset;
++              }
++              if (min_bw == 0)
++                      break;
++      }
++      sch_ep->offset = min_index;
++
++      debug_sch_ep(sch_ep);
++
++      bw_boundary = (udev->speed == USB_SPEED_SUPER)
++                              ? SS_BW_BOUNDARY : HS_BW_BOUNDARY;
++
++      /* check bandwidth */
++      if (min_bw + sch_ep->bw_cost_per_microframe > bw_boundary)
++              return -1;
++
++      /* update bus bandwidth info */
++      update_bus_bw(sch_bw, sch_ep, sch_ep->bw_cost_per_microframe);
++
++      return 0;
++}
++
++static void debug_sch_bw(struct mu3h_sch_bw_info *sch_bw)
++{
++      int i;
++
++      pr_debug("xhci_mtk_scheduler :bus_bw_info\n");
++      for (i = 0; i < XHCI_MTK_MAX_ESIT; i++)
++              pr_debug("%d  ", sch_bw->bus_bw[i]);
++
++      pr_debug("\n");
++}
++
++
++static int need_bw_sch(struct usb_host_endpoint *ep,
++      enum usb_device_speed speed, int has_tt)
++{
++      /* only for synchronous endpoints */
++      if (usb_endpoint_xfer_control(&ep->desc)
++              || usb_endpoint_xfer_bulk(&ep->desc))
++              return 0;
++      /*
++       * for LS & FS synchronous endpoints which its device don't attach
++       * to TT are also ignored, root-hub will schedule them directly
++       */
++      if (is_fs_or_ls(speed) && !has_tt)
++              return 0;
++
++      return 1;
++}
++
++int xhci_mtk_init_quirk(struct xhci_hcd *xhci)
++{
++      struct usb_hcd *hcd = xhci_to_hcd(xhci);
++      struct device *dev = hcd->self.controller;
++      struct mu3h_sch_bw_info *sch_array;
++      size_t array_size;
++      int num_usb_bus;
++      int i;
++
++      /* ss IN and OUT are separated */
++      num_usb_bus = xhci->num_usb3_ports * 2 + xhci->num_usb2_ports;
++      array_size = sizeof(*sch_array) * num_usb_bus;
++
++      sch_array = kzalloc(array_size, GFP_KERNEL);
++      if (sch_array == NULL)
++              return -ENOMEM;
++
++      for (i = 0; i < num_usb_bus; i++)
++              INIT_LIST_HEAD(&sch_array[i].bw_ep_list);
++
++      dev->platform_data = sch_array;
++      xhci->quirks |= XHCI_MTK_HOST;
++      /*
++       * MTK host controller gives a spurious successful event after a
++       * short transfer. Ignore it.
++       */
++      xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
++
++      return 0;
++}
++
++
++void xhci_mtk_exit_quirk(struct xhci_hcd *xhci)
++{
++      struct usb_hcd *hcd = xhci_to_hcd(xhci);
++      struct mu3h_sch_bw_info *sch_array;
++
++      sch_array = dev_get_platdata(hcd->self.controller);
++      kfree(sch_array);
++}
++
++
++int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++              struct usb_host_endpoint *ep)
++{
++      int ret = 0;
++      int port_id;
++      int bw_index;
++      struct xhci_hcd *xhci;
++      unsigned int ep_index;
++      struct xhci_ep_ctx *ep_ctx;
++      struct xhci_slot_ctx *slot_ctx;
++      struct xhci_virt_device *virt_dev;
++      struct mu3h_sch_bw_info *sch_bw;
++      struct mu3h_sch_ep_info *sch_ep;
++      struct mu3h_sch_bw_info *sch_array;
++
++      xhci = hcd_to_xhci(hcd);
++      virt_dev = xhci->devs[udev->slot_id];
++      ep_index = xhci_get_endpoint_index(&ep->desc);
++      slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
++      ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
++      sch_array = dev_get_platdata(hcd->self.controller);
++
++      port_id = virt_dev->real_port;
++      xhci_dbg(xhci, "%s() xfer_type: %d, speed:%d, ep:%p\n", __func__,
++              usb_endpoint_type(&ep->desc), udev->speed, ep);
++
++      if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))
++              return 0;
++
++      bw_index = get_bw_index(xhci, udev, ep);
++      sch_bw = &sch_array[bw_index];
++
++      sch_ep = kzalloc(sizeof(struct mu3h_sch_ep_info), GFP_KERNEL);
++      if (!sch_ep)
++              return -ENOMEM;
++
++      setup_sch_info(udev, ep_ctx, sch_ep);
++
++      ret = check_sch_bw(udev, sch_bw, sch_ep);
++      if (ret) {
++              xhci_err(xhci, "Not enough bandwidth!\n");
++              kfree(sch_ep);
++              return -ENOSPC;
++      }
++
++      list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
++      sch_ep->ep = ep;
++
++      ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
++              | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode));
++      ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
++              | EP_BREPEAT(sch_ep->repeat));
++
++      debug_sch_bw(sch_bw);
++      return 0;
++}
++
++void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++              struct usb_host_endpoint *ep)
++{
++      int bw_index;
++      struct xhci_hcd *xhci;
++      struct xhci_slot_ctx *slot_ctx;
++      struct xhci_virt_device *virt_dev;
++      struct mu3h_sch_bw_info *sch_array;
++      struct mu3h_sch_bw_info *sch_bw;
++      struct mu3h_sch_ep_info *sch_ep;
++
++      xhci = hcd_to_xhci(hcd);
++      virt_dev = xhci->devs[udev->slot_id];
++      slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
++      sch_array = dev_get_platdata(hcd->self.controller);
++
++      xhci_dbg(xhci, "%s() xfer_type: %d, speed:%d, ep:%p\n", __func__,
++              usb_endpoint_type(&ep->desc), udev->speed, ep);
++
++      if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))
++              return;
++
++      bw_index = get_bw_index(xhci, udev, ep);
++      sch_bw = &sch_array[bw_index];
++
++      list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) {
++              if (sch_ep->ep == ep) {
++                      update_bus_bw(sch_bw, sch_ep,
++                              -sch_ep->bw_cost_per_microframe);
++                      list_del(&sch_ep->endpoint);
++                      kfree(sch_ep);
++                      break;
++              }
++      }
++      debug_sch_bw(sch_bw);
++}
++
++
++/*
++ * The TD size is the number of bytes remaining in the TD (including this TRB),
++ * right shifted by 10.
++ * It must fit in bits 21:17, so it can't be bigger than 31.
++ */
++u32 xhci_mtk_td_remainder_quirk(unsigned int td_running_total,
++      unsigned trb_buffer_length, struct urb *urb)
++{
++      u32 max = 31;
++      int remainder, td_packet_count, packet_transferred;
++      unsigned int td_transfer_size = urb->transfer_buffer_length;
++      unsigned int maxp;
++
++      maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
++
++      /* 0 for the last TRB */
++      if (td_running_total + trb_buffer_length == td_transfer_size)
++              return 0;
++
++      packet_transferred = td_running_total / maxp;
++      td_packet_count = DIV_ROUND_UP(td_transfer_size, maxp);
++      remainder = td_packet_count - packet_transferred;
++
++      if (remainder > max)
++              return max << 17;
++      else
++              return remainder << 17;
++}
++
++
+--- /dev/null
++++ b/drivers/usb/host/xhci-mtk.h
+@@ -0,0 +1,119 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author:
++ *  Zhigang.Wun <zhigang.wei@mediatek.com>
++ *  Chunfeng.Yun <chunfeng.yun@mediatek.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * 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 _XHCI_MTK_H_
++#define _XHCI_MTK_H_
++
++#include "xhci.h"
++
++/**
++ * To simplify scheduler algorithm, set a upper limit for ESIT,
++ * if a synchromous ep's ESIT is larger than @XHCI_MTK_MAX_ESIT,
++ * round down to the limit value, that means allocating more
++ * bandwidth to it.
++ */
++#define XHCI_MTK_MAX_ESIT     64
++
++/**
++ * struct mu3h_sch_bw_info
++ * @bus_bw: array to keep track of bandwidth already used at each uframes
++ * @bw_ep_list: eps in the bandwidth domain
++ *
++ * treat a HS root port as a bandwidth domain, but treat a SS root port as
++ * two bandwidth domains, one for IN eps and another for OUT eps.
++ */
++struct mu3h_sch_bw_info {
++      u32 bus_bw[XHCI_MTK_MAX_ESIT];
++      struct list_head bw_ep_list;
++};
++
++/**
++ * struct mu3h_sch_ep_info
++ * @esit: unit is 125us, equal to 2 << Interval field in ep-context
++ * @num_budget_microframes: number of continuous uframes
++ *            (@repeat==1) scheduled within the interval
++ * @ep: address of usb_host_endpoint
++ * @offset: which uframe of the interval that transfer should be
++ *            scheduled first time within the interval
++ * @repeat: the time gap between two uframes that transfers are
++ *            scheduled within a interval. in the simple algorithm, only
++ *            assign 0 or 1 to it; 0 means using only one uframe in a
++ *            interval, and1 means using @num_budget_microframes
++ *            continuous uframes
++ * @pkts: number of packets to be transferred in the scheduled uframes
++ * @cs_count: number of CS that host will trigger
++ */
++struct mu3h_sch_ep_info {
++      u32 ep_type;
++      u32 max_packet_size;
++      u32 esit;
++      u32 num_budget_microframes;
++      u32 bw_cost_per_microframe;
++      void *ep;
++      struct list_head endpoint;
++
++      /* mtk xhci scheduling info */
++      u32 offset;
++      u32 repeat;
++      u32 pkts;
++      u32 cs_count;
++      u32 burst_mode;
++};
++
++
++#if IS_ENABLED(CONFIG_USB_XHCI_MTK)
++
++int xhci_mtk_init_quirk(struct xhci_hcd *xhci);
++void xhci_mtk_exit_quirk(struct xhci_hcd *xhci);
++int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++              struct usb_host_endpoint *ep);
++void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
++              struct usb_host_endpoint *ep);
++u32 xhci_mtk_td_remainder_quirk(unsigned int td_running_total,
++      unsigned trb_buffer_length, struct urb *urb);
++
++#else
++static inline int xhci_mtk_init_quirk(struct xhci_hcd *xhci)
++{
++      return 0;
++}
++
++static inline void xhci_mtk_exit_quirk(struct xhci_hcd *xhci)
++{
++}
++
++static inline int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd,
++      struct usb_device *udev, struct usb_host_endpoint *ep)
++{
++      return 0;
++}
++
++static inline void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd,
++      struct usb_device *udev, struct usb_host_endpoint *ep)
++{
++      return 0;
++}
++
++static inline u32 xhci_mtk_td_remainder_quirk(unsigned int td_running_total,
++      unsigned trb_buffer_length, struct urb *urb)
++{
++      return 0;
++}
++
++#endif
++
++#endif                /* _XHCI_MTK_H_ */
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -23,6 +23,7 @@
+ #include "xhci.h"
+ #include "xhci-mvebu.h"
+ #include "xhci-rcar.h"
++#include "xhci-mtk.h"
+ static struct hc_driver __read_mostly xhci_plat_hc_driver;
+@@ -49,7 +50,23 @@
+                       return ret;
+       }
+-      return xhci_gen_setup(hcd, xhci_plat_quirks);
++      ret = xhci_gen_setup(hcd, xhci_plat_quirks);
++      if (ret)
++              return ret;
++
++      if (of_device_is_compatible(of_node, "mediatek,mt8173-xhci")) {
++              struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++
++              if (!usb_hcd_is_primary_hcd(hcd))
++                      return 0;
++              ret = xhci_mtk_init_quirk(xhci);
++              if (ret) {
++                      kfree(xhci);
++                      return ret;
++              }
++      }
++
++      return ret;
+ }
+ static int xhci_plat_start(struct usb_hcd *hcd)
+@@ -207,6 +224,8 @@
+       if (!IS_ERR(clk))
+               clk_disable_unprepare(clk);
+       usb_put_hcd(hcd);
++      if (xhci->quirks & XHCI_MTK_HOST)
++              xhci_mtk_exit_quirk(xhci);
+       kfree(xhci);
+       return 0;
+@@ -253,6 +272,7 @@
+       { .compatible = "marvell,armada-380-xhci"},
+       { .compatible = "renesas,xhci-r8a7790"},
+       { .compatible = "renesas,xhci-r8a7791"},
++      { .compatible = "mediatek,mt8173-xhci"},
+       { },
+ };
+ MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -68,6 +68,7 @@
+ #include <linux/slab.h>
+ #include "xhci.h"
+ #include "xhci-trace.h"
++#include "xhci-mtk.h"
+ /*
+  * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
+@@ -3163,9 +3164,14 @@
+               /* Set the TRB length, TD size, and interrupter fields. */
+               if (xhci->hci_version < 0x100) {
+-                      remainder = xhci_td_remainder(
++                      if (xhci->quirks & XHCI_MTK_HOST) {
++                              remainder = xhci_mtk_td_remainder_quirk(
++                                      running_total, trb_buff_len, urb);
++                      } else {
++                              remainder = xhci_td_remainder(
+                                       urb->transfer_buffer_length -
+                                       running_total);
++                      }
+               } else {
+                       remainder = xhci_v1_0_td_remainder(running_total,
+                                       trb_buff_len, total_packet_count, urb,
+@@ -3336,9 +3342,14 @@
+               /* Set the TRB length, TD size, and interrupter fields. */
+               if (xhci->hci_version < 0x100) {
+-                      remainder = xhci_td_remainder(
++                      if (xhci->quirks & XHCI_MTK_HOST) {
++                              remainder = xhci_mtk_td_remainder_quirk(
++                                      running_total, trb_buff_len, urb);
++                      } else {
++                              remainder = xhci_td_remainder(
+                                       urb->transfer_buffer_length -
+                                       running_total);
++                      }
+               } else {
+                       remainder = xhci_v1_0_td_remainder(running_total,
+                                       trb_buff_len, total_packet_count, urb,
+@@ -3457,8 +3468,14 @@
+               field = TRB_TYPE(TRB_DATA);
+       length_field = TRB_LEN(urb->transfer_buffer_length) |
+-              xhci_td_remainder(urb->transfer_buffer_length) |
+               TRB_INTR_TARGET(0);
++
++      if (xhci->quirks & XHCI_MTK_HOST)
++              length_field |= xhci_mtk_td_remainder_quirk(0,
++                              urb->transfer_buffer_length, urb);
++      else
++              length_field |= xhci_td_remainder(urb->transfer_buffer_length);
++
+       if (urb->transfer_buffer_length > 0) {
+               if (setup->bRequestType & USB_DIR_IN)
+                       field |= TRB_DIR_IN;
+@@ -3682,8 +3699,14 @@
+                       /* Set the TRB length, TD size, & interrupter fields. */
+                       if (xhci->hci_version < 0x100) {
+-                              remainder = xhci_td_remainder(
+-                                              td_len - running_total);
++                              if (xhci->quirks & XHCI_MTK_HOST) {
++                                      remainder = xhci_mtk_td_remainder_quirk(
++                                              running_total, trb_buff_len,
++                                              urb);
++                              } else {
++                                      remainder = xhci_td_remainder(
++                                                      td_len - running_total);
++                              }
+                       } else {
+                               remainder = xhci_v1_0_td_remainder(
+                                               running_total, trb_buff_len,
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -31,6 +31,7 @@
+ #include "xhci.h"
+ #include "xhci-trace.h"
++#include "xhci-mtk.h"
+ #define DRIVER_AUTHOR "Sarah Sharp"
+ #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
+@@ -624,7 +625,11 @@
+                       "// Set the interrupt modulation register");
+       temp = readl(&xhci->ir_set->irq_control);
+       temp &= ~ER_IRQ_INTERVAL_MASK;
+-      temp |= (u32) 160;
++      /*
++       * 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);
+       writel(temp, &xhci->ir_set->irq_control);
+       /* Set the HCD state before we enable the irqs */
+@@ -1698,6 +1703,9 @@
+       xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
++      if (xhci->quirks & XHCI_MTK_HOST)
++              xhci_mtk_drop_ep_quirk(hcd, udev, ep);
++
+       xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
+                       (unsigned int) ep->desc.bEndpointAddress,
+                       udev->slot_id,
+@@ -1793,6 +1801,12 @@
+               return -ENOMEM;
+       }
++      if (xhci->quirks & XHCI_MTK_HOST) {
++              ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);
++              if (ret < 0)
++                      return ret;
++      }
++
+       ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
+       new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1568,6 +1568,7 @@
+ /* For controllers with a broken beyond repair streams implementation */
+ #define XHCI_BROKEN_STREAMS   (1 << 19)
+ #define XHCI_PME_STUCK_QUIRK  (1 << 20)
++#define XHCI_MTK_HOST         (1 << 21)
+       unsigned int            num_active_eps;
+       unsigned int            limit_active_eps;
+       /* There are two roothubs to keep track of bus suspend info for */
diff --git a/target/linux/mediatek/patches/0048-dt-bindings-mediatek-Modify-pinctrl-bindings-for-mt6.patch b/target/linux/mediatek/patches/0048-dt-bindings-mediatek-Modify-pinctrl-bindings-for-mt6.patch
new file mode 100644 (file)
index 0000000..40303c0
--- /dev/null
@@ -0,0 +1,46 @@
+From 69b78182d6d7777153323abe3cff8e533ca01143 Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:12 -0700
+Subject: [PATCH 48/76] dt-bindings: mediatek: Modify pinctrl bindings for
+ mt6397.
+
+Since 6397 is no need to support interrupt controller,
+moving interrupt controller relate property to optional list.
+Also adding mt8173 and mt8127 to bindings.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
+index 5868a0f..0480bc3 100644
+--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
++++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
+@@ -3,9 +3,11 @@
+ The Mediatek's Pin controller is used to control SoC pins.
+ Required properties:
+-- compatible: value should be either of the following.
++- compatible: value should be one of the following.
+     (a) "mediatek,mt8135-pinctrl", compatible with mt8135 pinctrl.
+-- mediatek,pctl-regmap: Should be a phandle of the syscfg node.
++    (b) "mediatek,mt8173-pinctrl", compatible with mt8173 pinctrl.
++    (c) "mediatek,mt6397-pinctrl", compatible with mt6397 pinctrl.
++    (d) "mediatek,mt8127-pinctrl", compatible with mt8127 pinctrl.
+ - pins-are-numbered: Specify the subnodes are using numbered pinmux to
+   specify pins.
+ - gpio-controller : Marks the device node as a gpio controller.
+@@ -24,6 +26,9 @@ Required properties:
+             Only the following flags are supported:
+             0 - GPIO_ACTIVE_HIGH
+             1 - GPIO_ACTIVE_LOW
++
++Optional properties:
++- mediatek,pctl-regmap: Should be a phandle of the syscfg node.
+ - reg: physicall address base for EINT registers
+ - interrupt-controller: Marks the device node as an interrupt controller
+ - #interrupt-cells: Should be two.
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0049-pinctrl-dt-bindings-mt6397-Add-pinfunc-header-file-f.patch b/target/linux/mediatek/patches/0049-pinctrl-dt-bindings-mt6397-Add-pinfunc-header-file-f.patch
new file mode 100644 (file)
index 0000000..8178761
--- /dev/null
@@ -0,0 +1,279 @@
+From 54596fafa4ce2723314d0381c7c1a525bda148ef Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:13 -0700
+Subject: [PATCH 49/76] pinctrl: dt bindings: mt6397: Add pinfunc header file
+ for mt6397.
+
+Add pinfunc header file, mt8135/mt8173 relate dts will include it.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ include/dt-bindings/pinctrl/mt6397-pinfunc.h |  256 ++++++++++++++++++++++++++
+ 1 file changed, 256 insertions(+)
+ create mode 100644 include/dt-bindings/pinctrl/mt6397-pinfunc.h
+
+diff --git a/include/dt-bindings/pinctrl/mt6397-pinfunc.h b/include/dt-bindings/pinctrl/mt6397-pinfunc.h
+new file mode 100644
+index 0000000..85739b3
+--- /dev/null
++++ b/include/dt-bindings/pinctrl/mt6397-pinfunc.h
+@@ -0,0 +1,256 @@
++#ifndef __DTS_MT6397_PINFUNC_H
++#define __DTS_MT6397_PINFUNC_H
++
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#define MT6397_PIN_0_INT__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
++#define MT6397_PIN_0_INT__FUNC_INT (MTK_PIN_NO(0) | 1)
++
++#define MT6397_PIN_1_SRCVOLTEN__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
++#define MT6397_PIN_1_SRCVOLTEN__FUNC_SRCVOLTEN (MTK_PIN_NO(1) | 1)
++#define MT6397_PIN_1_SRCVOLTEN__FUNC_TEST_CK1 (MTK_PIN_NO(1) | 6)
++
++#define MT6397_PIN_2_SRCLKEN_PERI__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
++#define MT6397_PIN_2_SRCLKEN_PERI__FUNC_SRCLKEN_PERI (MTK_PIN_NO(2) | 1)
++#define MT6397_PIN_2_SRCLKEN_PERI__FUNC_TEST_CK2 (MTK_PIN_NO(2) | 6)
++
++#define MT6397_PIN_3_RTC_32K1V8__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
++#define MT6397_PIN_3_RTC_32K1V8__FUNC_RTC_32K1V8 (MTK_PIN_NO(3) | 1)
++#define MT6397_PIN_3_RTC_32K1V8__FUNC_TEST_CK3 (MTK_PIN_NO(3) | 6)
++
++#define MT6397_PIN_4_WRAP_EVENT__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
++#define MT6397_PIN_4_WRAP_EVENT__FUNC_WRAP_EVENT (MTK_PIN_NO(4) | 1)
++
++#define MT6397_PIN_5_SPI_CLK__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
++#define MT6397_PIN_5_SPI_CLK__FUNC_SPI_CLK (MTK_PIN_NO(5) | 1)
++
++#define MT6397_PIN_6_SPI_CSN__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
++#define MT6397_PIN_6_SPI_CSN__FUNC_SPI_CSN (MTK_PIN_NO(6) | 1)
++
++#define MT6397_PIN_7_SPI_MOSI__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
++#define MT6397_PIN_7_SPI_MOSI__FUNC_SPI_MOSI (MTK_PIN_NO(7) | 1)
++
++#define MT6397_PIN_8_SPI_MISO__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
++#define MT6397_PIN_8_SPI_MISO__FUNC_SPI_MISO (MTK_PIN_NO(8) | 1)
++
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_AUD_CLK (MTK_PIN_NO(9) | 1)
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_TEST_IN0 (MTK_PIN_NO(9) | 6)
++#define MT6397_PIN_9_AUD_CLK_MOSI__FUNC_TEST_OUT0 (MTK_PIN_NO(9) | 7)
++
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_AUD_MISO (MTK_PIN_NO(10) | 1)
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_TEST_IN1 (MTK_PIN_NO(10) | 6)
++#define MT6397_PIN_10_AUD_DAT_MISO__FUNC_TEST_OUT1 (MTK_PIN_NO(10) | 7)
++
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_AUD_MOSI (MTK_PIN_NO(11) | 1)
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_TEST_IN2 (MTK_PIN_NO(11) | 6)
++#define MT6397_PIN_11_AUD_DAT_MOSI__FUNC_TEST_OUT2 (MTK_PIN_NO(11) | 7)
++
++#define MT6397_PIN_12_COL0__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
++#define MT6397_PIN_12_COL0__FUNC_COL0_USBDL (MTK_PIN_NO(12) | 1)
++#define MT6397_PIN_12_COL0__FUNC_EINT10_1X (MTK_PIN_NO(12) | 2)
++#define MT6397_PIN_12_COL0__FUNC_PWM1_3X (MTK_PIN_NO(12) | 3)
++#define MT6397_PIN_12_COL0__FUNC_TEST_IN3 (MTK_PIN_NO(12) | 6)
++#define MT6397_PIN_12_COL0__FUNC_TEST_OUT3 (MTK_PIN_NO(12) | 7)
++
++#define MT6397_PIN_13_COL1__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
++#define MT6397_PIN_13_COL1__FUNC_COL1 (MTK_PIN_NO(13) | 1)
++#define MT6397_PIN_13_COL1__FUNC_EINT11_1X (MTK_PIN_NO(13) | 2)
++#define MT6397_PIN_13_COL1__FUNC_SCL0_2X (MTK_PIN_NO(13) | 3)
++#define MT6397_PIN_13_COL1__FUNC_TEST_IN4 (MTK_PIN_NO(13) | 6)
++#define MT6397_PIN_13_COL1__FUNC_TEST_OUT4 (MTK_PIN_NO(13) | 7)
++
++#define MT6397_PIN_14_COL2__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
++#define MT6397_PIN_14_COL2__FUNC_COL2 (MTK_PIN_NO(14) | 1)
++#define MT6397_PIN_14_COL2__FUNC_EINT12_1X (MTK_PIN_NO(14) | 2)
++#define MT6397_PIN_14_COL2__FUNC_SDA0_2X (MTK_PIN_NO(14) | 3)
++#define MT6397_PIN_14_COL2__FUNC_TEST_IN5 (MTK_PIN_NO(14) | 6)
++#define MT6397_PIN_14_COL2__FUNC_TEST_OUT5 (MTK_PIN_NO(14) | 7)
++
++#define MT6397_PIN_15_COL3__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
++#define MT6397_PIN_15_COL3__FUNC_COL3 (MTK_PIN_NO(15) | 1)
++#define MT6397_PIN_15_COL3__FUNC_EINT13_1X (MTK_PIN_NO(15) | 2)
++#define MT6397_PIN_15_COL3__FUNC_SCL1_2X (MTK_PIN_NO(15) | 3)
++#define MT6397_PIN_15_COL3__FUNC_TEST_IN6 (MTK_PIN_NO(15) | 6)
++#define MT6397_PIN_15_COL3__FUNC_TEST_OUT6 (MTK_PIN_NO(15) | 7)
++
++#define MT6397_PIN_16_COL4__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
++#define MT6397_PIN_16_COL4__FUNC_COL4 (MTK_PIN_NO(16) | 1)
++#define MT6397_PIN_16_COL4__FUNC_EINT14_1X (MTK_PIN_NO(16) | 2)
++#define MT6397_PIN_16_COL4__FUNC_SDA1_2X (MTK_PIN_NO(16) | 3)
++#define MT6397_PIN_16_COL4__FUNC_TEST_IN7 (MTK_PIN_NO(16) | 6)
++#define MT6397_PIN_16_COL4__FUNC_TEST_OUT7 (MTK_PIN_NO(16) | 7)
++
++#define MT6397_PIN_17_COL5__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
++#define MT6397_PIN_17_COL5__FUNC_COL5 (MTK_PIN_NO(17) | 1)
++#define MT6397_PIN_17_COL5__FUNC_EINT15_1X (MTK_PIN_NO(17) | 2)
++#define MT6397_PIN_17_COL5__FUNC_SCL2_2X (MTK_PIN_NO(17) | 3)
++#define MT6397_PIN_17_COL5__FUNC_TEST_IN8 (MTK_PIN_NO(17) | 6)
++#define MT6397_PIN_17_COL5__FUNC_TEST_OUT8 (MTK_PIN_NO(17) | 7)
++
++#define MT6397_PIN_18_COL6__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
++#define MT6397_PIN_18_COL6__FUNC_COL6 (MTK_PIN_NO(18) | 1)
++#define MT6397_PIN_18_COL6__FUNC_EINT16_1X (MTK_PIN_NO(18) | 2)
++#define MT6397_PIN_18_COL6__FUNC_SDA2_2X (MTK_PIN_NO(18) | 3)
++#define MT6397_PIN_18_COL6__FUNC_GPIO32K_0 (MTK_PIN_NO(18) | 4)
++#define MT6397_PIN_18_COL6__FUNC_GPIO26M_0 (MTK_PIN_NO(18) | 5)
++#define MT6397_PIN_18_COL6__FUNC_TEST_IN9 (MTK_PIN_NO(18) | 6)
++#define MT6397_PIN_18_COL6__FUNC_TEST_OUT9 (MTK_PIN_NO(18) | 7)
++
++#define MT6397_PIN_19_COL7__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
++#define MT6397_PIN_19_COL7__FUNC_COL7 (MTK_PIN_NO(19) | 1)
++#define MT6397_PIN_19_COL7__FUNC_EINT17_1X (MTK_PIN_NO(19) | 2)
++#define MT6397_PIN_19_COL7__FUNC_PWM2_3X (MTK_PIN_NO(19) | 3)
++#define MT6397_PIN_19_COL7__FUNC_GPIO32K_1 (MTK_PIN_NO(19) | 4)
++#define MT6397_PIN_19_COL7__FUNC_GPIO26M_1 (MTK_PIN_NO(19) | 5)
++#define MT6397_PIN_19_COL7__FUNC_TEST_IN10 (MTK_PIN_NO(19) | 6)
++#define MT6397_PIN_19_COL7__FUNC_TEST_OUT10 (MTK_PIN_NO(19) | 7)
++
++#define MT6397_PIN_20_ROW0__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
++#define MT6397_PIN_20_ROW0__FUNC_ROW0 (MTK_PIN_NO(20) | 1)
++#define MT6397_PIN_20_ROW0__FUNC_EINT18_1X (MTK_PIN_NO(20) | 2)
++#define MT6397_PIN_20_ROW0__FUNC_SCL0_3X (MTK_PIN_NO(20) | 3)
++#define MT6397_PIN_20_ROW0__FUNC_TEST_IN11 (MTK_PIN_NO(20) | 6)
++#define MT6397_PIN_20_ROW0__FUNC_TEST_OUT11 (MTK_PIN_NO(20) | 7)
++
++#define MT6397_PIN_21_ROW1__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
++#define MT6397_PIN_21_ROW1__FUNC_ROW1 (MTK_PIN_NO(21) | 1)
++#define MT6397_PIN_21_ROW1__FUNC_EINT19_1X (MTK_PIN_NO(21) | 2)
++#define MT6397_PIN_21_ROW1__FUNC_SDA0_3X (MTK_PIN_NO(21) | 3)
++#define MT6397_PIN_21_ROW1__FUNC_AUD_TSTCK (MTK_PIN_NO(21) | 4)
++#define MT6397_PIN_21_ROW1__FUNC_TEST_IN12 (MTK_PIN_NO(21) | 6)
++#define MT6397_PIN_21_ROW1__FUNC_TEST_OUT12 (MTK_PIN_NO(21) | 7)
++
++#define MT6397_PIN_22_ROW2__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
++#define MT6397_PIN_22_ROW2__FUNC_ROW2 (MTK_PIN_NO(22) | 1)
++#define MT6397_PIN_22_ROW2__FUNC_EINT20_1X (MTK_PIN_NO(22) | 2)
++#define MT6397_PIN_22_ROW2__FUNC_SCL1_3X (MTK_PIN_NO(22) | 3)
++#define MT6397_PIN_22_ROW2__FUNC_TEST_IN13 (MTK_PIN_NO(22) | 6)
++#define MT6397_PIN_22_ROW2__FUNC_TEST_OUT13 (MTK_PIN_NO(22) | 7)
++
++#define MT6397_PIN_23_ROW3__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
++#define MT6397_PIN_23_ROW3__FUNC_ROW3 (MTK_PIN_NO(23) | 1)
++#define MT6397_PIN_23_ROW3__FUNC_EINT21_1X (MTK_PIN_NO(23) | 2)
++#define MT6397_PIN_23_ROW3__FUNC_SDA1_3X (MTK_PIN_NO(23) | 3)
++#define MT6397_PIN_23_ROW3__FUNC_TEST_IN14 (MTK_PIN_NO(23) | 6)
++#define MT6397_PIN_23_ROW3__FUNC_TEST_OUT14 (MTK_PIN_NO(23) | 7)
++
++#define MT6397_PIN_24_ROW4__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
++#define MT6397_PIN_24_ROW4__FUNC_ROW4 (MTK_PIN_NO(24) | 1)
++#define MT6397_PIN_24_ROW4__FUNC_EINT22_1X (MTK_PIN_NO(24) | 2)
++#define MT6397_PIN_24_ROW4__FUNC_SCL2_3X (MTK_PIN_NO(24) | 3)
++#define MT6397_PIN_24_ROW4__FUNC_TEST_IN15 (MTK_PIN_NO(24) | 6)
++#define MT6397_PIN_24_ROW4__FUNC_TEST_OUT15 (MTK_PIN_NO(24) | 7)
++
++#define MT6397_PIN_25_ROW5__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
++#define MT6397_PIN_25_ROW5__FUNC_ROW5 (MTK_PIN_NO(25) | 1)
++#define MT6397_PIN_25_ROW5__FUNC_EINT23_1X (MTK_PIN_NO(25) | 2)
++#define MT6397_PIN_25_ROW5__FUNC_SDA2_3X (MTK_PIN_NO(25) | 3)
++#define MT6397_PIN_25_ROW5__FUNC_TEST_IN16 (MTK_PIN_NO(25) | 6)
++#define MT6397_PIN_25_ROW5__FUNC_TEST_OUT16 (MTK_PIN_NO(25) | 7)
++
++#define MT6397_PIN_26_ROW6__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
++#define MT6397_PIN_26_ROW6__FUNC_ROW6 (MTK_PIN_NO(26) | 1)
++#define MT6397_PIN_26_ROW6__FUNC_EINT24_1X (MTK_PIN_NO(26) | 2)
++#define MT6397_PIN_26_ROW6__FUNC_PWM3_3X (MTK_PIN_NO(26) | 3)
++#define MT6397_PIN_26_ROW6__FUNC_GPIO32K_2 (MTK_PIN_NO(26) | 4)
++#define MT6397_PIN_26_ROW6__FUNC_GPIO26M_2 (MTK_PIN_NO(26) | 5)
++#define MT6397_PIN_26_ROW6__FUNC_TEST_IN17 (MTK_PIN_NO(26) | 6)
++#define MT6397_PIN_26_ROW6__FUNC_TEST_OUT17 (MTK_PIN_NO(26) | 7)
++
++#define MT6397_PIN_27_ROW7__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
++#define MT6397_PIN_27_ROW7__FUNC_ROW7 (MTK_PIN_NO(27) | 1)
++#define MT6397_PIN_27_ROW7__FUNC_EINT3_1X (MTK_PIN_NO(27) | 2)
++#define MT6397_PIN_27_ROW7__FUNC_CBUS (MTK_PIN_NO(27) | 3)
++#define MT6397_PIN_27_ROW7__FUNC_GPIO32K_3 (MTK_PIN_NO(27) | 4)
++#define MT6397_PIN_27_ROW7__FUNC_GPIO26M_3 (MTK_PIN_NO(27) | 5)
++#define MT6397_PIN_27_ROW7__FUNC_TEST_IN18 (MTK_PIN_NO(27) | 6)
++#define MT6397_PIN_27_ROW7__FUNC_TEST_OUT18 (MTK_PIN_NO(27) | 7)
++
++#define MT6397_PIN_28_PWM1__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
++#define MT6397_PIN_28_PWM1__FUNC_PWM1 (MTK_PIN_NO(28) | 1)
++#define MT6397_PIN_28_PWM1__FUNC_EINT4_1X (MTK_PIN_NO(28) | 2)
++#define MT6397_PIN_28_PWM1__FUNC_GPIO32K_4 (MTK_PIN_NO(28) | 4)
++#define MT6397_PIN_28_PWM1__FUNC_GPIO26M_4 (MTK_PIN_NO(28) | 5)
++#define MT6397_PIN_28_PWM1__FUNC_TEST_IN19 (MTK_PIN_NO(28) | 6)
++#define MT6397_PIN_28_PWM1__FUNC_TEST_OUT19 (MTK_PIN_NO(28) | 7)
++
++#define MT6397_PIN_29_PWM2__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
++#define MT6397_PIN_29_PWM2__FUNC_PWM2 (MTK_PIN_NO(29) | 1)
++#define MT6397_PIN_29_PWM2__FUNC_EINT5_1X (MTK_PIN_NO(29) | 2)
++#define MT6397_PIN_29_PWM2__FUNC_GPIO32K_5 (MTK_PIN_NO(29) | 4)
++#define MT6397_PIN_29_PWM2__FUNC_GPIO26M_5 (MTK_PIN_NO(29) | 5)
++#define MT6397_PIN_29_PWM2__FUNC_TEST_IN20 (MTK_PIN_NO(29) | 6)
++#define MT6397_PIN_29_PWM2__FUNC_TEST_OUT20 (MTK_PIN_NO(29) | 7)
++
++#define MT6397_PIN_30_PWM3__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
++#define MT6397_PIN_30_PWM3__FUNC_PWM3 (MTK_PIN_NO(30) | 1)
++#define MT6397_PIN_30_PWM3__FUNC_EINT6_1X (MTK_PIN_NO(30) | 2)
++#define MT6397_PIN_30_PWM3__FUNC_COL0 (MTK_PIN_NO(30) | 3)
++#define MT6397_PIN_30_PWM3__FUNC_GPIO32K_6 (MTK_PIN_NO(30) | 4)
++#define MT6397_PIN_30_PWM3__FUNC_GPIO26M_6 (MTK_PIN_NO(30) | 5)
++#define MT6397_PIN_30_PWM3__FUNC_TEST_IN21 (MTK_PIN_NO(30) | 6)
++#define MT6397_PIN_30_PWM3__FUNC_TEST_OUT21 (MTK_PIN_NO(30) | 7)
++
++#define MT6397_PIN_31_SCL0__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
++#define MT6397_PIN_31_SCL0__FUNC_SCL0 (MTK_PIN_NO(31) | 1)
++#define MT6397_PIN_31_SCL0__FUNC_EINT7_1X (MTK_PIN_NO(31) | 2)
++#define MT6397_PIN_31_SCL0__FUNC_PWM1_2X (MTK_PIN_NO(31) | 3)
++#define MT6397_PIN_31_SCL0__FUNC_TEST_IN22 (MTK_PIN_NO(31) | 6)
++#define MT6397_PIN_31_SCL0__FUNC_TEST_OUT22 (MTK_PIN_NO(31) | 7)
++
++#define MT6397_PIN_32_SDA0__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
++#define MT6397_PIN_32_SDA0__FUNC_SDA0 (MTK_PIN_NO(32) | 1)
++#define MT6397_PIN_32_SDA0__FUNC_EINT8_1X (MTK_PIN_NO(32) | 2)
++#define MT6397_PIN_32_SDA0__FUNC_TEST_IN23 (MTK_PIN_NO(32) | 6)
++#define MT6397_PIN_32_SDA0__FUNC_TEST_OUT23 (MTK_PIN_NO(32) | 7)
++
++#define MT6397_PIN_33_SCL1__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
++#define MT6397_PIN_33_SCL1__FUNC_SCL1 (MTK_PIN_NO(33) | 1)
++#define MT6397_PIN_33_SCL1__FUNC_EINT9_1X (MTK_PIN_NO(33) | 2)
++#define MT6397_PIN_33_SCL1__FUNC_PWM2_2X (MTK_PIN_NO(33) | 3)
++#define MT6397_PIN_33_SCL1__FUNC_TEST_IN24 (MTK_PIN_NO(33) | 6)
++#define MT6397_PIN_33_SCL1__FUNC_TEST_OUT24 (MTK_PIN_NO(33) | 7)
++
++#define MT6397_PIN_34_SDA1__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
++#define MT6397_PIN_34_SDA1__FUNC_SDA1 (MTK_PIN_NO(34) | 1)
++#define MT6397_PIN_34_SDA1__FUNC_EINT0_1X (MTK_PIN_NO(34) | 2)
++#define MT6397_PIN_34_SDA1__FUNC_TEST_IN25 (MTK_PIN_NO(34) | 6)
++#define MT6397_PIN_34_SDA1__FUNC_TEST_OUT25 (MTK_PIN_NO(34) | 7)
++
++#define MT6397_PIN_35_SCL2__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
++#define MT6397_PIN_35_SCL2__FUNC_SCL2 (MTK_PIN_NO(35) | 1)
++#define MT6397_PIN_35_SCL2__FUNC_EINT1_1X (MTK_PIN_NO(35) | 2)
++#define MT6397_PIN_35_SCL2__FUNC_PWM3_2X (MTK_PIN_NO(35) | 3)
++#define MT6397_PIN_35_SCL2__FUNC_TEST_IN26 (MTK_PIN_NO(35) | 6)
++#define MT6397_PIN_35_SCL2__FUNC_TEST_OUT26 (MTK_PIN_NO(35) | 7)
++
++#define MT6397_PIN_36_SDA2__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
++#define MT6397_PIN_36_SDA2__FUNC_SDA2 (MTK_PIN_NO(36) | 1)
++#define MT6397_PIN_36_SDA2__FUNC_EINT2_1X (MTK_PIN_NO(36) | 2)
++#define MT6397_PIN_36_SDA2__FUNC_TEST_IN27 (MTK_PIN_NO(36) | 6)
++#define MT6397_PIN_36_SDA2__FUNC_TEST_OUT27 (MTK_PIN_NO(36) | 7)
++
++#define MT6397_PIN_37_HDMISD__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
++#define MT6397_PIN_37_HDMISD__FUNC_HDMISD (MTK_PIN_NO(37) | 1)
++#define MT6397_PIN_37_HDMISD__FUNC_TEST_IN28 (MTK_PIN_NO(37) | 6)
++#define MT6397_PIN_37_HDMISD__FUNC_TEST_OUT28 (MTK_PIN_NO(37) | 7)
++
++#define MT6397_PIN_38_HDMISCK__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
++#define MT6397_PIN_38_HDMISCK__FUNC_HDMISCK (MTK_PIN_NO(38) | 1)
++#define MT6397_PIN_38_HDMISCK__FUNC_TEST_IN29 (MTK_PIN_NO(38) | 6)
++#define MT6397_PIN_38_HDMISCK__FUNC_TEST_OUT29 (MTK_PIN_NO(38) | 7)
++
++#define MT6397_PIN_39_HTPLG__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
++#define MT6397_PIN_39_HTPLG__FUNC_HTPLG (MTK_PIN_NO(39) | 1)
++#define MT6397_PIN_39_HTPLG__FUNC_TEST_IN30 (MTK_PIN_NO(39) | 6)
++#define MT6397_PIN_39_HTPLG__FUNC_TEST_OUT30 (MTK_PIN_NO(39) | 7)
++
++#define MT6397_PIN_40_CEC__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
++#define MT6397_PIN_40_CEC__FUNC_CEC (MTK_PIN_NO(40) | 1)
++#define MT6397_PIN_40_CEC__FUNC_TEST_IN31 (MTK_PIN_NO(40) | 6)
++#define MT6397_PIN_40_CEC__FUNC_TEST_OUT31 (MTK_PIN_NO(40) | 7)
++
++#endif /* __DTS_MT6397_PINFUNC_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0050-pinctrl-mediatek-data-struct-optimize-and-remove-unu.patch b/target/linux/mediatek/patches/0050-pinctrl-mediatek-data-struct-optimize-and-remove-unu.patch
new file mode 100644 (file)
index 0000000..7399746
--- /dev/null
@@ -0,0 +1,116 @@
+From 3eeb897a627e26083472f14e7512f53276a5e7ce Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:14 -0700
+Subject: [PATCH 50/76] pinctrl: mediatek: data struct optimize and remove
+ unused member
+
+struct mtk_desc_pin.chip, mtk_pinctrl_devdata.invser_offset
+and mtk_pinctrl_devdata.chip_type are never used in code.
+Remove them.
+
+Some per-pin data are using int for pin number and offsets.
+Change to short and rearrange to reduce const data size.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-mt8135.c     |   10 ++++------
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h |   10 ++--------
+ 2 files changed, 6 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+index f1e1e18..8e6abd5 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+@@ -32,12 +32,12 @@
+ #define R1_BASE2                              0x250
+ struct mtk_spec_pull_set {
+-      unsigned int pin;
+-      unsigned int pupd_offset;
++      unsigned char pin;
+       unsigned char pupd_bit;
+-      unsigned int r0_offset;
++      unsigned short pupd_offset;
++      unsigned short r0_offset;
++      unsigned short r1_offset;
+       unsigned char r0_bit;
+-      unsigned int r1_offset;
+       unsigned char r1_bit;
+ };
+@@ -305,7 +305,6 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
+       .pullen_offset = 0x0200,
+       .smt_offset = 0x0300,
+       .pullsel_offset = 0x0400,
+-      .invser_offset = 0x0600,
+       .dout_offset = 0x0800,
+       .din_offset = 0x0A00,
+       .pinmux_offset = 0x0C00,
+@@ -314,7 +313,6 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
+       .port_shf = 4,
+       .port_mask = 0xf,
+       .port_align = 4,
+-      .chip_type = MTK_CHIP_TYPE_BASE,
+       .eint_offsets = {
+               .name = "mt8135_eint",
+               .stat      = 0x000,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index 375771d..1508849 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -19,8 +19,6 @@
+ #include <linux/regmap.h>
+ #define NO_EINT_SUPPORT    255
+-#define MTK_CHIP_TYPE_BASE     0
+-#define MTK_CHIP_TYPE_PMIC     1
+ #define MT_EDGE_SENSITIVE           0
+ #define MT_LEVEL_SENSITIVE          1
+ #define EINT_DBNC_SET_DBNC_BITS     4
+@@ -39,7 +37,6 @@ struct mtk_desc_eint {
+ struct mtk_desc_pin {
+       struct pinctrl_pin_desc pin;
+-      const char *chip;
+       const struct mtk_desc_eint eint;
+       const struct mtk_desc_function  *functions;
+ };
+@@ -47,7 +44,6 @@ struct mtk_desc_pin {
+ #define MTK_PIN(_pin, _pad, _chip, _eint, ...)                \
+       {                                                       \
+               .pin = _pin,                                    \
+-              .chip = _chip,                                  \
+               .eint = _eint,                                  \
+               .functions = (struct mtk_desc_function[]){      \
+                       __VA_ARGS__, { } },                     \
+@@ -107,8 +103,8 @@ struct mtk_drv_group_desc {
+  * @grp: The group for this pin belongs to.
+  */
+ struct mtk_pin_drv_grp {
+-      unsigned int pin;
+-      unsigned int offset;
++      unsigned short pin;
++      unsigned short offset;
+       unsigned char bit;
+       unsigned char grp;
+ };
+@@ -193,7 +189,6 @@ struct mtk_pinctrl_devdata {
+       unsigned int pullen_offset;
+       unsigned int pullsel_offset;
+       unsigned int drv_offset;
+-      unsigned int invser_offset;
+       unsigned int dout_offset;
+       unsigned int din_offset;
+       unsigned int pinmux_offset;
+@@ -202,7 +197,6 @@ struct mtk_pinctrl_devdata {
+       unsigned char  port_shf;
+       unsigned char  port_mask;
+       unsigned char  port_align;
+-      unsigned char   chip_type;
+       struct mtk_eint_offsets eint_offsets;
+       unsigned int    ap_num;
+       unsigned int    db_cnt;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0051-pinctrl-mediatek-add-mtk_pctrl_spec_pull_set_samereg.patch b/target/linux/mediatek/patches/0051-pinctrl-mediatek-add-mtk_pctrl_spec_pull_set_samereg.patch
new file mode 100644 (file)
index 0000000..2e9eb60
--- /dev/null
@@ -0,0 +1,328 @@
+From aefbeb75a32e080445d72ddd4b9ab28c258597d0 Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:15 -0700
+Subject: [PATCH 51/76] pinctrl: mediatek: add mtk_pctrl_spec_pull_set_samereg
+ common code
+
+Several mediatek soc use similar pull setting procedure as mt8173,
+the pupd enable and resistance setting are in the same register.
+Add common code mtk_pctrl_spec_pull_set_samereg out of spec_pull_set
+in mt8173 to handle this case, so future soc driver can use it.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-mt8173.c     |  166 +++++++------------------
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c |   60 +++++++++
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h |   31 +++++
+ 3 files changed, 136 insertions(+), 121 deletions(-)
+
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+index 412ea84..cc44b27 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+@@ -47,130 +47,54 @@ struct mtk_pin_ies_smt_set {
+               .offset = _offset,      \
+       }
+-/**
+- * struct mtk_pin_spec_pupd_set - For special pins' pull up/down setting.
+- * @pin: The pin number.
+- * @offset: The offset of special pull up/down setting register.
+- * @pupd_bit: The pull up/down bit in this register.
+- * @r0_bit: The r0 bit of pull resistor.
+- * @r1_bit: The r1 bit of pull resistor.
+- */
+-struct mtk_pin_spec_pupd_set {
+-      unsigned int pin;
+-      unsigned int offset;
+-      unsigned char pupd_bit;
+-      unsigned char r1_bit;
+-      unsigned char r0_bit;
+-};
+-
+-#define MTK_PIN_PUPD_SPEC(_pin, _offset, _pupd, _r1, _r0)     \
+-      {       \
+-              .pin = _pin,    \
+-              .offset = _offset,      \
+-              .pupd_bit = _pupd,      \
+-              .r1_bit = _r1,          \
+-              .r0_bit = _r0,          \
+-      }
+-
+-static const struct mtk_pin_spec_pupd_set mt8173_spec_pupd[] = {
+-      MTK_PIN_PUPD_SPEC(119, 0xe00, 2, 1, 0),  /* KROW0 */
+-      MTK_PIN_PUPD_SPEC(120, 0xe00, 6, 5, 4),  /* KROW1 */
+-      MTK_PIN_PUPD_SPEC(121, 0xe00, 10, 9, 8), /* KROW2 */
+-      MTK_PIN_PUPD_SPEC(122, 0xe10, 2, 1, 0),  /* KCOL0 */
+-      MTK_PIN_PUPD_SPEC(123, 0xe10, 6, 5, 4),  /* KCOL1 */
+-      MTK_PIN_PUPD_SPEC(124, 0xe10, 10, 9, 8), /* KCOL2 */
+-
+-      MTK_PIN_PUPD_SPEC(67, 0xd10, 2, 1, 0),   /* ms0 DS */
+-      MTK_PIN_PUPD_SPEC(68, 0xd00, 2, 1, 0),   /* ms0 RST */
+-      MTK_PIN_PUPD_SPEC(66, 0xc10, 2, 1, 0),   /* ms0 cmd */
+-      MTK_PIN_PUPD_SPEC(65, 0xc00, 2, 1, 0),   /* ms0 clk */
+-      MTK_PIN_PUPD_SPEC(57, 0xc20, 2, 1, 0),   /* ms0 data0 */
+-      MTK_PIN_PUPD_SPEC(58, 0xc20, 2, 1, 0),   /* ms0 data1 */
+-      MTK_PIN_PUPD_SPEC(59, 0xc20, 2, 1, 0),   /* ms0 data2 */
+-      MTK_PIN_PUPD_SPEC(60, 0xc20, 2, 1, 0),   /* ms0 data3 */
+-      MTK_PIN_PUPD_SPEC(61, 0xc20, 2, 1, 0),   /* ms0 data4 */
+-      MTK_PIN_PUPD_SPEC(62, 0xc20, 2, 1, 0),   /* ms0 data5 */
+-      MTK_PIN_PUPD_SPEC(63, 0xc20, 2, 1, 0),   /* ms0 data6 */
+-      MTK_PIN_PUPD_SPEC(64, 0xc20, 2, 1, 0),   /* ms0 data7 */
+-
+-      MTK_PIN_PUPD_SPEC(78, 0xc50, 2, 1, 0),    /* ms1 cmd */
+-      MTK_PIN_PUPD_SPEC(73, 0xd20, 2, 1, 0),    /* ms1 dat0 */
+-      MTK_PIN_PUPD_SPEC(74, 0xd20, 6, 5, 4),    /* ms1 dat1 */
+-      MTK_PIN_PUPD_SPEC(75, 0xd20, 10, 9, 8),   /* ms1 dat2 */
+-      MTK_PIN_PUPD_SPEC(76, 0xd20, 14, 13, 12), /* ms1 dat3 */
+-      MTK_PIN_PUPD_SPEC(77, 0xc40, 2, 1, 0),    /* ms1 clk */
+-
+-      MTK_PIN_PUPD_SPEC(100, 0xd40, 2, 1, 0),    /* ms2 dat0 */
+-      MTK_PIN_PUPD_SPEC(101, 0xd40, 6, 5, 4),    /* ms2 dat1 */
+-      MTK_PIN_PUPD_SPEC(102, 0xd40, 10, 9, 8),   /* ms2 dat2 */
+-      MTK_PIN_PUPD_SPEC(103, 0xd40, 14, 13, 12), /* ms2 dat3 */
+-      MTK_PIN_PUPD_SPEC(104, 0xc80, 2, 1, 0),    /* ms2 clk */
+-      MTK_PIN_PUPD_SPEC(105, 0xc90, 2, 1, 0),    /* ms2 cmd */
+-
+-      MTK_PIN_PUPD_SPEC(22, 0xd60, 2, 1, 0),    /* ms3 dat0 */
+-      MTK_PIN_PUPD_SPEC(23, 0xd60, 6, 5, 4),    /* ms3 dat1 */
+-      MTK_PIN_PUPD_SPEC(24, 0xd60, 10, 9, 8),   /* ms3 dat2 */
+-      MTK_PIN_PUPD_SPEC(25, 0xd60, 14, 13, 12), /* ms3 dat3 */
+-      MTK_PIN_PUPD_SPEC(26, 0xcc0, 2, 1, 0),    /* ms3 clk */
+-      MTK_PIN_PUPD_SPEC(27, 0xcd0, 2, 1, 0)     /* ms3 cmd */
++static const struct mtk_pin_spec_pupd_set_samereg mt8173_spec_pupd[] = {
++      MTK_PIN_PUPD_SPEC_SR(119, 0xe00, 2, 1, 0),  /* KROW0 */
++      MTK_PIN_PUPD_SPEC_SR(120, 0xe00, 6, 5, 4),  /* KROW1 */
++      MTK_PIN_PUPD_SPEC_SR(121, 0xe00, 10, 9, 8), /* KROW2 */
++      MTK_PIN_PUPD_SPEC_SR(122, 0xe10, 2, 1, 0),  /* KCOL0 */
++      MTK_PIN_PUPD_SPEC_SR(123, 0xe10, 6, 5, 4),  /* KCOL1 */
++      MTK_PIN_PUPD_SPEC_SR(124, 0xe10, 10, 9, 8), /* KCOL2 */
++
++      MTK_PIN_PUPD_SPEC_SR(67, 0xd10, 2, 1, 0),   /* ms0 DS */
++      MTK_PIN_PUPD_SPEC_SR(68, 0xd00, 2, 1, 0),   /* ms0 RST */
++      MTK_PIN_PUPD_SPEC_SR(66, 0xc10, 2, 1, 0),   /* ms0 cmd */
++      MTK_PIN_PUPD_SPEC_SR(65, 0xc00, 2, 1, 0),   /* ms0 clk */
++      MTK_PIN_PUPD_SPEC_SR(57, 0xc20, 2, 1, 0),   /* ms0 data0 */
++      MTK_PIN_PUPD_SPEC_SR(58, 0xc20, 2, 1, 0),   /* ms0 data1 */
++      MTK_PIN_PUPD_SPEC_SR(59, 0xc20, 2, 1, 0),   /* ms0 data2 */
++      MTK_PIN_PUPD_SPEC_SR(60, 0xc20, 2, 1, 0),   /* ms0 data3 */
++      MTK_PIN_PUPD_SPEC_SR(61, 0xc20, 2, 1, 0),   /* ms0 data4 */
++      MTK_PIN_PUPD_SPEC_SR(62, 0xc20, 2, 1, 0),   /* ms0 data5 */
++      MTK_PIN_PUPD_SPEC_SR(63, 0xc20, 2, 1, 0),   /* ms0 data6 */
++      MTK_PIN_PUPD_SPEC_SR(64, 0xc20, 2, 1, 0),   /* ms0 data7 */
++
++      MTK_PIN_PUPD_SPEC_SR(78, 0xc50, 2, 1, 0),    /* ms1 cmd */
++      MTK_PIN_PUPD_SPEC_SR(73, 0xd20, 2, 1, 0),    /* ms1 dat0 */
++      MTK_PIN_PUPD_SPEC_SR(74, 0xd20, 6, 5, 4),    /* ms1 dat1 */
++      MTK_PIN_PUPD_SPEC_SR(75, 0xd20, 10, 9, 8),   /* ms1 dat2 */
++      MTK_PIN_PUPD_SPEC_SR(76, 0xd20, 14, 13, 12), /* ms1 dat3 */
++      MTK_PIN_PUPD_SPEC_SR(77, 0xc40, 2, 1, 0),    /* ms1 clk */
++
++      MTK_PIN_PUPD_SPEC_SR(100, 0xd40, 2, 1, 0),    /* ms2 dat0 */
++      MTK_PIN_PUPD_SPEC_SR(101, 0xd40, 6, 5, 4),    /* ms2 dat1 */
++      MTK_PIN_PUPD_SPEC_SR(102, 0xd40, 10, 9, 8),   /* ms2 dat2 */
++      MTK_PIN_PUPD_SPEC_SR(103, 0xd40, 14, 13, 12), /* ms2 dat3 */
++      MTK_PIN_PUPD_SPEC_SR(104, 0xc80, 2, 1, 0),    /* ms2 clk */
++      MTK_PIN_PUPD_SPEC_SR(105, 0xc90, 2, 1, 0),    /* ms2 cmd */
++
++      MTK_PIN_PUPD_SPEC_SR(22, 0xd60, 2, 1, 0),    /* ms3 dat0 */
++      MTK_PIN_PUPD_SPEC_SR(23, 0xd60, 6, 5, 4),    /* ms3 dat1 */
++      MTK_PIN_PUPD_SPEC_SR(24, 0xd60, 10, 9, 8),   /* ms3 dat2 */
++      MTK_PIN_PUPD_SPEC_SR(25, 0xd60, 14, 13, 12), /* ms3 dat3 */
++      MTK_PIN_PUPD_SPEC_SR(26, 0xcc0, 2, 1, 0),    /* ms3 clk */
++      MTK_PIN_PUPD_SPEC_SR(27, 0xcd0, 2, 1, 0)     /* ms3 cmd */
+ };
+-static int spec_pull_set(struct regmap *regmap, unsigned int pin,
++static int mt8173_spec_pull_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, bool isup, unsigned int r1r0)
+ {
+-      unsigned int i;
+-      unsigned int reg_pupd, reg_set, reg_rst;
+-      unsigned int bit_pupd, bit_r0, bit_r1;
+-      const struct mtk_pin_spec_pupd_set *spec_pupd_pin;
+-      bool find = false;
+-
+-      for (i = 0; i < ARRAY_SIZE(mt8173_spec_pupd); i++) {
+-              if (pin == mt8173_spec_pupd[i].pin) {
+-                      find = true;
+-                      break;
+-              }
+-      }
+-
+-      if (!find)
+-              return -EINVAL;
+-
+-      spec_pupd_pin = mt8173_spec_pupd + i;
+-      reg_set = spec_pupd_pin->offset + align;
+-      reg_rst = spec_pupd_pin->offset + (align << 1);
+-
+-      if (isup)
+-              reg_pupd = reg_rst;
+-      else
+-              reg_pupd = reg_set;
+-
+-      bit_pupd = BIT(spec_pupd_pin->pupd_bit);
+-      regmap_write(regmap, reg_pupd, bit_pupd);
+-
+-      bit_r0 = BIT(spec_pupd_pin->r0_bit);
+-      bit_r1 = BIT(spec_pupd_pin->r1_bit);
+-
+-      switch (r1r0) {
+-      case MTK_PUPD_SET_R1R0_00:
+-              regmap_write(regmap, reg_rst, bit_r0);
+-              regmap_write(regmap, reg_rst, bit_r1);
+-              break;
+-      case MTK_PUPD_SET_R1R0_01:
+-              regmap_write(regmap, reg_set, bit_r0);
+-              regmap_write(regmap, reg_rst, bit_r1);
+-              break;
+-      case MTK_PUPD_SET_R1R0_10:
+-              regmap_write(regmap, reg_rst, bit_r0);
+-              regmap_write(regmap, reg_set, bit_r1);
+-              break;
+-      case MTK_PUPD_SET_R1R0_11:
+-              regmap_write(regmap, reg_set, bit_r0);
+-              regmap_write(regmap, reg_set, bit_r1);
+-              break;
+-      default:
+-              return -EINVAL;
+-      }
+-
+-      return 0;
++      return mtk_pctrl_spec_pull_set_samereg(regmap, mt8173_spec_pupd,
++              ARRAY_SIZE(mt8173_spec_pupd), pin, align, isup, r1r0);
+ }
+ static const struct mtk_pin_ies_smt_set mt8173_ies_smt_set[] = {
+@@ -382,7 +306,7 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
+       .n_grp_cls = ARRAY_SIZE(mt8173_drv_grp),
+       .pin_drv_grp = mt8173_pin_drv,
+       .n_pin_drv_grps = ARRAY_SIZE(mt8173_pin_drv),
+-      .spec_pull_set = spec_pull_set,
++      .spec_pull_set = mt8173_spec_pull_set,
+       .spec_ies_smt_set = spec_ies_smt_set,
+       .dir_offset = 0x0000,
+       .pullen_offset = 0x0100,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+index 474812e..0d51145 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -186,6 +186,66 @@ static int mtk_pconf_set_driving(struct mtk_pinctrl *pctl,
+       return -EINVAL;
+ }
++int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
++              const struct mtk_pin_spec_pupd_set_samereg *pupd_infos,
++              unsigned int info_num, unsigned int pin,
++              unsigned char align, bool isup, unsigned int r1r0)
++{
++      unsigned int i;
++      unsigned int reg_pupd, reg_set, reg_rst;
++      unsigned int bit_pupd, bit_r0, bit_r1;
++      const struct mtk_pin_spec_pupd_set_samereg *spec_pupd_pin;
++      bool find = false;
++
++      for (i = 0; i < info_num; i++) {
++              if (pin == pupd_infos[i].pin) {
++                      find = true;
++                      break;
++              }
++      }
++
++      if (!find)
++              return -EINVAL;
++
++      spec_pupd_pin = pupd_infos + i;
++      reg_set = spec_pupd_pin->offset + align;
++      reg_rst = spec_pupd_pin->offset + (align << 1);
++
++      if (isup)
++              reg_pupd = reg_rst;
++      else
++              reg_pupd = reg_set;
++
++      bit_pupd = BIT(spec_pupd_pin->pupd_bit);
++      regmap_write(regmap, reg_pupd, bit_pupd);
++
++      bit_r0 = BIT(spec_pupd_pin->r0_bit);
++      bit_r1 = BIT(spec_pupd_pin->r1_bit);
++
++      switch (r1r0) {
++      case MTK_PUPD_SET_R1R0_00:
++              regmap_write(regmap, reg_rst, bit_r0);
++              regmap_write(regmap, reg_rst, bit_r1);
++              break;
++      case MTK_PUPD_SET_R1R0_01:
++              regmap_write(regmap, reg_set, bit_r0);
++              regmap_write(regmap, reg_rst, bit_r1);
++              break;
++      case MTK_PUPD_SET_R1R0_10:
++              regmap_write(regmap, reg_rst, bit_r0);
++              regmap_write(regmap, reg_set, bit_r1);
++              break;
++      case MTK_PUPD_SET_R1R0_11:
++              regmap_write(regmap, reg_set, bit_r0);
++              regmap_write(regmap, reg_set, bit_r1);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
+ static int mtk_pconf_set_pull_select(struct mtk_pinctrl *pctl,
+               unsigned int pin, bool enable, bool isup, unsigned int arg)
+ {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index 1508849..2a4b7be 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -117,6 +117,32 @@ struct mtk_pin_drv_grp {
+               .grp = _grp,    \
+       }
++/**
++ * struct mtk_pin_spec_pupd_set_samereg
++ * - For special pins' pull up/down setting which resides in same register
++ * @pin: The pin number.
++ * @offset: The offset of special pull up/down setting register.
++ * @pupd_bit: The pull up/down bit in this register.
++ * @r0_bit: The r0 bit of pull resistor.
++ * @r1_bit: The r1 bit of pull resistor.
++ */
++struct mtk_pin_spec_pupd_set_samereg {
++      unsigned short pin;
++      unsigned short offset;
++      unsigned char pupd_bit;
++      unsigned char r1_bit;
++      unsigned char r0_bit;
++};
++
++#define MTK_PIN_PUPD_SPEC_SR(_pin, _offset, _pupd, _r1, _r0)  \
++      {       \
++              .pin = _pin,    \
++              .offset = _offset,      \
++              .pupd_bit = _pupd,      \
++              .r1_bit = _r1,          \
++              .r0_bit = _r0,          \
++      }
++
+ struct mtk_eint_offsets {
+       const char *name;
+       unsigned int  stat;
+@@ -220,4 +246,9 @@ struct mtk_pinctrl {
+ int mtk_pctrl_init(struct platform_device *pdev,
+               const struct mtk_pinctrl_devdata *data);
++int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
++              const struct mtk_pin_spec_pupd_set_samereg *pupd_infos,
++              unsigned int info_num, unsigned int pin,
++              unsigned char align, bool isup, unsigned int r1r0);
++
+ #endif /* __PINCTRL_MTK_COMMON_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0052-pinctrl-mediatek-add-ies-smt-control-to-common-code.patch b/target/linux/mediatek/patches/0052-pinctrl-mediatek-add-ies-smt-control-to-common-code.patch
new file mode 100644 (file)
index 0000000..5467c21
--- /dev/null
@@ -0,0 +1,479 @@
+From 32ea3b91046bea40cd1a7a4f16a24d75f53ca92a Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:16 -0700
+Subject: [PATCH 52/76] pinctrl: mediatek: add ies/smt control to common code.
+
+Input enable and smt setting have different register,
+modify code to fix it.
+
+Several mediatek soc use similar input enable/smt setting
+procedure as mt8173, some soc use generic input enable/smt
+setting, some soc has no input enable/smt setting. Adding
+common code to handle all those cases, so future soc driver
+can use it.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-mt8173.c     |  201 +++++++++++++------------
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c |   82 +++++++---
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h |   31 +++-
+ 3 files changed, 198 insertions(+), 116 deletions(-)
+
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+index cc44b27..a7e5b24 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+@@ -18,6 +18,7 @@
+ #include <linux/of_device.h>
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/regmap.h>
++#include <linux/pinctrl/pinconf-generic.h>
+ #include <dt-bindings/pinctrl/mt65xx.h>
+ #include "pinctrl-mtk-common.h"
+@@ -25,28 +26,6 @@
+ #define DRV_BASE                              0xb00
+-/**
+- * struct mtk_pin_ies_smt_set - For special pins' ies and smt setting.
+- * @start: The start pin number of those special pins.
+- * @end: The end pin number of those special pins.
+- * @offset: The offset of special setting register.
+- * @bit: The bit of special setting register.
+- */
+-struct mtk_pin_ies_smt_set {
+-      unsigned int start;
+-      unsigned int end;
+-      unsigned int offset;
+-      unsigned char bit;
+-};
+-
+-#define MTK_PIN_IES_SMT_SET(_start, _end, _offset, _bit)      \
+-      {       \
+-              .start = _start,        \
+-              .end = _end,    \
+-              .bit = _bit,    \
+-              .offset = _offset,      \
+-      }
+-
+ static const struct mtk_pin_spec_pupd_set_samereg mt8173_spec_pupd[] = {
+       MTK_PIN_PUPD_SPEC_SR(119, 0xe00, 2, 1, 0),  /* KROW0 */
+       MTK_PIN_PUPD_SPEC_SR(120, 0xe00, 6, 5, 4),  /* KROW1 */
+@@ -97,80 +76,114 @@ static int mt8173_spec_pull_set(struct regmap *regmap, unsigned int pin,
+               ARRAY_SIZE(mt8173_spec_pupd), pin, align, isup, r1r0);
+ }
+-static const struct mtk_pin_ies_smt_set mt8173_ies_smt_set[] = {
+-      MTK_PIN_IES_SMT_SET(0, 4, 0x930, 1),
+-      MTK_PIN_IES_SMT_SET(5, 9, 0x930, 2),
+-      MTK_PIN_IES_SMT_SET(10, 13, 0x930, 10),
+-      MTK_PIN_IES_SMT_SET(14, 15, 0x940, 10),
+-      MTK_PIN_IES_SMT_SET(16, 16, 0x930, 0),
+-      MTK_PIN_IES_SMT_SET(17, 17, 0x950, 2),
+-      MTK_PIN_IES_SMT_SET(18, 21, 0x940, 3),
+-      MTK_PIN_IES_SMT_SET(29, 32, 0x930, 3),
+-      MTK_PIN_IES_SMT_SET(33, 33, 0x930, 4),
+-      MTK_PIN_IES_SMT_SET(34, 36, 0x930, 5),
+-      MTK_PIN_IES_SMT_SET(37, 38, 0x930, 6),
+-      MTK_PIN_IES_SMT_SET(39, 39, 0x930, 7),
+-      MTK_PIN_IES_SMT_SET(40, 41, 0x930, 9),
+-      MTK_PIN_IES_SMT_SET(42, 42, 0x940, 0),
+-      MTK_PIN_IES_SMT_SET(43, 44, 0x930, 11),
+-      MTK_PIN_IES_SMT_SET(45, 46, 0x930, 12),
+-      MTK_PIN_IES_SMT_SET(57, 64, 0xc20, 13),
+-      MTK_PIN_IES_SMT_SET(65, 65, 0xc10, 13),
+-      MTK_PIN_IES_SMT_SET(66, 66, 0xc00, 13),
+-      MTK_PIN_IES_SMT_SET(67, 67, 0xd10, 13),
+-      MTK_PIN_IES_SMT_SET(68, 68, 0xd00, 13),
+-      MTK_PIN_IES_SMT_SET(69, 72, 0x940, 14),
+-      MTK_PIN_IES_SMT_SET(73, 76, 0xc60, 13),
+-      MTK_PIN_IES_SMT_SET(77, 77, 0xc40, 13),
+-      MTK_PIN_IES_SMT_SET(78, 78, 0xc50, 13),
+-      MTK_PIN_IES_SMT_SET(79, 82, 0x940, 15),
+-      MTK_PIN_IES_SMT_SET(83, 83, 0x950, 0),
+-      MTK_PIN_IES_SMT_SET(84, 85, 0x950, 1),
+-      MTK_PIN_IES_SMT_SET(86, 91, 0x950, 2),
+-      MTK_PIN_IES_SMT_SET(92, 92, 0x930, 13),
+-      MTK_PIN_IES_SMT_SET(93, 95, 0x930, 14),
+-      MTK_PIN_IES_SMT_SET(96, 99, 0x930, 15),
+-      MTK_PIN_IES_SMT_SET(100, 103, 0xca0, 13),
+-      MTK_PIN_IES_SMT_SET(104, 104, 0xc80, 13),
+-      MTK_PIN_IES_SMT_SET(105, 105, 0xc90, 13),
+-      MTK_PIN_IES_SMT_SET(106, 107, 0x940, 4),
+-      MTK_PIN_IES_SMT_SET(108, 112, 0x940, 1),
+-      MTK_PIN_IES_SMT_SET(113, 116, 0x940, 2),
+-      MTK_PIN_IES_SMT_SET(117, 118, 0x940, 5),
+-      MTK_PIN_IES_SMT_SET(119, 124, 0x940, 6),
+-      MTK_PIN_IES_SMT_SET(125, 126, 0x940, 7),
+-      MTK_PIN_IES_SMT_SET(127, 127, 0x940, 0),
+-      MTK_PIN_IES_SMT_SET(128, 128, 0x950, 8),
+-      MTK_PIN_IES_SMT_SET(129, 130, 0x950, 9),
+-      MTK_PIN_IES_SMT_SET(131, 132, 0x950, 8),
+-      MTK_PIN_IES_SMT_SET(133, 134, 0x910, 8)
++static const struct mtk_pin_ies_smt_set mt8173_smt_set[] = {
++      MTK_PIN_IES_SMT_SPEC(0, 4, 0x930, 1),
++      MTK_PIN_IES_SMT_SPEC(5, 9, 0x930, 2),
++      MTK_PIN_IES_SMT_SPEC(10, 13, 0x930, 10),
++      MTK_PIN_IES_SMT_SPEC(14, 15, 0x940, 10),
++      MTK_PIN_IES_SMT_SPEC(16, 16, 0x930, 0),
++      MTK_PIN_IES_SMT_SPEC(17, 17, 0x950, 2),
++      MTK_PIN_IES_SMT_SPEC(18, 21, 0x940, 3),
++      MTK_PIN_IES_SMT_SPEC(29, 32, 0x930, 3),
++      MTK_PIN_IES_SMT_SPEC(33, 33, 0x930, 4),
++      MTK_PIN_IES_SMT_SPEC(34, 36, 0x930, 5),
++      MTK_PIN_IES_SMT_SPEC(37, 38, 0x930, 6),
++      MTK_PIN_IES_SMT_SPEC(39, 39, 0x930, 7),
++      MTK_PIN_IES_SMT_SPEC(40, 41, 0x930, 9),
++      MTK_PIN_IES_SMT_SPEC(42, 42, 0x940, 0),
++      MTK_PIN_IES_SMT_SPEC(43, 44, 0x930, 11),
++      MTK_PIN_IES_SMT_SPEC(45, 46, 0x930, 12),
++      MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 13),
++      MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 13),
++      MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 13),
++      MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 13),
++      MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 13),
++      MTK_PIN_IES_SMT_SPEC(69, 72, 0x940, 14),
++      MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 13),
++      MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 13),
++      MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 13),
++      MTK_PIN_IES_SMT_SPEC(79, 82, 0x940, 15),
++      MTK_PIN_IES_SMT_SPEC(83, 83, 0x950, 0),
++      MTK_PIN_IES_SMT_SPEC(84, 85, 0x950, 1),
++      MTK_PIN_IES_SMT_SPEC(86, 91, 0x950, 2),
++      MTK_PIN_IES_SMT_SPEC(92, 92, 0x930, 13),
++      MTK_PIN_IES_SMT_SPEC(93, 95, 0x930, 14),
++      MTK_PIN_IES_SMT_SPEC(96, 99, 0x930, 15),
++      MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 13),
++      MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 13),
++      MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 13),
++      MTK_PIN_IES_SMT_SPEC(106, 107, 0x940, 4),
++      MTK_PIN_IES_SMT_SPEC(108, 112, 0x940, 1),
++      MTK_PIN_IES_SMT_SPEC(113, 116, 0x940, 2),
++      MTK_PIN_IES_SMT_SPEC(117, 118, 0x940, 5),
++      MTK_PIN_IES_SMT_SPEC(119, 124, 0x940, 6),
++      MTK_PIN_IES_SMT_SPEC(125, 126, 0x940, 7),
++      MTK_PIN_IES_SMT_SPEC(127, 127, 0x940, 0),
++      MTK_PIN_IES_SMT_SPEC(128, 128, 0x950, 8),
++      MTK_PIN_IES_SMT_SPEC(129, 130, 0x950, 9),
++      MTK_PIN_IES_SMT_SPEC(131, 132, 0x950, 8),
++      MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
+ };
+-static int spec_ies_smt_set(struct regmap *regmap, unsigned int pin,
+-              unsigned char align, int value)
+-{
+-      unsigned int i, reg_addr, bit;
+-      bool find = false;
+-
+-      for (i = 0; i < ARRAY_SIZE(mt8173_ies_smt_set); i++) {
+-              if (pin >= mt8173_ies_smt_set[i].start &&
+-                              pin <= mt8173_ies_smt_set[i].end) {
+-                      find = true;
+-                      break;
+-              }
+-      }
+-
+-      if (!find)
+-              return -EINVAL;
+-
+-      if (value)
+-              reg_addr = mt8173_ies_smt_set[i].offset + align;
+-      else
+-              reg_addr = mt8173_ies_smt_set[i].offset + (align << 1);
++static const struct mtk_pin_ies_smt_set mt8173_ies_set[] = {
++      MTK_PIN_IES_SMT_SPEC(0, 4, 0x900, 1),
++      MTK_PIN_IES_SMT_SPEC(5, 9, 0x900, 2),
++      MTK_PIN_IES_SMT_SPEC(10, 13, 0x900, 10),
++      MTK_PIN_IES_SMT_SPEC(14, 15, 0x910, 10),
++      MTK_PIN_IES_SMT_SPEC(16, 16, 0x900, 0),
++      MTK_PIN_IES_SMT_SPEC(17, 17, 0x920, 2),
++      MTK_PIN_IES_SMT_SPEC(18, 21, 0x910, 3),
++      MTK_PIN_IES_SMT_SPEC(29, 32, 0x900, 3),
++      MTK_PIN_IES_SMT_SPEC(33, 33, 0x900, 4),
++      MTK_PIN_IES_SMT_SPEC(34, 36, 0x900, 5),
++      MTK_PIN_IES_SMT_SPEC(37, 38, 0x900, 6),
++      MTK_PIN_IES_SMT_SPEC(39, 39, 0x900, 7),
++      MTK_PIN_IES_SMT_SPEC(40, 41, 0x900, 9),
++      MTK_PIN_IES_SMT_SPEC(42, 42, 0x910, 0),
++      MTK_PIN_IES_SMT_SPEC(43, 44, 0x900, 11),
++      MTK_PIN_IES_SMT_SPEC(45, 46, 0x900, 12),
++      MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 14),
++      MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 14),
++      MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 14),
++      MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 14),
++      MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 14),
++      MTK_PIN_IES_SMT_SPEC(69, 72, 0x910, 14),
++      MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 14),
++      MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 14),
++      MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 14),
++      MTK_PIN_IES_SMT_SPEC(79, 82, 0x910, 15),
++      MTK_PIN_IES_SMT_SPEC(83, 83, 0x920, 0),
++      MTK_PIN_IES_SMT_SPEC(84, 85, 0x920, 1),
++      MTK_PIN_IES_SMT_SPEC(86, 91, 0x920, 2),
++      MTK_PIN_IES_SMT_SPEC(92, 92, 0x900, 13),
++      MTK_PIN_IES_SMT_SPEC(93, 95, 0x900, 14),
++      MTK_PIN_IES_SMT_SPEC(96, 99, 0x900, 15),
++      MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 14),
++      MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 14),
++      MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 14),
++      MTK_PIN_IES_SMT_SPEC(106, 107, 0x91, 4),
++      MTK_PIN_IES_SMT_SPEC(108, 112, 0x910, 1),
++      MTK_PIN_IES_SMT_SPEC(113, 116, 0x910, 2),
++      MTK_PIN_IES_SMT_SPEC(117, 118, 0x910, 5),
++      MTK_PIN_IES_SMT_SPEC(119, 124, 0x910, 6),
++      MTK_PIN_IES_SMT_SPEC(125, 126, 0x910, 7),
++      MTK_PIN_IES_SMT_SPEC(127, 127, 0x910, 0),
++      MTK_PIN_IES_SMT_SPEC(128, 128, 0x920, 8),
++      MTK_PIN_IES_SMT_SPEC(129, 130, 0x920, 9),
++      MTK_PIN_IES_SMT_SPEC(131, 132, 0x920, 8),
++      MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
++};
+-      bit = BIT(mt8173_ies_smt_set[i].bit);
+-      regmap_write(regmap, reg_addr, bit);
+-      return 0;
++static int mt8173_ies_smt_set(struct regmap *regmap, unsigned int pin,
++              unsigned char align, int value, enum pin_config_param arg)
++{
++      if (arg == PIN_CONFIG_INPUT_ENABLE)
++              return mtk_pconf_spec_set_ies_smt_range(regmap, mt8173_ies_set,
++                      ARRAY_SIZE(mt8173_ies_set), pin, align, value);
++      else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++              return mtk_pconf_spec_set_ies_smt_range(regmap, mt8173_smt_set,
++                      ARRAY_SIZE(mt8173_smt_set), pin, align, value);
++      return -EINVAL;
+ }
+ static const struct mtk_drv_group_desc mt8173_drv_grp[] =  {
+@@ -307,7 +320,7 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
+       .pin_drv_grp = mt8173_pin_drv,
+       .n_pin_drv_grps = ARRAY_SIZE(mt8173_pin_drv),
+       .spec_pull_set = mt8173_spec_pull_set,
+-      .spec_ies_smt_set = spec_ies_smt_set,
++      .spec_ies_smt_set = mt8173_ies_smt_set,
+       .dir_offset = 0x0000,
+       .pullen_offset = 0x0100,
+       .pullsel_offset = 0x0200,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+index 0d51145..97fe2ab 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -107,28 +107,38 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+       regmap_write(mtk_get_regmap(pctl, offset), reg_addr, bit);
+ }
+-static void mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
+-              int value, enum pin_config_param param)
++static int mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
++              int value, enum pin_config_param arg)
+ {
+       unsigned int reg_addr, offset;
+       unsigned int bit;
+-      int ret;
++
++      /**
++       * Due to some soc are not support ies/smt config, add this special
++       * control to handle it.
++       */
++      if (!pctl->devdata->spec_ies_smt_set &&
++              pctl->devdata->ies_offset == MTK_PINCTRL_NOT_SUPPORT &&
++                      arg == PIN_CONFIG_INPUT_ENABLE)
++              return -EINVAL;
++
++      if (!pctl->devdata->spec_ies_smt_set &&
++              pctl->devdata->smt_offset == MTK_PINCTRL_NOT_SUPPORT &&
++                      arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++              return -EINVAL;
+       /*
+        * Due to some pins are irregular, their input enable and smt
+-       * control register are discontinuous, but they are mapping together.
+-       * So we need this special handle.
++       * control register are discontinuous, so we need this special handle.
+        */
+       if (pctl->devdata->spec_ies_smt_set) {
+-              ret = pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin),
+-                      pin, pctl->devdata->port_align, value);
+-              if (!ret)
+-                      return;
++              return pctl->devdata->spec_ies_smt_set(mtk_get_regmap(pctl, pin),
++                      pin, pctl->devdata->port_align, value, arg);
+       }
+       bit = BIT(pin & 0xf);
+-      if (param == PIN_CONFIG_INPUT_ENABLE)
++      if (arg == PIN_CONFIG_INPUT_ENABLE)
+               offset = pctl->devdata->ies_offset;
+       else
+               offset = pctl->devdata->smt_offset;
+@@ -139,6 +149,33 @@ static void mtk_pconf_set_ies_smt(struct mtk_pinctrl *pctl, unsigned pin,
+               reg_addr = CLR_ADDR(mtk_get_port(pctl, pin) + offset, pctl);
+       regmap_write(mtk_get_regmap(pctl, pin), reg_addr, bit);
++      return 0;
++}
++
++int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
++              const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num,
++              unsigned int pin, unsigned char align, int value)
++{
++      unsigned int i, reg_addr, bit;
++
++      for (i = 0; i < info_num; i++) {
++              if (pin >= ies_smt_infos[i].start &&
++                              pin <= ies_smt_infos[i].end) {
++                      break;
++              }
++      }
++
++      if (i == info_num)
++              return -EINVAL;
++
++      if (value)
++              reg_addr = ies_smt_infos[i].offset + align;
++      else
++              reg_addr = ies_smt_infos[i].offset + (align << 1);
++
++      bit = BIT(ies_smt_infos[i].bit);
++      regmap_write(regmap, reg_addr, bit);
++      return 0;
+ }
+ static const struct mtk_pin_drv_grp *mtk_find_pin_drv_grp_by_pin(
+@@ -295,36 +332,37 @@ static int mtk_pconf_parse_conf(struct pinctrl_dev *pctldev,
+               unsigned int pin, enum pin_config_param param,
+               enum pin_config_param arg)
+ {
++      int ret = 0;
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+-              mtk_pconf_set_pull_select(pctl, pin, false, false, arg);
++              ret = mtk_pconf_set_pull_select(pctl, pin, false, false, arg);
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+-              mtk_pconf_set_pull_select(pctl, pin, true, true, arg);
++              ret = mtk_pconf_set_pull_select(pctl, pin, true, true, arg);
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+-              mtk_pconf_set_pull_select(pctl, pin, true, false, arg);
++              ret = mtk_pconf_set_pull_select(pctl, pin, true, false, arg);
+               break;
+       case PIN_CONFIG_INPUT_ENABLE:
+-              mtk_pconf_set_ies_smt(pctl, pin, arg, param);
++              ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param);
+               break;
+       case PIN_CONFIG_OUTPUT:
+               mtk_gpio_set(pctl->chip, pin, arg);
+-              mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
++              ret = mtk_pmx_gpio_set_direction(pctldev, NULL, pin, false);
+               break;
+       case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+-              mtk_pconf_set_ies_smt(pctl, pin, arg, param);
++              ret = mtk_pconf_set_ies_smt(pctl, pin, arg, param);
+               break;
+       case PIN_CONFIG_DRIVE_STRENGTH:
+-              mtk_pconf_set_driving(pctl, pin, arg);
++              ret = mtk_pconf_set_driving(pctl, pin, arg);
+               break;
+       default:
+-              return -EINVAL;
++              ret = -EINVAL;
+       }
+-      return 0;
++      return ret;
+ }
+ static int mtk_pconf_group_get(struct pinctrl_dev *pctldev,
+@@ -343,12 +381,14 @@ static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+ {
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct mtk_pinctrl_group *g = &pctl->groups[group];
+-      int i;
++      int i, ret;
+       for (i = 0; i < num_configs; i++) {
+-              mtk_pconf_parse_conf(pctldev, g->pin,
++              ret = mtk_pconf_parse_conf(pctldev, g->pin,
+                       pinconf_to_config_param(configs[i]),
+                       pinconf_to_config_argument(configs[i]));
++              if (ret < 0)
++                      return ret;
+               g->config = configs[i];
+       }
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index 2a4b7be..c703e7d 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -17,6 +17,7 @@
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/regmap.h>
++#include <linux/pinctrl/pinconf-generic.h>
+ #define NO_EINT_SUPPORT    255
+ #define MT_EDGE_SENSITIVE           0
+@@ -25,6 +26,8 @@
+ #define EINT_DBNC_RST_BIT           (0x1 << 1)
+ #define EINT_DBNC_SET_EN            (0x1 << 0)
++#define MTK_PINCTRL_NOT_SUPPORT       (0xffff)
++
+ struct mtk_desc_function {
+       const char *name;
+       unsigned char muxval;
+@@ -143,6 +146,28 @@ struct mtk_pin_spec_pupd_set_samereg {
+               .r0_bit = _r0,          \
+       }
++/**
++ * struct mtk_pin_ies_set - For special pins' ies and smt setting.
++ * @start: The start pin number of those special pins.
++ * @end: The end pin number of those special pins.
++ * @offset: The offset of special setting register.
++ * @bit: The bit of special setting register.
++ */
++struct mtk_pin_ies_smt_set {
++      unsigned short start;
++      unsigned short end;
++      unsigned short offset;
++      unsigned char bit;
++};
++
++#define MTK_PIN_IES_SMT_SPEC(_start, _end, _offset, _bit)     \
++      {       \
++              .start = _start,        \
++              .end = _end,    \
++              .bit = _bit,    \
++              .offset = _offset,      \
++      }
++
+ struct mtk_eint_offsets {
+       const char *name;
+       unsigned int  stat;
+@@ -208,7 +233,7 @@ struct mtk_pinctrl_devdata {
+       int (*spec_pull_set)(struct regmap *reg, unsigned int pin,
+                       unsigned char align, bool isup, unsigned int arg);
+       int (*spec_ies_smt_set)(struct regmap *reg, unsigned int pin,
+-                      unsigned char align, int value);
++                      unsigned char align, int value, enum pin_config_param arg);
+       unsigned int dir_offset;
+       unsigned int ies_offset;
+       unsigned int smt_offset;
+@@ -251,4 +276,8 @@ int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
+               unsigned int info_num, unsigned int pin,
+               unsigned char align, bool isup, unsigned int r1r0);
++int mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
++              const struct mtk_pin_ies_smt_set *ies_smt_infos, unsigned int info_num,
++              unsigned int pin, unsigned char align, int value);
++
+ #endif /* __PINCTRL_MTK_COMMON_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0053-pinctrl-mediatek-Add-Pinctrl-GPIO-driver-for-mt6397.patch b/target/linux/mediatek/patches/0053-pinctrl-mediatek-Add-Pinctrl-GPIO-driver-for-mt6397.patch
new file mode 100644 (file)
index 0000000..2813f40
--- /dev/null
@@ -0,0 +1,654 @@
+From 3031cefd8cd323e04be11a8058616d8cf21c1313 Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:17 -0700
+Subject: [PATCH 53/76] pinctrl: mediatek: Add Pinctrl/GPIO driver for mt6397.
+
+Add mt6397 support using mediatek common pinctrl driver.
+
+mt6397 is a PMIC, and pinctrl/GPIO is part of 6397 chip.
+Pinctrl/GPIO driver should obtain regmap from PMIC,
+so adding this support to common code.
+
+Also, mt6397 is no need to support interrupt controller,
+so changing common code to skip it.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/Kconfig              |    6 +
+ drivers/pinctrl/mediatek/Makefile             |    1 +
+ drivers/pinctrl/mediatek/pinctrl-mt6397.c     |   78 +++++
+ drivers/pinctrl/mediatek/pinctrl-mt8135.c     |    2 +-
+ drivers/pinctrl/mediatek/pinctrl-mt8173.c     |    2 +-
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.c |   13 +-
+ drivers/pinctrl/mediatek/pinctrl-mtk-common.h |    3 +-
+ drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h |  424 +++++++++++++++++++++++++
+ 8 files changed, 524 insertions(+), 5 deletions(-)
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt6397.c
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h
+
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index 6b3551c..ddae479 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -23,4 +23,10 @@ config PINCTRL_MT8173
+       default ARM64 && ARCH_MEDIATEK
+       select PINCTRL_MTK_COMMON
++# For PMIC
++config PINCTRL_MT6397
++      bool "Mediatek MT6397 pin control" if COMPILE_TEST && !MFD_MT6397
++      default MFD_MT6397
++      select PINCTRL_MTK_COMMON
++
+ endif
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index d8606a2..ad0180c 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_MTK_COMMON)       += pinctrl-mtk-common.o
+ # SoC Drivers
+ obj-$(CONFIG_PINCTRL_MT8135)          += pinctrl-mt8135.o
+ obj-$(CONFIG_PINCTRL_MT8173)          += pinctrl-mt8173.o
++obj-$(CONFIG_PINCTRL_MT6397)          += pinctrl-mt6397.o
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6397.c b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
+new file mode 100644
+index 0000000..767bbdf
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mt6397.c
+@@ -0,0 +1,78 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Hongzhou.Yang <hongzhou.yang@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/module.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinconf-generic.h>
++#include <linux/mfd/mt6397/core.h>
++
++#include "pinctrl-mtk-common.h"
++#include "pinctrl-mtk-mt6397.h"
++
++#define MT6397_PIN_REG_BASE  0xc000
++
++static const struct mtk_pinctrl_devdata mt6397_pinctrl_data = {
++      .pins = mtk_pins_mt6397,
++      .npins = ARRAY_SIZE(mtk_pins_mt6397),
++      .dir_offset = (MT6397_PIN_REG_BASE + 0x000),
++      .ies_offset = MTK_PINCTRL_NOT_SUPPORT,
++      .smt_offset = MTK_PINCTRL_NOT_SUPPORT,
++      .pullen_offset = (MT6397_PIN_REG_BASE + 0x020),
++      .pullsel_offset = (MT6397_PIN_REG_BASE + 0x040),
++      .dout_offset = (MT6397_PIN_REG_BASE + 0x080),
++      .din_offset = (MT6397_PIN_REG_BASE + 0x0a0),
++      .pinmux_offset = (MT6397_PIN_REG_BASE + 0x0c0),
++      .type1_start = 41,
++      .type1_end = 41,
++      .port_shf = 3,
++      .port_mask = 0x3,
++      .port_align = 2,
++};
++
++static int mt6397_pinctrl_probe(struct platform_device *pdev)
++{
++      struct mt6397_chip *mt6397;
++
++      mt6397 = dev_get_drvdata(pdev->dev.parent);
++      return mtk_pctrl_init(pdev, &mt6397_pinctrl_data, mt6397->regmap);
++}
++
++static const struct of_device_id mt6397_pctrl_match[] = {
++      { .compatible = "mediatek,mt6397-pinctrl", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, mt6397_pctrl_match);
++
++static struct platform_driver mtk_pinctrl_driver = {
++      .probe = mt6397_pinctrl_probe,
++      .driver = {
++              .name = "mediatek-mt6397-pinctrl",
++              .owner = THIS_MODULE,
++              .of_match_table = mt6397_pctrl_match,
++      },
++};
++
++static int __init mtk_pinctrl_init(void)
++{
++      return platform_driver_register(&mtk_pinctrl_driver);
++}
++
++module_init(mtk_pinctrl_init);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek MT6397 Pinctrl Driver");
++MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+index 8e6abd5..203bd2a 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+@@ -342,7 +342,7 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
+ static int mt8135_pinctrl_probe(struct platform_device *pdev)
+ {
+-      return mtk_pctrl_init(pdev, &mt8135_pinctrl_data);
++      return mtk_pctrl_init(pdev, &mt8135_pinctrl_data, NULL);
+ }
+ static const struct of_device_id mt8135_pctrl_match[] = {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+index a7e5b24..cf4ed6e 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+@@ -361,7 +361,7 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
+ static int mt8173_pinctrl_probe(struct platform_device *pdev)
+ {
+-      return mtk_pctrl_init(pdev, &mt8173_pinctrl_data);
++      return mtk_pctrl_init(pdev, &mt8173_pinctrl_data, NULL);
+ }
+ static const struct of_device_id mt8173_pctrl_match[] = {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+index 97fe2ab..e772cef 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+@@ -1209,7 +1209,8 @@ static struct pinctrl_desc mtk_pctrl_desc = {
+ };
+ int mtk_pctrl_init(struct platform_device *pdev,
+-              const struct mtk_pinctrl_devdata *data)
++              const struct mtk_pinctrl_devdata *data,
++              struct regmap *regmap)
+ {
+       struct pinctrl_pin_desc *pins;
+       struct mtk_pinctrl *pctl;
+@@ -1235,6 +1236,11 @@ int mtk_pctrl_init(struct platform_device *pdev,
+               pctl->regmap1 = syscon_node_to_regmap(node);
+               if (IS_ERR(pctl->regmap1))
+                       return PTR_ERR(pctl->regmap1);
++      } else if (regmap) {
++              pctl->regmap1  = regmap;
++      } else {
++              dev_err(&pdev->dev, "Pinctrl node has not register regmap.\n");
++              return -EINVAL;
+       }
+       /* Only 8135 has two base addr, other SoCs have only one. */
+@@ -1280,7 +1286,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
+       pctl->chip->ngpio = pctl->devdata->npins;
+       pctl->chip->label = dev_name(&pdev->dev);
+       pctl->chip->dev = &pdev->dev;
+-      pctl->chip->base = 0;
++      pctl->chip->base = -1;
+       ret = gpiochip_add(pctl->chip);
+       if (ret) {
+@@ -1296,6 +1302,9 @@ int mtk_pctrl_init(struct platform_device *pdev,
+               goto chip_error;
+       }
++      if (of_find_property(np, "interrupt-controller", NULL))
++              return 0;
++
+       /* Get EINT register base from dts. */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+index c703e7d..30213e5 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h
+@@ -269,7 +269,8 @@ struct mtk_pinctrl {
+ };
+ int mtk_pctrl_init(struct platform_device *pdev,
+-              const struct mtk_pinctrl_devdata *data);
++              const struct mtk_pinctrl_devdata *data,
++              struct regmap *regmap);
+ int mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
+               const struct mtk_pin_spec_pupd_set_samereg *pupd_infos,
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h
+new file mode 100644
+index 0000000..4eb98dd
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6397.h
+@@ -0,0 +1,424 @@
++#ifndef __PINCTRL_MTK_MT6397_H
++#define __PINCTRL_MTK_MT6397_H
++
++#include <linux/pinctrl/pinctrl.h>
++#include "pinctrl-mtk-common.h"
++
++static const struct mtk_desc_pin mtk_pins_mt6397[] = {
++      MTK_PIN(
++              PINCTRL_PIN(0, "INT"),
++              "N2", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO0"),
++              MTK_FUNCTION(1, "INT")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(1, "SRCVOLTEN"),
++              "M4", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO1"),
++              MTK_FUNCTION(1, "SRCVOLTEN"),
++              MTK_FUNCTION(6, "TEST_CK1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(2, "SRCLKEN_PERI"),
++              "M2", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO2"),
++              MTK_FUNCTION(1, "SRCLKEN_PERI"),
++              MTK_FUNCTION(6, "TEST_CK2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(3, "RTC_32K1V8"),
++              "K3", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO3"),
++              MTK_FUNCTION(1, "RTC_32K1V8"),
++              MTK_FUNCTION(6, "TEST_CK3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(4, "WRAP_EVENT"),
++              "J2", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO4"),
++              MTK_FUNCTION(1, "WRAP_EVENT")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(5, "SPI_CLK"),
++              "L4", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO5"),
++              MTK_FUNCTION(1, "SPI_CLK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(6, "SPI_CSN"),
++              "J3", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO6"),
++              MTK_FUNCTION(1, "SPI_CSN")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(7, "SPI_MOSI"),
++              "J1", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO7"),
++              MTK_FUNCTION(1, "SPI_MOSI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(8, "SPI_MISO"),
++              "L3", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO8"),
++              MTK_FUNCTION(1, "SPI_MISO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(9, "AUD_CLK_MOSI"),
++              "H2", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO9"),
++              MTK_FUNCTION(1, "AUD_CLK"),
++              MTK_FUNCTION(6, "TEST_IN0"),
++              MTK_FUNCTION(7, "TEST_OUT0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(10, "AUD_DAT_MISO"),
++              "H3", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO10"),
++              MTK_FUNCTION(1, "AUD_MISO"),
++              MTK_FUNCTION(6, "TEST_IN1"),
++              MTK_FUNCTION(7, "TEST_OUT1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(11, "AUD_DAT_MOSI"),
++              "H1", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO11"),
++              MTK_FUNCTION(1, "AUD_MOSI"),
++              MTK_FUNCTION(6, "TEST_IN2"),
++              MTK_FUNCTION(7, "TEST_OUT2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(12, "COL0"),
++              "F3", "mt6397",
++              MTK_EINT_FUNCTION(2, 10),
++              MTK_FUNCTION(0, "GPIO12"),
++              MTK_FUNCTION(1, "COL0_USBDL"),
++              MTK_FUNCTION(2, "EINT10_1X"),
++              MTK_FUNCTION(3, "PWM1_3X"),
++              MTK_FUNCTION(6, "TEST_IN3"),
++              MTK_FUNCTION(7, "TEST_OUT3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(13, "COL1"),
++              "G8", "mt6397",
++              MTK_EINT_FUNCTION(2, 11),
++              MTK_FUNCTION(0, "GPIO13"),
++              MTK_FUNCTION(1, "COL1"),
++              MTK_FUNCTION(2, "EINT11_1X"),
++              MTK_FUNCTION(3, "SCL0_2X"),
++              MTK_FUNCTION(6, "TEST_IN4"),
++              MTK_FUNCTION(7, "TEST_OUT4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(14, "COL2"),
++              "H4", "mt6397",
++              MTK_EINT_FUNCTION(2, 12),
++              MTK_FUNCTION(0, "GPIO14"),
++              MTK_FUNCTION(1, "COL2"),
++              MTK_FUNCTION(2, "EINT12_1X"),
++              MTK_FUNCTION(3, "SDA0_2X"),
++              MTK_FUNCTION(6, "TEST_IN5"),
++              MTK_FUNCTION(7, "TEST_OUT5")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(15, "COL3"),
++              "G2", "mt6397",
++              MTK_EINT_FUNCTION(2, 13),
++              MTK_FUNCTION(0, "GPIO15"),
++              MTK_FUNCTION(1, "COL3"),
++              MTK_FUNCTION(2, "EINT13_1X"),
++              MTK_FUNCTION(3, "SCL1_2X"),
++              MTK_FUNCTION(6, "TEST_IN6"),
++              MTK_FUNCTION(7, "TEST_OUT6")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(16, "COL4"),
++              "F2", "mt6397",
++              MTK_EINT_FUNCTION(2, 14),
++              MTK_FUNCTION(0, "GPIO16"),
++              MTK_FUNCTION(1, "COL4"),
++              MTK_FUNCTION(2, "EINT14_1X"),
++              MTK_FUNCTION(3, "SDA1_2X"),
++              MTK_FUNCTION(6, "TEST_IN7"),
++              MTK_FUNCTION(7, "TEST_OUT7")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(17, "COL5"),
++              "G7", "mt6397",
++              MTK_EINT_FUNCTION(2, 15),
++              MTK_FUNCTION(0, "GPIO17"),
++              MTK_FUNCTION(1, "COL5"),
++              MTK_FUNCTION(2, "EINT15_1X"),
++              MTK_FUNCTION(3, "SCL2_2X"),
++              MTK_FUNCTION(6, "TEST_IN8"),
++              MTK_FUNCTION(7, "TEST_OUT8")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(18, "COL6"),
++              "J6", "mt6397",
++              MTK_EINT_FUNCTION(2, 16),
++              MTK_FUNCTION(0, "GPIO18"),
++              MTK_FUNCTION(1, "COL6"),
++              MTK_FUNCTION(2, "EINT16_1X"),
++              MTK_FUNCTION(3, "SDA2_2X"),
++              MTK_FUNCTION(4, "GPIO32K_0"),
++              MTK_FUNCTION(5, "GPIO26M_0"),
++              MTK_FUNCTION(6, "TEST_IN9"),
++              MTK_FUNCTION(7, "TEST_OUT9")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(19, "COL7"),
++              "J5", "mt6397",
++              MTK_EINT_FUNCTION(2, 17),
++              MTK_FUNCTION(0, "GPIO19"),
++              MTK_FUNCTION(1, "COL7"),
++              MTK_FUNCTION(2, "EINT17_1X"),
++              MTK_FUNCTION(3, "PWM2_3X"),
++              MTK_FUNCTION(4, "GPIO32K_1"),
++              MTK_FUNCTION(5, "GPIO26M_1"),
++              MTK_FUNCTION(6, "TEST_IN10"),
++              MTK_FUNCTION(7, "TEST_OUT10")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(20, "ROW0"),
++              "L7", "mt6397",
++              MTK_EINT_FUNCTION(2, 18),
++              MTK_FUNCTION(0, "GPIO20"),
++              MTK_FUNCTION(1, "ROW0"),
++              MTK_FUNCTION(2, "EINT18_1X"),
++              MTK_FUNCTION(3, "SCL0_3X"),
++              MTK_FUNCTION(6, "TEST_IN11"),
++              MTK_FUNCTION(7, "TEST_OUT11")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(21, "ROW1"),
++              "P1", "mt6397",
++              MTK_EINT_FUNCTION(2, 19),
++              MTK_FUNCTION(0, "GPIO21"),
++              MTK_FUNCTION(1, "ROW1"),
++              MTK_FUNCTION(2, "EINT19_1X"),
++              MTK_FUNCTION(3, "SDA0_3X"),
++              MTK_FUNCTION(4, "AUD_TSTCK"),
++              MTK_FUNCTION(6, "TEST_IN12"),
++              MTK_FUNCTION(7, "TEST_OUT12")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(22, "ROW2"),
++              "J8", "mt6397",
++              MTK_EINT_FUNCTION(2, 20),
++              MTK_FUNCTION(0, "GPIO22"),
++              MTK_FUNCTION(1, "ROW2"),
++              MTK_FUNCTION(2, "EINT20_1X"),
++              MTK_FUNCTION(3, "SCL1_3X"),
++              MTK_FUNCTION(6, "TEST_IN13"),
++              MTK_FUNCTION(7, "TEST_OUT13")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(23, "ROW3"),
++              "J7", "mt6397",
++              MTK_EINT_FUNCTION(2, 21),
++              MTK_FUNCTION(0, "GPIO23"),
++              MTK_FUNCTION(1, "ROW3"),
++              MTK_FUNCTION(2, "EINT21_1X"),
++              MTK_FUNCTION(3, "SDA1_3X"),
++              MTK_FUNCTION(6, "TEST_IN14"),
++              MTK_FUNCTION(7, "TEST_OUT14")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(24, "ROW4"),
++              "L5", "mt6397",
++              MTK_EINT_FUNCTION(2, 22),
++              MTK_FUNCTION(0, "GPIO24"),
++              MTK_FUNCTION(1, "ROW4"),
++              MTK_FUNCTION(2, "EINT22_1X"),
++              MTK_FUNCTION(3, "SCL2_3X"),
++              MTK_FUNCTION(6, "TEST_IN15"),
++              MTK_FUNCTION(7, "TEST_OUT15")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(25, "ROW5"),
++              "N6", "mt6397",
++              MTK_EINT_FUNCTION(2, 23),
++              MTK_FUNCTION(0, "GPIO25"),
++              MTK_FUNCTION(1, "ROW5"),
++              MTK_FUNCTION(2, "EINT23_1X"),
++              MTK_FUNCTION(3, "SDA2_3X"),
++              MTK_FUNCTION(6, "TEST_IN16"),
++              MTK_FUNCTION(7, "TEST_OUT16")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(26, "ROW6"),
++              "L6", "mt6397",
++              MTK_EINT_FUNCTION(2, 24),
++              MTK_FUNCTION(0, "GPIO26"),
++              MTK_FUNCTION(1, "ROW6"),
++              MTK_FUNCTION(2, "EINT24_1X"),
++              MTK_FUNCTION(3, "PWM3_3X"),
++              MTK_FUNCTION(4, "GPIO32K_2"),
++              MTK_FUNCTION(5, "GPIO26M_2"),
++              MTK_FUNCTION(6, "TEST_IN17"),
++              MTK_FUNCTION(7, "TEST_OUT17")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(27, "ROW7"),
++              "P2", "mt6397",
++              MTK_EINT_FUNCTION(2, 3),
++              MTK_FUNCTION(0, "GPIO27"),
++              MTK_FUNCTION(1, "ROW7"),
++              MTK_FUNCTION(2, "EINT3_1X"),
++              MTK_FUNCTION(3, "CBUS"),
++              MTK_FUNCTION(4, "GPIO32K_3"),
++              MTK_FUNCTION(5, "GPIO26M_3"),
++              MTK_FUNCTION(6, "TEST_IN18"),
++              MTK_FUNCTION(7, "TEST_OUT18")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(28, "PWM1(VMSEL1)"),
++              "J4", "mt6397",
++              MTK_EINT_FUNCTION(2, 4),
++              MTK_FUNCTION(0, "GPIO28"),
++              MTK_FUNCTION(1, "PWM1"),
++              MTK_FUNCTION(2, "EINT4_1X"),
++              MTK_FUNCTION(4, "GPIO32K_4"),
++              MTK_FUNCTION(5, "GPIO26M_4"),
++              MTK_FUNCTION(6, "TEST_IN19"),
++              MTK_FUNCTION(7, "TEST_OUT19")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(29, "PWM2(VMSEL2)"),
++              "N5", "mt6397",
++              MTK_EINT_FUNCTION(2, 5),
++              MTK_FUNCTION(0, "GPIO29"),
++              MTK_FUNCTION(1, "PWM2"),
++              MTK_FUNCTION(2, "EINT5_1X"),
++              MTK_FUNCTION(4, "GPIO32K_5"),
++              MTK_FUNCTION(5, "GPIO26M_5"),
++              MTK_FUNCTION(6, "TEST_IN20"),
++              MTK_FUNCTION(7, "TEST_OUT20")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(30, "PWM3(PWM)"),
++              "R3", "mt6397",
++              MTK_EINT_FUNCTION(2, 6),
++              MTK_FUNCTION(0, "GPIO30"),
++              MTK_FUNCTION(1, "PWM3"),
++              MTK_FUNCTION(2, "EINT6_1X"),
++              MTK_FUNCTION(3, "COL0"),
++              MTK_FUNCTION(4, "GPIO32K_6"),
++              MTK_FUNCTION(5, "GPIO26M_6"),
++              MTK_FUNCTION(6, "TEST_IN21"),
++              MTK_FUNCTION(7, "TEST_OUT21")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(31, "SCL0"),
++              "N1", "mt6397",
++              MTK_EINT_FUNCTION(2, 7),
++              MTK_FUNCTION(0, "GPIO31"),
++              MTK_FUNCTION(1, "SCL0"),
++              MTK_FUNCTION(2, "EINT7_1X"),
++              MTK_FUNCTION(3, "PWM1_2X"),
++              MTK_FUNCTION(6, "TEST_IN22"),
++              MTK_FUNCTION(7, "TEST_OUT22")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(32, "SDA0"),
++              "N3", "mt6397",
++              MTK_EINT_FUNCTION(2, 8),
++              MTK_FUNCTION(0, "GPIO32"),
++              MTK_FUNCTION(1, "SDA0"),
++              MTK_FUNCTION(2, "EINT8_1X"),
++              MTK_FUNCTION(6, "TEST_IN23"),
++              MTK_FUNCTION(7, "TEST_OUT23")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(33, "SCL1"),
++              "T1", "mt6397",
++              MTK_EINT_FUNCTION(2, 9),
++              MTK_FUNCTION(0, "GPIO33"),
++              MTK_FUNCTION(1, "SCL1"),
++              MTK_FUNCTION(2, "EINT9_1X"),
++              MTK_FUNCTION(3, "PWM2_2X"),
++              MTK_FUNCTION(6, "TEST_IN24"),
++              MTK_FUNCTION(7, "TEST_OUT24")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(34, "SDA1"),
++              "T2", "mt6397",
++              MTK_EINT_FUNCTION(2, 0),
++              MTK_FUNCTION(0, "GPIO34"),
++              MTK_FUNCTION(1, "SDA1"),
++              MTK_FUNCTION(2, "EINT0_1X"),
++              MTK_FUNCTION(6, "TEST_IN25"),
++              MTK_FUNCTION(7, "TEST_OUT25")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(35, "SCL2"),
++              "T3", "mt6397",
++              MTK_EINT_FUNCTION(2, 1),
++              MTK_FUNCTION(0, "GPIO35"),
++              MTK_FUNCTION(1, "SCL2"),
++              MTK_FUNCTION(2, "EINT1_1X"),
++              MTK_FUNCTION(3, "PWM3_2X"),
++              MTK_FUNCTION(6, "TEST_IN26"),
++              MTK_FUNCTION(7, "TEST_OUT26")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(36, "SDA2"),
++              "U2", "mt6397",
++              MTK_EINT_FUNCTION(2, 2),
++              MTK_FUNCTION(0, "GPIO36"),
++              MTK_FUNCTION(1, "SDA2"),
++              MTK_FUNCTION(2, "EINT2_1X"),
++              MTK_FUNCTION(6, "TEST_IN27"),
++              MTK_FUNCTION(7, "TEST_OUT27")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(37, "HDMISD"),
++              "H6", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO37"),
++              MTK_FUNCTION(1, "HDMISD"),
++              MTK_FUNCTION(6, "TEST_IN28"),
++              MTK_FUNCTION(7, "TEST_OUT28")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(38, "HDMISCK"),
++              "H5", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO38"),
++              MTK_FUNCTION(1, "HDMISCK"),
++              MTK_FUNCTION(6, "TEST_IN29"),
++              MTK_FUNCTION(7, "TEST_OUT29")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(39, "HTPLG"),
++              "H7", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO39"),
++              MTK_FUNCTION(1, "HTPLG"),
++              MTK_FUNCTION(6, "TEST_IN30"),
++              MTK_FUNCTION(7, "TEST_OUT30")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(40, "CEC"),
++              "J9", "mt6397",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO40"),
++              MTK_FUNCTION(1, "CEC"),
++              MTK_FUNCTION(6, "TEST_IN31"),
++              MTK_FUNCTION(7, "TEST_OUT31")
++      ),
++};
++
++#endif /* __PINCTRL_MTK_MT6397_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0054-pinctrl-mediatek-add-pinctrl-GPIO-EINT-driver-for-mt.patch b/target/linux/mediatek/patches/0054-pinctrl-mediatek-add-pinctrl-GPIO-EINT-driver-for-mt.patch
new file mode 100644 (file)
index 0000000..763037c
--- /dev/null
@@ -0,0 +1,1740 @@
+From 0fabcb34ad6506e9d8dadf373f4ebfe1b5129765 Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:18 -0700
+Subject: [PATCH 54/76] pinctrl: mediatek: add pinctrl/GPIO/EINT driver for
+ mt8127
+
+MT8127 pinctrl/eint are similar to mt8135 and mt8173, add
+support for mt8127 using mediatek common pinctrl driver.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+---
+ drivers/pinctrl/mediatek/Kconfig              |    6 +
+ drivers/pinctrl/mediatek/Makefile             |    1 +
+ drivers/pinctrl/mediatek/pinctrl-mt8127.c     |  359 +++++++
+ drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h | 1318 +++++++++++++++++++++++++
+ 4 files changed, 1684 insertions(+)
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt8127.c
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h
+
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index ddae479..0bc84fb 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -15,6 +15,12 @@ config PINCTRL_MT8135
+       default MACH_MT8135
+       select PINCTRL_MTK_COMMON
++config PINCTRL_MT8127
++      bool "Mediatek MT8127 pin control" if COMPILE_TEST && !MACH_MT8127
++      depends on OF
++      default MACH_MT8127
++      select PINCTRL_MTK_COMMON
++
+ # For ARMv8 SoCs
+ config PINCTRL_MT8173
+       bool "Mediatek MT8173 pin control"
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index ad0180c..eb923d6 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -3,5 +3,6 @@ obj-$(CONFIG_PINCTRL_MTK_COMMON)       += pinctrl-mtk-common.o
+ # SoC Drivers
+ obj-$(CONFIG_PINCTRL_MT8135)          += pinctrl-mt8135.o
++obj-$(CONFIG_PINCTRL_MT8127)          += pinctrl-mt8127.o
+ obj-$(CONFIG_PINCTRL_MT8173)          += pinctrl-mt8173.o
+ obj-$(CONFIG_PINCTRL_MT6397)          += pinctrl-mt6397.o
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+new file mode 100644
+index 0000000..6a26cfa
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+@@ -0,0 +1,359 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Hongzhou.Yang <hongzhou.yang@mediatek.com>
++ *         Yingjoe Chen <yingjoe.chen@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/module.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/regmap.h>
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#include "pinctrl-mtk-common.h"
++#include "pinctrl-mtk-mt8127.h"
++
++static const struct mtk_drv_group_desc mt8127_drv_grp[] =  {
++      /* 0E4E8SR 4/8/12/16 */
++      MTK_DRV_GRP(4, 16, 1, 2, 4),
++      /* 0E2E4SR  2/4/6/8 */
++      MTK_DRV_GRP(2, 8, 1, 2, 2),
++      /* E8E4E2  2/4/6/8/10/12/14/16 */
++      MTK_DRV_GRP(2, 16, 0, 2, 2)
++};
++
++static const struct mtk_pin_drv_grp mt8127_pin_drv[] = {
++      MTK_PIN_DRV_GRP(0,   0xb00,  0, 1),
++      MTK_PIN_DRV_GRP(1,   0xb00,  0, 1),
++      MTK_PIN_DRV_GRP(2,   0xb00,  0, 1),
++      MTK_PIN_DRV_GRP(3,   0xb00,  0, 1),
++      MTK_PIN_DRV_GRP(4,   0xb00,  0, 1),
++      MTK_PIN_DRV_GRP(5,   0xb00,  0, 1),
++      MTK_PIN_DRV_GRP(6,   0xb00,  0, 1),
++      MTK_PIN_DRV_GRP(7,   0xb00, 12, 1),
++      MTK_PIN_DRV_GRP(8,   0xb00, 12, 1),
++      MTK_PIN_DRV_GRP(9,   0xb00, 12, 1),
++      MTK_PIN_DRV_GRP(10,  0xb00,  8, 1),
++      MTK_PIN_DRV_GRP(11,  0xb00,  8, 1),
++      MTK_PIN_DRV_GRP(12,  0xb00,  8, 1),
++      MTK_PIN_DRV_GRP(13,  0xb00,  8, 1),
++      MTK_PIN_DRV_GRP(14,  0xb10,  4, 0),
++      MTK_PIN_DRV_GRP(15,  0xb10,  4, 0),
++      MTK_PIN_DRV_GRP(16,  0xb10,  4, 0),
++      MTK_PIN_DRV_GRP(17,  0xb10,  4, 0),
++      MTK_PIN_DRV_GRP(18,  0xb10,  8, 0),
++      MTK_PIN_DRV_GRP(19,  0xb10,  8, 0),
++      MTK_PIN_DRV_GRP(20,  0xb10,  8, 0),
++      MTK_PIN_DRV_GRP(21,  0xb10,  8, 0),
++      MTK_PIN_DRV_GRP(22,  0xb20,  0, 0),
++      MTK_PIN_DRV_GRP(23,  0xb20,  0, 0),
++      MTK_PIN_DRV_GRP(24,  0xb20,  0, 0),
++      MTK_PIN_DRV_GRP(25,  0xb20,  0, 0),
++      MTK_PIN_DRV_GRP(26,  0xb20,  0, 0),
++      MTK_PIN_DRV_GRP(27,  0xb20,  4, 0),
++      MTK_PIN_DRV_GRP(28,  0xb20,  4, 0),
++      MTK_PIN_DRV_GRP(29,  0xb20,  4, 0),
++      MTK_PIN_DRV_GRP(30,  0xb20,  4, 0),
++      MTK_PIN_DRV_GRP(31,  0xb20,  4, 0),
++      MTK_PIN_DRV_GRP(32,  0xb20,  4, 0),
++      MTK_PIN_DRV_GRP(33,  0xb30,  4, 1),
++      MTK_PIN_DRV_GRP(34,  0xb30,  8, 1),
++      MTK_PIN_DRV_GRP(35,  0xb30,  8, 1),
++      MTK_PIN_DRV_GRP(36,  0xb30,  8, 1),
++      MTK_PIN_DRV_GRP(37,  0xb30,  8, 1),
++      MTK_PIN_DRV_GRP(38,  0xb30,  8, 1),
++      MTK_PIN_DRV_GRP(39,  0xb30, 12, 1),
++      MTK_PIN_DRV_GRP(40,  0xb30, 12, 1),
++      MTK_PIN_DRV_GRP(41,  0xb30, 12, 1),
++      MTK_PIN_DRV_GRP(42,  0xb30, 12, 1),
++      MTK_PIN_DRV_GRP(43,  0xb40, 12, 0),
++      MTK_PIN_DRV_GRP(44,  0xb40, 12, 0),
++      MTK_PIN_DRV_GRP(45,  0xb40, 12, 0),
++      MTK_PIN_DRV_GRP(46,  0xb50,  0, 2),
++      MTK_PIN_DRV_GRP(47,  0xb50,  0, 2),
++      MTK_PIN_DRV_GRP(48,  0xb50,  0, 2),
++      MTK_PIN_DRV_GRP(49,  0xb50,  0, 2),
++      MTK_PIN_DRV_GRP(50,  0xb70,  0, 1),
++      MTK_PIN_DRV_GRP(51,  0xb70,  0, 1),
++      MTK_PIN_DRV_GRP(52,  0xb70,  0, 1),
++      MTK_PIN_DRV_GRP(53,  0xb50, 12, 1),
++      MTK_PIN_DRV_GRP(54,  0xb50, 12, 1),
++      MTK_PIN_DRV_GRP(55,  0xb50, 12, 1),
++      MTK_PIN_DRV_GRP(56,  0xb50, 12, 1),
++      MTK_PIN_DRV_GRP(59,  0xb40,  4, 1),
++      MTK_PIN_DRV_GRP(60,  0xb40,  0, 1),
++      MTK_PIN_DRV_GRP(61,  0xb40,  0, 1),
++      MTK_PIN_DRV_GRP(62,  0xb40,  0, 1),
++      MTK_PIN_DRV_GRP(63,  0xb40,  4, 1),
++      MTK_PIN_DRV_GRP(64,  0xb40,  4, 1),
++      MTK_PIN_DRV_GRP(65,  0xb40,  4, 1),
++      MTK_PIN_DRV_GRP(66,  0xb40,  8, 1),
++      MTK_PIN_DRV_GRP(67,  0xb40,  8, 1),
++      MTK_PIN_DRV_GRP(68,  0xb40,  8, 1),
++      MTK_PIN_DRV_GRP(69,  0xb40,  8, 1),
++      MTK_PIN_DRV_GRP(70,  0xb40,  8, 1),
++      MTK_PIN_DRV_GRP(71,  0xb40,  8, 1),
++      MTK_PIN_DRV_GRP(72,  0xb50,  4, 1),
++      MTK_PIN_DRV_GRP(73,  0xb50,  4, 1),
++      MTK_PIN_DRV_GRP(74,  0xb50,  4, 1),
++      MTK_PIN_DRV_GRP(79,  0xb50,  8, 1),
++      MTK_PIN_DRV_GRP(80,  0xb50,  8, 1),
++      MTK_PIN_DRV_GRP(81,  0xb50,  8, 1),
++      MTK_PIN_DRV_GRP(82,  0xb50,  8, 1),
++      MTK_PIN_DRV_GRP(83,  0xb50,  8, 1),
++      MTK_PIN_DRV_GRP(84,  0xb50,  8, 1),
++      MTK_PIN_DRV_GRP(85,  0xce0,  0, 2),
++      MTK_PIN_DRV_GRP(86,  0xcd0,  0, 2),
++      MTK_PIN_DRV_GRP(87,  0xcf0,  0, 2),
++      MTK_PIN_DRV_GRP(88,  0xcf0,  0, 2),
++      MTK_PIN_DRV_GRP(89,  0xcf0,  0, 2),
++      MTK_PIN_DRV_GRP(90,  0xcf0,  0, 2),
++      MTK_PIN_DRV_GRP(117, 0xb60, 12, 1),
++      MTK_PIN_DRV_GRP(118, 0xb60, 12, 1),
++      MTK_PIN_DRV_GRP(119, 0xb60, 12, 1),
++      MTK_PIN_DRV_GRP(120, 0xb60, 12, 1),
++      MTK_PIN_DRV_GRP(121, 0xc80,  0, 2),
++      MTK_PIN_DRV_GRP(122, 0xc70,  0, 2),
++      MTK_PIN_DRV_GRP(123, 0xc90,  0, 2),
++      MTK_PIN_DRV_GRP(124, 0xc90,  0, 2),
++      MTK_PIN_DRV_GRP(125, 0xc90,  0, 2),
++      MTK_PIN_DRV_GRP(126, 0xc90,  0, 2),
++      MTK_PIN_DRV_GRP(127, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(128, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(129, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(130, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(131, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(132, 0xc10,  0, 2),
++      MTK_PIN_DRV_GRP(133, 0xc00,  0, 2),
++      MTK_PIN_DRV_GRP(134, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(135, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(136, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(137, 0xc20,  0, 2),
++      MTK_PIN_DRV_GRP(142, 0xb50,  0, 2),
++};
++
++static const struct mtk_pin_spec_pupd_set_samereg mt8127_spec_pupd[] = {
++      MTK_PIN_PUPD_SPEC_SR(33,  0xd90, 2, 0, 1),      /* KPROW0 */
++      MTK_PIN_PUPD_SPEC_SR(34,  0xd90, 6, 4, 5),      /* KPROW1 */
++      MTK_PIN_PUPD_SPEC_SR(35,  0xd90, 10, 8, 9),     /* KPROW2 */
++      MTK_PIN_PUPD_SPEC_SR(36,  0xda0, 2, 0, 1),      /* KPCOL0 */
++      MTK_PIN_PUPD_SPEC_SR(37,  0xda0, 6, 4, 5),      /* KPCOL1 */
++      MTK_PIN_PUPD_SPEC_SR(38,  0xda0, 10, 8, 9),     /* KPCOL2 */
++      MTK_PIN_PUPD_SPEC_SR(46,  0xdb0, 2, 0, 1),      /* EINT14 */
++      MTK_PIN_PUPD_SPEC_SR(47,  0xdb0, 6, 4, 5),      /* EINT15 */
++      MTK_PIN_PUPD_SPEC_SR(48,  0xdb0, 10, 8, 9),     /* EINT16 */
++      MTK_PIN_PUPD_SPEC_SR(49,  0xdb0, 14, 12, 13),   /* EINT17 */
++      MTK_PIN_PUPD_SPEC_SR(85,  0xce0, 8, 10, 9),     /* MSDC2_CMD */
++      MTK_PIN_PUPD_SPEC_SR(86,  0xcd0, 8, 10, 9),     /* MSDC2_CLK */
++      MTK_PIN_PUPD_SPEC_SR(87,  0xd00, 0, 2, 1),      /* MSDC2_DAT0 */
++      MTK_PIN_PUPD_SPEC_SR(88,  0xd00, 4, 6, 5),      /* MSDC2_DAT1 */
++      MTK_PIN_PUPD_SPEC_SR(89,  0xd00, 8, 10, 9),     /* MSDC2_DAT2 */
++      MTK_PIN_PUPD_SPEC_SR(90,  0xd00, 12, 14, 13),   /* MSDC2_DAT3 */
++      MTK_PIN_PUPD_SPEC_SR(121, 0xc80, 8, 10, 9),     /* MSDC1_CMD */
++      MTK_PIN_PUPD_SPEC_SR(122, 0xc70, 8, 10, 9),     /* MSDC1_CLK */
++      MTK_PIN_PUPD_SPEC_SR(123, 0xca0, 0, 2, 1),      /* MSDC1_DAT0 */
++      MTK_PIN_PUPD_SPEC_SR(124, 0xca0, 4, 6, 5),      /* MSDC1_DAT1 */
++      MTK_PIN_PUPD_SPEC_SR(125, 0xca0, 8, 10, 9),     /* MSDC1_DAT2 */
++      MTK_PIN_PUPD_SPEC_SR(126, 0xca0, 12, 14, 13),   /* MSDC1_DAT3 */
++      MTK_PIN_PUPD_SPEC_SR(127, 0xc40, 12, 14, 13),   /* MSDC0_DAT7 */
++      MTK_PIN_PUPD_SPEC_SR(128, 0xc40, 8, 10, 9),     /* MSDC0_DAT6 */
++      MTK_PIN_PUPD_SPEC_SR(129, 0xc40, 4, 6, 5),      /* MSDC0_DAT5 */
++      MTK_PIN_PUPD_SPEC_SR(130, 0xc40, 0, 2, 1),      /* MSDC0_DAT4 */
++      MTK_PIN_PUPD_SPEC_SR(131, 0xc50, 0, 2, 1),      /* MSDC0_RSTB */
++      MTK_PIN_PUPD_SPEC_SR(132, 0xc10, 8, 10, 9),     /* MSDC0_CMD */
++      MTK_PIN_PUPD_SPEC_SR(133, 0xc00, 8, 10, 9),     /* MSDC0_CLK */
++      MTK_PIN_PUPD_SPEC_SR(134, 0xc30, 12, 14, 13),   /* MSDC0_DAT3 */
++      MTK_PIN_PUPD_SPEC_SR(135, 0xc30, 8, 10, 9),     /* MSDC0_DAT2 */
++      MTK_PIN_PUPD_SPEC_SR(136, 0xc30, 4, 6, 5),      /* MSDC0_DAT1 */
++      MTK_PIN_PUPD_SPEC_SR(137, 0xc30, 0, 2, 1),      /* MSDC0_DAT0 */
++      MTK_PIN_PUPD_SPEC_SR(142, 0xdc0, 2, 0, 1),      /* EINT21 */
++};
++
++static int mt8127_spec_pull_set(struct regmap *regmap, unsigned int pin,
++              unsigned char align, bool isup, unsigned int r1r0)
++{
++      return mtk_pctrl_spec_pull_set_samereg(regmap, mt8127_spec_pupd,
++              ARRAY_SIZE(mt8127_spec_pupd), pin, align, isup, r1r0);
++}
++
++static const struct mtk_pin_ies_smt_set mt8127_ies_set[] = {
++      MTK_PIN_IES_SMT_SPEC(0, 9, 0x900, 0),
++      MTK_PIN_IES_SMT_SPEC(10, 13, 0x900, 1),
++      MTK_PIN_IES_SMT_SPEC(14, 28, 0x900, 2),
++      MTK_PIN_IES_SMT_SPEC(29, 32, 0x900, 3),
++      MTK_PIN_IES_SMT_SPEC(33, 33, 0x910, 11),
++      MTK_PIN_IES_SMT_SPEC(34, 38, 0x900, 10),
++      MTK_PIN_IES_SMT_SPEC(39, 42, 0x900, 11),
++      MTK_PIN_IES_SMT_SPEC(43, 45, 0x900, 12),
++      MTK_PIN_IES_SMT_SPEC(46, 49, 0x900, 13),
++      MTK_PIN_IES_SMT_SPEC(50, 52, 0x910, 10),
++      MTK_PIN_IES_SMT_SPEC(53, 56, 0x900, 14),
++      MTK_PIN_IES_SMT_SPEC(57, 58, 0x910, 0),
++      MTK_PIN_IES_SMT_SPEC(59, 65, 0x910, 2),
++      MTK_PIN_IES_SMT_SPEC(66, 71, 0x910, 3),
++      MTK_PIN_IES_SMT_SPEC(72, 74, 0x910, 4),
++      MTK_PIN_IES_SMT_SPEC(75, 76, 0x900, 15),
++      MTK_PIN_IES_SMT_SPEC(77, 78, 0x910, 1),
++      MTK_PIN_IES_SMT_SPEC(79, 82, 0x910, 5),
++      MTK_PIN_IES_SMT_SPEC(83, 84, 0x910, 6),
++      MTK_PIN_IES_SMT_SPEC(117, 120, 0x910, 7),
++      MTK_PIN_IES_SMT_SPEC(121, 121, 0xc80, 4),
++      MTK_PIN_IES_SMT_SPEC(122, 122, 0xc70, 4),
++      MTK_PIN_IES_SMT_SPEC(123, 126, 0xc90, 4),
++      MTK_PIN_IES_SMT_SPEC(127, 131, 0xc20, 4),
++      MTK_PIN_IES_SMT_SPEC(132, 132, 0xc10, 4),
++      MTK_PIN_IES_SMT_SPEC(133, 133, 0xc00, 4),
++      MTK_PIN_IES_SMT_SPEC(134, 137, 0xc20, 4),
++      MTK_PIN_IES_SMT_SPEC(138, 141, 0x910, 9),
++      MTK_PIN_IES_SMT_SPEC(142, 142, 0x900, 13),
++};
++
++static const struct mtk_pin_ies_smt_set mt8127_smt_set[] = {
++      MTK_PIN_IES_SMT_SPEC(0, 9, 0x920, 0),
++      MTK_PIN_IES_SMT_SPEC(10, 13, 0x920, 1),
++      MTK_PIN_IES_SMT_SPEC(14, 28, 0x920, 2),
++      MTK_PIN_IES_SMT_SPEC(29, 32, 0x920, 3),
++      MTK_PIN_IES_SMT_SPEC(33, 33, 0x930, 11),
++      MTK_PIN_IES_SMT_SPEC(34, 38, 0x920, 10),
++      MTK_PIN_IES_SMT_SPEC(39, 42, 0x920, 11),
++      MTK_PIN_IES_SMT_SPEC(43, 45, 0x920, 12),
++      MTK_PIN_IES_SMT_SPEC(46, 49, 0x920, 13),
++      MTK_PIN_IES_SMT_SPEC(50, 52, 0x930, 10),
++      MTK_PIN_IES_SMT_SPEC(53, 56, 0x920, 14),
++      MTK_PIN_IES_SMT_SPEC(57, 58, 0x930, 0),
++      MTK_PIN_IES_SMT_SPEC(59, 65, 0x930, 2),
++      MTK_PIN_IES_SMT_SPEC(66, 71, 0x930, 3),
++      MTK_PIN_IES_SMT_SPEC(72, 74, 0x930, 4),
++      MTK_PIN_IES_SMT_SPEC(75, 76, 0x920, 15),
++      MTK_PIN_IES_SMT_SPEC(77, 78, 0x930, 1),
++      MTK_PIN_IES_SMT_SPEC(79, 82, 0x930, 5),
++      MTK_PIN_IES_SMT_SPEC(83, 84, 0x930, 6),
++      MTK_PIN_IES_SMT_SPEC(85, 85, 0xce0, 11),
++      MTK_PIN_IES_SMT_SPEC(86, 86, 0xcd0, 11),
++      MTK_PIN_IES_SMT_SPEC(87, 87, 0xd00, 3),
++      MTK_PIN_IES_SMT_SPEC(88, 88, 0xd00, 7),
++      MTK_PIN_IES_SMT_SPEC(89, 89, 0xd00, 11),
++      MTK_PIN_IES_SMT_SPEC(90, 90, 0xd00, 15),
++      MTK_PIN_IES_SMT_SPEC(117, 120, 0x930, 7),
++      MTK_PIN_IES_SMT_SPEC(121, 121, 0xc80, 11),
++      MTK_PIN_IES_SMT_SPEC(122, 122, 0xc70, 11),
++      MTK_PIN_IES_SMT_SPEC(123, 123, 0xca0, 3),
++      MTK_PIN_IES_SMT_SPEC(124, 124, 0xca0, 7),
++      MTK_PIN_IES_SMT_SPEC(125, 125, 0xca0, 11),
++      MTK_PIN_IES_SMT_SPEC(126, 126, 0xca0, 15),
++      MTK_PIN_IES_SMT_SPEC(127, 127, 0xc40, 15),
++      MTK_PIN_IES_SMT_SPEC(128, 128, 0xc40, 11),
++      MTK_PIN_IES_SMT_SPEC(129, 129, 0xc40, 7),
++      MTK_PIN_IES_SMT_SPEC(130, 130, 0xc40, 3),
++      MTK_PIN_IES_SMT_SPEC(131, 131, 0xc50, 3),
++      MTK_PIN_IES_SMT_SPEC(132, 132, 0xc10, 11),
++      MTK_PIN_IES_SMT_SPEC(133, 133, 0xc00, 11),
++      MTK_PIN_IES_SMT_SPEC(134, 134, 0xc30, 15),
++      MTK_PIN_IES_SMT_SPEC(135, 135, 0xc30, 11),
++      MTK_PIN_IES_SMT_SPEC(136, 136, 0xc30, 7),
++      MTK_PIN_IES_SMT_SPEC(137, 137, 0xc30, 3),
++      MTK_PIN_IES_SMT_SPEC(138, 141, 0x930, 9),
++      MTK_PIN_IES_SMT_SPEC(142, 142, 0x920, 13),
++};
++
++static int mt8127_ies_smt_set(struct regmap *regmap, unsigned int pin,
++              unsigned char align, int value, enum pin_config_param arg)
++{
++      if (arg == PIN_CONFIG_INPUT_ENABLE)
++              return mtk_pconf_spec_set_ies_smt_range(regmap, mt8127_ies_set,
++                      ARRAY_SIZE(mt8127_ies_set), pin, align, value);
++      else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++              return mtk_pconf_spec_set_ies_smt_range(regmap, mt8127_smt_set,
++                      ARRAY_SIZE(mt8127_smt_set), pin, align, value);
++      return -EINVAL;
++}
++
++
++static const struct mtk_pinctrl_devdata mt8127_pinctrl_data = {
++      .pins = mtk_pins_mt8127,
++      .npins = ARRAY_SIZE(mtk_pins_mt8127),
++      .grp_desc = mt8127_drv_grp,
++      .n_grp_cls = ARRAY_SIZE(mt8127_drv_grp),
++      .pin_drv_grp = mt8127_pin_drv,
++      .n_pin_drv_grps = ARRAY_SIZE(mt8127_pin_drv),
++      .spec_pull_set = mt8127_spec_pull_set,
++      .spec_ies_smt_set = mt8127_ies_smt_set,
++      .dir_offset = 0x0000,
++      .pullen_offset = 0x0100,
++      .pullsel_offset = 0x0200,
++      .dout_offset = 0x0400,
++      .din_offset = 0x0500,
++      .pinmux_offset = 0x0600,
++      .type1_start = 143,
++      .type1_end = 143,
++      .port_shf = 4,
++      .port_mask = 0xf,
++      .port_align = 4,
++      .eint_offsets = {
++              .name = "mt8127_eint",
++              .stat      = 0x000,
++              .ack       = 0x040,
++              .mask      = 0x080,
++              .mask_set  = 0x0c0,
++              .mask_clr  = 0x100,
++              .sens      = 0x140,
++              .sens_set  = 0x180,
++              .sens_clr  = 0x1c0,
++              .soft      = 0x200,
++              .soft_set  = 0x240,
++              .soft_clr  = 0x280,
++              .pol       = 0x300,
++              .pol_set   = 0x340,
++              .pol_clr   = 0x380,
++              .dom_en    = 0x400,
++              .dbnc_ctrl = 0x500,
++              .dbnc_set  = 0x600,
++              .dbnc_clr  = 0x700,
++              .port_mask = 7,
++              .ports     = 6,
++      },
++      .ap_num = 143,
++      .db_cnt = 16,
++};
++
++static int mt8127_pinctrl_probe(struct platform_device *pdev)
++{
++      return mtk_pctrl_init(pdev, &mt8127_pinctrl_data, NULL);
++}
++
++static const struct of_device_id mt8127_pctrl_match[] = {
++      { .compatible = "mediatek,mt8127-pinctrl", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, mt8127_pctrl_match);
++
++static struct platform_driver mtk_pinctrl_driver = {
++      .probe = mt8127_pinctrl_probe,
++      .driver = {
++              .name = "mediatek-mt8127-pinctrl",
++              .owner = THIS_MODULE,
++              .of_match_table = mt8127_pctrl_match,
++      },
++};
++
++static int __init mtk_pinctrl_init(void)
++{
++      return platform_driver_register(&mtk_pinctrl_driver);
++}
++
++module_init(mtk_pinctrl_init);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek MT8127 Pinctrl Driver");
++MODULE_AUTHOR("Yingjoe Chen <yingjoe.chen@mediatek.com>");
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h
+new file mode 100644
+index 0000000..212559c
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8127.h
+@@ -0,0 +1,1318 @@
++#ifndef __PINCTRL_MTK_MT8127_H
++#define __PINCTRL_MTK_MT8127_H
++
++#include <linux/pinctrl/pinctrl.h>
++#include "pinctrl-mtk-common.h"
++
++static const struct mtk_desc_pin mtk_pins_mt8127[] = {
++      MTK_PIN(
++              PINCTRL_PIN(0, "PWRAP_SPI0_MI"),
++              "P22", "mt8127",
++              MTK_EINT_FUNCTION(0, 22),
++              MTK_FUNCTION(0, "GPIO0"),
++              MTK_FUNCTION(1, "PWRAP_SPIDO"),
++              MTK_FUNCTION(2, "PWRAP_SPIDI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(1, "PWRAP_SPI0_MO"),
++              "M22", "mt8127",
++              MTK_EINT_FUNCTION(0, 23),
++              MTK_FUNCTION(0, "GPIO1"),
++              MTK_FUNCTION(1, "PWRAP_SPIDI"),
++              MTK_FUNCTION(2, "PWRAP_SPIDO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(2, "PWRAP_INT"),
++              "L23", "mt8127",
++              MTK_EINT_FUNCTION(0, 24),
++              MTK_FUNCTION(0, "GPIO2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(3, "PWRAP_SPI0_CK"),
++              "N23", "mt8127",
++              MTK_EINT_FUNCTION(0, 25),
++              MTK_FUNCTION(0, "GPIO3"),
++              MTK_FUNCTION(1, "PWRAP_SPICK_I")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(4, "PWRAP_SPI0_CSN"),
++              "N22", "mt8127",
++              MTK_EINT_FUNCTION(0, 26),
++              MTK_FUNCTION(0, "GPIO4"),
++              MTK_FUNCTION(1, "PWRAP_SPICS_B_I")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(5, "PWRAP_SPI0_CK2"),
++              "L19", "mt8127",
++              MTK_EINT_FUNCTION(0, 27),
++              MTK_FUNCTION(0, "GPIO5"),
++              MTK_FUNCTION(1, "PWRAP_SPICK2_I"),
++              MTK_FUNCTION(2, "ANT_SEL1"),
++              MTK_FUNCTION(3, "VDEC_TEST_CK"),
++              MTK_FUNCTION(7, "DBG_MON_B[0]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"),
++              "M23", "mt8127",
++              MTK_EINT_FUNCTION(0, 28),
++              MTK_FUNCTION(0, "GPIO6"),
++              MTK_FUNCTION(1, "PWRAP_SPICS2_B_I"),
++              MTK_FUNCTION(2, "ANT_SEL0"),
++              MTK_FUNCTION(3, "MM_TEST_CK"),
++              MTK_FUNCTION(7, "DBG_MON_B[1]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(7, "AUD_CLK_MOSI"),
++              "K23", "mt8127",
++              MTK_EINT_FUNCTION(0, 29),
++              MTK_FUNCTION(0, "GPIO7"),
++              MTK_FUNCTION(1, "AUD_CLK"),
++              MTK_FUNCTION(2, "ADC_CK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(8, "AUD_DAT_MISO"),
++              "K24", "mt8127",
++              MTK_EINT_FUNCTION(0, 30),
++              MTK_FUNCTION(0, "GPIO8"),
++              MTK_FUNCTION(1, "AUD_MISO"),
++              MTK_FUNCTION(2, "ADC_DAT_IN"),
++              MTK_FUNCTION(3, "AUD_MOSI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(9, "AUD_DAT_MOSI"),
++              "K22", "mt8127",
++              MTK_EINT_FUNCTION(0, 31),
++              MTK_FUNCTION(0, "GPIO9"),
++              MTK_FUNCTION(1, "AUD_MOSI"),
++              MTK_FUNCTION(2, "ADC_WS"),
++              MTK_FUNCTION(3, "AUD_MISO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(10, "RTC32K_CK"),
++              "R21", "mt8127",
++              MTK_EINT_FUNCTION(0, 32),
++              MTK_FUNCTION(0, "GPIO10"),
++              MTK_FUNCTION(1, "RTC32K_CK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(11, "WATCHDOG"),
++              "P24", "mt8127",
++              MTK_EINT_FUNCTION(0, 33),
++              MTK_FUNCTION(0, "GPIO11"),
++              MTK_FUNCTION(1, "WATCHDOG")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(12, "SRCLKENA"),
++              "R22", "mt8127",
++              MTK_EINT_FUNCTION(0, 34),
++              MTK_FUNCTION(0, "GPIO12"),
++              MTK_FUNCTION(1, "SRCLKENA")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(13, "SRCLKENAI"),
++              "P23", "mt8127",
++              MTK_EINT_FUNCTION(0, 35),
++              MTK_FUNCTION(0, "GPIO13"),
++              MTK_FUNCTION(1, "SRCLKENAI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(14, "URXD2"),
++              "U19", "mt8127",
++              MTK_EINT_FUNCTION(0, 36),
++              MTK_FUNCTION(0, "GPIO14"),
++              MTK_FUNCTION(1, "URXD2"),
++              MTK_FUNCTION(2, "DPI_D5"),
++              MTK_FUNCTION(3, "UTXD2"),
++              MTK_FUNCTION(5, "SRCCLKENAI2"),
++              MTK_FUNCTION(6, "KROW4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(15, "UTXD2"),
++              "U20", "mt8127",
++              MTK_EINT_FUNCTION(0, 37),
++              MTK_FUNCTION(0, "GPIO15"),
++              MTK_FUNCTION(1, "UTXD2"),
++              MTK_FUNCTION(2, "DPI_HSYNC"),
++              MTK_FUNCTION(3, "URXD2"),
++              MTK_FUNCTION(6, "KROW5")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(16, "URXD3"),
++              "U18", "mt8127",
++              MTK_EINT_FUNCTION(0, 38),
++              MTK_FUNCTION(0, "GPIO16"),
++              MTK_FUNCTION(1, "URXD3"),
++              MTK_FUNCTION(2, "DPI_DE"),
++              MTK_FUNCTION(3, "UTXD3"),
++              MTK_FUNCTION(4, "UCTS2"),
++              MTK_FUNCTION(5, "PWM3"),
++              MTK_FUNCTION(6, "KROW6")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(17, "UTXD3"),
++              "R18", "mt8127",
++              MTK_EINT_FUNCTION(0, 39),
++              MTK_FUNCTION(0, "GPIO17"),
++              MTK_FUNCTION(1, "UTXD3"),
++              MTK_FUNCTION(2, "DPI_VSYNC"),
++              MTK_FUNCTION(3, "URXD3"),
++              MTK_FUNCTION(4, "URTS2"),
++              MTK_FUNCTION(5, "PWM4"),
++              MTK_FUNCTION(6, "KROW7")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(18, "PCM_CLK"),
++              "U22", "mt8127",
++              MTK_EINT_FUNCTION(0, 40),
++              MTK_FUNCTION(0, "GPIO18"),
++              MTK_FUNCTION(1, "PCM_CLK0"),
++              MTK_FUNCTION(2, "DPI_D4"),
++              MTK_FUNCTION(3, "I2SIN1_BCK0"),
++              MTK_FUNCTION(4, "I2SOUT_BCK"),
++              MTK_FUNCTION(5, "CONN_DSP_JCK"),
++              MTK_FUNCTION(6, "IR"),
++              MTK_FUNCTION(7, "DBG_MON_A[0]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(19, "PCM_SYNC"),
++              "U23", "mt8127",
++              MTK_EINT_FUNCTION(0, 41),
++              MTK_FUNCTION(0, "GPIO19"),
++              MTK_FUNCTION(1, "PCM_SYNC"),
++              MTK_FUNCTION(2, "DPI_D3"),
++              MTK_FUNCTION(3, "I2SIN1_LRCK"),
++              MTK_FUNCTION(4, "I2SOUT_LRCK"),
++              MTK_FUNCTION(5, "CONN_DSP_JINTP"),
++              MTK_FUNCTION(6, "EXT_COL"),
++              MTK_FUNCTION(7, "DBG_MON_A[1]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(20, "PCM_RX"),
++              "V22", "mt8127",
++              MTK_EINT_FUNCTION(0, 42),
++              MTK_FUNCTION(0, "GPIO20"),
++              MTK_FUNCTION(1, "PCM_RX"),
++              MTK_FUNCTION(2, "DPI_D1"),
++              MTK_FUNCTION(3, "I2SIN1_DATA_IN"),
++              MTK_FUNCTION(4, "PCM_TX"),
++              MTK_FUNCTION(5, "CONN_DSP_JDI"),
++              MTK_FUNCTION(6, "EXT_MDIO"),
++              MTK_FUNCTION(7, "DBG_MON_A[2]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(21, "PCM_TX"),
++              "U21", "mt8127",
++              MTK_EINT_FUNCTION(0, 43),
++              MTK_FUNCTION(0, "GPIO21"),
++              MTK_FUNCTION(1, "PCM_TX"),
++              MTK_FUNCTION(2, "DPI_D2"),
++              MTK_FUNCTION(3, "I2SOUT_DATA_OUT"),
++              MTK_FUNCTION(4, "PCM_RX"),
++              MTK_FUNCTION(5, "CONN_DSP_JMS"),
++              MTK_FUNCTION(6, "EXT_MDC"),
++              MTK_FUNCTION(7, "DBG_MON_A[3]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(22, "EINT0"),
++              "AB19", "mt8127",
++              MTK_EINT_FUNCTION(0, 0),
++              MTK_FUNCTION(0, "GPIO22"),
++              MTK_FUNCTION(1, "PWM1"),
++              MTK_FUNCTION(2, "DPI_CK"),
++              MTK_FUNCTION(4, "EXT_TXD0"),
++              MTK_FUNCTION(5, "CONN_DSP_JDO"),
++              MTK_FUNCTION(7, "DBG_MON_A[4]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(23, "EINT1"),
++              "AA21", "mt8127",
++              MTK_EINT_FUNCTION(0, 1),
++              MTK_FUNCTION(0, "GPIO23"),
++              MTK_FUNCTION(1, "PWM2"),
++              MTK_FUNCTION(2, "DPI_D12"),
++              MTK_FUNCTION(4, "EXT_TXD1"),
++              MTK_FUNCTION(5, "CONN_MCU_TDO"),
++              MTK_FUNCTION(7, "DBG_MON_A[5]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(24, "EINT2"),
++              "AA19", "mt8127",
++              MTK_EINT_FUNCTION(0, 2),
++              MTK_FUNCTION(0, "GPIO24"),
++              MTK_FUNCTION(1, "CLKM0"),
++              MTK_FUNCTION(2, "DPI_D13"),
++              MTK_FUNCTION(4, "EXT_TXD2"),
++              MTK_FUNCTION(5, "CONN_MCU_DBGACK_N"),
++              MTK_FUNCTION(6, "KCOL4"),
++              MTK_FUNCTION(7, "DBG_MON_A[6]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(25, "EINT3"),
++              "Y19", "mt8127",
++              MTK_EINT_FUNCTION(0, 3),
++              MTK_FUNCTION(0, "GPIO25"),
++              MTK_FUNCTION(1, "CLKM1"),
++              MTK_FUNCTION(2, "DPI_D14"),
++              MTK_FUNCTION(3, "SPI_MI"),
++              MTK_FUNCTION(4, "EXT_TXD3"),
++              MTK_FUNCTION(5, "CONN_MCU_DBGI_N"),
++              MTK_FUNCTION(6, "KCOL5"),
++              MTK_FUNCTION(7, "DBG_MON_A[7]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(26, "EINT4"),
++              "V21", "mt8127",
++              MTK_EINT_FUNCTION(0, 4),
++              MTK_FUNCTION(0, "GPIO26"),
++              MTK_FUNCTION(1, "CLKM2"),
++              MTK_FUNCTION(2, "DPI_D15"),
++              MTK_FUNCTION(3, "SPI_MO"),
++              MTK_FUNCTION(4, "EXT_TXC"),
++              MTK_FUNCTION(5, "CONN_MCU_TCK0"),
++              MTK_FUNCTION(6, "CONN_MCU_AICE_JCKC"),
++              MTK_FUNCTION(7, "DBG_MON_A[8]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(27, "EINT5"),
++              "AB22", "mt8127",
++              MTK_EINT_FUNCTION(0, 5),
++              MTK_FUNCTION(0, "GPIO27"),
++              MTK_FUNCTION(1, "UCTS2"),
++              MTK_FUNCTION(2, "DPI_D16"),
++              MTK_FUNCTION(3, "SPI_CS"),
++              MTK_FUNCTION(4, "EXT_RXER"),
++              MTK_FUNCTION(5, "CONN_MCU_TDI"),
++              MTK_FUNCTION(6, "KCOL6"),
++              MTK_FUNCTION(7, "DBG_MON_A[9]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(28, "EINT6"),
++              "AA23", "mt8127",
++              MTK_EINT_FUNCTION(0, 6),
++              MTK_FUNCTION(0, "GPIO28"),
++              MTK_FUNCTION(1, "URTS2"),
++              MTK_FUNCTION(2, "DPI_D17"),
++              MTK_FUNCTION(3, "SPI_CK"),
++              MTK_FUNCTION(4, "EXT_RXC"),
++              MTK_FUNCTION(5, "CONN_MCU_TRST_B"),
++              MTK_FUNCTION(6, "KCOL7"),
++              MTK_FUNCTION(7, "DBG_MON_A[10]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(29, "EINT7"),
++              "Y23", "mt8127",
++              MTK_EINT_FUNCTION(0, 7),
++              MTK_FUNCTION(0, "GPIO29"),
++              MTK_FUNCTION(1, "UCTS3"),
++              MTK_FUNCTION(2, "DPI_D6"),
++              MTK_FUNCTION(3, "SDA1"),
++              MTK_FUNCTION(4, "EXT_RXDV"),
++              MTK_FUNCTION(5, "CONN_MCU_TMS"),
++              MTK_FUNCTION(6, "CONN_MCU_AICE_JMSC"),
++              MTK_FUNCTION(7, "DBG_MON_A[11]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(30, "EINT8"),
++              "Y24", "mt8127",
++              MTK_EINT_FUNCTION(0, 8),
++              MTK_FUNCTION(0, "GPIO30"),
++              MTK_FUNCTION(1, "URTS3"),
++              MTK_FUNCTION(2, "CLKM3"),
++              MTK_FUNCTION(3, "SCL1"),
++              MTK_FUNCTION(4, "EXT_RXD0"),
++              MTK_FUNCTION(5, "ANT_SEL0"),
++              MTK_FUNCTION(6, "DPI_D7"),
++              MTK_FUNCTION(7, "DBG_MON_B[2]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(31, "EINT9"),
++              "W23", "mt8127",
++              MTK_EINT_FUNCTION(0, 9),
++              MTK_FUNCTION(0, "GPIO31"),
++              MTK_FUNCTION(1, "CLKM4"),
++              MTK_FUNCTION(2, "SDA2"),
++              MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++              MTK_FUNCTION(4, "EXT_RXD1"),
++              MTK_FUNCTION(5, "ANT_SEL1"),
++              MTK_FUNCTION(6, "DPI_D8"),
++              MTK_FUNCTION(7, "DBG_MON_B[3]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(32, "EINT10"),
++              "W24", "mt8127",
++              MTK_EINT_FUNCTION(0, 10),
++              MTK_FUNCTION(0, "GPIO32"),
++              MTK_FUNCTION(1, "CLKM5"),
++              MTK_FUNCTION(2, "SCL2"),
++              MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++              MTK_FUNCTION(4, "EXT_RXD2"),
++              MTK_FUNCTION(5, "ANT_SEL2"),
++              MTK_FUNCTION(6, "DPI_D9"),
++              MTK_FUNCTION(7, "DBG_MON_B[4]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(33, "KPROW0"),
++              "AB24", "mt8127",
++              MTK_EINT_FUNCTION(0, 44),
++              MTK_FUNCTION(0, "GPIO33"),
++              MTK_FUNCTION(1, "KROW0"),
++              MTK_FUNCTION(4, "IMG_TEST_CK"),
++              MTK_FUNCTION(7, "DBG_MON_A[12]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(34, "KPROW1"),
++              "AC24", "mt8127",
++              MTK_EINT_FUNCTION(0, 45),
++              MTK_FUNCTION(0, "GPIO34"),
++              MTK_FUNCTION(1, "KROW1"),
++              MTK_FUNCTION(2, "IDDIG"),
++              MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++              MTK_FUNCTION(4, "MFG_TEST_CK"),
++              MTK_FUNCTION(7, "DBG_MON_B[5]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(35, "KPROW2"),
++              "AD24", "mt8127",
++              MTK_EINT_FUNCTION(0, 46),
++              MTK_FUNCTION(0, "GPIO35"),
++              MTK_FUNCTION(1, "KROW2"),
++              MTK_FUNCTION(2, "DRV_VBUS"),
++              MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++              MTK_FUNCTION(4, "CONN_TEST_CK"),
++              MTK_FUNCTION(7, "DBG_MON_B[6]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(36, "KPCOL0"),
++              "AB23", "mt8127",
++              MTK_EINT_FUNCTION(0, 47),
++              MTK_FUNCTION(0, "GPIO36"),
++              MTK_FUNCTION(1, "KCOL0"),
++              MTK_FUNCTION(7, "DBG_MON_A[13]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(37, "KPCOL1"),
++              "AC22", "mt8127",
++              MTK_EINT_FUNCTION(0, 48),
++              MTK_FUNCTION(0, "GPIO37"),
++              MTK_FUNCTION(1, "KCOL1"),
++              MTK_FUNCTION(7, "DBG_MON_B[7]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(38, "KPCOL2"),
++              "AC23", "mt8127",
++              MTK_EINT_FUNCTION(0, 49),
++              MTK_FUNCTION(0, "GPIO38"),
++              MTK_FUNCTION(1, "KCOL2"),
++              MTK_FUNCTION(2, "IDDIG"),
++              MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
++              MTK_FUNCTION(7, "DBG_MON_B[8]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(39, "JTMS"),
++              "V18", "mt8127",
++              MTK_EINT_FUNCTION(0, 50),
++              MTK_FUNCTION(0, "GPIO39"),
++              MTK_FUNCTION(1, "JTMS"),
++              MTK_FUNCTION(2, "CONN_MCU_TMS"),
++              MTK_FUNCTION(3, "CONN_MCU_AICE_JMSC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(40, "JTCK"),
++              "AA18", "mt8127",
++              MTK_EINT_FUNCTION(0, 51),
++              MTK_FUNCTION(0, "GPIO40"),
++              MTK_FUNCTION(1, "JTCK"),
++              MTK_FUNCTION(2, "CONN_MCU_TCK1"),
++              MTK_FUNCTION(3, "CONN_MCU_AICE_JCKC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(41, "JTDI"),
++              "W18", "mt8127",
++              MTK_EINT_FUNCTION(0, 52),
++              MTK_FUNCTION(0, "GPIO41"),
++              MTK_FUNCTION(1, "JTDI"),
++              MTK_FUNCTION(2, "CONN_MCU_TDI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(42, "JTDO"),
++              "Y18", "mt8127",
++              MTK_EINT_FUNCTION(0, 53),
++              MTK_FUNCTION(0, "GPIO42"),
++              MTK_FUNCTION(1, "JTDO"),
++              MTK_FUNCTION(2, "CONN_MCU_TDO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(43, "EINT11"),
++              "W22", "mt8127",
++              MTK_EINT_FUNCTION(0, 11),
++              MTK_FUNCTION(0, "GPIO43"),
++              MTK_FUNCTION(1, "CLKM4"),
++              MTK_FUNCTION(2, "PWM2"),
++              MTK_FUNCTION(3, "KROW3"),
++              MTK_FUNCTION(4, "ANT_SEL3"),
++              MTK_FUNCTION(5, "DPI_D10"),
++              MTK_FUNCTION(6, "EXT_RXD3"),
++              MTK_FUNCTION(7, "DBG_MON_B[9]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(44, "EINT12"),
++              "V23", "mt8127",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO44"),
++              MTK_FUNCTION(1, "CLKM5"),
++              MTK_FUNCTION(2, "PWM0"),
++              MTK_FUNCTION(3, "KCOL3"),
++              MTK_FUNCTION(4, "ANT_SEL4"),
++              MTK_FUNCTION(5, "DPI_D11"),
++              MTK_FUNCTION(6, "EXT_TXEN"),
++              MTK_FUNCTION(7, "DBG_MON_B[10]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(45, "EINT13"),
++              "Y21", "mt8127",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO45"),
++              MTK_FUNCTION(4, "ANT_SEL5"),
++              MTK_FUNCTION(5, "DPI_D0"),
++              MTK_FUNCTION(6, "SPDIF"),
++              MTK_FUNCTION(7, "DBG_MON_B[11]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(46, "EINT14"),
++              "F23", "mt8127",
++              MTK_EINT_FUNCTION(0, 14),
++              MTK_FUNCTION(0, "GPIO46"),
++              MTK_FUNCTION(2, "DAC_DAT_OUT"),
++              MTK_FUNCTION(4, "ANT_SEL1"),
++              MTK_FUNCTION(5, "CONN_MCU_DBGACK_N"),
++              MTK_FUNCTION(6, "NCLE"),
++              MTK_FUNCTION(7, "DBG_MON_A[14]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(47, "EINT15"),
++              "G23", "mt8127",
++              MTK_EINT_FUNCTION(0, 15),
++              MTK_FUNCTION(0, "GPIO47"),
++              MTK_FUNCTION(2, "DAC_WS"),
++              MTK_FUNCTION(4, "ANT_SEL2"),
++              MTK_FUNCTION(5, "CONN_MCU_DBGI_N"),
++              MTK_FUNCTION(6, "NCEB1"),
++              MTK_FUNCTION(7, "DBG_MON_A[15]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(48, "EINT16"),
++              "H23", "mt8127",
++              MTK_EINT_FUNCTION(0, 16),
++              MTK_FUNCTION(0, "GPIO48"),
++              MTK_FUNCTION(2, "DAC_CK"),
++              MTK_FUNCTION(4, "ANT_SEL3"),
++              MTK_FUNCTION(5, "CONN_MCU_TRST_B"),
++              MTK_FUNCTION(6, "NCEB0"),
++              MTK_FUNCTION(7, "DBG_MON_A[16]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(49, "EINT17"),
++              "J22", "mt8127",
++              MTK_EINT_FUNCTION(0, 17),
++              MTK_FUNCTION(0, "GPIO49"),
++              MTK_FUNCTION(1, "UCTS0"),
++              MTK_FUNCTION(3, "CLKM0"),
++              MTK_FUNCTION(4, "IDDIG"),
++              MTK_FUNCTION(5, "ANT_SEL4"),
++              MTK_FUNCTION(6, "NREB"),
++              MTK_FUNCTION(7, "DBG_MON_A[17]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(50, "EINT18"),
++              "AD20", "mt8127",
++              MTK_EINT_FUNCTION(0, 18),
++              MTK_FUNCTION(0, "GPIO50"),
++              MTK_FUNCTION(1, "URTS0"),
++              MTK_FUNCTION(2, "CLKM3"),
++              MTK_FUNCTION(3, "I2SOUT_LRCK"),
++              MTK_FUNCTION(4, "DRV_VBUS"),
++              MTK_FUNCTION(5, "ANT_SEL3"),
++              MTK_FUNCTION(6, "ADC_CK"),
++              MTK_FUNCTION(7, "DBG_MON_B[12]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(51, "EINT19"),
++              "AC21", "mt8127",
++              MTK_EINT_FUNCTION(0, 19),
++              MTK_FUNCTION(0, "GPIO51"),
++              MTK_FUNCTION(1, "UCTS1"),
++              MTK_FUNCTION(3, "I2SOUT_BCK"),
++              MTK_FUNCTION(4, "CLKM1"),
++              MTK_FUNCTION(5, "ANT_SEL4"),
++              MTK_FUNCTION(6, "ADC_DAT_IN"),
++              MTK_FUNCTION(7, "DBG_MON_B[13]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(52, "EINT20"),
++              "V20", "mt8127",
++              MTK_EINT_FUNCTION(0, 20),
++              MTK_FUNCTION(0, "GPIO52"),
++              MTK_FUNCTION(1, "URTS1"),
++              MTK_FUNCTION(2, "PCM_TX"),
++              MTK_FUNCTION(3, "I2SOUT_DATA_OUT"),
++              MTK_FUNCTION(4, "CLKM2"),
++              MTK_FUNCTION(5, "ANT_SEL5"),
++              MTK_FUNCTION(6, "ADC_WS"),
++              MTK_FUNCTION(7, "DBG_MON_B[14]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(53, "SPI_CS"),
++              "AD19", "mt8127",
++              MTK_EINT_FUNCTION(0, 54),
++              MTK_FUNCTION(0, "GPIO53"),
++              MTK_FUNCTION(1, "SPI_CS"),
++              MTK_FUNCTION(3, "I2SIN1_DATA_IN"),
++              MTK_FUNCTION(4, "ADC_CK"),
++              MTK_FUNCTION(7, "DBG_MON_B[15]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(54, "SPI_CK"),
++              "AC18", "mt8127",
++              MTK_EINT_FUNCTION(0, 55),
++              MTK_FUNCTION(0, "GPIO54"),
++              MTK_FUNCTION(1, "SPI_CK"),
++              MTK_FUNCTION(3, "I2SIN1_LRCK"),
++              MTK_FUNCTION(4, "ADC_DAT_IN"),
++              MTK_FUNCTION(7, "DBG_MON_B[16]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(55, "SPI_MI"),
++              "AC19", "mt8127",
++              MTK_EINT_FUNCTION(0, 56),
++              MTK_FUNCTION(0, "GPIO55"),
++              MTK_FUNCTION(1, "SPI_MI"),
++              MTK_FUNCTION(2, "SPI_MO"),
++              MTK_FUNCTION(3, "I2SIN1_BCK1"),
++              MTK_FUNCTION(4, "ADC_WS"),
++              MTK_FUNCTION(7, "DBG_MON_B[17]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(56, "SPI_MO"),
++              "AD18", "mt8127",
++              MTK_EINT_FUNCTION(0, 57),
++              MTK_FUNCTION(0, "GPIO56"),
++              MTK_FUNCTION(1, "SPI_MO"),
++              MTK_FUNCTION(2, "SPI_MI"),
++              MTK_FUNCTION(7, "DBG_MON_B[18]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(57, "SDA1"),
++              "AE23", "mt8127",
++              MTK_EINT_FUNCTION(0, 58),
++              MTK_FUNCTION(0, "GPIO57"),
++              MTK_FUNCTION(1, "SDA1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(58, "SCL1"),
++              "AD23", "mt8127",
++              MTK_EINT_FUNCTION(0, 59),
++              MTK_FUNCTION(0, "GPIO58"),
++              MTK_FUNCTION(1, "SCL1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(59, "DISP_PWM"),
++              "AC20", "mt8127",
++              MTK_EINT_FUNCTION(0, 60),
++              MTK_FUNCTION(0, "GPIO59"),
++              MTK_FUNCTION(1, "DISP_PWM"),
++              MTK_FUNCTION(2, "PWM1"),
++              MTK_FUNCTION(7, "DBG_MON_A[18]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(60, "WB_RSTB"),
++              "AD7", "mt8127",
++              MTK_EINT_FUNCTION(0, 61),
++              MTK_FUNCTION(0, "GPIO60"),
++              MTK_FUNCTION(1, "WB_RSTB"),
++              MTK_FUNCTION(7, "DBG_MON_A[19]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(61, "F2W_DATA"),
++              "Y10", "mt8127",
++              MTK_EINT_FUNCTION(0, 62),
++              MTK_FUNCTION(0, "GPIO61"),
++              MTK_FUNCTION(1, "F2W_DATA"),
++              MTK_FUNCTION(7, "DBG_MON_A[20]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(62, "F2W_CLK"),
++              "W10", "mt8127",
++              MTK_EINT_FUNCTION(0, 63),
++              MTK_FUNCTION(0, "GPIO62"),
++              MTK_FUNCTION(1, "F2W_CK"),
++              MTK_FUNCTION(7, "DBG_MON_A[21]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(63, "WB_SCLK"),
++              "AB7", "mt8127",
++              MTK_EINT_FUNCTION(0, 64),
++              MTK_FUNCTION(0, "GPIO63"),
++              MTK_FUNCTION(1, "WB_SCLK"),
++              MTK_FUNCTION(7, "DBG_MON_A[22]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(64, "WB_SDATA"),
++              "AA7", "mt8127",
++              MTK_EINT_FUNCTION(0, 65),
++              MTK_FUNCTION(0, "GPIO64"),
++              MTK_FUNCTION(1, "WB_SDATA"),
++              MTK_FUNCTION(7, "DBG_MON_A[23]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(65, "WB_SEN"),
++              "Y7", "mt8127",
++              MTK_EINT_FUNCTION(0, 66),
++              MTK_FUNCTION(0, "GPIO65"),
++              MTK_FUNCTION(1, "WB_SEN"),
++              MTK_FUNCTION(7, "DBG_MON_A[24]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(66, "WB_CRTL0"),
++              "AA1", "mt8127",
++              MTK_EINT_FUNCTION(0, 67),
++              MTK_FUNCTION(0, "GPIO66"),
++              MTK_FUNCTION(1, "WB_CRTL0"),
++              MTK_FUNCTION(2, "DFD_NTRST_XI"),
++              MTK_FUNCTION(7, "DBG_MON_A[25]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(67, "WB_CRTL1"),
++              "AA2", "mt8127",
++              MTK_EINT_FUNCTION(0, 68),
++              MTK_FUNCTION(0, "GPIO67"),
++              MTK_FUNCTION(1, "WB_CRTL1"),
++              MTK_FUNCTION(2, "DFD_TMS_XI"),
++              MTK_FUNCTION(7, "DBG_MON_A[26]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(68, "WB_CRTL2"),
++              "Y1", "mt8127",
++              MTK_EINT_FUNCTION(0, 69),
++              MTK_FUNCTION(0, "GPIO68"),
++              MTK_FUNCTION(1, "WB_CRTL2"),
++              MTK_FUNCTION(2, "DFD_TCK_XI"),
++              MTK_FUNCTION(7, "DBG_MON_A[27]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(69, "WB_CRTL3"),
++              "Y2", "mt8127",
++              MTK_EINT_FUNCTION(0, 70),
++              MTK_FUNCTION(0, "GPIO69"),
++              MTK_FUNCTION(1, "WB_CRTL3"),
++              MTK_FUNCTION(2, "DFD_TDI_XI"),
++              MTK_FUNCTION(7, "DBG_MON_A[28]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(70, "WB_CRTL4"),
++              "Y3", "mt8127",
++              MTK_EINT_FUNCTION(0, 71),
++              MTK_FUNCTION(0, "GPIO70"),
++              MTK_FUNCTION(1, "WB_CRTL4"),
++              MTK_FUNCTION(2, "DFD_TDO"),
++              MTK_FUNCTION(7, "DBG_MON_A[29]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(71, "WB_CRTL5"),
++              "Y4", "mt8127",
++              MTK_EINT_FUNCTION(0, 72),
++              MTK_FUNCTION(0, "GPIO71"),
++              MTK_FUNCTION(1, "WB_CRTL5"),
++              MTK_FUNCTION(7, "DBG_MON_A[30]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(72, "I2S_DATA_IN"),
++              "K21", "mt8127",
++              MTK_EINT_FUNCTION(0, 73),
++              MTK_FUNCTION(0, "GPIO72"),
++              MTK_FUNCTION(1, "I2SIN1_DATA_IN"),
++              MTK_FUNCTION(2, "PCM_RX"),
++              MTK_FUNCTION(3, "I2SOUT_DATA_OUT"),
++              MTK_FUNCTION(4, "DAC_DAT_OUT"),
++              MTK_FUNCTION(5, "PWM0"),
++              MTK_FUNCTION(6, "ADC_CK"),
++              MTK_FUNCTION(7, "DBG_MON_B[19]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(73, "I2S_LRCK"),
++              "L21", "mt8127",
++              MTK_EINT_FUNCTION(0, 74),
++              MTK_FUNCTION(0, "GPIO73"),
++              MTK_FUNCTION(1, "I2SIN1_LRCK"),
++              MTK_FUNCTION(2, "PCM_SYNC"),
++              MTK_FUNCTION(3, "I2SOUT_LRCK"),
++              MTK_FUNCTION(4, "DAC_WS"),
++              MTK_FUNCTION(5, "PWM3"),
++              MTK_FUNCTION(6, "ADC_DAT_IN"),
++              MTK_FUNCTION(7, "DBG_MON_B[20]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(74, "I2S_BCK"),
++              "L20", "mt8127",
++              MTK_EINT_FUNCTION(0, 75),
++              MTK_FUNCTION(0, "GPIO74"),
++              MTK_FUNCTION(1, "I2SIN1_BCK2"),
++              MTK_FUNCTION(2, "PCM_CLK1"),
++              MTK_FUNCTION(3, "I2SOUT_BCK"),
++              MTK_FUNCTION(4, "DAC_CK"),
++              MTK_FUNCTION(5, "PWM4"),
++              MTK_FUNCTION(6, "ADC_WS"),
++              MTK_FUNCTION(7, "DBG_MON_B[21]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(75, "SDA0"),
++              "W3", "mt8127",
++              MTK_EINT_FUNCTION(0, 76),
++              MTK_FUNCTION(0, "GPIO75"),
++              MTK_FUNCTION(1, "SDA0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(76, "SCL0"),
++              "W4", "mt8127",
++              MTK_EINT_FUNCTION(0, 77),
++              MTK_FUNCTION(0, "GPIO76"),
++              MTK_FUNCTION(1, "SCL0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(77, "SDA2"),
++              "K19", "mt8127",
++              MTK_EINT_FUNCTION(0, 78),
++              MTK_FUNCTION(0, "GPIO77"),
++              MTK_FUNCTION(1, "SDA2"),
++              MTK_FUNCTION(2, "PWM1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(78, "SCL2"),
++              "K20", "mt8127",
++              MTK_EINT_FUNCTION(0, 79),
++              MTK_FUNCTION(0, "GPIO78"),
++              MTK_FUNCTION(1, "SCL2"),
++              MTK_FUNCTION(2, "PWM2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(79, "URXD0"),
++              "K18", "mt8127",
++              MTK_EINT_FUNCTION(0, 80),
++              MTK_FUNCTION(0, "GPIO79"),
++              MTK_FUNCTION(1, "URXD0"),
++              MTK_FUNCTION(2, "UTXD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(80, "UTXD0"),
++              "K17", "mt8127",
++              MTK_EINT_FUNCTION(0, 81),
++              MTK_FUNCTION(0, "GPIO80"),
++              MTK_FUNCTION(1, "UTXD0"),
++              MTK_FUNCTION(2, "URXD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(81, "URXD1"),
++              "L17", "mt8127",
++              MTK_EINT_FUNCTION(0, 82),
++              MTK_FUNCTION(0, "GPIO81"),
++              MTK_FUNCTION(1, "URXD1"),
++              MTK_FUNCTION(2, "UTXD1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(82, "UTXD1"),
++              "L18", "mt8127",
++              MTK_EINT_FUNCTION(0, 83),
++              MTK_FUNCTION(0, "GPIO82"),
++              MTK_FUNCTION(1, "UTXD1"),
++              MTK_FUNCTION(2, "URXD1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(83, "LCM_RST"),
++              "W5", "mt8127",
++              MTK_EINT_FUNCTION(0, 84),
++              MTK_FUNCTION(0, "GPIO83"),
++              MTK_FUNCTION(1, "LCM_RST"),
++              MTK_FUNCTION(2, "VDAC_CK_XI"),
++              MTK_FUNCTION(7, "DBG_MON_A[31]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(84, "DSI_TE"),
++              "W6", "mt8127",
++              MTK_EINT_FUNCTION(0, 85),
++              MTK_FUNCTION(0, "GPIO84"),
++              MTK_FUNCTION(1, "DSI_TE"),
++              MTK_FUNCTION(7, "DBG_MON_A[32]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(85, "MSDC2_CMD"),
++              "U7", "mt8127",
++              MTK_EINT_FUNCTION(0, 86),
++              MTK_FUNCTION(0, "GPIO85"),
++              MTK_FUNCTION(1, "MSDC2_CMD"),
++              MTK_FUNCTION(2, "ANT_SEL0"),
++              MTK_FUNCTION(3, "SDA1"),
++              MTK_FUNCTION(6, "I2SOUT_BCK"),
++              MTK_FUNCTION(7, "DBG_MON_B[22]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(86, "MSDC2_CLK"),
++              "T8", "mt8127",
++              MTK_EINT_FUNCTION(0, 87),
++              MTK_FUNCTION(0, "GPIO86"),
++              MTK_FUNCTION(1, "MSDC2_CLK"),
++              MTK_FUNCTION(2, "ANT_SEL1"),
++              MTK_FUNCTION(3, "SCL1"),
++              MTK_FUNCTION(6, "I2SOUT_LRCK"),
++              MTK_FUNCTION(7, "DBG_MON_B[23]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(87, "MSDC2_DAT0"),
++              "V3", "mt8127",
++              MTK_EINT_FUNCTION(0, 88),
++              MTK_FUNCTION(0, "GPIO87"),
++              MTK_FUNCTION(1, "MSDC2_DAT0"),
++              MTK_FUNCTION(2, "ANT_SEL2"),
++              MTK_FUNCTION(5, "UTXD0"),
++              MTK_FUNCTION(6, "I2SOUT_DATA_OUT"),
++              MTK_FUNCTION(7, "DBG_MON_B[24]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(88, "MSDC2_DAT1"),
++              "V4", "mt8127",
++              MTK_EINT_FUNCTION(0, 89),
++              MTK_FUNCTION(0, "GPIO88"),
++              MTK_FUNCTION(1, "MSDC2_DAT1"),
++              MTK_FUNCTION(2, "ANT_SEL3"),
++              MTK_FUNCTION(3, "PWM0"),
++              MTK_FUNCTION(5, "URXD0"),
++              MTK_FUNCTION(6, "PWM1"),
++              MTK_FUNCTION(7, "DBG_MON_B[25]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(89, "MSDC2_DAT2"),
++              "U5", "mt8127",
++              MTK_EINT_FUNCTION(0, 90),
++              MTK_FUNCTION(0, "GPIO89"),
++              MTK_FUNCTION(1, "MSDC2_DAT2"),
++              MTK_FUNCTION(2, "ANT_SEL4"),
++              MTK_FUNCTION(3, "SDA2"),
++              MTK_FUNCTION(5, "UTXD1"),
++              MTK_FUNCTION(6, "PWM2"),
++              MTK_FUNCTION(7, "DBG_MON_B[26]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(90, "MSDC2_DAT3"),
++              "U6", "mt8127",
++              MTK_EINT_FUNCTION(0, 91),
++              MTK_FUNCTION(0, "GPIO90"),
++              MTK_FUNCTION(1, "MSDC2_DAT3"),
++              MTK_FUNCTION(2, "ANT_SEL5"),
++              MTK_FUNCTION(3, "SCL2"),
++              MTK_FUNCTION(4, "EXT_FRAME_SYNC"),
++              MTK_FUNCTION(5, "URXD1"),
++              MTK_FUNCTION(6, "PWM3"),
++              MTK_FUNCTION(7, "DBG_MON_B[27]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(91, "TDN3"),
++              "U2", "mt8127",
++              MTK_EINT_FUNCTION(0, 92),
++              MTK_FUNCTION(0, "GPI91"),
++              MTK_FUNCTION(1, "TDN3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(92, "TDP3"),
++              "U1", "mt8127",
++              MTK_EINT_FUNCTION(0, 93),
++              MTK_FUNCTION(0, "GPI92"),
++              MTK_FUNCTION(1, "TDP3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(93, "TDN2"),
++              "T2", "mt8127",
++              MTK_EINT_FUNCTION(0, 94),
++              MTK_FUNCTION(0, "GPI93"),
++              MTK_FUNCTION(1, "TDN2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(94, "TDP2"),
++              "T1", "mt8127",
++              MTK_EINT_FUNCTION(0, 95),
++              MTK_FUNCTION(0, "GPI94"),
++              MTK_FUNCTION(1, "TDP2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(95, "TCN"),
++              "R5", "mt8127",
++              MTK_EINT_FUNCTION(0, 96),
++              MTK_FUNCTION(0, "GPI95"),
++              MTK_FUNCTION(1, "TCN")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(96, "TCP"),
++              "R4", "mt8127",
++              MTK_EINT_FUNCTION(0, 97),
++              MTK_FUNCTION(0, "GPI96"),
++              MTK_FUNCTION(1, "TCP")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(97, "TDN1"),
++              "R3", "mt8127",
++              MTK_EINT_FUNCTION(0, 98),
++              MTK_FUNCTION(0, "GPI97"),
++              MTK_FUNCTION(1, "TDN1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(98, "TDP1"),
++              "R2", "mt8127",
++              MTK_EINT_FUNCTION(0, 99),
++              MTK_FUNCTION(0, "GPI98"),
++              MTK_FUNCTION(1, "TDP1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(99, "TDN0"),
++              "P3", "mt8127",
++              MTK_EINT_FUNCTION(0, 100),
++              MTK_FUNCTION(0, "GPI99"),
++              MTK_FUNCTION(1, "TDN0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(100, "TDP0"),
++              "P2", "mt8127",
++              MTK_EINT_FUNCTION(0, 101),
++              MTK_FUNCTION(0, "GPI100"),
++              MTK_FUNCTION(1, "TDP0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(101, "RDN0"),
++              "K1", "mt8127",
++              MTK_EINT_FUNCTION(0, 102),
++              MTK_FUNCTION(0, "GPI101"),
++              MTK_FUNCTION(1, "RDN0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(102, "RDP0"),
++              "K2", "mt8127",
++              MTK_EINT_FUNCTION(0, 103),
++              MTK_FUNCTION(0, "GPI102"),
++              MTK_FUNCTION(1, "RDP0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(103, "RDN1"),
++              "L2", "mt8127",
++              MTK_EINT_FUNCTION(0, 104),
++              MTK_FUNCTION(0, "GPI103"),
++              MTK_FUNCTION(1, "RDN1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(104, "RDP1"),
++              "L3", "mt8127",
++              MTK_EINT_FUNCTION(0, 105),
++              MTK_FUNCTION(0, "GPI104"),
++              MTK_FUNCTION(1, "RDP1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(105, "RCN"),
++              "M4", "mt8127",
++              MTK_EINT_FUNCTION(0, 106),
++              MTK_FUNCTION(0, "GPI105"),
++              MTK_FUNCTION(1, "RCN")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(106, "RCP"),
++              "M5", "mt8127",
++              MTK_EINT_FUNCTION(0, 107),
++              MTK_FUNCTION(0, "GPI106"),
++              MTK_FUNCTION(1, "RCP")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(107, "RDN2"),
++              "M2", "mt8127",
++              MTK_EINT_FUNCTION(0, 108),
++              MTK_FUNCTION(0, "GPI107"),
++              MTK_FUNCTION(1, "RDN2"),
++              MTK_FUNCTION(2, "CMDAT8")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(108, "RDP2"),
++              "M3", "mt8127",
++              MTK_EINT_FUNCTION(0, 109),
++              MTK_FUNCTION(0, "GPI108"),
++              MTK_FUNCTION(1, "RDP2"),
++              MTK_FUNCTION(2, "CMDAT9")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(109, "RDN3"),
++              "N2", "mt8127",
++              MTK_EINT_FUNCTION(0, 110),
++              MTK_FUNCTION(0, "GPI109"),
++              MTK_FUNCTION(1, "RDN3"),
++              MTK_FUNCTION(2, "CMDAT4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(110, "RDP3"),
++              "N3", "mt8127",
++              MTK_EINT_FUNCTION(0, 111),
++              MTK_FUNCTION(0, "GPI110"),
++              MTK_FUNCTION(1, "RDP3"),
++              MTK_FUNCTION(2, "CMDAT5")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(111, "RCN_A"),
++              "J5", "mt8127",
++              MTK_EINT_FUNCTION(0, 112),
++              MTK_FUNCTION(0, "GPI111"),
++              MTK_FUNCTION(1, "RCN_A"),
++              MTK_FUNCTION(2, "CMDAT6")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(112, "RCP_A"),
++              "J4", "mt8127",
++              MTK_EINT_FUNCTION(0, 113),
++              MTK_FUNCTION(0, "GPI112"),
++              MTK_FUNCTION(1, "RCP_A"),
++              MTK_FUNCTION(2, "CMDAT7")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(113, "RDN1_A"),
++              "J2", "mt8127",
++              MTK_EINT_FUNCTION(0, 114),
++              MTK_FUNCTION(0, "GPI113"),
++              MTK_FUNCTION(1, "RDN1_A"),
++              MTK_FUNCTION(2, "CMDAT2"),
++              MTK_FUNCTION(3, "CMCSD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(114, "RDP1_A"),
++              "J3", "mt8127",
++              MTK_EINT_FUNCTION(0, 115),
++              MTK_FUNCTION(0, "GPI114"),
++              MTK_FUNCTION(1, "RDP1_A"),
++              MTK_FUNCTION(2, "CMDAT3"),
++              MTK_FUNCTION(3, "CMCSD3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(115, "RDN0_A"),
++              "H2", "mt8127",
++              MTK_EINT_FUNCTION(0, 116),
++              MTK_FUNCTION(0, "GPI115"),
++              MTK_FUNCTION(1, "RDN0_A"),
++              MTK_FUNCTION(2, "CMHSYNC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(116, "RDP0_A"),
++              "H3", "mt8127",
++              MTK_EINT_FUNCTION(0, 117),
++              MTK_FUNCTION(0, "GPI116"),
++              MTK_FUNCTION(1, "RDP0_A"),
++              MTK_FUNCTION(2, "CMVSYNC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(117, "CMDAT0"),
++              "G5", "mt8127",
++              MTK_EINT_FUNCTION(0, 118),
++              MTK_FUNCTION(0, "GPIO117"),
++              MTK_FUNCTION(1, "CMDAT0"),
++              MTK_FUNCTION(2, "CMCSD0"),
++              MTK_FUNCTION(3, "ANT_SEL2"),
++              MTK_FUNCTION(7, "DBG_MON_B[28]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(118, "CMDAT1"),
++              "G4", "mt8127",
++              MTK_EINT_FUNCTION(0, 119),
++              MTK_FUNCTION(0, "GPIO118"),
++              MTK_FUNCTION(1, "CMDAT1"),
++              MTK_FUNCTION(2, "CMCSD1"),
++              MTK_FUNCTION(3, "ANT_SEL3"),
++              MTK_FUNCTION(7, "DBG_MON_B[29]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(119, "CMMCLK"),
++              "F3", "mt8127",
++              MTK_EINT_FUNCTION(0, 120),
++              MTK_FUNCTION(0, "GPIO119"),
++              MTK_FUNCTION(1, "CMMCLK"),
++              MTK_FUNCTION(3, "ANT_SEL4"),
++              MTK_FUNCTION(7, "DBG_MON_B[30]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(120, "CMPCLK"),
++              "G6", "mt8127",
++              MTK_EINT_FUNCTION(0, 121),
++              MTK_FUNCTION(0, "GPIO120"),
++              MTK_FUNCTION(1, "CMPCLK"),
++              MTK_FUNCTION(2, "CMCSK"),
++              MTK_FUNCTION(3, "ANT_SEL5"),
++              MTK_FUNCTION(7, "DBG_MON_B[31]")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(121, "MSDC1_CMD"),
++              "E3", "mt8127",
++              MTK_EINT_FUNCTION(0, 122),
++              MTK_FUNCTION(0, "GPIO121"),
++              MTK_FUNCTION(1, "MSDC1_CMD")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(122, "MSDC1_CLK"),
++              "D1", "mt8127",
++              MTK_EINT_FUNCTION(0, 123),
++              MTK_FUNCTION(0, "GPIO122"),
++              MTK_FUNCTION(1, "MSDC1_CLK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(123, "MSDC1_DAT0"),
++              "D2", "mt8127",
++              MTK_EINT_FUNCTION(0, 124),
++              MTK_FUNCTION(0, "GPIO123"),
++              MTK_FUNCTION(1, "MSDC1_DAT0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(124, "MSDC1_DAT1"),
++              "D3", "mt8127",
++              MTK_EINT_FUNCTION(0, 125),
++              MTK_FUNCTION(0, "GPIO124"),
++              MTK_FUNCTION(1, "MSDC1_DAT1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(125, "MSDC1_DAT2"),
++              "F2", "mt8127",
++              MTK_EINT_FUNCTION(0, 126),
++              MTK_FUNCTION(0, "GPIO125"),
++              MTK_FUNCTION(1, "MSDC1_DAT2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(126, "MSDC1_DAT3"),
++              "E2", "mt8127",
++              MTK_EINT_FUNCTION(0, 127),
++              MTK_FUNCTION(0, "GPIO126"),
++              MTK_FUNCTION(1, "MSDC1_DAT3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(127, "MSDC0_DAT7"),
++              "C23", "mt8127",
++              MTK_EINT_FUNCTION(0, 128),
++              MTK_FUNCTION(0, "GPIO127"),
++              MTK_FUNCTION(1, "MSDC0_DAT7"),
++              MTK_FUNCTION(4, "NLD7")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(128, "MSDC0_DAT6"),
++              "C24", "mt8127",
++              MTK_EINT_FUNCTION(0, 129),
++              MTK_FUNCTION(0, "GPIO128"),
++              MTK_FUNCTION(1, "MSDC0_DAT6"),
++              MTK_FUNCTION(4, "NLD6")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(129, "MSDC0_DAT5"),
++              "D22", "mt8127",
++              MTK_EINT_FUNCTION(0, 130),
++              MTK_FUNCTION(0, "GPIO129"),
++              MTK_FUNCTION(1, "MSDC0_DAT5"),
++              MTK_FUNCTION(4, "NLD4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(130, "MSDC0_DAT4"),
++              "D24", "mt8127",
++              MTK_EINT_FUNCTION(0, 131),
++              MTK_FUNCTION(0, "GPIO130"),
++              MTK_FUNCTION(1, "MSDC0_DAT4"),
++              MTK_FUNCTION(4, "NLD3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(131, "MSDC0_RSTB"),
++              "F24", "mt8127",
++              MTK_EINT_FUNCTION(0, 132),
++              MTK_FUNCTION(0, "GPIO131"),
++              MTK_FUNCTION(1, "MSDC0_RSTB"),
++              MTK_FUNCTION(4, "NLD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(132, "MSDC0_CMD"),
++              "G20", "mt8127",
++              MTK_EINT_FUNCTION(0, 133),
++              MTK_FUNCTION(0, "GPIO132"),
++              MTK_FUNCTION(1, "MSDC0_CMD"),
++              MTK_FUNCTION(4, "NALE")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(133, "MSDC0_CLK"),
++              "G21", "mt8127",
++              MTK_EINT_FUNCTION(0, 134),
++              MTK_FUNCTION(0, "GPIO133"),
++              MTK_FUNCTION(1, "MSDC0_CLK"),
++              MTK_FUNCTION(4, "NWEB")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(134, "MSDC0_DAT3"),
++              "D23", "mt8127",
++              MTK_EINT_FUNCTION(0, 135),
++              MTK_FUNCTION(0, "GPIO134"),
++              MTK_FUNCTION(1, "MSDC0_DAT3"),
++              MTK_FUNCTION(4, "NLD1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(135, "MSDC0_DAT2"),
++              "E22", "mt8127",
++              MTK_EINT_FUNCTION(0, 136),
++              MTK_FUNCTION(0, "GPIO135"),
++              MTK_FUNCTION(1, "MSDC0_DAT2"),
++              MTK_FUNCTION(4, "NLD5")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(136, "MSDC0_DAT1"),
++              "E23", "mt8127",
++              MTK_EINT_FUNCTION(0, 137),
++              MTK_FUNCTION(0, "GPIO136"),
++              MTK_FUNCTION(1, "MSDC0_DAT1"),
++              MTK_FUNCTION(4, "NLD8")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(137, "MSDC0_DAT0"),
++              "F22", "mt8127",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO137"),
++              MTK_FUNCTION(1, "MSDC0_DAT0"),
++              MTK_FUNCTION(4, "WATCHDOG"),
++              MTK_FUNCTION(5, "NLD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(138, "CEC"),
++              "AE21", "mt8127",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO138"),
++              MTK_FUNCTION(1, "CEC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(139, "HTPLG"),
++              "AD21", "mt8127",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO139"),
++              MTK_FUNCTION(1, "HTPLG")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(140, "HDMISCK"),
++              "AE22", "mt8127",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO140"),
++              MTK_FUNCTION(1, "HDMISCK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(141, "HDMISD"),
++              "AD22", "mt8127",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO141"),
++              MTK_FUNCTION(1, "HDMISD")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(142, "EINT21"),
++              "J23", "mt8127",
++              MTK_EINT_FUNCTION(0, 21),
++              MTK_FUNCTION(0, "GPIO142"),
++              MTK_FUNCTION(1, "NRNB"),
++              MTK_FUNCTION(2, "ANT_SEL0"),
++              MTK_FUNCTION(7, "DBG_MON_B[32]")
++      ),
++};
++
++#endif /* __PINCTRL_MTK_MT8127_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0055-mfd-mediatek-Add-GPIO-sub-module-support-into-mfd.patch b/target/linux/mediatek/patches/0055-mfd-mediatek-Add-GPIO-sub-module-support-into-mfd.patch
new file mode 100644 (file)
index 0000000..d9c0676
--- /dev/null
@@ -0,0 +1,30 @@
+From e5de6556a25d4b2e2d30683d629095bce102c792 Mon Sep 17 00:00:00 2001
+From: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Date: Mon, 18 May 2015 23:11:19 -0700
+Subject: [PATCH 55/76] mfd: mediatek: Add GPIO sub module support into mfd.
+
+Register pinctrl subnode into 6397 mfd cell.
+
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/mfd/mt6397-core.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
+index 09bc780..012c620 100644
+--- a/drivers/mfd/mt6397-core.c
++++ b/drivers/mfd/mt6397-core.c
+@@ -34,6 +34,9 @@ static const struct mfd_cell mt6397_devs[] = {
+       }, {
+               .name = "mt6397-clk",
+               .of_compatible = "mediatek,mt6397-clk",
++      }, {
++              .name = "mediatek-mt6397-pinctrl",
++              .of_compatible = "mediatek,mt6397-pinctrl",
+       },
+ };
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0056-ARM-dts-mt8127-add-pinctrl-GPIO-EINT-node-for-mt8127.patch b/target/linux/mediatek/patches/0056-ARM-dts-mt8127-add-pinctrl-GPIO-EINT-node-for-mt8127.patch
new file mode 100644 (file)
index 0000000..a59d2c6
--- /dev/null
@@ -0,0 +1,809 @@
+From 619e31dbd73885249f3db545ed0b7678ca98c248 Mon Sep 17 00:00:00 2001
+From: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Date: Mon, 18 May 2015 23:11:20 -0700
+Subject: [PATCH 56/76] ARM: dts: mt8127: add pinctrl/GPIO/EINT node for
+ mt8127
+
+Add pinctrl,GPIO and EINT node to mt8127.dtsi.
+
+Signed-off-by: Yingjoe Chen <yingjoe.chen@mediatek.com>
+Signed-off-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Acked-by: Matthias Brugger <matthias.bgg@gmail.com>
+---
+ arch/arm/boot/dts/mt8127-pinfunc.h |  742 ++++++++++++++++++++++++++++++++++++
+ arch/arm/boot/dts/mt8127.dtsi      |   22 ++
+ 2 files changed, 764 insertions(+)
+ create mode 100644 arch/arm/boot/dts/mt8127-pinfunc.h
+
+diff --git a/arch/arm/boot/dts/mt8127-pinfunc.h b/arch/arm/boot/dts/mt8127-pinfunc.h
+new file mode 100644
+index 0000000..9198331
+--- /dev/null
++++ b/arch/arm/boot/dts/mt8127-pinfunc.h
+@@ -0,0 +1,742 @@
++#ifndef __DTS_MT8127_PINFUNC_H
++#define __DTS_MT8127_PINFUNC_H
++
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#define MT8127_PIN_0_PWRAP_SPI0_MI__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
++#define MT8127_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDO (MTK_PIN_NO(0) | 1)
++#define MT8127_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDI (MTK_PIN_NO(0) | 2)
++
++#define MT8127_PIN_1_PWRAP_SPI0_MO__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
++#define MT8127_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDI (MTK_PIN_NO(1) | 1)
++#define MT8127_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDO (MTK_PIN_NO(1) | 2)
++
++#define MT8127_PIN_2_PWRAP_INT__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
++
++#define MT8127_PIN_3_PWRAP_SPI0_CK__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
++#define MT8127_PIN_3_PWRAP_SPI0_CK__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(3) | 1)
++
++#define MT8127_PIN_4_PWRAP_SPI0_CSN__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
++#define MT8127_PIN_4_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(4) | 1)
++
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_ANT_SEL1 (MTK_PIN_NO(5) | 2)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_VDEC_TEST_CK (MTK_PIN_NO(5) | 3)
++#define MT8127_PIN_5_PWRAP_SPI0_CK2__FUNC_DBG_MON_B_0 (MTK_PIN_NO(5) | 7)
++
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_ANT_SEL0 (MTK_PIN_NO(6) | 2)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_MM_TEST_CK (MTK_PIN_NO(6) | 3)
++#define MT8127_PIN_6_PWRAP_SPI0_CSN2__FUNC_DBG_MON_B_1 (MTK_PIN_NO(6) | 7)
++
++#define MT8127_PIN_7_AUD_CLK_MOSI__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
++#define MT8127_PIN_7_AUD_CLK_MOSI__FUNC_AUD_CLK (MTK_PIN_NO(7) | 1)
++#define MT8127_PIN_7_AUD_CLK_MOSI__FUNC_ADC_CK (MTK_PIN_NO(7) | 2)
++
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_AUD_MISO (MTK_PIN_NO(8) | 1)
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_ADC_DAT_IN (MTK_PIN_NO(8) | 2)
++#define MT8127_PIN_8_AUD_DAT_MISO__FUNC_AUD_MOSI (MTK_PIN_NO(8) | 3)
++
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_AUD_MOSI (MTK_PIN_NO(9) | 1)
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_ADC_WS (MTK_PIN_NO(9) | 2)
++#define MT8127_PIN_9_AUD_DAT_MOSI__FUNC_AUD_MISO (MTK_PIN_NO(9) | 3)
++
++#define MT8127_PIN_10_RTC32K_CK__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
++#define MT8127_PIN_10_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1)
++
++#define MT8127_PIN_11_WATCHDOG__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
++#define MT8127_PIN_11_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(11) | 1)
++
++#define MT8127_PIN_12_SRCLKENA__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
++#define MT8127_PIN_12_SRCLKENA__FUNC_SRCLKENA (MTK_PIN_NO(12) | 1)
++
++#define MT8127_PIN_13_SRCLKENAI__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
++#define MT8127_PIN_13_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(13) | 1)
++
++#define MT8127_PIN_14_URXD2__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
++#define MT8127_PIN_14_URXD2__FUNC_URXD2 (MTK_PIN_NO(14) | 1)
++#define MT8127_PIN_14_URXD2__FUNC_DPI_D5 (MTK_PIN_NO(14) | 2)
++#define MT8127_PIN_14_URXD2__FUNC_UTXD2 (MTK_PIN_NO(14) | 3)
++#define MT8127_PIN_14_URXD2__FUNC_SRCCLKENAI2 (MTK_PIN_NO(14) | 5)
++#define MT8127_PIN_14_URXD2__FUNC_KROW4 (MTK_PIN_NO(14) | 6)
++
++#define MT8127_PIN_15_UTXD2__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
++#define MT8127_PIN_15_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(15) | 1)
++#define MT8127_PIN_15_UTXD2__FUNC_DPI_HSYNC (MTK_PIN_NO(15) | 2)
++#define MT8127_PIN_15_UTXD2__FUNC_URXD2 (MTK_PIN_NO(15) | 3)
++#define MT8127_PIN_15_UTXD2__FUNC_KROW5 (MTK_PIN_NO(15) | 6)
++
++#define MT8127_PIN_16_URXD3__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
++#define MT8127_PIN_16_URXD3__FUNC_URXD3 (MTK_PIN_NO(16) | 1)
++#define MT8127_PIN_16_URXD3__FUNC_DPI_DE (MTK_PIN_NO(16) | 2)
++#define MT8127_PIN_16_URXD3__FUNC_UTXD3 (MTK_PIN_NO(16) | 3)
++#define MT8127_PIN_16_URXD3__FUNC_UCTS2 (MTK_PIN_NO(16) | 4)
++#define MT8127_PIN_16_URXD3__FUNC_PWM3 (MTK_PIN_NO(16) | 5)
++#define MT8127_PIN_16_URXD3__FUNC_KROW6 (MTK_PIN_NO(16) | 6)
++
++#define MT8127_PIN_17_UTXD3__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
++#define MT8127_PIN_17_UTXD3__FUNC_UTXD3 (MTK_PIN_NO(17) | 1)
++#define MT8127_PIN_17_UTXD3__FUNC_DPI_VSYNC (MTK_PIN_NO(17) | 2)
++#define MT8127_PIN_17_UTXD3__FUNC_URXD3 (MTK_PIN_NO(17) | 3)
++#define MT8127_PIN_17_UTXD3__FUNC_URTS2 (MTK_PIN_NO(17) | 4)
++#define MT8127_PIN_17_UTXD3__FUNC_PWM4 (MTK_PIN_NO(17) | 5)
++#define MT8127_PIN_17_UTXD3__FUNC_KROW7 (MTK_PIN_NO(17) | 6)
++
++#define MT8127_PIN_18_PCM_CLK__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
++#define MT8127_PIN_18_PCM_CLK__FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1)
++#define MT8127_PIN_18_PCM_CLK__FUNC_DPI_D4 (MTK_PIN_NO(18) | 2)
++#define MT8127_PIN_18_PCM_CLK__FUNC_I2SIN1_BCK0 (MTK_PIN_NO(18) | 3)
++#define MT8127_PIN_18_PCM_CLK__FUNC_I2SOUT_BCK (MTK_PIN_NO(18) | 4)
++#define MT8127_PIN_18_PCM_CLK__FUNC_CONN_DSP_JCK (MTK_PIN_NO(18) | 5)
++#define MT8127_PIN_18_PCM_CLK__FUNC_IR (MTK_PIN_NO(18) | 6)
++#define MT8127_PIN_18_PCM_CLK__FUNC_DBG_MON_A_0 (MTK_PIN_NO(18) | 7)
++
++#define MT8127_PIN_19_PCM_SYNC__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_DPI_D3 (MTK_PIN_NO(19) | 2)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_I2SIN1_LRCK (MTK_PIN_NO(19) | 3)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_I2SOUT_LRCK (MTK_PIN_NO(19) | 4)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(19) | 5)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_EXT_COL (MTK_PIN_NO(19) | 6)
++#define MT8127_PIN_19_PCM_SYNC__FUNC_DBG_MON_A_1 (MTK_PIN_NO(19) | 7)
++
++#define MT8127_PIN_20_PCM_RX__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
++#define MT8127_PIN_20_PCM_RX__FUNC_PCM_RX (MTK_PIN_NO(20) | 1)
++#define MT8127_PIN_20_PCM_RX__FUNC_DPI_D1 (MTK_PIN_NO(20) | 2)
++#define MT8127_PIN_20_PCM_RX__FUNC_I2SIN1_DATA_IN (MTK_PIN_NO(20) | 3)
++#define MT8127_PIN_20_PCM_RX__FUNC_PCM_TX (MTK_PIN_NO(20) | 4)
++#define MT8127_PIN_20_PCM_RX__FUNC_CONN_DSP_JDI (MTK_PIN_NO(20) | 5)
++#define MT8127_PIN_20_PCM_RX__FUNC_EXT_MDIO (MTK_PIN_NO(20) | 6)
++#define MT8127_PIN_20_PCM_RX__FUNC_DBG_MON_A_2 (MTK_PIN_NO(20) | 7)
++
++#define MT8127_PIN_21_PCM_TX__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
++#define MT8127_PIN_21_PCM_TX__FUNC_PCM_TX (MTK_PIN_NO(21) | 1)
++#define MT8127_PIN_21_PCM_TX__FUNC_DPI_D2 (MTK_PIN_NO(21) | 2)
++#define MT8127_PIN_21_PCM_TX__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(21) | 3)
++#define MT8127_PIN_21_PCM_TX__FUNC_PCM_RX (MTK_PIN_NO(21) | 4)
++#define MT8127_PIN_21_PCM_TX__FUNC_CONN_DSP_JMS (MTK_PIN_NO(21) | 5)
++#define MT8127_PIN_21_PCM_TX__FUNC_EXT_MDC (MTK_PIN_NO(21) | 6)
++#define MT8127_PIN_21_PCM_TX__FUNC_DBG_MON_A_3 (MTK_PIN_NO(21) | 7)
++
++#define MT8127_PIN_22_EINT0__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
++#define MT8127_PIN_22_EINT0__FUNC_PWM1 (MTK_PIN_NO(22) | 1)
++#define MT8127_PIN_22_EINT0__FUNC_DPI_CK (MTK_PIN_NO(22) | 2)
++#define MT8127_PIN_22_EINT0__FUNC_EXT_TXD0 (MTK_PIN_NO(22) | 4)
++#define MT8127_PIN_22_EINT0__FUNC_CONN_DSP_JDO (MTK_PIN_NO(22) | 5)
++#define MT8127_PIN_22_EINT0__FUNC_DBG_MON_A_4 (MTK_PIN_NO(22) | 7)
++
++#define MT8127_PIN_23_EINT1__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
++#define MT8127_PIN_23_EINT1__FUNC_PWM2 (MTK_PIN_NO(23) | 1)
++#define MT8127_PIN_23_EINT1__FUNC_DPI_D12 (MTK_PIN_NO(23) | 2)
++#define MT8127_PIN_23_EINT1__FUNC_EXT_TXD1 (MTK_PIN_NO(23) | 4)
++#define MT8127_PIN_23_EINT1__FUNC_CONN_MCU_TDO (MTK_PIN_NO(23) | 5)
++#define MT8127_PIN_23_EINT1__FUNC_DBG_MON_A_5 (MTK_PIN_NO(23) | 7)
++
++#define MT8127_PIN_24_EINT2__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
++#define MT8127_PIN_24_EINT2__FUNC_CLKM0 (MTK_PIN_NO(24) | 1)
++#define MT8127_PIN_24_EINT2__FUNC_DPI_D13 (MTK_PIN_NO(24) | 2)
++#define MT8127_PIN_24_EINT2__FUNC_EXT_TXD2 (MTK_PIN_NO(24) | 4)
++#define MT8127_PIN_24_EINT2__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(24) | 5)
++#define MT8127_PIN_24_EINT2__FUNC_KCOL4 (MTK_PIN_NO(24) | 6)
++#define MT8127_PIN_24_EINT2__FUNC_DBG_MON_A_6 (MTK_PIN_NO(24) | 7)
++
++#define MT8127_PIN_25_EINT3__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
++#define MT8127_PIN_25_EINT3__FUNC_CLKM1 (MTK_PIN_NO(25) | 1)
++#define MT8127_PIN_25_EINT3__FUNC_DPI_D14 (MTK_PIN_NO(25) | 2)
++#define MT8127_PIN_25_EINT3__FUNC_SPI_MI (MTK_PIN_NO(25) | 3)
++#define MT8127_PIN_25_EINT3__FUNC_EXT_TXD3 (MTK_PIN_NO(25) | 4)
++#define MT8127_PIN_25_EINT3__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(25) | 5)
++#define MT8127_PIN_25_EINT3__FUNC_KCOL5 (MTK_PIN_NO(25) | 6)
++#define MT8127_PIN_25_EINT3__FUNC_DBG_MON_A_7 (MTK_PIN_NO(25) | 7)
++
++#define MT8127_PIN_26_EINT4__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
++#define MT8127_PIN_26_EINT4__FUNC_CLKM2 (MTK_PIN_NO(26) | 1)
++#define MT8127_PIN_26_EINT4__FUNC_DPI_D15 (MTK_PIN_NO(26) | 2)
++#define MT8127_PIN_26_EINT4__FUNC_SPI_MO (MTK_PIN_NO(26) | 3)
++#define MT8127_PIN_26_EINT4__FUNC_EXT_TXC (MTK_PIN_NO(26) | 4)
++#define MT8127_PIN_26_EINT4__FUNC_CONN_MCU_TCK0 (MTK_PIN_NO(26) | 5)
++#define MT8127_PIN_26_EINT4__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(26) | 6)
++#define MT8127_PIN_26_EINT4__FUNC_DBG_MON_A_8 (MTK_PIN_NO(26) | 7)
++
++#define MT8127_PIN_27_EINT5__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
++#define MT8127_PIN_27_EINT5__FUNC_UCTS2 (MTK_PIN_NO(27) | 1)
++#define MT8127_PIN_27_EINT5__FUNC_DPI_D16 (MTK_PIN_NO(27) | 2)
++#define MT8127_PIN_27_EINT5__FUNC_SPI_CS (MTK_PIN_NO(27) | 3)
++#define MT8127_PIN_27_EINT5__FUNC_EXT_RXER (MTK_PIN_NO(27) | 4)
++#define MT8127_PIN_27_EINT5__FUNC_CONN_MCU_TDI (MTK_PIN_NO(27) | 5)
++#define MT8127_PIN_27_EINT5__FUNC_KCOL6 (MTK_PIN_NO(27) | 6)
++#define MT8127_PIN_27_EINT5__FUNC_DBG_MON_A_9 (MTK_PIN_NO(27) | 7)
++
++#define MT8127_PIN_28_EINT6__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
++#define MT8127_PIN_28_EINT6__FUNC_URTS2 (MTK_PIN_NO(28) | 1)
++#define MT8127_PIN_28_EINT6__FUNC_DPI_D17 (MTK_PIN_NO(28) | 2)
++#define MT8127_PIN_28_EINT6__FUNC_SPI_CK (MTK_PIN_NO(28) | 3)
++#define MT8127_PIN_28_EINT6__FUNC_EXT_RXC (MTK_PIN_NO(28) | 4)
++#define MT8127_PIN_28_EINT6__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(28) | 5)
++#define MT8127_PIN_28_EINT6__FUNC_KCOL7 (MTK_PIN_NO(28) | 6)
++#define MT8127_PIN_28_EINT6__FUNC_DBG_MON_A_10 (MTK_PIN_NO(28) | 7)
++
++#define MT8127_PIN_29_EINT7__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
++#define MT8127_PIN_29_EINT7__FUNC_UCTS3 (MTK_PIN_NO(29) | 1)
++#define MT8127_PIN_29_EINT7__FUNC_DPI_D6 (MTK_PIN_NO(29) | 2)
++#define MT8127_PIN_29_EINT7__FUNC_SDA1 (MTK_PIN_NO(29) | 3)
++#define MT8127_PIN_29_EINT7__FUNC_EXT_RXDV (MTK_PIN_NO(29) | 4)
++#define MT8127_PIN_29_EINT7__FUNC_CONN_MCU_TMS (MTK_PIN_NO(29) | 5)
++#define MT8127_PIN_29_EINT7__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(29) | 6)
++#define MT8127_PIN_29_EINT7__FUNC_DBG_MON_A_11 (MTK_PIN_NO(29) | 7)
++
++#define MT8127_PIN_30_EINT8__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
++#define MT8127_PIN_30_EINT8__FUNC_URTS3 (MTK_PIN_NO(30) | 1)
++#define MT8127_PIN_30_EINT8__FUNC_CLKM3 (MTK_PIN_NO(30) | 2)
++#define MT8127_PIN_30_EINT8__FUNC_SCL1 (MTK_PIN_NO(30) | 3)
++#define MT8127_PIN_30_EINT8__FUNC_EXT_RXD0 (MTK_PIN_NO(30) | 4)
++#define MT8127_PIN_30_EINT8__FUNC_ANT_SEL0 (MTK_PIN_NO(30) | 5)
++#define MT8127_PIN_30_EINT8__FUNC_DPI_D7 (MTK_PIN_NO(30) | 6)
++#define MT8127_PIN_30_EINT8__FUNC_DBG_MON_B_2 (MTK_PIN_NO(30) | 7)
++
++#define MT8127_PIN_31_EINT9__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
++#define MT8127_PIN_31_EINT9__FUNC_CLKM4 (MTK_PIN_NO(31) | 1)
++#define MT8127_PIN_31_EINT9__FUNC_SDA2 (MTK_PIN_NO(31) | 2)
++#define MT8127_PIN_31_EINT9__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(31) | 3)
++#define MT8127_PIN_31_EINT9__FUNC_EXT_RXD1 (MTK_PIN_NO(31) | 4)
++#define MT8127_PIN_31_EINT9__FUNC_ANT_SEL1 (MTK_PIN_NO(31) | 5)
++#define MT8127_PIN_31_EINT9__FUNC_DPI_D8 (MTK_PIN_NO(31) | 6)
++#define MT8127_PIN_31_EINT9__FUNC_DBG_MON_B_3 (MTK_PIN_NO(31) | 7)
++
++#define MT8127_PIN_32_EINT10__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
++#define MT8127_PIN_32_EINT10__FUNC_CLKM5 (MTK_PIN_NO(32) | 1)
++#define MT8127_PIN_32_EINT10__FUNC_SCL2 (MTK_PIN_NO(32) | 2)
++#define MT8127_PIN_32_EINT10__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(32) | 3)
++#define MT8127_PIN_32_EINT10__FUNC_EXT_RXD2 (MTK_PIN_NO(32) | 4)
++#define MT8127_PIN_32_EINT10__FUNC_ANT_SEL2 (MTK_PIN_NO(32) | 5)
++#define MT8127_PIN_32_EINT10__FUNC_DPI_D9 (MTK_PIN_NO(32) | 6)
++#define MT8127_PIN_32_EINT10__FUNC_DBG_MON_B_4 (MTK_PIN_NO(32) | 7)
++
++#define MT8127_PIN_33_KPROW0__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
++#define MT8127_PIN_33_KPROW0__FUNC_KROW0 (MTK_PIN_NO(33) | 1)
++#define MT8127_PIN_33_KPROW0__FUNC_IMG_TEST_CK (MTK_PIN_NO(33) | 4)
++#define MT8127_PIN_33_KPROW0__FUNC_DBG_MON_A_12 (MTK_PIN_NO(33) | 7)
++
++#define MT8127_PIN_34_KPROW1__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
++#define MT8127_PIN_34_KPROW1__FUNC_KROW1 (MTK_PIN_NO(34) | 1)
++#define MT8127_PIN_34_KPROW1__FUNC_IDDIG (MTK_PIN_NO(34) | 2)
++#define MT8127_PIN_34_KPROW1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(34) | 3)
++#define MT8127_PIN_34_KPROW1__FUNC_MFG_TEST_CK (MTK_PIN_NO(34) | 4)
++#define MT8127_PIN_34_KPROW1__FUNC_DBG_MON_B_5 (MTK_PIN_NO(34) | 7)
++
++#define MT8127_PIN_35_KPROW2__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
++#define MT8127_PIN_35_KPROW2__FUNC_KROW2 (MTK_PIN_NO(35) | 1)
++#define MT8127_PIN_35_KPROW2__FUNC_DRV_VBUS (MTK_PIN_NO(35) | 2)
++#define MT8127_PIN_35_KPROW2__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(35) | 3)
++#define MT8127_PIN_35_KPROW2__FUNC_CONN_TEST_CK (MTK_PIN_NO(35) | 4)
++#define MT8127_PIN_35_KPROW2__FUNC_DBG_MON_B_6 (MTK_PIN_NO(35) | 7)
++
++#define MT8127_PIN_36_KPCOL0__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
++#define MT8127_PIN_36_KPCOL0__FUNC_KCOL0 (MTK_PIN_NO(36) | 1)
++#define MT8127_PIN_36_KPCOL0__FUNC_DBG_MON_A_13 (MTK_PIN_NO(36) | 7)
++
++#define MT8127_PIN_37_KPCOL1__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
++#define MT8127_PIN_37_KPCOL1__FUNC_KCOL1 (MTK_PIN_NO(37) | 1)
++#define MT8127_PIN_37_KPCOL1__FUNC_DBG_MON_B_7 (MTK_PIN_NO(37) | 7)
++
++#define MT8127_PIN_38_KPCOL2__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
++#define MT8127_PIN_38_KPCOL2__FUNC_KCOL2 (MTK_PIN_NO(38) | 1)
++#define MT8127_PIN_38_KPCOL2__FUNC_IDDIG (MTK_PIN_NO(38) | 2)
++#define MT8127_PIN_38_KPCOL2__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(38) | 3)
++#define MT8127_PIN_38_KPCOL2__FUNC_DBG_MON_B_8 (MTK_PIN_NO(38) | 7)
++
++#define MT8127_PIN_39_JTMS__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
++#define MT8127_PIN_39_JTMS__FUNC_JTMS (MTK_PIN_NO(39) | 1)
++#define MT8127_PIN_39_JTMS__FUNC_CONN_MCU_TMS (MTK_PIN_NO(39) | 2)
++#define MT8127_PIN_39_JTMS__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(39) | 3)
++
++#define MT8127_PIN_40_JTCK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
++#define MT8127_PIN_40_JTCK__FUNC_JTCK (MTK_PIN_NO(40) | 1)
++#define MT8127_PIN_40_JTCK__FUNC_CONN_MCU_TCK1 (MTK_PIN_NO(40) | 2)
++#define MT8127_PIN_40_JTCK__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(40) | 3)
++
++#define MT8127_PIN_41_JTDI__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
++#define MT8127_PIN_41_JTDI__FUNC_JTDI (MTK_PIN_NO(41) | 1)
++#define MT8127_PIN_41_JTDI__FUNC_CONN_MCU_TDI (MTK_PIN_NO(41) | 2)
++
++#define MT8127_PIN_42_JTDO__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
++#define MT8127_PIN_42_JTDO__FUNC_JTDO (MTK_PIN_NO(42) | 1)
++#define MT8127_PIN_42_JTDO__FUNC_CONN_MCU_TDO (MTK_PIN_NO(42) | 2)
++
++#define MT8127_PIN_43_EINT11__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
++#define MT8127_PIN_43_EINT11__FUNC_CLKM4 (MTK_PIN_NO(43) | 1)
++#define MT8127_PIN_43_EINT11__FUNC_PWM2 (MTK_PIN_NO(43) | 2)
++#define MT8127_PIN_43_EINT11__FUNC_KROW3 (MTK_PIN_NO(43) | 3)
++#define MT8127_PIN_43_EINT11__FUNC_ANT_SEL3 (MTK_PIN_NO(43) | 4)
++#define MT8127_PIN_43_EINT11__FUNC_DPI_D10 (MTK_PIN_NO(43) | 5)
++#define MT8127_PIN_43_EINT11__FUNC_EXT_RXD3 (MTK_PIN_NO(43) | 6)
++#define MT8127_PIN_43_EINT11__FUNC_DBG_MON_B_9 (MTK_PIN_NO(43) | 7)
++
++#define MT8127_PIN_44_EINT12__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
++#define MT8127_PIN_44_EINT12__FUNC_CLKM5 (MTK_PIN_NO(44) | 1)
++#define MT8127_PIN_44_EINT12__FUNC_PWM0 (MTK_PIN_NO(44) | 2)
++#define MT8127_PIN_44_EINT12__FUNC_KCOL3 (MTK_PIN_NO(44) | 3)
++#define MT8127_PIN_44_EINT12__FUNC_ANT_SEL4 (MTK_PIN_NO(44) | 4)
++#define MT8127_PIN_44_EINT12__FUNC_DPI_D11 (MTK_PIN_NO(44) | 5)
++#define MT8127_PIN_44_EINT12__FUNC_EXT_TXEN (MTK_PIN_NO(44) | 6)
++#define MT8127_PIN_44_EINT12__FUNC_DBG_MON_B_10 (MTK_PIN_NO(44) | 7)
++
++#define MT8127_PIN_45_EINT13__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
++#define MT8127_PIN_45_EINT13__FUNC_ANT_SEL5 (MTK_PIN_NO(45) | 4)
++#define MT8127_PIN_45_EINT13__FUNC_DPI_D0 (MTK_PIN_NO(45) | 5)
++#define MT8127_PIN_45_EINT13__FUNC_SPDIF (MTK_PIN_NO(45) | 6)
++#define MT8127_PIN_45_EINT13__FUNC_DBG_MON_B_11 (MTK_PIN_NO(45) | 7)
++
++#define MT8127_PIN_46_EINT14__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
++#define MT8127_PIN_46_EINT14__FUNC_DAC_DAT_OUT (MTK_PIN_NO(46) | 2)
++#define MT8127_PIN_46_EINT14__FUNC_ANT_SEL1 (MTK_PIN_NO(46) | 4)
++#define MT8127_PIN_46_EINT14__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(46) | 5)
++#define MT8127_PIN_46_EINT14__FUNC_NCLE (MTK_PIN_NO(46) | 6)
++#define MT8127_PIN_46_EINT14__FUNC_DBG_MON_A_14 (MTK_PIN_NO(46) | 7)
++
++#define MT8127_PIN_47_EINT15__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
++#define MT8127_PIN_47_EINT15__FUNC_DAC_WS (MTK_PIN_NO(47) | 2)
++#define MT8127_PIN_47_EINT15__FUNC_ANT_SEL2 (MTK_PIN_NO(47) | 4)
++#define MT8127_PIN_47_EINT15__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(47) | 5)
++#define MT8127_PIN_47_EINT15__FUNC_NCEB1 (MTK_PIN_NO(47) | 6)
++#define MT8127_PIN_47_EINT15__FUNC_DBG_MON_A_15 (MTK_PIN_NO(47) | 7)
++
++#define MT8127_PIN_48_EINT16__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
++#define MT8127_PIN_48_EINT16__FUNC_DAC_CK (MTK_PIN_NO(48) | 2)
++#define MT8127_PIN_48_EINT16__FUNC_ANT_SEL3 (MTK_PIN_NO(48) | 4)
++#define MT8127_PIN_48_EINT16__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(48) | 5)
++#define MT8127_PIN_48_EINT16__FUNC_NCEB0 (MTK_PIN_NO(48) | 6)
++#define MT8127_PIN_48_EINT16__FUNC_DBG_MON_A_16 (MTK_PIN_NO(48) | 7)
++
++#define MT8127_PIN_49_EINT17__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
++#define MT8127_PIN_49_EINT17__FUNC_UCTS0 (MTK_PIN_NO(49) | 1)
++#define MT8127_PIN_49_EINT17__FUNC_CLKM0 (MTK_PIN_NO(49) | 3)
++#define MT8127_PIN_49_EINT17__FUNC_IDDIG (MTK_PIN_NO(49) | 4)
++#define MT8127_PIN_49_EINT17__FUNC_ANT_SEL4 (MTK_PIN_NO(49) | 5)
++#define MT8127_PIN_49_EINT17__FUNC_NREB (MTK_PIN_NO(49) | 6)
++#define MT8127_PIN_49_EINT17__FUNC_DBG_MON_A_17 (MTK_PIN_NO(49) | 7)
++
++#define MT8127_PIN_50_EINT18__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
++#define MT8127_PIN_50_EINT18__FUNC_URTS0 (MTK_PIN_NO(50) | 1)
++#define MT8127_PIN_50_EINT18__FUNC_CLKM3 (MTK_PIN_NO(50) | 2)
++#define MT8127_PIN_50_EINT18__FUNC_I2SOUT_LRCK (MTK_PIN_NO(50) | 3)
++#define MT8127_PIN_50_EINT18__FUNC_DRV_VBUS (MTK_PIN_NO(50) | 4)
++#define MT8127_PIN_50_EINT18__FUNC_ANT_SEL3 (MTK_PIN_NO(50) | 5)
++#define MT8127_PIN_50_EINT18__FUNC_ADC_CK (MTK_PIN_NO(50) | 6)
++#define MT8127_PIN_50_EINT18__FUNC_DBG_MON_B_12 (MTK_PIN_NO(50) | 7)
++
++#define MT8127_PIN_51_EINT19__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
++#define MT8127_PIN_51_EINT19__FUNC_UCTS1 (MTK_PIN_NO(51) | 1)
++#define MT8127_PIN_51_EINT19__FUNC_I2SOUT_BCK (MTK_PIN_NO(51) | 3)
++#define MT8127_PIN_51_EINT19__FUNC_CLKM1 (MTK_PIN_NO(51) | 4)
++#define MT8127_PIN_51_EINT19__FUNC_ANT_SEL4 (MTK_PIN_NO(51) | 5)
++#define MT8127_PIN_51_EINT19__FUNC_ADC_DAT_IN (MTK_PIN_NO(51) | 6)
++#define MT8127_PIN_51_EINT19__FUNC_DBG_MON_B_13 (MTK_PIN_NO(51) | 7)
++
++#define MT8127_PIN_52_EINT20__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
++#define MT8127_PIN_52_EINT20__FUNC_URTS1 (MTK_PIN_NO(52) | 1)
++#define MT8127_PIN_52_EINT20__FUNC_PCM_TX (MTK_PIN_NO(52) | 2)
++#define MT8127_PIN_52_EINT20__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(52) | 3)
++#define MT8127_PIN_52_EINT20__FUNC_CLKM2 (MTK_PIN_NO(52) | 4)
++#define MT8127_PIN_52_EINT20__FUNC_ANT_SEL5 (MTK_PIN_NO(52) | 5)
++#define MT8127_PIN_52_EINT20__FUNC_ADC_WS (MTK_PIN_NO(52) | 6)
++#define MT8127_PIN_52_EINT20__FUNC_DBG_MON_B_14 (MTK_PIN_NO(52) | 7)
++
++#define MT8127_PIN_53_SPI_CS__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
++#define MT8127_PIN_53_SPI_CS__FUNC_SPI_CS (MTK_PIN_NO(53) | 1)
++#define MT8127_PIN_53_SPI_CS__FUNC_I2SIN1_DATA_IN (MTK_PIN_NO(53) | 3)
++#define MT8127_PIN_53_SPI_CS__FUNC_ADC_CK (MTK_PIN_NO(53) | 4)
++#define MT8127_PIN_53_SPI_CS__FUNC_DBG_MON_B_15 (MTK_PIN_NO(53) | 7)
++
++#define MT8127_PIN_54_SPI_CK__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
++#define MT8127_PIN_54_SPI_CK__FUNC_SPI_CK (MTK_PIN_NO(54) | 1)
++#define MT8127_PIN_54_SPI_CK__FUNC_I2SIN1_LRCK (MTK_PIN_NO(54) | 3)
++#define MT8127_PIN_54_SPI_CK__FUNC_ADC_DAT_IN (MTK_PIN_NO(54) | 4)
++#define MT8127_PIN_54_SPI_CK__FUNC_DBG_MON_B_16 (MTK_PIN_NO(54) | 7)
++
++#define MT8127_PIN_55_SPI_MI__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
++#define MT8127_PIN_55_SPI_MI__FUNC_SPI_MI (MTK_PIN_NO(55) | 1)
++#define MT8127_PIN_55_SPI_MI__FUNC_SPI_MO (MTK_PIN_NO(55) | 2)
++#define MT8127_PIN_55_SPI_MI__FUNC_I2SIN1_BCK1 (MTK_PIN_NO(55) | 3)
++#define MT8127_PIN_55_SPI_MI__FUNC_ADC_WS (MTK_PIN_NO(55) | 4)
++#define MT8127_PIN_55_SPI_MI__FUNC_DBG_MON_B_17 (MTK_PIN_NO(55) | 7)
++
++#define MT8127_PIN_56_SPI_MO__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
++#define MT8127_PIN_56_SPI_MO__FUNC_SPI_MO (MTK_PIN_NO(56) | 1)
++#define MT8127_PIN_56_SPI_MO__FUNC_SPI_MI (MTK_PIN_NO(56) | 2)
++#define MT8127_PIN_56_SPI_MO__FUNC_DBG_MON_B_18 (MTK_PIN_NO(56) | 7)
++
++#define MT8127_PIN_57_SDA1__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
++#define MT8127_PIN_57_SDA1__FUNC_SDA1 (MTK_PIN_NO(57) | 1)
++
++#define MT8127_PIN_58_SCL1__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
++#define MT8127_PIN_58_SCL1__FUNC_SCL1 (MTK_PIN_NO(58) | 1)
++
++#define MT8127_PIN_59_DISP_PWM__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
++#define MT8127_PIN_59_DISP_PWM__FUNC_DISP_PWM (MTK_PIN_NO(59) | 1)
++#define MT8127_PIN_59_DISP_PWM__FUNC_PWM1 (MTK_PIN_NO(59) | 2)
++#define MT8127_PIN_59_DISP_PWM__FUNC_DBG_MON_A_18 (MTK_PIN_NO(59) | 7)
++
++#define MT8127_PIN_60_WB_RSTB__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
++#define MT8127_PIN_60_WB_RSTB__FUNC_WB_RSTB (MTK_PIN_NO(60) | 1)
++#define MT8127_PIN_60_WB_RSTB__FUNC_DBG_MON_A_19 (MTK_PIN_NO(60) | 7)
++
++#define MT8127_PIN_61_F2W_DATA__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
++#define MT8127_PIN_61_F2W_DATA__FUNC_F2W_DATA (MTK_PIN_NO(61) | 1)
++#define MT8127_PIN_61_F2W_DATA__FUNC_DBG_MON_A_20 (MTK_PIN_NO(61) | 7)
++
++#define MT8127_PIN_62_F2W_CLK__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
++#define MT8127_PIN_62_F2W_CLK__FUNC_F2W_CK (MTK_PIN_NO(62) | 1)
++#define MT8127_PIN_62_F2W_CLK__FUNC_DBG_MON_A_21 (MTK_PIN_NO(62) | 7)
++
++#define MT8127_PIN_63_WB_SCLK__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
++#define MT8127_PIN_63_WB_SCLK__FUNC_WB_SCLK (MTK_PIN_NO(63) | 1)
++#define MT8127_PIN_63_WB_SCLK__FUNC_DBG_MON_A_22 (MTK_PIN_NO(63) | 7)
++
++#define MT8127_PIN_64_WB_SDATA__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
++#define MT8127_PIN_64_WB_SDATA__FUNC_WB_SDATA (MTK_PIN_NO(64) | 1)
++#define MT8127_PIN_64_WB_SDATA__FUNC_DBG_MON_A_23 (MTK_PIN_NO(64) | 7)
++
++#define MT8127_PIN_65_WB_SEN__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
++#define MT8127_PIN_65_WB_SEN__FUNC_WB_SEN (MTK_PIN_NO(65) | 1)
++#define MT8127_PIN_65_WB_SEN__FUNC_DBG_MON_A_24 (MTK_PIN_NO(65) | 7)
++
++#define MT8127_PIN_66_WB_CRTL0__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
++#define MT8127_PIN_66_WB_CRTL0__FUNC_WB_CRTL0 (MTK_PIN_NO(66) | 1)
++#define MT8127_PIN_66_WB_CRTL0__FUNC_DFD_NTRST_XI (MTK_PIN_NO(66) | 2)
++#define MT8127_PIN_66_WB_CRTL0__FUNC_DBG_MON_A_25 (MTK_PIN_NO(66) | 7)
++
++#define MT8127_PIN_67_WB_CRTL1__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
++#define MT8127_PIN_67_WB_CRTL1__FUNC_WB_CRTL1 (MTK_PIN_NO(67) | 1)
++#define MT8127_PIN_67_WB_CRTL1__FUNC_DFD_TMS_XI (MTK_PIN_NO(67) | 2)
++#define MT8127_PIN_67_WB_CRTL1__FUNC_DBG_MON_A_26 (MTK_PIN_NO(67) | 7)
++
++#define MT8127_PIN_68_WB_CRTL2__FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
++#define MT8127_PIN_68_WB_CRTL2__FUNC_WB_CRTL2 (MTK_PIN_NO(68) | 1)
++#define MT8127_PIN_68_WB_CRTL2__FUNC_DFD_TCK_XI (MTK_PIN_NO(68) | 2)
++#define MT8127_PIN_68_WB_CRTL2__FUNC_DBG_MON_A_27 (MTK_PIN_NO(68) | 7)
++
++#define MT8127_PIN_69_WB_CRTL3__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
++#define MT8127_PIN_69_WB_CRTL3__FUNC_WB_CRTL3 (MTK_PIN_NO(69) | 1)
++#define MT8127_PIN_69_WB_CRTL3__FUNC_DFD_TDI_XI (MTK_PIN_NO(69) | 2)
++#define MT8127_PIN_69_WB_CRTL3__FUNC_DBG_MON_A_28 (MTK_PIN_NO(69) | 7)
++
++#define MT8127_PIN_70_WB_CRTL4__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
++#define MT8127_PIN_70_WB_CRTL4__FUNC_WB_CRTL4 (MTK_PIN_NO(70) | 1)
++#define MT8127_PIN_70_WB_CRTL4__FUNC_DFD_TDO (MTK_PIN_NO(70) | 2)
++#define MT8127_PIN_70_WB_CRTL4__FUNC_DBG_MON_A_29 (MTK_PIN_NO(70) | 7)
++
++#define MT8127_PIN_71_WB_CRTL5__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
++#define MT8127_PIN_71_WB_CRTL5__FUNC_WB_CRTL5 (MTK_PIN_NO(71) | 1)
++#define MT8127_PIN_71_WB_CRTL5__FUNC_DBG_MON_A_30 (MTK_PIN_NO(71) | 7)
++
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_I2SIN1_DATA_IN (MTK_PIN_NO(72) | 1)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_PCM_RX (MTK_PIN_NO(72) | 2)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(72) | 3)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_DAC_DAT_OUT (MTK_PIN_NO(72) | 4)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_PWM0 (MTK_PIN_NO(72) | 5)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_ADC_CK (MTK_PIN_NO(72) | 6)
++#define MT8127_PIN_72_I2S_DATA_IN__FUNC_DBG_MON_B_19 (MTK_PIN_NO(72) | 7)
++
++#define MT8127_PIN_73_I2S_LRCK__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_I2SIN1_LRCK (MTK_PIN_NO(73) | 1)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_PCM_SYNC (MTK_PIN_NO(73) | 2)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_I2SOUT_LRCK (MTK_PIN_NO(73) | 3)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_DAC_WS (MTK_PIN_NO(73) | 4)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_PWM3 (MTK_PIN_NO(73) | 5)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_ADC_DAT_IN (MTK_PIN_NO(73) | 6)
++#define MT8127_PIN_73_I2S_LRCK__FUNC_DBG_MON_B_20 (MTK_PIN_NO(73) | 7)
++
++#define MT8127_PIN_74_I2S_BCK__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
++#define MT8127_PIN_74_I2S_BCK__FUNC_I2SIN1_BCK2 (MTK_PIN_NO(74) | 1)
++#define MT8127_PIN_74_I2S_BCK__FUNC_PCM_CLK1 (MTK_PIN_NO(74) | 2)
++#define MT8127_PIN_74_I2S_BCK__FUNC_I2SOUT_BCK (MTK_PIN_NO(74) | 3)
++#define MT8127_PIN_74_I2S_BCK__FUNC_DAC_CK (MTK_PIN_NO(74) | 4)
++#define MT8127_PIN_74_I2S_BCK__FUNC_PWM4 (MTK_PIN_NO(74) | 5)
++#define MT8127_PIN_74_I2S_BCK__FUNC_ADC_WS (MTK_PIN_NO(74) | 6)
++#define MT8127_PIN_74_I2S_BCK__FUNC_DBG_MON_B_21 (MTK_PIN_NO(74) | 7)
++
++#define MT8127_PIN_75_SDA0__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
++#define MT8127_PIN_75_SDA0__FUNC_SDA0 (MTK_PIN_NO(75) | 1)
++
++#define MT8127_PIN_76_SCL0__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
++#define MT8127_PIN_76_SCL0__FUNC_SCL0 (MTK_PIN_NO(76) | 1)
++
++#define MT8127_PIN_77_SDA2__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
++#define MT8127_PIN_77_SDA2__FUNC_SDA2 (MTK_PIN_NO(77) | 1)
++#define MT8127_PIN_77_SDA2__FUNC_PWM1 (MTK_PIN_NO(77) | 2)
++
++#define MT8127_PIN_78_SCL2__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
++#define MT8127_PIN_78_SCL2__FUNC_SCL2 (MTK_PIN_NO(78) | 1)
++#define MT8127_PIN_78_SCL2__FUNC_PWM2 (MTK_PIN_NO(78) | 2)
++
++#define MT8127_PIN_79_URXD0__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
++#define MT8127_PIN_79_URXD0__FUNC_URXD0 (MTK_PIN_NO(79) | 1)
++#define MT8127_PIN_79_URXD0__FUNC_UTXD0 (MTK_PIN_NO(79) | 2)
++
++#define MT8127_PIN_80_UTXD0__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
++#define MT8127_PIN_80_UTXD0__FUNC_UTXD0 (MTK_PIN_NO(80) | 1)
++#define MT8127_PIN_80_UTXD0__FUNC_URXD0 (MTK_PIN_NO(80) | 2)
++
++#define MT8127_PIN_81_URXD1__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
++#define MT8127_PIN_81_URXD1__FUNC_URXD1 (MTK_PIN_NO(81) | 1)
++#define MT8127_PIN_81_URXD1__FUNC_UTXD1 (MTK_PIN_NO(81) | 2)
++
++#define MT8127_PIN_82_UTXD1__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
++#define MT8127_PIN_82_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(82) | 1)
++#define MT8127_PIN_82_UTXD1__FUNC_URXD1 (MTK_PIN_NO(82) | 2)
++
++#define MT8127_PIN_83_LCM_RST__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
++#define MT8127_PIN_83_LCM_RST__FUNC_LCM_RST (MTK_PIN_NO(83) | 1)
++#define MT8127_PIN_83_LCM_RST__FUNC_VDAC_CK_XI (MTK_PIN_NO(83) | 2)
++#define MT8127_PIN_83_LCM_RST__FUNC_DBG_MON_A_31 (MTK_PIN_NO(83) | 7)
++
++#define MT8127_PIN_84_DSI_TE__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
++#define MT8127_PIN_84_DSI_TE__FUNC_DSI_TE (MTK_PIN_NO(84) | 1)
++#define MT8127_PIN_84_DSI_TE__FUNC_DBG_MON_A_32 (MTK_PIN_NO(84) | 7)
++
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(85) | 1)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_ANT_SEL0 (MTK_PIN_NO(85) | 2)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_SDA1 (MTK_PIN_NO(85) | 3)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_I2SOUT_BCK (MTK_PIN_NO(85) | 6)
++#define MT8127_PIN_85_MSDC2_CMD__FUNC_DBG_MON_B_22 (MTK_PIN_NO(85) | 7)
++
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(86) | 1)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_ANT_SEL1 (MTK_PIN_NO(86) | 2)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_SCL1 (MTK_PIN_NO(86) | 3)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_I2SOUT_LRCK (MTK_PIN_NO(86) | 6)
++#define MT8127_PIN_86_MSDC2_CLK__FUNC_DBG_MON_B_23 (MTK_PIN_NO(86) | 7)
++
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(87) | 1)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_ANT_SEL2 (MTK_PIN_NO(87) | 2)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_UTXD0 (MTK_PIN_NO(87) | 5)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(87) | 6)
++#define MT8127_PIN_87_MSDC2_DAT0__FUNC_DBG_MON_B_24 (MTK_PIN_NO(87) | 7)
++
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(88) | 1)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_ANT_SEL3 (MTK_PIN_NO(88) | 2)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_PWM0 (MTK_PIN_NO(88) | 3)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_URXD0 (MTK_PIN_NO(88) | 5)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_PWM1 (MTK_PIN_NO(88) | 6)
++#define MT8127_PIN_88_MSDC2_DAT1__FUNC_DBG_MON_B_25 (MTK_PIN_NO(88) | 7)
++
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(89) | 1)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_ANT_SEL4 (MTK_PIN_NO(89) | 2)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_SDA2 (MTK_PIN_NO(89) | 3)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_UTXD1 (MTK_PIN_NO(89) | 5)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_PWM2 (MTK_PIN_NO(89) | 6)
++#define MT8127_PIN_89_MSDC2_DAT2__FUNC_DBG_MON_B_26 (MTK_PIN_NO(89) | 7)
++
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(90) | 1)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_ANT_SEL5 (MTK_PIN_NO(90) | 2)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_SCL2 (MTK_PIN_NO(90) | 3)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(90) | 4)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_URXD1 (MTK_PIN_NO(90) | 5)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_PWM3 (MTK_PIN_NO(90) | 6)
++#define MT8127_PIN_90_MSDC2_DAT3__FUNC_DBG_MON_B_27 (MTK_PIN_NO(90) | 7)
++
++#define MT8127_PIN_91_TDN3__FUNC_GPI91 (MTK_PIN_NO(91) | 0)
++#define MT8127_PIN_91_TDN3__FUNC_TDN3 (MTK_PIN_NO(91) | 1)
++
++#define MT8127_PIN_92_TDP3__FUNC_GPI92 (MTK_PIN_NO(92) | 0)
++#define MT8127_PIN_92_TDP3__FUNC_TDP3 (MTK_PIN_NO(92) | 1)
++
++#define MT8127_PIN_93_TDN2__FUNC_GPI93 (MTK_PIN_NO(93) | 0)
++#define MT8127_PIN_93_TDN2__FUNC_TDN2 (MTK_PIN_NO(93) | 1)
++
++#define MT8127_PIN_94_TDP2__FUNC_GPI94 (MTK_PIN_NO(94) | 0)
++#define MT8127_PIN_94_TDP2__FUNC_TDP2 (MTK_PIN_NO(94) | 1)
++
++#define MT8127_PIN_95_TCN__FUNC_GPI95 (MTK_PIN_NO(95) | 0)
++#define MT8127_PIN_95_TCN__FUNC_TCN (MTK_PIN_NO(95) | 1)
++
++#define MT8127_PIN_96_TCP__FUNC_GPI96 (MTK_PIN_NO(96) | 0)
++#define MT8127_PIN_96_TCP__FUNC_TCP (MTK_PIN_NO(96) | 1)
++
++#define MT8127_PIN_97_TDN1__FUNC_GPI97 (MTK_PIN_NO(97) | 0)
++#define MT8127_PIN_97_TDN1__FUNC_TDN1 (MTK_PIN_NO(97) | 1)
++
++#define MT8127_PIN_98_TDP1__FUNC_GPI98 (MTK_PIN_NO(98) | 0)
++#define MT8127_PIN_98_TDP1__FUNC_TDP1 (MTK_PIN_NO(98) | 1)
++
++#define MT8127_PIN_99_TDN0__FUNC_GPI99 (MTK_PIN_NO(99) | 0)
++#define MT8127_PIN_99_TDN0__FUNC_TDN0 (MTK_PIN_NO(99) | 1)
++
++#define MT8127_PIN_100_TDP0__FUNC_GPI100 (MTK_PIN_NO(100) | 0)
++#define MT8127_PIN_100_TDP0__FUNC_TDP0 (MTK_PIN_NO(100) | 1)
++
++#define MT8127_PIN_101_RDN0__FUNC_GPI101 (MTK_PIN_NO(101) | 0)
++#define MT8127_PIN_101_RDN0__FUNC_RDN0 (MTK_PIN_NO(101) | 1)
++
++#define MT8127_PIN_102_RDP0__FUNC_GPI102 (MTK_PIN_NO(102) | 0)
++#define MT8127_PIN_102_RDP0__FUNC_RDP0 (MTK_PIN_NO(102) | 1)
++
++#define MT8127_PIN_103_RDN1__FUNC_GPI103 (MTK_PIN_NO(103) | 0)
++#define MT8127_PIN_103_RDN1__FUNC_RDN1 (MTK_PIN_NO(103) | 1)
++
++#define MT8127_PIN_104_RDP1__FUNC_GPI104 (MTK_PIN_NO(104) | 0)
++#define MT8127_PIN_104_RDP1__FUNC_RDP1 (MTK_PIN_NO(104) | 1)
++
++#define MT8127_PIN_105_RCN__FUNC_GPI105 (MTK_PIN_NO(105) | 0)
++#define MT8127_PIN_105_RCN__FUNC_RCN (MTK_PIN_NO(105) | 1)
++
++#define MT8127_PIN_106_RCP__FUNC_GPI106 (MTK_PIN_NO(106) | 0)
++#define MT8127_PIN_106_RCP__FUNC_RCP (MTK_PIN_NO(106) | 1)
++
++#define MT8127_PIN_107_RDN2__FUNC_GPI107 (MTK_PIN_NO(107) | 0)
++#define MT8127_PIN_107_RDN2__FUNC_RDN2 (MTK_PIN_NO(107) | 1)
++#define MT8127_PIN_107_RDN2__FUNC_CMDAT8 (MTK_PIN_NO(107) | 2)
++
++#define MT8127_PIN_108_RDP2__FUNC_GPI108 (MTK_PIN_NO(108) | 0)
++#define MT8127_PIN_108_RDP2__FUNC_RDP2 (MTK_PIN_NO(108) | 1)
++#define MT8127_PIN_108_RDP2__FUNC_CMDAT9 (MTK_PIN_NO(108) | 2)
++
++#define MT8127_PIN_109_RDN3__FUNC_GPI109 (MTK_PIN_NO(109) | 0)
++#define MT8127_PIN_109_RDN3__FUNC_RDN3 (MTK_PIN_NO(109) | 1)
++#define MT8127_PIN_109_RDN3__FUNC_CMDAT4 (MTK_PIN_NO(109) | 2)
++
++#define MT8127_PIN_110_RDP3__FUNC_GPI110 (MTK_PIN_NO(110) | 0)
++#define MT8127_PIN_110_RDP3__FUNC_RDP3 (MTK_PIN_NO(110) | 1)
++#define MT8127_PIN_110_RDP3__FUNC_CMDAT5 (MTK_PIN_NO(110) | 2)
++
++#define MT8127_PIN_111_RCN_A__FUNC_GPI111 (MTK_PIN_NO(111) | 0)
++#define MT8127_PIN_111_RCN_A__FUNC_RCN_A (MTK_PIN_NO(111) | 1)
++#define MT8127_PIN_111_RCN_A__FUNC_CMDAT6 (MTK_PIN_NO(111) | 2)
++
++#define MT8127_PIN_112_RCP_A__FUNC_GPI112 (MTK_PIN_NO(112) | 0)
++#define MT8127_PIN_112_RCP_A__FUNC_RCP_A (MTK_PIN_NO(112) | 1)
++#define MT8127_PIN_112_RCP_A__FUNC_CMDAT7 (MTK_PIN_NO(112) | 2)
++
++#define MT8127_PIN_113_RDN1_A__FUNC_GPI113 (MTK_PIN_NO(113) | 0)
++#define MT8127_PIN_113_RDN1_A__FUNC_RDN1_A (MTK_PIN_NO(113) | 1)
++#define MT8127_PIN_113_RDN1_A__FUNC_CMDAT2 (MTK_PIN_NO(113) | 2)
++#define MT8127_PIN_113_RDN1_A__FUNC_CMCSD2 (MTK_PIN_NO(113) | 3)
++
++#define MT8127_PIN_114_RDP1_A__FUNC_GPI114 (MTK_PIN_NO(114) | 0)
++#define MT8127_PIN_114_RDP1_A__FUNC_RDP1_A (MTK_PIN_NO(114) | 1)
++#define MT8127_PIN_114_RDP1_A__FUNC_CMDAT3 (MTK_PIN_NO(114) | 2)
++#define MT8127_PIN_114_RDP1_A__FUNC_CMCSD3 (MTK_PIN_NO(114) | 3)
++
++#define MT8127_PIN_115_RDN0_A__FUNC_GPI115 (MTK_PIN_NO(115) | 0)
++#define MT8127_PIN_115_RDN0_A__FUNC_RDN0_A (MTK_PIN_NO(115) | 1)
++#define MT8127_PIN_115_RDN0_A__FUNC_CMHSYNC (MTK_PIN_NO(115) | 2)
++
++#define MT8127_PIN_116_RDP0_A__FUNC_GPI116 (MTK_PIN_NO(116) | 0)
++#define MT8127_PIN_116_RDP0_A__FUNC_RDP0_A (MTK_PIN_NO(116) | 1)
++#define MT8127_PIN_116_RDP0_A__FUNC_CMVSYNC (MTK_PIN_NO(116) | 2)
++
++#define MT8127_PIN_117_CMDAT0__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
++#define MT8127_PIN_117_CMDAT0__FUNC_CMDAT0 (MTK_PIN_NO(117) | 1)
++#define MT8127_PIN_117_CMDAT0__FUNC_CMCSD0 (MTK_PIN_NO(117) | 2)
++#define MT8127_PIN_117_CMDAT0__FUNC_ANT_SEL2 (MTK_PIN_NO(117) | 3)
++#define MT8127_PIN_117_CMDAT0__FUNC_DBG_MON_B_28 (MTK_PIN_NO(117) | 7)
++
++#define MT8127_PIN_118_CMDAT1__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
++#define MT8127_PIN_118_CMDAT1__FUNC_CMDAT1 (MTK_PIN_NO(118) | 1)
++#define MT8127_PIN_118_CMDAT1__FUNC_CMCSD1 (MTK_PIN_NO(118) | 2)
++#define MT8127_PIN_118_CMDAT1__FUNC_ANT_SEL3 (MTK_PIN_NO(118) | 3)
++#define MT8127_PIN_118_CMDAT1__FUNC_DBG_MON_B_29 (MTK_PIN_NO(118) | 7)
++
++#define MT8127_PIN_119_CMMCLK__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
++#define MT8127_PIN_119_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(119) | 1)
++#define MT8127_PIN_119_CMMCLK__FUNC_ANT_SEL4 (MTK_PIN_NO(119) | 3)
++#define MT8127_PIN_119_CMMCLK__FUNC_DBG_MON_B_30 (MTK_PIN_NO(119) | 7)
++
++#define MT8127_PIN_120_CMPCLK__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
++#define MT8127_PIN_120_CMPCLK__FUNC_CMPCLK (MTK_PIN_NO(120) | 1)
++#define MT8127_PIN_120_CMPCLK__FUNC_CMCSK (MTK_PIN_NO(120) | 2)
++#define MT8127_PIN_120_CMPCLK__FUNC_ANT_SEL5 (MTK_PIN_NO(120) | 3)
++#define MT8127_PIN_120_CMPCLK__FUNC_DBG_MON_B_31 (MTK_PIN_NO(120) | 7)
++
++#define MT8127_PIN_121_MSDC1_CMD__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
++#define MT8127_PIN_121_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(121) | 1)
++
++#define MT8127_PIN_122_MSDC1_CLK__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
++#define MT8127_PIN_122_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(122) | 1)
++
++#define MT8127_PIN_123_MSDC1_DAT0__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
++#define MT8127_PIN_123_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(123) | 1)
++
++#define MT8127_PIN_124_MSDC1_DAT1__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
++#define MT8127_PIN_124_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(124) | 1)
++
++#define MT8127_PIN_125_MSDC1_DAT2__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
++#define MT8127_PIN_125_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(125) | 1)
++
++#define MT8127_PIN_126_MSDC1_DAT3__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
++#define MT8127_PIN_126_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(126) | 1)
++
++#define MT8127_PIN_127_MSDC0_DAT7__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
++#define MT8127_PIN_127_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(127) | 1)
++#define MT8127_PIN_127_MSDC0_DAT7__FUNC_NLD7 (MTK_PIN_NO(127) | 4)
++
++#define MT8127_PIN_128_MSDC0_DAT6__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
++#define MT8127_PIN_128_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(128) | 1)
++#define MT8127_PIN_128_MSDC0_DAT6__FUNC_NLD6 (MTK_PIN_NO(128) | 4)
++
++#define MT8127_PIN_129_MSDC0_DAT5__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
++#define MT8127_PIN_129_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(129) | 1)
++#define MT8127_PIN_129_MSDC0_DAT5__FUNC_NLD4 (MTK_PIN_NO(129) | 4)
++
++#define MT8127_PIN_130_MSDC0_DAT4__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
++#define MT8127_PIN_130_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(130) | 1)
++#define MT8127_PIN_130_MSDC0_DAT4__FUNC_NLD3 (MTK_PIN_NO(130) | 4)
++
++#define MT8127_PIN_131_MSDC0_RSTB__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
++#define MT8127_PIN_131_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(131) | 1)
++#define MT8127_PIN_131_MSDC0_RSTB__FUNC_NLD0 (MTK_PIN_NO(131) | 4)
++
++#define MT8127_PIN_132_MSDC0_CMD__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
++#define MT8127_PIN_132_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(132) | 1)
++#define MT8127_PIN_132_MSDC0_CMD__FUNC_NALE (MTK_PIN_NO(132) | 4)
++
++#define MT8127_PIN_133_MSDC0_CLK__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
++#define MT8127_PIN_133_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(133) | 1)
++#define MT8127_PIN_133_MSDC0_CLK__FUNC_NWEB (MTK_PIN_NO(133) | 4)
++
++#define MT8127_PIN_134_MSDC0_DAT3__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
++#define MT8127_PIN_134_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(134) | 1)
++#define MT8127_PIN_134_MSDC0_DAT3__FUNC_NLD1 (MTK_PIN_NO(134) | 4)
++
++#define MT8127_PIN_135_MSDC0_DAT2__FUNC_GPIO135 (MTK_PIN_NO(135) | 0)
++#define MT8127_PIN_135_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(135) | 1)
++#define MT8127_PIN_135_MSDC0_DAT2__FUNC_NLD5 (MTK_PIN_NO(135) | 4)
++
++#define MT8127_PIN_136_MSDC0_DAT1__FUNC_GPIO136 (MTK_PIN_NO(136) | 0)
++#define MT8127_PIN_136_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(136) | 1)
++#define MT8127_PIN_136_MSDC0_DAT1__FUNC_NLD8 (MTK_PIN_NO(136) | 4)
++
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_GPIO137 (MTK_PIN_NO(137) | 0)
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(137) | 1)
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_WATCHDOG (MTK_PIN_NO(137) | 4)
++#define MT8127_PIN_137_MSDC0_DAT0__FUNC_NLD2 (MTK_PIN_NO(137) | 5)
++
++#define MT8127_PIN_138_CEC__FUNC_GPIO138 (MTK_PIN_NO(138) | 0)
++#define MT8127_PIN_138_CEC__FUNC_CEC (MTK_PIN_NO(138) | 1)
++
++#define MT8127_PIN_139_HTPLG__FUNC_GPIO139 (MTK_PIN_NO(139) | 0)
++#define MT8127_PIN_139_HTPLG__FUNC_HTPLG (MTK_PIN_NO(139) | 1)
++
++#define MT8127_PIN_140_HDMISCK__FUNC_GPIO140 (MTK_PIN_NO(140) | 0)
++#define MT8127_PIN_140_HDMISCK__FUNC_HDMISCK (MTK_PIN_NO(140) | 1)
++
++#define MT8127_PIN_141_HDMISD__FUNC_GPIO141 (MTK_PIN_NO(141) | 0)
++#define MT8127_PIN_141_HDMISD__FUNC_HDMISD (MTK_PIN_NO(141) | 1)
++
++#define MT8127_PIN_142_EINT21__FUNC_GPIO142 (MTK_PIN_NO(142) | 0)
++#define MT8127_PIN_142_EINT21__FUNC_NRNB (MTK_PIN_NO(142) | 1)
++#define MT8127_PIN_142_EINT21__FUNC_ANT_SEL0 (MTK_PIN_NO(142) | 2)
++#define MT8127_PIN_142_EINT21__FUNC_DBG_MON_B_32 (MTK_PIN_NO(142) | 7)
++
++#endif /* __DTS_MT8127_PINFUNC_H */
+diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi
+index 7c2090d..1d429ed 100644
+--- a/arch/arm/boot/dts/mt8127.dtsi
++++ b/arch/arm/boot/dts/mt8127.dtsi
+@@ -14,6 +14,7 @@
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
++#include "mt8127-pinfunc.h"
+ #include "skeleton64.dtsi"
+ / {
+@@ -94,6 +95,27 @@
+               compatible = "simple-bus";
+               ranges;
++              /*
++               * Pinctrl access register at 0x10005000 through regmap.
++               * Register 0x1000b000 is used by EINT.
++               */
++              pio: pinctrl@10005000 {
++                      compatible = "mediatek,mt8127-pinctrl";
++                      reg = <0 0x1000b000 0 0x1000>;
++                      mediatek,pctl-regmap = <&syscfg_pctl_a>;
++                      pins-are-numbered;
++                      gpio-controller;
++                      #gpio-cells = <2>;
++                      interrupt-controller;
++                      #interrupt-cells = <2>;
++                      interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              syscfg_pctl_a: syscfg_pctl_a@10005000 {
++                      compatible = "mediatek,mt8127-pctl-a-syscfg", "syscon";
++                      reg = <0 0x10005000 0 0x1000>;
++              };
++
+               timer: timer@10008000 {
+                       compatible = "mediatek,mt8127-timer",
+                                       "mediatek,mt6577-timer";
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0057-thermal-oops.patch b/target/linux/mediatek/patches/0057-thermal-oops.patch
new file mode 100644 (file)
index 0000000..e7684f1
--- /dev/null
@@ -0,0 +1,27 @@
+From d1a856804b84affae30274b391b3c685e901093f Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 11:35:29 +0200
+Subject: [PATCH 57/76] thermal oops
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/thermal/mtk_thermal.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
+index 27aab12..5fdcbf6 100644
+--- a/drivers/thermal/mtk_thermal.c
++++ b/drivers/thermal/mtk_thermal.c
+@@ -394,7 +394,8 @@ static irqreturn_t mtk_thermal_irq(int irq, void *dev_id)
+       for (i = 0; i < MT8173_NUM_BANKS; i++) {
+               if (!(irqstat & (1 << i)))
+-                      mtk_thermal_irq_bank(&mt->banks[i]);
++                      if (!IS_ERR(mt->banks[i].tz))
++                              mtk_thermal_irq_bank(&mt->banks[i]);
+       }
+       return IRQ_HANDLED;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0058-dont-disable-clocks.patch b/target/linux/mediatek/patches/0058-dont-disable-clocks.patch
new file mode 100644 (file)
index 0000000..e30d5dc
--- /dev/null
@@ -0,0 +1,25 @@
+From b1c69201563ae3ff878abf4ba192e73031de8653 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 23 Jun 2015 23:46:00 +0200
+Subject: [PATCH 58/76] dont disable clocks
+
+---
+ drivers/clk/clk.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 5b0f418..360e6e4 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -541,7 +541,7 @@ unlock_out:
+       clk_enable_unlock(flags);
+ }
+-static bool clk_ignore_unused;
++static bool clk_ignore_unused = true;
+ static int __init clk_ignore_unused_setup(char *__unused)
+ {
+       clk_ignore_unused = true;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0059-arm-mediatek-basic-mt6323-pmic-support.patch b/target/linux/mediatek/patches/0059-arm-mediatek-basic-mt6323-pmic-support.patch
new file mode 100644 (file)
index 0000000..ca28251
--- /dev/null
@@ -0,0 +1,1099 @@
+From 7f157285f2a01921917e0eed79b5d8cf734f5d27 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 24 Jun 2015 15:24:45 +0200
+Subject: [PATCH 59/76] arm: mediatek: basic mt6323 pmic support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mfd/Kconfig                  |   10 +
+ drivers/mfd/Makefile                 |    1 +
+ drivers/mfd/mt6323-core.c            |  230 +++++++++++++++++++++
+ drivers/regulator/Kconfig            |    9 +
+ drivers/regulator/Makefile           |    1 +
+ drivers/regulator/mt6323-regulator.c |  332 +++++++++++++++++++++++++++++++
+ include/linux/mfd/mt6323/core.h      |   64 ++++++
+ include/linux/mfd/mt6323/registers.h |  362 ++++++++++++++++++++++++++++++++++
+ 8 files changed, 1009 insertions(+)
+ create mode 100644 drivers/mfd/mt6323-core.c
+ create mode 100644 drivers/regulator/mt6323-regulator.c
+ create mode 100644 include/linux/mfd/mt6323/core.h
+ create mode 100644 include/linux/mfd/mt6323/registers.h
+
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index d5ad04d..ff2c14e 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -529,6 +529,16 @@ config MFD_MAX8998
+         additional drivers must be enabled in order to use the functionality
+         of the device.
++config MFD_MT6323
++      tristate "MediaTek MT6323 PMIC Support"
++      select MFD_CORE
++      select IRQ_DOMAIN
++      help
++        Say yes here to add support for MediaTek MT6323 PMIC. This is
++        a Power Management IC. This driver provides common support for
++        accessing the device; additional drivers must be enabled in order
++        to use the functionality of the device.
++
+ config MFD_MT6397
+       tristate "MediaTek MT6397 PMIC Support"
+       select MFD_CORE
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index 0e5cfeb..6e91123 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -184,4 +184,5 @@ obj-$(CONFIG_MFD_SKY81452) += sky81452.o
+ intel-soc-pmic-objs           := intel_soc_pmic_core.o intel_soc_pmic_crc.o
+ obj-$(CONFIG_INTEL_SOC_PMIC)  += intel-soc-pmic.o
++obj-$(CONFIG_MFD_MT6323)      += mt6323-core.o
+ obj-$(CONFIG_MFD_MT6397)      += mt6397-core.o
+diff --git a/drivers/mfd/mt6323-core.c b/drivers/mfd/mt6323-core.c
+new file mode 100644
+index 0000000..012c620
+--- /dev/null
++++ b/drivers/mfd/mt6323-core.c
+@@ -0,0 +1,230 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * 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/interrupt.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/of_irq.h>
++#include <linux/regmap.h>
++#include <linux/mfd/core.h>
++#include <linux/mfd/mt6397/core.h>
++#include <linux/mfd/mt6397/registers.h>
++
++static const struct mfd_cell mt6397_devs[] = {
++      {
++              .name = "mt6397-rtc",
++              .of_compatible = "mediatek,mt6397-rtc",
++      }, {
++              .name = "mt6397-regulator",
++              .of_compatible = "mediatek,mt6397-regulator",
++      }, {
++              .name = "mt6397-codec",
++              .of_compatible = "mediatek,mt6397-codec",
++      }, {
++              .name = "mt6397-clk",
++              .of_compatible = "mediatek,mt6397-clk",
++      }, {
++              .name = "mediatek-mt6397-pinctrl",
++              .of_compatible = "mediatek,mt6397-pinctrl",
++      },
++};
++
++static void mt6397_irq_lock(struct irq_data *data)
++{
++      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++
++      mutex_lock(&mt6397->irqlock);
++}
++
++static void mt6397_irq_sync_unlock(struct irq_data *data)
++{
++      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++
++      regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
++      regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
++
++      mutex_unlock(&mt6397->irqlock);
++}
++
++static void mt6397_irq_disable(struct irq_data *data)
++{
++      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++      int shift = data->hwirq & 0xf;
++      int reg = data->hwirq >> 4;
++
++      mt6397->irq_masks_cur[reg] &= ~BIT(shift);
++}
++
++static void mt6397_irq_enable(struct irq_data *data)
++{
++      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++      int shift = data->hwirq & 0xf;
++      int reg = data->hwirq >> 4;
++
++      mt6397->irq_masks_cur[reg] |= BIT(shift);
++}
++
++static struct irq_chip mt6397_irq_chip = {
++      .name = "mt6397-irq",
++      .irq_bus_lock = mt6397_irq_lock,
++      .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
++      .irq_enable = mt6397_irq_enable,
++      .irq_disable = mt6397_irq_disable,
++};
++
++static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
++              int irqbase)
++{
++      unsigned int status;
++      int i, irq, ret;
++
++      ret = regmap_read(mt6397->regmap, reg, &status);
++      if (ret) {
++              dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
++              return;
++      }
++
++      for (i = 0; i < 16; i++) {
++              if (status & BIT(i)) {
++                      irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
++                      if (irq)
++                              handle_nested_irq(irq);
++              }
++      }
++
++      regmap_write(mt6397->regmap, reg, status);
++}
++
++static irqreturn_t mt6397_irq_thread(int irq, void *data)
++{
++      struct mt6397_chip *mt6397 = data;
++
++      mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
++      mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
++
++      return IRQ_HANDLED;
++}
++
++static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
++                                      irq_hw_number_t hw)
++{
++      struct mt6397_chip *mt6397 = d->host_data;
++
++      irq_set_chip_data(irq, mt6397);
++      irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
++      irq_set_nested_thread(irq, 1);
++#ifdef CONFIG_ARM
++      set_irq_flags(irq, IRQF_VALID);
++#else
++      irq_set_noprobe(irq);
++#endif
++
++      return 0;
++}
++
++static struct irq_domain_ops mt6397_irq_domain_ops = {
++      .map = mt6397_irq_domain_map,
++};
++
++static int mt6397_irq_init(struct mt6397_chip *mt6397)
++{
++      int ret;
++
++      mutex_init(&mt6397->irqlock);
++
++      /* Mask all interrupt sources */
++      regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
++      regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
++
++      mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
++              MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
++      if (!mt6397->irq_domain) {
++              dev_err(mt6397->dev, "could not create irq domain\n");
++              return -ENOMEM;
++      }
++
++      ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
++              mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
++      if (ret) {
++              dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
++                      mt6397->irq, ret);
++              return ret;
++      }
++
++      return 0;
++}
++
++static int mt6397_probe(struct platform_device *pdev)
++{
++      int ret;
++      struct mt6397_chip *mt6397;
++
++      mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
++      if (!mt6397)
++              return -ENOMEM;
++
++      mt6397->dev = &pdev->dev;
++      /*
++       * mt6397 MFD is child device of soc pmic wrapper.
++       * Regmap is set from its parent.
++       */
++      mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
++      if (!mt6397->regmap)
++              return -ENODEV;
++
++      platform_set_drvdata(pdev, mt6397);
++
++      mt6397->irq = platform_get_irq(pdev, 0);
++      if (mt6397->irq > 0) {
++              ret = mt6397_irq_init(mt6397);
++              if (ret)
++                      return ret;
++      }
++
++      ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
++                      ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
++      if (ret)
++              dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
++
++      return ret;
++}
++
++static int mt6397_remove(struct platform_device *pdev)
++{
++      mfd_remove_devices(&pdev->dev);
++
++      return 0;
++}
++
++static const struct of_device_id mt6397_of_match[] = {
++      { .compatible = "mediatek,mt6397" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, mt6397_of_match);
++
++static struct platform_driver mt6397_driver = {
++      .probe = mt6397_probe,
++      .remove = mt6397_remove,
++      .driver = {
++              .name = "mt6397",
++              .of_match_table = of_match_ptr(mt6397_of_match),
++      },
++};
++
++module_platform_driver(mt6397_driver);
++
++MODULE_AUTHOR("Flora Fu, MediaTek");
++MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:mt6397");
+diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
+index a6f116a..336d4c6 100644
+--- a/drivers/regulator/Kconfig
++++ b/drivers/regulator/Kconfig
+@@ -441,6 +441,15 @@ config REGULATOR_MC13892
+         Say y here to support the regulators found on the Freescale MC13892
+         PMIC.
++config REGULATOR_MT6323
++      tristate "MediaTek MT6323 PMIC"
++      depends on MFD_MT6323
++      help
++        Say y here to select this option to enable the power regulator of
++        MediaTek MT6323 PMIC.
++        This driver supports the control of different power rails of device
++        through regulator interface.
++
+ config REGULATOR_MT6397
+       tristate "MediaTek MT6397 PMIC"
+       depends on MFD_MT6397
+diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
+index 2c4da15..ac6a9da 100644
+--- a/drivers/regulator/Makefile
++++ b/drivers/regulator/Makefile
+@@ -59,6 +59,7 @@ obj-$(CONFIG_REGULATOR_MAX77843) += max77843.o
+ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
+ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
+ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
++obj-$(CONFIG_REGULATOR_MT6323)        += mt6323-regulator.o
+ obj-$(CONFIG_REGULATOR_MT6397)        += mt6397-regulator.o
+ obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
+ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+diff --git a/drivers/regulator/mt6323-regulator.c b/drivers/regulator/mt6323-regulator.c
+new file mode 100644
+index 0000000..a5b2f47
+--- /dev/null
++++ b/drivers/regulator/mt6323-regulator.c
+@@ -0,0 +1,332 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu <flora.fu@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/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/mfd/mt6397/core.h>
++#include <linux/mfd/mt6397/registers.h>
++#include <linux/regulator/driver.h>
++#include <linux/regulator/machine.h>
++#include <linux/regulator/mt6397-regulator.h>
++#include <linux/regulator/of_regulator.h>
++
++/*
++ * MT6397 regulators' information
++ *
++ * @desc: standard fields of regulator description.
++ * @qi: Mask for query enable signal status of regulators
++ * @vselon_reg: Register sections for hardware control mode of bucks
++ * @vselctrl_reg: Register for controlling the buck control mode.
++ * @vselctrl_mask: Mask for query buck's voltage control mode.
++ */
++struct mt6397_regulator_info {
++      struct regulator_desc desc;
++      u32 qi;
++      u32 vselon_reg;
++      u32 vselctrl_reg;
++      u32 vselctrl_mask;
++};
++
++#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg,  \
++              vosel, vosel_mask, voselon, vosel_ctrl)                 \
++[MT6397_ID_##vreg] = {                                                        \
++      .desc = {                                                       \
++              .name = #vreg,                                          \
++              .of_match = of_match_ptr(match),                        \
++              .ops = &mt6397_volt_range_ops,                          \
++              .type = REGULATOR_VOLTAGE,                              \
++              .id = MT6397_ID_##vreg,                                 \
++              .owner = THIS_MODULE,                                   \
++              .n_voltages = (max - min)/step + 1,                     \
++              .linear_ranges = volt_ranges,                           \
++              .n_linear_ranges = ARRAY_SIZE(volt_ranges),             \
++              .vsel_reg = vosel,                                      \
++              .vsel_mask = vosel_mask,                                \
++              .enable_reg = enreg,                                    \
++              .enable_mask = BIT(0),                                  \
++      },                                                              \
++      .qi = BIT(13),                                                  \
++      .vselon_reg = voselon,                                          \
++      .vselctrl_reg = vosel_ctrl,                                     \
++      .vselctrl_mask = BIT(1),                                        \
++}
++
++#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,  \
++              vosel_mask)                                             \
++[MT6397_ID_##vreg] = {                                                        \
++      .desc = {                                                       \
++              .name = #vreg,                                          \
++              .of_match = of_match_ptr(match),                        \
++              .ops = &mt6397_volt_table_ops,                          \
++              .type = REGULATOR_VOLTAGE,                              \
++              .id = MT6397_ID_##vreg,                                 \
++              .owner = THIS_MODULE,                                   \
++              .n_voltages = ARRAY_SIZE(ldo_volt_table),               \
++              .volt_table = ldo_volt_table,                           \
++              .vsel_reg = vosel,                                      \
++              .vsel_mask = vosel_mask,                                \
++              .enable_reg = enreg,                                    \
++              .enable_mask = BIT(enbit),                              \
++      },                                                              \
++      .qi = BIT(15),                                                  \
++}
++
++#define MT6397_REG_FIXED(match, vreg, enreg, enbit, volt)             \
++[MT6397_ID_##vreg] = {                                                        \
++      .desc = {                                                       \
++              .name = #vreg,                                          \
++              .of_match = of_match_ptr(match),                        \
++              .ops = &mt6397_volt_fixed_ops,                          \
++              .type = REGULATOR_VOLTAGE,                              \
++              .id = MT6397_ID_##vreg,                                 \
++              .owner = THIS_MODULE,                                   \
++              .n_voltages = 1,                                        \
++              .enable_reg = enreg,                                    \
++              .enable_mask = BIT(enbit),                              \
++              .min_uV = volt,                                         \
++      },                                                              \
++      .qi = BIT(15),                                                  \
++}
++
++static const struct regulator_linear_range buck_volt_range1[] = {
++      REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
++};
++
++static const struct regulator_linear_range buck_volt_range2[] = {
++      REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
++};
++
++static const struct regulator_linear_range buck_volt_range3[] = {
++      REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),
++};
++
++static const u32 ldo_volt_table1[] = {
++      1500000, 1800000, 2500000, 2800000,
++};
++
++static const u32 ldo_volt_table2[] = {
++      1800000, 3300000,
++};
++
++static const u32 ldo_volt_table3[] = {
++      3000000, 3300000,
++};
++
++static const u32 ldo_volt_table4[] = {
++      1220000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static const u32 ldo_volt_table5[] = {
++      1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static const u32 ldo_volt_table5_v2[] = {
++      1200000, 1000000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static const u32 ldo_volt_table6[] = {
++      1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
++};
++
++static const u32 ldo_volt_table7[] = {
++      1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
++};
++
++static int mt6397_get_status(struct regulator_dev *rdev)
++{
++      int ret;
++      u32 regval;
++      struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
++
++      ret = regmap_read(rdev->regmap, info->desc.enable_reg, &regval);
++      if (ret != 0) {
++              dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);
++              return ret;
++      }
++
++      return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
++}
++
++static struct regulator_ops mt6397_volt_range_ops = {
++      .list_voltage = regulator_list_voltage_linear_range,
++      .map_voltage = regulator_map_voltage_linear_range,
++      .set_voltage_sel = regulator_set_voltage_sel_regmap,
++      .get_voltage_sel = regulator_get_voltage_sel_regmap,
++      .set_voltage_time_sel = regulator_set_voltage_time_sel,
++      .enable = regulator_enable_regmap,
++      .disable = regulator_disable_regmap,
++      .is_enabled = regulator_is_enabled_regmap,
++      .get_status = mt6397_get_status,
++};
++
++static struct regulator_ops mt6397_volt_table_ops = {
++      .list_voltage = regulator_list_voltage_table,
++      .map_voltage = regulator_map_voltage_iterate,
++      .set_voltage_sel = regulator_set_voltage_sel_regmap,
++      .get_voltage_sel = regulator_get_voltage_sel_regmap,
++      .set_voltage_time_sel = regulator_set_voltage_time_sel,
++      .enable = regulator_enable_regmap,
++      .disable = regulator_disable_regmap,
++      .is_enabled = regulator_is_enabled_regmap,
++      .get_status = mt6397_get_status,
++};
++
++static struct regulator_ops mt6397_volt_fixed_ops = {
++      .list_voltage = regulator_list_voltage_linear,
++      .enable = regulator_enable_regmap,
++      .disable = regulator_disable_regmap,
++      .is_enabled = regulator_is_enabled_regmap,
++      .get_status = mt6397_get_status,
++};
++
++/* The array is indexed by id(MT6397_ID_XXX) */
++static struct mt6397_regulator_info mt6397_regulators[] = {
++      MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
++              buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
++              MT6397_VCA15_CON10, MT6397_VCA15_CON5),
++      MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
++              buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
++              MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
++      MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
++              buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
++              0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
++      MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
++              buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
++              0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
++      MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
++              buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
++              MT6397_VCORE_CON10, MT6397_VCORE_CON5),
++      MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
++              MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
++              MT6397_VGPU_CON10, MT6397_VGPU_CON5),
++      MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
++              MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
++              MT6397_VDRM_CON10, MT6397_VDRM_CON5),
++      MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
++              buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
++              MT6397_VIO18_CON10, MT6397_VIO18_CON5),
++      MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
++      MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
++      MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
++              MT6397_ANALDO_CON2, 15, MT6397_ANALDO_CON6, 0xC0),
++      MT6397_REG_FIXED("ldo_vio28", VIO28, MT6397_DIGLDO_CON0, 14, 2800000),
++      MT6397_REG_FIXED("ldo_vusb", VUSB, MT6397_DIGLDO_CON1, 14, 3300000),
++      MT6397_LDO("ldo_vmc", VMC, ldo_volt_table2,
++              MT6397_DIGLDO_CON2, 12, MT6397_DIGLDO_CON29, 0x10),
++      MT6397_LDO("ldo_vmch", VMCH, ldo_volt_table3,
++              MT6397_DIGLDO_CON3, 14, MT6397_DIGLDO_CON17, 0x80),
++      MT6397_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table3,
++              MT6397_DIGLDO_CON4, 14, MT6397_DIGLDO_CON18, 0x10),
++      MT6397_LDO("ldo_vgp1", VGP1, ldo_volt_table4,
++              MT6397_DIGLDO_CON5, 15, MT6397_DIGLDO_CON19, 0xE0),
++      MT6397_LDO("ldo_vgp2", VGP2, ldo_volt_table5,
++              MT6397_DIGLDO_CON6, 15, MT6397_DIGLDO_CON20, 0xE0),
++      MT6397_LDO("ldo_vgp3", VGP3, ldo_volt_table5,
++              MT6397_DIGLDO_CON7, 15, MT6397_DIGLDO_CON21, 0xE0),
++      MT6397_LDO("ldo_vgp4", VGP4, ldo_volt_table5,
++              MT6397_DIGLDO_CON8, 15, MT6397_DIGLDO_CON22, 0xE0),
++      MT6397_LDO("ldo_vgp5", VGP5, ldo_volt_table6,
++              MT6397_DIGLDO_CON9, 15, MT6397_DIGLDO_CON23, 0xE0),
++      MT6397_LDO("ldo_vgp6", VGP6, ldo_volt_table5,
++              MT6397_DIGLDO_CON10, 15, MT6397_DIGLDO_CON33, 0xE0),
++      MT6397_LDO("ldo_vibr", VIBR, ldo_volt_table7,
++              MT6397_DIGLDO_CON24, 15, MT6397_DIGLDO_CON25, 0xE00),
++};
++
++static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)
++{
++      struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++      int i;
++      u32 regval;
++
++      for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
++              if (mt6397_regulators[i].vselctrl_reg) {
++                      if (regmap_read(mt6397->regmap,
++                              mt6397_regulators[i].vselctrl_reg,
++                              &regval) < 0) {
++                              dev_err(&pdev->dev,
++                                      "Failed to read buck ctrl\n");
++                              return -EIO;
++                      }
++
++                      if (regval & mt6397_regulators[i].vselctrl_mask) {
++                              mt6397_regulators[i].desc.vsel_reg =
++                              mt6397_regulators[i].vselon_reg;
++                      }
++              }
++      }
++
++      return 0;
++}
++
++static int mt6397_regulator_probe(struct platform_device *pdev)
++{
++      struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++      struct regulator_config config = {};
++      struct regulator_dev *rdev;
++      int i;
++      u32 reg_value, version;
++
++      /* Query buck controller to select activated voltage register part */
++      if (mt6397_set_buck_vosel_reg(pdev))
++              return -EIO;
++
++      /* Read PMIC chip revision to update constraints and voltage table */
++      if (regmap_read(mt6397->regmap, MT6397_CID, &reg_value) < 0) {
++              dev_err(&pdev->dev, "Failed to read Chip ID\n");
++              return -EIO;
++      }
++      dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
++
++      version = (reg_value & 0xFF);
++      switch (version) {
++      case MT6397_REGULATOR_ID91:
++              mt6397_regulators[MT6397_ID_VGP2].desc.volt_table =
++              ldo_volt_table5_v2;
++              break;
++      default:
++              break;
++      }
++
++      for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
++              config.dev = &pdev->dev;
++              config.driver_data = &mt6397_regulators[i];
++              config.regmap = mt6397->regmap;
++              rdev = devm_regulator_register(&pdev->dev,
++                              &mt6397_regulators[i].desc, &config);
++              if (IS_ERR(rdev)) {
++                      dev_err(&pdev->dev, "failed to register %s\n",
++                              mt6397_regulators[i].desc.name);
++                      return PTR_ERR(rdev);
++              }
++      }
++
++      return 0;
++}
++
++static struct platform_driver mt6397_regulator_driver = {
++      .driver = {
++              .name = "mt6397-regulator",
++      },
++      .probe = mt6397_regulator_probe,
++};
++
++module_platform_driver(mt6397_regulator_driver);
++
++MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");
++MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:mt6397-regulator");
+diff --git a/include/linux/mfd/mt6323/core.h b/include/linux/mfd/mt6323/core.h
+new file mode 100644
+index 0000000..cf5265b
+--- /dev/null
++++ b/include/linux/mfd/mt6323/core.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * 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 __MFD_MT6397_CORE_H__
++#define __MFD_MT6397_CORE_H__
++
++enum mt6397_irq_numbers {
++      MT6397_IRQ_SPKL_AB = 0,
++      MT6397_IRQ_SPKR_AB,
++      MT6397_IRQ_SPKL,
++      MT6397_IRQ_SPKR,
++      MT6397_IRQ_BAT_L,
++      MT6397_IRQ_BAT_H,
++      MT6397_IRQ_FG_BAT_L,
++      MT6397_IRQ_FG_BAT_H,
++      MT6397_IRQ_WATCHDOG,
++      MT6397_IRQ_PWRKEY,
++      MT6397_IRQ_THR_L,
++      MT6397_IRQ_THR_H,
++      MT6397_IRQ_VBATON_UNDET,
++      MT6397_IRQ_BVALID_DET,
++      MT6397_IRQ_CHRDET,
++      MT6397_IRQ_OV,
++      MT6397_IRQ_LDO,
++      MT6397_IRQ_HOMEKEY,
++      MT6397_IRQ_ACCDET,
++      MT6397_IRQ_AUDIO,
++      MT6397_IRQ_RTC,
++      MT6397_IRQ_PWRKEY_RSTB,
++      MT6397_IRQ_HDMI_SIFM,
++      MT6397_IRQ_HDMI_CEC,
++      MT6397_IRQ_VCA15,
++      MT6397_IRQ_VSRMCA15,
++      MT6397_IRQ_VCORE,
++      MT6397_IRQ_VGPU,
++      MT6397_IRQ_VIO18,
++      MT6397_IRQ_VPCA7,
++      MT6397_IRQ_VSRMCA7,
++      MT6397_IRQ_VDRM,
++      MT6397_IRQ_NR,
++};
++
++struct mt6397_chip {
++      struct device *dev;
++      struct regmap *regmap;
++      int irq;
++      struct irq_domain *irq_domain;
++      struct mutex irqlock;
++      u16 irq_masks_cur[2];
++      u16 irq_masks_cache[2];
++};
++
++#endif /* __MFD_MT6397_CORE_H__ */
+diff --git a/include/linux/mfd/mt6323/registers.h b/include/linux/mfd/mt6323/registers.h
+new file mode 100644
+index 0000000..f23a0a6
+--- /dev/null
++++ b/include/linux/mfd/mt6323/registers.h
+@@ -0,0 +1,362 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Flora Fu, MediaTek
++ *
++ * 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 __MFD_MT6397_REGISTERS_H__
++#define __MFD_MT6397_REGISTERS_H__
++
++/* PMIC Registers */
++#define MT6397_CID                    0x0100
++#define MT6397_TOP_CKPDN              0x0102
++#define MT6397_TOP_CKPDN_SET          0x0104
++#define MT6397_TOP_CKPDN_CLR          0x0106
++#define MT6397_TOP_CKPDN2             0x0108
++#define MT6397_TOP_CKPDN2_SET         0x010A
++#define MT6397_TOP_CKPDN2_CLR         0x010C
++#define MT6397_TOP_GPIO_CKPDN         0x010E
++#define MT6397_TOP_RST_CON            0x0114
++#define MT6397_WRP_CKPDN              0x011A
++#define MT6397_WRP_RST_CON            0x0120
++#define MT6397_TOP_RST_MISC           0x0126
++#define MT6397_TOP_CKCON1             0x0128
++#define MT6397_TOP_CKCON2             0x012A
++#define MT6397_TOP_CKTST1             0x012C
++#define MT6397_TOP_CKTST2             0x012E
++#define MT6397_OC_DEG_EN              0x0130
++#define MT6397_OC_CTL0                        0x0132
++#define MT6397_OC_CTL1                        0x0134
++#define MT6397_OC_CTL2                        0x0136
++#define MT6397_INT_RSV                        0x0138
++#define MT6397_TEST_CON0              0x013A
++#define MT6397_TEST_CON1              0x013C
++#define MT6397_STATUS0                        0x013E
++#define MT6397_STATUS1                        0x0140
++#define MT6397_PGSTATUS                       0x0142
++#define MT6397_CHRSTATUS              0x0144
++#define MT6397_OCSTATUS0              0x0146
++#define MT6397_OCSTATUS1              0x0148
++#define MT6397_OCSTATUS2              0x014A
++#define MT6397_HDMI_PAD_IE            0x014C
++#define MT6397_TEST_OUT_L             0x014E
++#define MT6397_TEST_OUT_H             0x0150
++#define MT6397_TDSEL_CON              0x0152
++#define MT6397_RDSEL_CON              0x0154
++#define MT6397_GPIO_SMT_CON0          0x0156
++#define MT6397_GPIO_SMT_CON1          0x0158
++#define MT6397_GPIO_SMT_CON2          0x015A
++#define MT6397_GPIO_SMT_CON3          0x015C
++#define MT6397_DRV_CON0                       0x015E
++#define MT6397_DRV_CON1                       0x0160
++#define MT6397_DRV_CON2                       0x0162
++#define MT6397_DRV_CON3                       0x0164
++#define MT6397_DRV_CON4                       0x0166
++#define MT6397_DRV_CON5                       0x0168
++#define MT6397_DRV_CON6                       0x016A
++#define MT6397_DRV_CON7                       0x016C
++#define MT6397_DRV_CON8                       0x016E
++#define MT6397_DRV_CON9                       0x0170
++#define MT6397_DRV_CON10              0x0172
++#define MT6397_DRV_CON11              0x0174
++#define MT6397_DRV_CON12              0x0176
++#define MT6397_INT_CON0                       0x0178
++#define MT6397_INT_CON1                       0x017E
++#define MT6397_INT_STATUS0            0x0184
++#define MT6397_INT_STATUS1            0x0186
++#define MT6397_FQMTR_CON0             0x0188
++#define MT6397_FQMTR_CON1             0x018A
++#define MT6397_FQMTR_CON2             0x018C
++#define MT6397_EFUSE_DOUT_0_15                0x01C4
++#define MT6397_EFUSE_DOUT_16_31               0x01C6
++#define MT6397_EFUSE_DOUT_32_47               0x01C8
++#define MT6397_EFUSE_DOUT_48_63               0x01CA
++#define MT6397_SPI_CON                        0x01CC
++#define MT6397_TOP_CKPDN3             0x01CE
++#define MT6397_TOP_CKCON3             0x01D4
++#define MT6397_EFUSE_DOUT_64_79               0x01D6
++#define MT6397_EFUSE_DOUT_80_95               0x01D8
++#define MT6397_EFUSE_DOUT_96_111      0x01DA
++#define MT6397_EFUSE_DOUT_112_127     0x01DC
++#define MT6397_EFUSE_DOUT_128_143     0x01DE
++#define MT6397_EFUSE_DOUT_144_159     0x01E0
++#define MT6397_EFUSE_DOUT_160_175     0x01E2
++#define MT6397_EFUSE_DOUT_176_191     0x01E4
++#define MT6397_EFUSE_DOUT_192_207     0x01E6
++#define MT6397_EFUSE_DOUT_208_223     0x01E8
++#define MT6397_EFUSE_DOUT_224_239     0x01EA
++#define MT6397_EFUSE_DOUT_240_255     0x01EC
++#define MT6397_EFUSE_DOUT_256_271     0x01EE
++#define MT6397_EFUSE_DOUT_272_287     0x01F0
++#define MT6397_EFUSE_DOUT_288_300     0x01F2
++#define MT6397_EFUSE_DOUT_304_319     0x01F4
++#define MT6397_BUCK_CON0              0x0200
++#define MT6397_BUCK_CON1              0x0202
++#define MT6397_BUCK_CON2              0x0204
++#define MT6397_BUCK_CON3              0x0206
++#define MT6397_BUCK_CON4              0x0208
++#define MT6397_BUCK_CON5              0x020A
++#define MT6397_BUCK_CON6              0x020C
++#define MT6397_BUCK_CON7              0x020E
++#define MT6397_BUCK_CON8              0x0210
++#define MT6397_BUCK_CON9              0x0212
++#define MT6397_VCA15_CON0             0x0214
++#define MT6397_VCA15_CON1             0x0216
++#define MT6397_VCA15_CON2             0x0218
++#define MT6397_VCA15_CON3             0x021A
++#define MT6397_VCA15_CON4             0x021C
++#define MT6397_VCA15_CON5             0x021E
++#define MT6397_VCA15_CON6             0x0220
++#define MT6397_VCA15_CON7             0x0222
++#define MT6397_VCA15_CON8             0x0224
++#define MT6397_VCA15_CON9             0x0226
++#define MT6397_VCA15_CON10            0x0228
++#define MT6397_VCA15_CON11            0x022A
++#define MT6397_VCA15_CON12            0x022C
++#define MT6397_VCA15_CON13            0x022E
++#define MT6397_VCA15_CON14            0x0230
++#define MT6397_VCA15_CON15            0x0232
++#define MT6397_VCA15_CON16            0x0234
++#define MT6397_VCA15_CON17            0x0236
++#define MT6397_VCA15_CON18            0x0238
++#define MT6397_VSRMCA15_CON0          0x023A
++#define MT6397_VSRMCA15_CON1          0x023C
++#define MT6397_VSRMCA15_CON2          0x023E
++#define MT6397_VSRMCA15_CON3          0x0240
++#define MT6397_VSRMCA15_CON4          0x0242
++#define MT6397_VSRMCA15_CON5          0x0244
++#define MT6397_VSRMCA15_CON6          0x0246
++#define MT6397_VSRMCA15_CON7          0x0248
++#define MT6397_VSRMCA15_CON8          0x024A
++#define MT6397_VSRMCA15_CON9          0x024C
++#define MT6397_VSRMCA15_CON10         0x024E
++#define MT6397_VSRMCA15_CON11         0x0250
++#define MT6397_VSRMCA15_CON12         0x0252
++#define MT6397_VSRMCA15_CON13         0x0254
++#define MT6397_VSRMCA15_CON14         0x0256
++#define MT6397_VSRMCA15_CON15         0x0258
++#define MT6397_VSRMCA15_CON16         0x025A
++#define MT6397_VSRMCA15_CON17         0x025C
++#define MT6397_VSRMCA15_CON18         0x025E
++#define MT6397_VSRMCA15_CON19         0x0260
++#define MT6397_VSRMCA15_CON20         0x0262
++#define MT6397_VSRMCA15_CON21         0x0264
++#define MT6397_VCORE_CON0             0x0266
++#define MT6397_VCORE_CON1             0x0268
++#define MT6397_VCORE_CON2             0x026A
++#define MT6397_VCORE_CON3             0x026C
++#define MT6397_VCORE_CON4             0x026E
++#define MT6397_VCORE_CON5             0x0270
++#define MT6397_VCORE_CON6             0x0272
++#define MT6397_VCORE_CON7             0x0274
++#define MT6397_VCORE_CON8             0x0276
++#define MT6397_VCORE_CON9             0x0278
++#define MT6397_VCORE_CON10            0x027A
++#define MT6397_VCORE_CON11            0x027C
++#define MT6397_VCORE_CON12            0x027E
++#define MT6397_VCORE_CON13            0x0280
++#define MT6397_VCORE_CON14            0x0282
++#define MT6397_VCORE_CON15            0x0284
++#define MT6397_VCORE_CON16            0x0286
++#define MT6397_VCORE_CON17            0x0288
++#define MT6397_VCORE_CON18            0x028A
++#define MT6397_VGPU_CON0              0x028C
++#define MT6397_VGPU_CON1              0x028E
++#define MT6397_VGPU_CON2              0x0290
++#define MT6397_VGPU_CON3              0x0292
++#define MT6397_VGPU_CON4              0x0294
++#define MT6397_VGPU_CON5              0x0296
++#define MT6397_VGPU_CON6              0x0298
++#define MT6397_VGPU_CON7              0x029A
++#define MT6397_VGPU_CON8              0x029C
++#define MT6397_VGPU_CON9              0x029E
++#define MT6397_VGPU_CON10             0x02A0
++#define MT6397_VGPU_CON11             0x02A2
++#define MT6397_VGPU_CON12             0x02A4
++#define MT6397_VGPU_CON13             0x02A6
++#define MT6397_VGPU_CON14             0x02A8
++#define MT6397_VGPU_CON15             0x02AA
++#define MT6397_VGPU_CON16             0x02AC
++#define MT6397_VGPU_CON17             0x02AE
++#define MT6397_VGPU_CON18             0x02B0
++#define MT6397_VIO18_CON0             0x0300
++#define MT6397_VIO18_CON1             0x0302
++#define MT6397_VIO18_CON2             0x0304
++#define MT6397_VIO18_CON3             0x0306
++#define MT6397_VIO18_CON4             0x0308
++#define MT6397_VIO18_CON5             0x030A
++#define MT6397_VIO18_CON6             0x030C
++#define MT6397_VIO18_CON7             0x030E
++#define MT6397_VIO18_CON8             0x0310
++#define MT6397_VIO18_CON9             0x0312
++#define MT6397_VIO18_CON10            0x0314
++#define MT6397_VIO18_CON11            0x0316
++#define MT6397_VIO18_CON12            0x0318
++#define MT6397_VIO18_CON13            0x031A
++#define MT6397_VIO18_CON14            0x031C
++#define MT6397_VIO18_CON15            0x031E
++#define MT6397_VIO18_CON16            0x0320
++#define MT6397_VIO18_CON17            0x0322
++#define MT6397_VIO18_CON18            0x0324
++#define MT6397_VPCA7_CON0             0x0326
++#define MT6397_VPCA7_CON1             0x0328
++#define MT6397_VPCA7_CON2             0x032A
++#define MT6397_VPCA7_CON3             0x032C
++#define MT6397_VPCA7_CON4             0x032E
++#define MT6397_VPCA7_CON5             0x0330
++#define MT6397_VPCA7_CON6             0x0332
++#define MT6397_VPCA7_CON7             0x0334
++#define MT6397_VPCA7_CON8             0x0336
++#define MT6397_VPCA7_CON9             0x0338
++#define MT6397_VPCA7_CON10            0x033A
++#define MT6397_VPCA7_CON11            0x033C
++#define MT6397_VPCA7_CON12            0x033E
++#define MT6397_VPCA7_CON13            0x0340
++#define MT6397_VPCA7_CON14            0x0342
++#define MT6397_VPCA7_CON15            0x0344
++#define MT6397_VPCA7_CON16            0x0346
++#define MT6397_VPCA7_CON17            0x0348
++#define MT6397_VPCA7_CON18            0x034A
++#define MT6397_VSRMCA7_CON0           0x034C
++#define MT6397_VSRMCA7_CON1           0x034E
++#define MT6397_VSRMCA7_CON2           0x0350
++#define MT6397_VSRMCA7_CON3           0x0352
++#define MT6397_VSRMCA7_CON4           0x0354
++#define MT6397_VSRMCA7_CON5           0x0356
++#define MT6397_VSRMCA7_CON6           0x0358
++#define MT6397_VSRMCA7_CON7           0x035A
++#define MT6397_VSRMCA7_CON8           0x035C
++#define MT6397_VSRMCA7_CON9           0x035E
++#define MT6397_VSRMCA7_CON10          0x0360
++#define MT6397_VSRMCA7_CON11          0x0362
++#define MT6397_VSRMCA7_CON12          0x0364
++#define MT6397_VSRMCA7_CON13          0x0366
++#define MT6397_VSRMCA7_CON14          0x0368
++#define MT6397_VSRMCA7_CON15          0x036A
++#define MT6397_VSRMCA7_CON16          0x036C
++#define MT6397_VSRMCA7_CON17          0x036E
++#define MT6397_VSRMCA7_CON18          0x0370
++#define MT6397_VSRMCA7_CON19          0x0372
++#define MT6397_VSRMCA7_CON20          0x0374
++#define MT6397_VSRMCA7_CON21          0x0376
++#define MT6397_VDRM_CON0              0x0378
++#define MT6397_VDRM_CON1              0x037A
++#define MT6397_VDRM_CON2              0x037C
++#define MT6397_VDRM_CON3              0x037E
++#define MT6397_VDRM_CON4              0x0380
++#define MT6397_VDRM_CON5              0x0382
++#define MT6397_VDRM_CON6              0x0384
++#define MT6397_VDRM_CON7              0x0386
++#define MT6397_VDRM_CON8              0x0388
++#define MT6397_VDRM_CON9              0x038A
++#define MT6397_VDRM_CON10             0x038C
++#define MT6397_VDRM_CON11             0x038E
++#define MT6397_VDRM_CON12             0x0390
++#define MT6397_VDRM_CON13             0x0392
++#define MT6397_VDRM_CON14             0x0394
++#define MT6397_VDRM_CON15             0x0396
++#define MT6397_VDRM_CON16             0x0398
++#define MT6397_VDRM_CON17             0x039A
++#define MT6397_VDRM_CON18             0x039C
++#define MT6397_BUCK_K_CON0            0x039E
++#define MT6397_BUCK_K_CON1            0x03A0
++#define MT6397_ANALDO_CON0            0x0400
++#define MT6397_ANALDO_CON1            0x0402
++#define MT6397_ANALDO_CON2            0x0404
++#define MT6397_ANALDO_CON3            0x0406
++#define MT6397_ANALDO_CON4            0x0408
++#define MT6397_ANALDO_CON5            0x040A
++#define MT6397_ANALDO_CON6            0x040C
++#define MT6397_ANALDO_CON7            0x040E
++#define MT6397_DIGLDO_CON0            0x0410
++#define MT6397_DIGLDO_CON1            0x0412
++#define MT6397_DIGLDO_CON2            0x0414
++#define MT6397_DIGLDO_CON3            0x0416
++#define MT6397_DIGLDO_CON4            0x0418
++#define MT6397_DIGLDO_CON5            0x041A
++#define MT6397_DIGLDO_CON6            0x041C
++#define MT6397_DIGLDO_CON7            0x041E
++#define MT6397_DIGLDO_CON8            0x0420
++#define MT6397_DIGLDO_CON9            0x0422
++#define MT6397_DIGLDO_CON10           0x0424
++#define MT6397_DIGLDO_CON11           0x0426
++#define MT6397_DIGLDO_CON12           0x0428
++#define MT6397_DIGLDO_CON13           0x042A
++#define MT6397_DIGLDO_CON14           0x042C
++#define MT6397_DIGLDO_CON15           0x042E
++#define MT6397_DIGLDO_CON16           0x0430
++#define MT6397_DIGLDO_CON17           0x0432
++#define MT6397_DIGLDO_CON18           0x0434
++#define MT6397_DIGLDO_CON19           0x0436
++#define MT6397_DIGLDO_CON20           0x0438
++#define MT6397_DIGLDO_CON21           0x043A
++#define MT6397_DIGLDO_CON22           0x043C
++#define MT6397_DIGLDO_CON23           0x043E
++#define MT6397_DIGLDO_CON24           0x0440
++#define MT6397_DIGLDO_CON25           0x0442
++#define MT6397_DIGLDO_CON26           0x0444
++#define MT6397_DIGLDO_CON27           0x0446
++#define MT6397_DIGLDO_CON28           0x0448
++#define MT6397_DIGLDO_CON29           0x044A
++#define MT6397_DIGLDO_CON30           0x044C
++#define MT6397_DIGLDO_CON31           0x044E
++#define MT6397_DIGLDO_CON32           0x0450
++#define MT6397_DIGLDO_CON33           0x045A
++#define MT6397_SPK_CON0                       0x0600
++#define MT6397_SPK_CON1                       0x0602
++#define MT6397_SPK_CON2                       0x0604
++#define MT6397_SPK_CON3                       0x0606
++#define MT6397_SPK_CON4                       0x0608
++#define MT6397_SPK_CON5                       0x060A
++#define MT6397_SPK_CON6                       0x060C
++#define MT6397_SPK_CON7                       0x060E
++#define MT6397_SPK_CON8                       0x0610
++#define MT6397_SPK_CON9                       0x0612
++#define MT6397_SPK_CON10              0x0614
++#define MT6397_SPK_CON11              0x0616
++#define MT6397_AUDDAC_CON0            0x0700
++#define MT6397_AUDBUF_CFG0            0x0702
++#define MT6397_AUDBUF_CFG1            0x0704
++#define MT6397_AUDBUF_CFG2            0x0706
++#define MT6397_AUDBUF_CFG3            0x0708
++#define MT6397_AUDBUF_CFG4            0x070A
++#define MT6397_IBIASDIST_CFG0         0x070C
++#define MT6397_AUDACCDEPOP_CFG0               0x070E
++#define MT6397_AUD_IV_CFG0            0x0710
++#define MT6397_AUDCLKGEN_CFG0         0x0712
++#define MT6397_AUDLDO_CFG0            0x0714
++#define MT6397_AUDLDO_CFG1            0x0716
++#define MT6397_AUDNVREGGLB_CFG0               0x0718
++#define MT6397_AUD_NCP0                       0x071A
++#define MT6397_AUDPREAMP_CON0         0x071C
++#define MT6397_AUDADC_CON0            0x071E
++#define MT6397_AUDADC_CON1            0x0720
++#define MT6397_AUDADC_CON2            0x0722
++#define MT6397_AUDADC_CON3            0x0724
++#define MT6397_AUDADC_CON4            0x0726
++#define MT6397_AUDADC_CON5            0x0728
++#define MT6397_AUDADC_CON6            0x072A
++#define MT6397_AUDDIGMI_CON0          0x072C
++#define MT6397_AUDLSBUF_CON0          0x072E
++#define MT6397_AUDLSBUF_CON1          0x0730
++#define MT6397_AUDENCSPARE_CON0               0x0732
++#define MT6397_AUDENCCLKSQ_CON0               0x0734
++#define MT6397_AUDPREAMPGAIN_CON0     0x0736
++#define MT6397_ZCD_CON0                       0x0738
++#define MT6397_ZCD_CON1                       0x073A
++#define MT6397_ZCD_CON2                       0x073C
++#define MT6397_ZCD_CON3                       0x073E
++#define MT6397_ZCD_CON4                       0x0740
++#define MT6397_ZCD_CON5                       0x0742
++#define MT6397_NCP_CLKDIV_CON0                0x0744
++#define MT6397_NCP_CLKDIV_CON1                0x0746
++
++#endif /* __MFD_MT6397_REGISTERS_H__ */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0060-arm-mediatek-select-the-arm-timer-by-default.patch b/target/linux/mediatek/patches/0060-arm-mediatek-select-the-arm-timer-by-default.patch
new file mode 100644 (file)
index 0000000..2b64186
--- /dev/null
@@ -0,0 +1,26 @@
+From 46c695d8285b73d39b0e16fcfd7da332fd2398d4 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:00:27 +0200
+Subject: [PATCH 60/76] arm: mediatek: select the arm timer by default
+
+select ARM_ARCH_TIMER inside the Kconfig
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/Kconfig |    1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
+index 9f59e58..7704818 100644
+--- a/arch/arm/mach-mediatek/Kconfig
++++ b/arch/arm/mach-mediatek/Kconfig
+@@ -1,5 +1,6 @@
+ menuconfig ARCH_MEDIATEK
+       bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
++      select ARM_ARCH_TIMER
+       select ARM_GIC
+       select PINCTRL
+       select MTK_TIMER
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0061-arm-mediatek-add-mt7623-clock.patch b/target/linux/mediatek/patches/0061-arm-mediatek-add-mt7623-clock.patch
new file mode 100644 (file)
index 0000000..f12ebb1
--- /dev/null
@@ -0,0 +1,846 @@
+From 7342787e992a70443081b9203d2131cbf6bc3562 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:12:38 +0200
+Subject: [PATCH 61/76] arm: mediatek: add mt7623 clock
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/clk/mediatek/Makefile          |    1 +
+ drivers/clk/mediatek/clk-mt7623.c      |  634 ++++++++++++++++++++++++++++++++
+ include/dt-bindings/clock/mt7623-clk.h |  173 +++++++++
+ 3 files changed, 808 insertions(+)
+ create mode 100644 drivers/clk/mediatek/clk-mt7623.c
+ create mode 100644 include/dt-bindings/clock/mt7623-clk.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 8e4b2a4..19a3763 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,4 +1,5 @@
+ obj-y += clk-mtk.o clk-pll.o clk-gate.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
++obj-y += clk-mt7623.o
+ obj-y += clk-mt8135.o
+ obj-y += clk-mt8173.o
+diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c
+new file mode 100644
+index 0000000..07843bb
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-mt7623.c
+@@ -0,0 +1,634 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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/of.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/mfd/syscon.h>
++#include <dt-bindings/clock/mt7623-clk.h>
++
++#include "clk-mtk.h"
++#include "clk-gate.h"
++
++static DEFINE_SPINLOCK(mt7623_clk_lock);
++
++static struct clk_onecell_data *mt7623_top_clk_data;
++static struct clk_onecell_data *mt7623_pll_clk_data;
++
++static void mtk_clk_enable_critical(void)
++{
++      if (!mt7623_top_clk_data || !mt7623_pll_clk_data)
++              return;
++
++      clk_prepare_enable(mt7623_pll_clk_data->clks[CLK_APMIXED_ARMPLL]);
++      clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_MEM_SEL]);
++      clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_DDR_SEL]);
++      clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_RTC_SEL]);
++}
++
++static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
++      FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
++      FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
++};
++
++static const struct mtk_fixed_factor top_divs[] __initconst = {
++      FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_650m", "mainpll", 1, 2),
++      FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_433p3m", "mainpll", 1, 3),
++      FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_260m", "mainpll", 1, 5),
++      FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_185p6m", "mainpll", 1, 7),
++
++      FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
++      FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
++      FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
++      FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
++
++      FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll", 1, 4),
++      FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll", 1, 8),
++      FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll", 1, 16),
++      FACTOR(CLK_TOP_AUDPLL_24, "audpll_d24", "audpll", 1, 24),
++
++      FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
++      FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
++      FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
++      FACTOR(CLK_TOP_LVDS_ETH, "lvdspll_eth", "lvdspll", 1, 16),
++
++      FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
++
++      FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
++
++      FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll_650m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll_650m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll_650m", 1, 8),
++      FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "mainpll_650m", 1, 16),
++      FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "mainpll_650m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll_650m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll_650m", 1, 8),
++      FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll_650m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll_650m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll_650m", 1, 2),
++      FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll_650m", 1, 4),
++      FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_433p3m", 1, 1),
++      FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_260m", 1, 1),
++      FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll_185p6m", 1, 1),
++
++      FACTOR(CLK_TOP_TVDPLL_d2, "tvdpll_d2", "tvdpll", 1, 2),
++      FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
++
++      FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
++      FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
++
++      FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
++
++      FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
++      FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
++      FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
++
++      FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
++      FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
++      FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
++      FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
++
++      FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
++      FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
++
++
++      FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
++};
++
++static const char * const axi_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d2",
++      "syspll_d5",
++      "syspll1_d4",
++      "univpll_d5",
++      "univpll2_d2",
++      "dmpll_ck",
++      "dmpll_d2"
++};
++
++static const char * const mem_parents[] __initconst = {
++      "clk26m",
++      "dmpll_ck",
++};
++
++static const char * const ddr_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d8",
++};
++
++static const char * const mm_parents[] __initconst = {
++      "clk26m",
++      "clk26m",
++      "vencpll_ck",
++      "syspll1_d2",
++      "syspll1_d4",
++      "univpll_d5",
++      "univpll1_d2",
++      "univpll2_d2",
++      "dmpll_ck"
++};
++
++static const char * const pwm_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d4",
++      "univpll3_d2",
++      "univpll1_d4",
++};
++
++static const char * const vdec_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d2",
++      "syspll_d5",
++      "syspll1_d4",
++      "univpll_d5",
++      "univpll2_d2",
++      "univpll2_d4",
++      "msdcpll_d2",
++      "mmpll_d2",
++};
++
++static const char * const mfg_parents[] __initconst = {
++      "clk26m",
++      "mmpll_ck",
++      "dmpll_x2_ck",
++      "msdcpll_ck",
++      "clk26m",
++      "syspll_d3",
++      "univpll_d3",
++      "univpll1_d2",
++};
++
++static const char * const cam_parents[] __initconst = {
++      "clk26m",
++      "univpll_d26",
++      "univpll2_d2",
++      "syspll3_d2",
++      "syspll3_d4",
++      "msdcpll_d2",
++      "mmpll_d2",
++      "clk26m",
++};
++
++static const char * const uart_parents[] __initconst = {
++      "clk26m",
++      "univpll2_d8",
++};
++
++static const char * const spi_parents[] __initconst = {
++      "clk26m",
++      "syspll3_d2",
++      "syspll4_d2",
++      "univpll2_d4",
++      "univpll1_d8",
++};
++
++static const char * const usb20_parents[] __initconst = {
++      "clk26m",
++      "univpll1_d8",
++      "univpll3_d4",
++      "clk26m",
++};
++
++static const char * const msdc_30_0_parents[] __initconst = {
++      "clk26m",
++      "msdcpll_d2",
++      "syspll2_d2",
++      "syspll1_d4",
++      "univpll1_d4",
++      "univpll2_d4",
++      "clk26m",
++      "clk26m",
++};
++
++static const char * const msdc_30_1_parents[] __initconst = {
++      "clk26m",
++      "msdcpll_d2",
++      "syspll2_d2",
++      "syspll1_d4",
++      "univpll1_d4",
++      "univpll2_d4",
++      "clk26m",
++      "clk26m",
++};
++
++static const char * const msdc_30_2_parents[] __initconst = {
++      "clk26m",
++      "msdcpll_d2",
++      "syspll2_d2",
++      "syspll1_d4",
++      "univpll1_d4",
++      "univpll2_d4",
++      "clk26m",
++      "clk26m",
++};
++
++static const char * const audio_parents[] __initconst = {
++      "f_f26m_ck",
++      "syspll1_d16",
++};
++
++static const char * const audio_intbus_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d4",
++      "syspll3_d2",
++      "syspll4_d2",
++      "univpll3_d2",
++      "univpll2_d4",
++};
++
++static const char * const pmic_spi_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d8",
++      "syspll2_d4",
++      "syspll4_d2",
++      "syspll3_d4",
++      "syspll2_d8",
++      "syspll1_d16",
++      "univpll3_d4",
++      "univpll_d26",
++      "dmpll_d2",
++      "dmpll_d4",
++};
++
++static const char * const scp_parents[] __initconst = {
++      "clk26m",
++      "syspll1_d8",
++      "dmpll_d2",
++      "dmpll_d4",
++};
++
++static const char * const dpi0_parents[] __initconst = {
++      "clk26m",
++      "mipipll",
++      "mipipll_d2",
++      "mipipll_d4",
++      "lvdspll",
++      "lvdspll_d2",
++      "lvdspll_d4",
++      "lvdspll_d8",
++};
++
++static const char * const dpi1_parents[] __initconst = {
++      "clk26m",
++      "tvdpll",
++      "tvdpll_d2",
++      "tvdpll_d4",
++};
++
++static const char * const tve_parents[] __initconst = {
++      "clk26m",
++      "mipipll",
++      "mipipll_d2",
++      "mipipll_d4",
++      "clk26m",
++      "tvdpll",
++      "tvdpll_d2",
++      "tvdpll_d4",
++};
++
++static const char * const apll_parents[] __initconst = {
++      "clk26m",
++      "audpll",
++      "audpll_d4",
++      "audpll_d8",
++      "audpll_d16",
++      "audpll_d24",
++      "clk26m",
++      "clk26m",
++};
++
++static const char * const dpilvds_parents[] __initconst = {
++      "clk26m",
++      "lvdspll",
++      "lvdspll_d2",
++      "lvdspll_d4",
++      "lvdspll_d8",
++      "fpc_ck",
++      "clk26m",
++      "clk26m",
++};
++
++static const char * const rtc_parents[] __initconst = {
++      "clk32k",
++      "external_32k",
++      "clk26m",
++      "univpll3_d8",
++};
++
++static const char * const nfi2x_parents[] __initconst = {
++      "clk26m",
++      "syspll2_d2",
++      "syspll_d7",
++      "univpll3_d2",
++      "syspll2_d4",
++      "univpll3_d4",
++      "syspll4_d4",
++      "clk26m",
++};
++
++static const char * const eth_parents[] __initconst = {
++      "clk26m",
++      "syspll3_d4",
++      "univpll2_d8",
++      "lvdspll_eth",
++      "univpll_d26",
++      "syspll2_d8",
++      "syspll4_d4",
++      "univpll3_d8",
++};
++
++static const struct mtk_composite top_muxes[] __initconst = {
++      /* CLK_CFG_0 */
++      MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
++              0x0140, 0, 3, INVALID_MUX_GATE_BIT),
++      MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 2, 15),
++      MUX_GATE(CLK_TOP_DDR_SEL, "ddr_sel", ddr_parents, 0x0040, 16, 2, 23),
++      MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
++              0x0140, 24, 3, INVALID_MUX_GATE_BIT),
++      /* CLK_CFG_1 */
++      MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
++      MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
++      MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 16, 3, 23),
++      MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0050, 24, 3, 31),
++      /* CLK_CFG_2 */
++      MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 0, 1, 7),
++      MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 8, 3, 15),
++      MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 16, 2, 23),
++      MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc_30_0_sel", msdc_30_0_parents, 0x0060, 24, 3, 31),
++      /* CLK_CFG_3 */
++      MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc_30_1_sel", msdc_30_1_parents, 0x0070, 0, 3, 7),
++      MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc_30_2_sel", msdc_30_2_parents, 0x0070, 8, 3, 15),
++      MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0070, 16, 1, 23),
++      MUX_GATE(CLK_TOP_AUDIO_INTBUS_SEL,
++                              "audio_intbus_sel", audio_intbus_parents, 0x0070, 24, 3, 31),
++      /* CLK_CFG_4 */
++      MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmic_spi_parents, 0x0080, 0, 4, 7),
++      MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0080, 8, 2, 15),
++      MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x0080, 16, 3, 23),
++      MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0080, 24, 2, 31),
++      /* CLK_CFG_5 */
++      MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents, 0x0090, 0, 3, 7),
++      MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0090, 16, 3, 23),
++      MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x0090, 24, 3, 31),
++      /* CLK_CFG_6 */
++      MUX_GATE(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00a0, 0, 2, 7),
++      MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents, 0x00a0, 8, 3, 15),
++      MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, 0x00a0, 16, 3, 23),
++};
++
++static const struct mtk_gate_regs infra_cg_regs = {
++      .set_ofs = 0x0040,
++      .clr_ofs = 0x0044,
++      .sta_ofs = 0x0048,
++};
++
++#define GATE_ICG(_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[] __initconst = {
++      GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
++      GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
++      GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
++      GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "axi_sel", 5),
++      GATE_ICG(CLK_INFRA_EFUSE, "l2c_sram_ck", "axi_sel", 5),
++      GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
++      GATE_ICG(CLK_INFRA_CONNMCU, "connmcu_ck", "axi_sel", 8),
++      GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 8),
++      GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
++      GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
++      GATE_ICG(CLK_INFRA_CEC, "cec_ck", "axi_sel", 16),
++      GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 16),
++      GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
++      GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
++};
++
++static const struct mtk_gate_regs peri0_cg_regs = {
++      .set_ofs = 0x0008,
++      .clr_ofs = 0x0010,
++      .sta_ofs = 0x0018,
++};
++
++static const struct mtk_gate_regs peri1_cg_regs = {
++      .set_ofs = 0x000c,
++      .clr_ofs = 0x0014,
++      .sta_ofs = 0x001c,
++};
++
++#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 const struct mtk_gate peri_gates[] __initconst = {
++      /* PERI0 */
++      GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
++      GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
++      GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
++      GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
++      GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
++      GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
++      GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
++      GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
++      GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
++      GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
++      GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
++      GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
++      GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
++      GATE_PERI0(CLK_PERI_MSDC20_1, "msdc_20_1_ck", "msdc_30_0_sel", 13),
++      GATE_PERI0(CLK_PERI_MSDC20_2, "msdc_20_2_ck", "msdc_30_1_sel", 14),
++      GATE_PERI0(CLK_PERI_MSDC30_1, "msdc_30_1_ck", "msdc_30_2_sel", 15),
++      GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 16),
++      GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 17),
++      GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 18),
++      GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 19),
++      GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 20),
++      GATE_PERI0(CLK_PERI_BTIF, "btif_ck", "axi_sel", 21),
++      GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 22),
++      GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 23),
++      GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 24),
++      GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 25),
++      GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "axi_sel", 26),
++      GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 27),
++      GATE_PERI0(CLK_PERI_ETH, "eth_ck", "eth_sel", 28),
++      GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu", "axi_sel", 29),
++      GATE_PERI0(CLK_PERI_USB1_MCU, "usb1_mcu","axi_sel", 30),
++      GATE_PERI0(CLK_PERI_USB_SLV, "usb_slv", "axi_sel", 31),
++
++      /* PERI1 */
++      GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 0),
++      GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "axi_sel", 1),
++      GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "axi_sel", 2),
++};
++
++static const char * const uart_ck_sel_parents[] __initconst = {
++      "clk26m",
++      "uart_sel",
++};
++
++static const struct mtk_composite peri_clks[] __initconst = {
++      MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
++      MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
++      MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
++      MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
++};
++
++static void __init mtk_topckgen_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++      void __iomem *base;
++      int r;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      mt7623_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
++
++      mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), 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,
++                      &mt7623_clk_lock, clk_data);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_clk_enable_critical();
++}
++CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt7623-topckgen", mtk_topckgen_init);
++
++static void __init mtk_infrasys_init(struct device_node *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);
++
++      clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_register_reset_controller(node, 2, 0x30);
++}
++CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt7623-infracfg", mtk_infrasys_init);
++
++static void __init mtk_pericfg_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++      int r;
++      void __iomem *base;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
++
++      mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
++                                              clk_data);
++      mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
++                      &mt7623_clk_lock, clk_data);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_register_reset_controller(node, 2, 0);
++}
++CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt7623-pericfg", mtk_pericfg_init);
++
++#define MT7623_PLL_FMAX               (2000 * MHZ)
++#define CON0_MT7623_RST_BAR   BIT(27)
++
++#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
++              .id = _id,                                              \
++              .name = _name,                                          \
++              .reg = _reg,                                            \
++              .pwr_reg = _pwr_reg,                                    \
++              .en_mask = _en_mask,                                    \
++              .flags = _flags,                                        \
++              .rst_bar_mask = CON0_MT7623_RST_BAR,                    \
++              .fmax = MT7623_PLL_FMAX,                                \
++              .pcwbits = _pcwbits,                                    \
++              .pd_reg = _pd_reg,                                      \
++              .pd_shift = _pd_shift,                                  \
++              .tuner_reg = _tuner_reg,                                \
++              .pcw_reg = _pcw_reg,                                    \
++              .pcw_shift = _pcw_shift,                                \
++      }
++
++static const struct mtk_pll_data plls[] = {
++      PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
++      PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0x78000001, HAVE_RST_BAR, 21, 0x214, 6, 0x0, 0x214, 0),
++      PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xFC000001, HAVE_RST_BAR, 7, 0x224, 6, 0x0, 0x224, 0),
++      PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0, 21, 0x254, 6, 0x0, 0x258, 0),
++      PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 6, 0x0, 0x244, 0),
++      PLL(CLK_APMIXED_AUDPLL, "audpll", 0x250, 0x25c, 0x00000001, 0, 31, 0x2e8, 6, 0x2f8, 0x254, 0),
++      PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x260, 0x26c, 0x00000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
++      PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x270, 0x27c, 0x00000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
++};
++
++static void __init mtk_apmixedsys_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++
++      mt7623_pll_clk_data = clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
++      if (!clk_data)
++              return;
++
++      mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
++      mtk_clk_enable_critical();
++}
++CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt7623-apmixedsys",
++              mtk_apmixedsys_init);
+diff --git a/include/dt-bindings/clock/mt7623-clk.h b/include/dt-bindings/clock/mt7623-clk.h
+new file mode 100644
+index 0000000..cb1e8a9
+--- /dev/null
++++ b/include/dt-bindings/clock/mt7623-clk.h
+@@ -0,0 +1,173 @@
++/*
++ * Copyright c 2014 MediaTek Inc.
++ * Author: James Liao <jamesjj.liao@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_MT7623_H
++#define _DT_BINDINGS_CLK_MT7623_H
++
++/* TOPCKGEN */
++
++#define CLK_TOP_AUDPLL_24             1
++#define CLK_TOP_AUDPLL_D16            2
++#define CLK_TOP_AUDPLL_D4             3
++#define CLK_TOP_AUDPLL_D8             4
++#define CLK_TOP_CLKPH_MCK             5
++#define CLK_TOP_CPUM_TCK_IN           6
++#define CLK_TOP_DSI0_LNTC_DSICLK      7
++#define CLK_TOP_HDMITX_CLKDIG_CTS     8
++#define CLK_TOP_LVDS_ETH              9
++#define CLK_TOP_LVDSPLL_D2            10
++#define CLK_TOP_LVDSPLL_D4            11
++#define CLK_TOP_LVDSPLL_D8            12
++#define CLK_TOP_MAINPLL_230P3M                13
++#define CLK_TOP_MAINPLL_322P4M                14
++#define CLK_TOP_MAINPLL_537P3M                15
++#define CLK_TOP_MAINPLL_806M          16
++#define CLK_TOP_MEMPLL_MCK_D4         17
++#define CLK_TOP_MMPLL_D2              18
++#define CLK_TOP_MSDCPLL_D2            19
++#define CLK_TOP_SYSPLL1_D16           20
++#define CLK_TOP_SYSPLL1_D2            21
++#define CLK_TOP_SYSPLL1_D4            22
++#define CLK_TOP_SYSPLL1_D8            23
++#define CLK_TOP_SYSPLL2_D2            24
++#define CLK_TOP_SYSPLL2_D4            25
++#define CLK_TOP_SYSPLL2_D8            26
++#define CLK_TOP_SYSPLL3_D2            27
++#define CLK_TOP_SYSPLL3_D4            28
++#define CLK_TOP_SYSPLL4_D2            29
++#define CLK_TOP_SYSPLL4_D4            30
++#define CLK_TOP_SYSPLL_D3             31
++#define CLK_TOP_SYSPLL_D5             32
++#define CLK_TOP_SYSPLL_D7             33
++#define CLK_TOP_TVDPLL_d2             34
++#define CLK_TOP_TVDPLL_D4             35
++#define CLK_TOP_UNIVPLL_178P3M                36
++#define CLK_TOP_UNIVPLL1_D10          37
++#define CLK_TOP_UNIVPLL1_D2           38
++#define CLK_TOP_UNIVPLL1_D4           39
++#define CLK_TOP_UNIVPLL1_D6           40
++#define CLK_TOP_UNIVPLL1_D8           41
++#define CLK_TOP_UNIVPLL_249P6M                42
++#define CLK_TOP_UNIVPLL2_D2           43
++#define CLK_TOP_UNIVPLL2_D4           44
++#define CLK_TOP_UNIVPLL2_D6           45
++#define CLK_TOP_UNIVPLL2_D8           46
++#define CLK_TOP_UNIVPLL_416M          47
++#define CLK_TOP_UNIVPLL_48M           48
++#define CLK_TOP_UNIVPLL_624M          49
++#define CLK_TOP_UNIVPLL_D26           50
++#define CLK_TOP_UNIVPLL_D5            51
++#define CLK_TOP_APLL_SEL              52
++#define CLK_TOP_AUDIO_INTBUS_SEL      53
++#define CLK_TOP_AUDIO_SEL             54
++#define CLK_TOP_AXI_SEL                       55
++#define CLK_TOP_CAM_SEL                       56
++#define CLK_TOP_DDR_SEL                       57
++#define CLK_TOP_DPI0_SEL              58
++#define CLK_TOP_DPI1_SEL              59
++#define CLK_TOP_DPILVDS_SEL           60
++#define CLK_TOP_ETH_SEL                       61
++#define CLK_TOP_MEM_SEL                       62
++#define CLK_TOP_MFG_SEL                       63
++#define CLK_TOP_MM_SEL                        64
++#define CLK_TOP_MSDC30_0_SEL          65
++#define CLK_TOP_MSDC30_1_SEL          66
++#define CLK_TOP_MSDC30_2_SEL          67
++#define CLK_TOP_NFI2X_SEL             68
++#define CLK_TOP_PMICSPI_SEL           69
++#define CLK_TOP_PWM_SEL                       70
++#define CLK_TOP_RTC_SEL                       71
++#define CLK_TOP_SCP_SEL                       72
++#define CLK_TOP_SPI_SEL                       73
++#define CLK_TOP_TVE_SEL                       74
++#define CLK_TOP_UART_SEL              75
++#define CLK_TOP_USB20_SEL             76
++#define CLK_TOP_VDEC_SEL              77
++#define CLK_TOP_NR_CLK                        78
++
++/* APMIXED_SYS */
++
++#define CLK_APMIXED_ARMPLL            1
++#define CLK_APMIXED_MAINPLL           2
++#define CLK_APMIXED_MSDCPLL           3
++#define CLK_APMIXED_UNIVPLL           4
++#define CLK_APMIXED_MMPLL             5
++#define CLK_APMIXED_VENCPLL           6
++#define CLK_APMIXED_TVDPLL            7
++#define CLK_APMIXED_LVDSPLL           8
++#define CLK_APMIXED_AUDPLL            9
++
++/* INFRA_SYS */
++
++#define CLK_INFRA_DBGCLK              0
++#define CLK_INFRA_SMI                 1
++#define CLK_INFRA_AUDIO                       5
++#define CLK_INFRA_EFUSE                       6
++#define CLK_INFRA_L2C_SRAM            7
++#define CLK_INFRA_M4U                 8
++#define CLK_INFRA_CONNMCU             12
++#define CLK_INFRA_TRNG                        13
++#define CLK_INFRA_CPUM                        15
++#define CLK_INFRA_KP                  16
++#define CLK_INFRA_CEC                 18
++#define CLK_INFRA_IRRX                        19
++#define CLK_INFRA_PMICSPI             22
++#define CLK_INFRA_PMIC_WRAP           23
++#define CLK_INFRA_NR_CLK              24
++
++/* PERI_SYS */
++
++#define CLK_PERI_NFI                  0
++#define CLK_PERI_THERM                        1
++#define CLK_PERI_PWM1                 2
++#define CLK_PERI_PWM2                 3
++#define CLK_PERI_PWM3                 4
++#define CLK_PERI_PWM4                 5
++#define CLK_PERI_PWM5                 6
++#define CLK_PERI_PWM6                 7
++#define CLK_PERI_PWM7                 8
++#define CLK_PERI_PWM                  9
++#define CLK_PERI_USB0                 10
++#define CLK_PERI_USB1                 11
++#define CLK_PERI_AP_DMA                       12
++#define CLK_PERI_MSDC20_1             13
++#define CLK_PERI_MSDC20_2             14
++#define CLK_PERI_MSDC30_1             15
++#define CLK_PERI_NLI                  16
++#define CLK_PERI_UART0                        17
++#define CLK_PERI_UART1                        18
++#define CLK_PERI_UART2                        19
++#define CLK_PERI_UART3                        20
++#define CLK_PERI_BTIF                 21
++#define CLK_PERI_I2C0                 22
++#define CLK_PERI_I2C1                 23
++#define CLK_PERI_I2C2                 24
++#define CLK_PERI_I2C3                 25
++#define CLK_PERI_AUXADC                       26
++#define CLK_PERI_SPI0                 27
++#define CLK_PERI_ETH                  28
++#define CLK_PERI_USB0_MCU             29
++#define CLK_PERI_USB1_MCU             30
++#define CLK_PERI_USB_SLV              31
++#define CLK_PERI_GCPU                 32
++#define CLK_PERI_NFI_ECC              33
++#define CLK_PERI_NFI_PAD              34
++#define CLK_PERI_UART0_SEL            35
++#define CLK_PERI_UART1_SEL            36
++#define CLK_PERI_UART2_SEL            37
++#define CLK_PERI_UART3_SEL            38
++#define CLK_PERI_NR_CLK                       39
++
++#endif /* _DT_BINDINGS_CLK_MT7623_H */
++
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0062-arm-mediatek-add-mt7623-pinctrl-supoort.patch b/target/linux/mediatek/patches/0062-arm-mediatek-add-mt7623-pinctrl-supoort.patch
new file mode 100644 (file)
index 0000000..c9ea40e
--- /dev/null
@@ -0,0 +1,2889 @@
+From 718f377d37a737b133a3d904f5a038d6aa55c23e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:13:05 +0200
+Subject: [PATCH 62/76] arm: mediatek: add mt7623 pinctrl supoort
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/pinctrl/mediatek/Kconfig              |    6 +
+ drivers/pinctrl/mediatek/Makefile             |    1 +
+ drivers/pinctrl/mediatek/pinctrl-mt7623.c     |  368 +++++
+ drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h | 1926 +++++++++++++++++++++++++
+ include/dt-bindings/pinctrl/mt7623-pinfunc.h  |  526 +++++++
+ 5 files changed, 2827 insertions(+)
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7623.c
+ create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
+ create mode 100644 include/dt-bindings/pinctrl/mt7623-pinfunc.h
+
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index 0bc84fb..27c5673 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -9,6 +9,12 @@ config PINCTRL_MTK_COMMON
+       select OF_GPIO
+ # For ARMv7 SoCs
++config PINCTRL_MT7623
++      bool "Mediatek MT7623 pin control" if COMPILE_TEST && !MACH_MT7623
++      depends on OF
++      default MACH_MT7623
++      select PINCTRL_MTK_COMMON
++
+ config PINCTRL_MT8135
+       bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135
+       depends on OF
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index eb923d6..8998433 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -2,6 +2,7 @@
+ obj-$(CONFIG_PINCTRL_MTK_COMMON)      += pinctrl-mtk-common.o
+ # SoC Drivers
++obj-$(CONFIG_PINCTRL_MT7623)          += pinctrl-mt7623.o
+ obj-$(CONFIG_PINCTRL_MT8135)          += pinctrl-mt8135.o
+ obj-$(CONFIG_PINCTRL_MT8127)          += pinctrl-mt8127.o
+ obj-$(CONFIG_PINCTRL_MT8173)          += pinctrl-mt8173.o
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7623.c b/drivers/pinctrl/mediatek/pinctrl-mt7623.c
+new file mode 100644
+index 0000000..77e1a66
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mt7623.c
+@@ -0,0 +1,368 @@
++/*
++ * Copyright (c) 2014-2015 MediaTek Inc.
++ * Author: Hongzhou.Yang <hongzhou.yang@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/module.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/regmap.h>
++#include <linux/pinctrl/pinconf-generic.h>
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#include "pinctrl-mtk-common.h"
++#include "pinctrl-mtk-mt7623.h"
++
++#define DRV_BASE                              0xb00
++
++static const struct mtk_pin_spec_pupd_set_samereg mt7623_spec_pupd[] = {
++      MTK_PIN_PUPD_SPEC_SR(65, 0xcc0, 8, 9, 10),      /* ms0 clk */
++      MTK_PIN_PUPD_SPEC_SR(57, 0xcd0, 8, 9, 10),      /* ms0 cmd */
++      MTK_PIN_PUPD_SPEC_SR(60, 0xcf0, 0, 1, 2),       /* ms0 data0 */
++      MTK_PIN_PUPD_SPEC_SR(59, 0xcf0, 4, 5, 6),       /* ms0 data1 */
++      MTK_PIN_PUPD_SPEC_SR(58, 0xcf0, 8, 9, 10),      /* ms0 data2 */
++      MTK_PIN_PUPD_SPEC_SR(57, 0xcf0, 12, 13, 14),    /* ms0 data3 */
++      MTK_PIN_PUPD_SPEC_SR(61, 0xd00, 0, 1, 2),       /* ms0 data4 */
++      MTK_PIN_PUPD_SPEC_SR(62, 0xd00, 4, 5, 6),       /* ms0 data5 */
++      MTK_PIN_PUPD_SPEC_SR(63, 0xd00, 8, 9, 10),      /* ms0 data6 */
++      MTK_PIN_PUPD_SPEC_SR(64, 0xd00, 12, 13, 14),    /* ms0 data7 */
++      MTK_PIN_PUPD_SPEC_SR(67, 0xd10, 0, 1, 2),       /* ms0 RST */
++
++      MTK_PIN_PUPD_SPEC_SR(78, 0xc50, 2, 1, 0),       /* ms1 cmd */
++      MTK_PIN_PUPD_SPEC_SR(73, 0xd20, 2, 1, 0),       /* ms1 dat0 */
++      MTK_PIN_PUPD_SPEC_SR(74, 0xd20, 6, 5, 4),       /* ms1 dat1 */
++      MTK_PIN_PUPD_SPEC_SR(75, 0xd20, 10, 9, 8),      /* ms1 dat2 */
++      MTK_PIN_PUPD_SPEC_SR(76, 0xd20, 14, 13, 12),    /* ms1 dat3 */
++      MTK_PIN_PUPD_SPEC_SR(77, 0xc40, 2, 1, 0),       /* ms1 clk */
++};
++
++static int mt7623_spec_pull_set(struct regmap *regmap, unsigned int pin,
++              unsigned char align, bool isup, unsigned int r1r0)
++{
++      return mtk_pctrl_spec_pull_set_samereg(regmap, mt7623_spec_pupd,
++              ARRAY_SIZE(mt7623_spec_pupd), pin, align, isup, r1r0);
++}
++
++/*static const struct mtk_pin_ies_smt_set mt7623_smt_set[] = {
++      MTK_PIN_IES_SMT_SPEC(0, 4, 0x930, 1),
++      MTK_PIN_IES_SMT_SPEC(5, 9, 0x930, 2),
++      MTK_PIN_IES_SMT_SPEC(10, 13, 0x930, 10),
++      MTK_PIN_IES_SMT_SPEC(14, 15, 0x940, 10),
++      MTK_PIN_IES_SMT_SPEC(16, 16, 0x930, 0),
++      MTK_PIN_IES_SMT_SPEC(17, 17, 0x950, 2),
++      MTK_PIN_IES_SMT_SPEC(18, 21, 0x940, 3),
++      MTK_PIN_IES_SMT_SPEC(29, 32, 0x930, 3),
++      MTK_PIN_IES_SMT_SPEC(33, 33, 0x930, 4),
++      MTK_PIN_IES_SMT_SPEC(34, 36, 0x930, 5),
++      MTK_PIN_IES_SMT_SPEC(37, 38, 0x930, 6),
++      MTK_PIN_IES_SMT_SPEC(39, 39, 0x930, 7),
++      MTK_PIN_IES_SMT_SPEC(40, 41, 0x930, 9),
++      MTK_PIN_IES_SMT_SPEC(42, 42, 0x940, 0),
++      MTK_PIN_IES_SMT_SPEC(43, 44, 0x930, 11),
++      MTK_PIN_IES_SMT_SPEC(45, 46, 0x930, 12),
++      MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 13),
++      MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 13),
++      MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 13),
++      MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 13),
++      MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 13),
++      MTK_PIN_IES_SMT_SPEC(69, 72, 0x940, 14),
++      MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 13),
++      MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 13),
++      MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 13),
++      MTK_PIN_IES_SMT_SPEC(79, 82, 0x940, 15),
++      MTK_PIN_IES_SMT_SPEC(83, 83, 0x950, 0),
++      MTK_PIN_IES_SMT_SPEC(84, 85, 0x950, 1),
++      MTK_PIN_IES_SMT_SPEC(86, 91, 0x950, 2),
++      MTK_PIN_IES_SMT_SPEC(92, 92, 0x930, 13),
++      MTK_PIN_IES_SMT_SPEC(93, 95, 0x930, 14),
++      MTK_PIN_IES_SMT_SPEC(96, 99, 0x930, 15),
++      MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 13),
++      MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 13),
++      MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 13),
++      MTK_PIN_IES_SMT_SPEC(106, 107, 0x940, 4),
++      MTK_PIN_IES_SMT_SPEC(108, 112, 0x940, 1),
++      MTK_PIN_IES_SMT_SPEC(113, 116, 0x940, 2),
++      MTK_PIN_IES_SMT_SPEC(117, 118, 0x940, 5),
++      MTK_PIN_IES_SMT_SPEC(119, 124, 0x940, 6),
++      MTK_PIN_IES_SMT_SPEC(125, 126, 0x940, 7),
++      MTK_PIN_IES_SMT_SPEC(127, 127, 0x940, 0),
++      MTK_PIN_IES_SMT_SPEC(128, 128, 0x950, 8),
++      MTK_PIN_IES_SMT_SPEC(129, 130, 0x950, 9),
++      MTK_PIN_IES_SMT_SPEC(131, 132, 0x950, 8),
++      MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
++};
++
++static const struct mtk_pin_ies_smt_set mt7623_ies_set[] = {
++      MTK_PIN_IES_SMT_SPEC(0, 4, 0x900, 1),
++      MTK_PIN_IES_SMT_SPEC(5, 9, 0x900, 2),
++      MTK_PIN_IES_SMT_SPEC(10, 13, 0x900, 10),
++      MTK_PIN_IES_SMT_SPEC(14, 15, 0x910, 10),
++      MTK_PIN_IES_SMT_SPEC(16, 16, 0x900, 0),
++      MTK_PIN_IES_SMT_SPEC(17, 17, 0x920, 2),
++      MTK_PIN_IES_SMT_SPEC(18, 21, 0x910, 3),
++      MTK_PIN_IES_SMT_SPEC(29, 32, 0x900, 3),
++      MTK_PIN_IES_SMT_SPEC(33, 33, 0x900, 4),
++      MTK_PIN_IES_SMT_SPEC(34, 36, 0x900, 5),
++      MTK_PIN_IES_SMT_SPEC(37, 38, 0x900, 6),
++      MTK_PIN_IES_SMT_SPEC(39, 39, 0x900, 7),
++      MTK_PIN_IES_SMT_SPEC(40, 41, 0x900, 9),
++      MTK_PIN_IES_SMT_SPEC(42, 42, 0x910, 0),
++      MTK_PIN_IES_SMT_SPEC(43, 44, 0x900, 11),
++      MTK_PIN_IES_SMT_SPEC(45, 46, 0x900, 12),
++      MTK_PIN_IES_SMT_SPEC(57, 64, 0xc20, 14),
++      MTK_PIN_IES_SMT_SPEC(65, 65, 0xc10, 14),
++      MTK_PIN_IES_SMT_SPEC(66, 66, 0xc00, 14),
++      MTK_PIN_IES_SMT_SPEC(67, 67, 0xd10, 14),
++      MTK_PIN_IES_SMT_SPEC(68, 68, 0xd00, 14),
++      MTK_PIN_IES_SMT_SPEC(69, 72, 0x910, 14),
++      MTK_PIN_IES_SMT_SPEC(73, 76, 0xc60, 14),
++      MTK_PIN_IES_SMT_SPEC(77, 77, 0xc40, 14),
++      MTK_PIN_IES_SMT_SPEC(78, 78, 0xc50, 14),
++      MTK_PIN_IES_SMT_SPEC(79, 82, 0x910, 15),
++      MTK_PIN_IES_SMT_SPEC(83, 83, 0x920, 0),
++      MTK_PIN_IES_SMT_SPEC(84, 85, 0x920, 1),
++      MTK_PIN_IES_SMT_SPEC(86, 91, 0x920, 2),
++      MTK_PIN_IES_SMT_SPEC(92, 92, 0x900, 13),
++      MTK_PIN_IES_SMT_SPEC(93, 95, 0x900, 14),
++      MTK_PIN_IES_SMT_SPEC(96, 99, 0x900, 15),
++      MTK_PIN_IES_SMT_SPEC(100, 103, 0xca0, 14),
++      MTK_PIN_IES_SMT_SPEC(104, 104, 0xc80, 14),
++      MTK_PIN_IES_SMT_SPEC(105, 105, 0xc90, 14),
++      MTK_PIN_IES_SMT_SPEC(106, 107, 0x91, 4),
++      MTK_PIN_IES_SMT_SPEC(108, 112, 0x910, 1),
++      MTK_PIN_IES_SMT_SPEC(113, 116, 0x910, 2),
++      MTK_PIN_IES_SMT_SPEC(117, 118, 0x910, 5),
++      MTK_PIN_IES_SMT_SPEC(119, 124, 0x910, 6),
++      MTK_PIN_IES_SMT_SPEC(125, 126, 0x910, 7),
++      MTK_PIN_IES_SMT_SPEC(127, 127, 0x910, 0),
++      MTK_PIN_IES_SMT_SPEC(128, 128, 0x920, 8),
++      MTK_PIN_IES_SMT_SPEC(129, 130, 0x920, 9),
++      MTK_PIN_IES_SMT_SPEC(131, 132, 0x920, 8),
++      MTK_PIN_IES_SMT_SPEC(133, 134, 0x910, 8)
++};
++
++static int mt7623_ies_smt_set(struct regmap *regmap, unsigned int pin,
++              unsigned char align, int value, enum pin_config_param arg)
++{
++      if (arg == PIN_CONFIG_INPUT_ENABLE)
++              return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_ies_set,
++                      ARRAY_SIZE(mt7623_ies_set), pin, align, value);
++      else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
++              return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_smt_set,
++                      ARRAY_SIZE(mt7623_smt_set), pin, align, value);
++      return -EINVAL;
++}
++*/
++static const struct mtk_drv_group_desc mt7623_drv_grp[] =  {
++      /* 0E4E8SR 4/8/12/16 */
++      MTK_DRV_GRP(4, 16, 1, 2, 4),
++      /* 0E2E4SR  2/4/6/8 */
++      MTK_DRV_GRP(2, 8, 1, 2, 2),
++      /* E8E4E2  2/4/6/8/10/12/14/16 */
++      MTK_DRV_GRP(2, 16, 0, 2, 2)
++};
++
++/*static const struct mtk_pin_drv_grp mt7623_pin_drv[] = {
++      MTK_PIN_DRV_GRP(0, DRV_BASE+0x20, 12, 0),
++      MTK_PIN_DRV_GRP(1, DRV_BASE+0x20, 12, 0),
++      MTK_PIN_DRV_GRP(2, DRV_BASE+0x20, 12, 0),
++      MTK_PIN_DRV_GRP(3, DRV_BASE+0x20, 12, 0),
++      MTK_PIN_DRV_GRP(4, DRV_BASE+0x20, 12, 0),
++      MTK_PIN_DRV_GRP(5, DRV_BASE+0x30, 0, 0),
++      MTK_PIN_DRV_GRP(6, DRV_BASE+0x30, 0, 0),
++      MTK_PIN_DRV_GRP(7, DRV_BASE+0x30, 0, 0),
++      MTK_PIN_DRV_GRP(8, DRV_BASE+0x30, 0, 0),
++      MTK_PIN_DRV_GRP(9, DRV_BASE+0x30, 0, 0),
++      MTK_PIN_DRV_GRP(10, DRV_BASE+0x30, 4, 1),
++      MTK_PIN_DRV_GRP(11, DRV_BASE+0x30, 4, 1),
++      MTK_PIN_DRV_GRP(12, DRV_BASE+0x30, 4, 1),
++      MTK_PIN_DRV_GRP(13, DRV_BASE+0x30, 4, 1),
++      MTK_PIN_DRV_GRP(14, DRV_BASE+0x40, 8, 1),
++      MTK_PIN_DRV_GRP(15, DRV_BASE+0x40, 8, 1),
++      MTK_PIN_DRV_GRP(16, DRV_BASE, 8, 1),
++      MTK_PIN_DRV_GRP(17, 0xce0, 8, 2),
++      MTK_PIN_DRV_GRP(22, 0xce0, 8, 2),
++      MTK_PIN_DRV_GRP(23, 0xce0, 8, 2),
++      MTK_PIN_DRV_GRP(24, 0xce0, 8, 2),
++      MTK_PIN_DRV_GRP(25, 0xce0, 8, 2),
++      MTK_PIN_DRV_GRP(26, 0xcc0, 8, 2),
++      MTK_PIN_DRV_GRP(27, 0xcd0, 8, 2),
++      MTK_PIN_DRV_GRP(28, 0xd70, 8, 2),
++      MTK_PIN_DRV_GRP(29, DRV_BASE+0x80, 12, 1),
++      MTK_PIN_DRV_GRP(30, DRV_BASE+0x80, 12, 1),
++      MTK_PIN_DRV_GRP(31, DRV_BASE+0x80, 12, 1),
++      MTK_PIN_DRV_GRP(32, DRV_BASE+0x80, 12, 1),
++      MTK_PIN_DRV_GRP(33, DRV_BASE+0x10, 12, 1),
++      MTK_PIN_DRV_GRP(34, DRV_BASE+0x10, 8, 1),
++      MTK_PIN_DRV_GRP(35, DRV_BASE+0x10, 8, 1),
++      MTK_PIN_DRV_GRP(36, DRV_BASE+0x10, 8, 1),
++      MTK_PIN_DRV_GRP(37, DRV_BASE+0x10, 4, 1),
++      MTK_PIN_DRV_GRP(38, DRV_BASE+0x10, 4, 1),
++      MTK_PIN_DRV_GRP(39, DRV_BASE+0x20, 0, 0),
++      MTK_PIN_DRV_GRP(40, DRV_BASE+0x20, 8, 0),
++      MTK_PIN_DRV_GRP(41, DRV_BASE+0x20, 8, 0),
++      MTK_PIN_DRV_GRP(42, DRV_BASE+0x50, 8, 1),
++      MTK_PIN_DRV_GRP(57, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(58, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(59, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(60, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(61, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(62, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(63, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(64, 0xc20, 8, 2),
++      MTK_PIN_DRV_GRP(65, 0xc00, 8, 2),
++      MTK_PIN_DRV_GRP(66, 0xc10, 8, 2),
++      MTK_PIN_DRV_GRP(67, 0xd10, 8, 2),
++      MTK_PIN_DRV_GRP(68, 0xd00, 8, 2),
++      MTK_PIN_DRV_GRP(69, DRV_BASE+0x80, 0, 1),
++      MTK_PIN_DRV_GRP(70, DRV_BASE+0x80, 0, 1),
++      MTK_PIN_DRV_GRP(71, DRV_BASE+0x80, 0, 1),
++      MTK_PIN_DRV_GRP(72, DRV_BASE+0x80, 0, 1),
++      MTK_PIN_DRV_GRP(73, 0xc60, 8, 2),
++      MTK_PIN_DRV_GRP(74, 0xc60, 8, 2),
++      MTK_PIN_DRV_GRP(75, 0xc60, 8, 2),
++      MTK_PIN_DRV_GRP(76, 0xc60, 8, 2),
++      MTK_PIN_DRV_GRP(77, 0xc40, 8, 2),
++      MTK_PIN_DRV_GRP(78, 0xc50, 8, 2),
++      MTK_PIN_DRV_GRP(79, DRV_BASE+0x70, 12, 1),
++      MTK_PIN_DRV_GRP(80, DRV_BASE+0x70, 12, 1),
++      MTK_PIN_DRV_GRP(81, DRV_BASE+0x70, 12, 1),
++      MTK_PIN_DRV_GRP(82, DRV_BASE+0x70, 12, 1),
++      MTK_PIN_DRV_GRP(83, DRV_BASE, 4, 1),
++      MTK_PIN_DRV_GRP(84, DRV_BASE, 0, 1),
++      MTK_PIN_DRV_GRP(85, DRV_BASE, 0, 1),
++      MTK_PIN_DRV_GRP(85, DRV_BASE+0x60, 8, 1),
++      MTK_PIN_DRV_GRP(86, DRV_BASE+0x60, 8, 1),
++      MTK_PIN_DRV_GRP(87, DRV_BASE+0x60, 8, 1),
++      MTK_PIN_DRV_GRP(88, DRV_BASE+0x60, 8, 1),
++      MTK_PIN_DRV_GRP(89, DRV_BASE+0x60, 8, 1),
++      MTK_PIN_DRV_GRP(90, DRV_BASE+0x60, 8, 1),
++      MTK_PIN_DRV_GRP(91, DRV_BASE+0x60, 8, 1),
++      MTK_PIN_DRV_GRP(92, DRV_BASE+0x60, 4, 0),
++      MTK_PIN_DRV_GRP(93, DRV_BASE+0x60, 0, 0),
++      MTK_PIN_DRV_GRP(94, DRV_BASE+0x60, 0, 0),
++      MTK_PIN_DRV_GRP(95, DRV_BASE+0x60, 0, 0),
++      MTK_PIN_DRV_GRP(96, DRV_BASE+0x80, 8, 1),
++      MTK_PIN_DRV_GRP(97, DRV_BASE+0x80, 8, 1),
++      MTK_PIN_DRV_GRP(98, DRV_BASE+0x80, 8, 1),
++      MTK_PIN_DRV_GRP(99, DRV_BASE+0x80, 8, 1),
++      MTK_PIN_DRV_GRP(100, 0xca0, 8, 2),
++      MTK_PIN_DRV_GRP(101, 0xca0, 8, 2),
++      MTK_PIN_DRV_GRP(102, 0xca0, 8, 2),
++      MTK_PIN_DRV_GRP(103, 0xca0, 8, 2),
++      MTK_PIN_DRV_GRP(104, 0xc80, 8, 2),
++      MTK_PIN_DRV_GRP(105, 0xc90, 8, 2),
++      MTK_PIN_DRV_GRP(108, DRV_BASE+0x50, 0, 1),
++      MTK_PIN_DRV_GRP(109, DRV_BASE+0x50, 0, 1),
++      MTK_PIN_DRV_GRP(110, DRV_BASE+0x50, 0, 1),
++      MTK_PIN_DRV_GRP(111, DRV_BASE+0x50, 0, 1),
++      MTK_PIN_DRV_GRP(112, DRV_BASE+0x50, 0, 1),
++      MTK_PIN_DRV_GRP(113, DRV_BASE+0x80, 4, 1),
++      MTK_PIN_DRV_GRP(114, DRV_BASE+0x80, 4, 1),
++      MTK_PIN_DRV_GRP(115, DRV_BASE+0x80, 4, 1),
++      MTK_PIN_DRV_GRP(116, DRV_BASE+0x80, 4, 1),
++      MTK_PIN_DRV_GRP(117, DRV_BASE+0x90, 0, 1),
++      MTK_PIN_DRV_GRP(118, DRV_BASE+0x90, 0, 1),
++      MTK_PIN_DRV_GRP(119, DRV_BASE+0x50, 4, 1),
++      MTK_PIN_DRV_GRP(120, DRV_BASE+0x50, 4, 1),
++      MTK_PIN_DRV_GRP(121, DRV_BASE+0x50, 4, 1),
++      MTK_PIN_DRV_GRP(122, DRV_BASE+0x50, 4, 1),
++      MTK_PIN_DRV_GRP(123, DRV_BASE+0x50, 4, 1),
++      MTK_PIN_DRV_GRP(124, DRV_BASE+0x50, 4, 1),
++      MTK_PIN_DRV_GRP(125, DRV_BASE+0x30, 12, 1),
++      MTK_PIN_DRV_GRP(126, DRV_BASE+0x30, 12, 1),
++      MTK_PIN_DRV_GRP(127, DRV_BASE+0x50, 8, 1),
++      MTK_PIN_DRV_GRP(128, DRV_BASE+0x40, 0, 1),
++      MTK_PIN_DRV_GRP(129, DRV_BASE+0x40, 0, 1),
++      MTK_PIN_DRV_GRP(130, DRV_BASE+0x40, 0, 1),
++      MTK_PIN_DRV_GRP(131, DRV_BASE+0x40, 0, 1),
++      MTK_PIN_DRV_GRP(132, DRV_BASE+0x40, 0, 1)
++};
++*/
++static const struct mtk_pinctrl_devdata mt7623_pinctrl_data = {
++      .pins = mtk_pins_mt7623,
++      .npins = ARRAY_SIZE(mtk_pins_mt7623),
++      .grp_desc = mt7623_drv_grp,
++      .n_grp_cls = ARRAY_SIZE(mt7623_drv_grp),
++//    .pin_drv_grp = mt7623_pin_drv,
++//    .n_pin_drv_grps = ARRAY_SIZE(mt7623_pin_drv),
++      .spec_pull_set = mt7623_spec_pull_set,
++      //.spec_ies_smt_set = mt7623_ies_smt_set,
++      .dir_offset = 0x0000,
++      .pullen_offset = 0x0150,
++      .pullsel_offset = 0x0280,
++      .dout_offset = 0x0550,
++      .din_offset = 0x0630,
++      .pinmux_offset = 0x0760,
++      .port_shf = 4,
++      .port_mask = 0xf,
++      .port_align = 4,
++      .eint_offsets = {
++              .name = "mt7623_eint",
++              .stat      = 0x000,
++              .ack       = 0x040,
++              .mask      = 0x080,
++              .mask_set  = 0x0c0,
++              .mask_clr  = 0x100,
++              .sens      = 0x140,
++              .sens_set  = 0x180,
++              .sens_clr  = 0x1c0,
++              .soft      = 0x200,
++              .soft_set  = 0x240,
++              .soft_clr  = 0x280,
++              .pol       = 0x300,
++              .pol_set   = 0x340,
++              .pol_clr   = 0x380,
++              .dom_en    = 0x400,
++              .dbnc_ctrl = 0x500,
++              .dbnc_set  = 0x600,
++              .dbnc_clr  = 0x700,
++              .port_mask = 7,
++              .ports     = 6,
++      },
++      .ap_num = 224,
++      .db_cnt = 16,
++};
++
++static int mt7623_pinctrl_probe(struct platform_device *pdev)
++{
++      return mtk_pctrl_init(pdev, &mt7623_pinctrl_data, NULL);
++}
++
++static const struct of_device_id mt7623_pctrl_match[] = {
++      {
++              .compatible = "mediatek,mt7623-pinctrl",
++      },
++      { }
++};
++MODULE_DEVICE_TABLE(of, mt7623_pctrl_match);
++
++static struct platform_driver mtk_pinctrl_driver = {
++      .probe = mt7623_pinctrl_probe,
++      .driver = {
++              .name = "mediatek-mt7623-pinctrl",
++              .of_match_table = mt7623_pctrl_match,
++      },
++};
++
++static int __init mtk_pinctrl_init(void)
++{
++      return platform_driver_register(&mtk_pinctrl_driver);
++}
++
++module_init(mtk_pinctrl_init);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
+new file mode 100644
+index 0000000..4b65668
+--- /dev/null
++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
+@@ -0,0 +1,1926 @@
++#ifndef __PINCTRL_MTK_MT7623_H
++#define __PINCTRL_MTK_MT7623_H
++
++#include <linux/pinctrl/pinctrl.h>
++#include "pinctrl-mtk-common.h"
++
++static const struct mtk_desc_pin mtk_pins_mt7623[] = {
++      MTK_PIN(
++              PINCTRL_PIN(0, "PWRAP_SPI0_MI"),
++              "F11", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO0"),
++              MTK_FUNCTION(1, "PWRAP_SPIDO"),
++              MTK_FUNCTION(2, "PWRAP_SPIDI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(1, "PWRAP_SPI0_MO"),
++              "D10", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO1"),
++              MTK_FUNCTION(1, "PWRAP_SPIDI"),
++              MTK_FUNCTION(2, "PWRAP_SPIDO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(2, "PWRAP_INT"),
++              "E11", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO2"),
++              MTK_FUNCTION(1, "PWRAP_INT")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(3, "PWRAP_SPI0_CK"),
++              "H12", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO3"),
++              MTK_FUNCTION(1, "PWRAP_SPICK_I")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(4, "PWRAP_SPI0_CSN"),
++              "E12", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO4"),
++              MTK_FUNCTION(1, "PWRAP_SPICS_B_I")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(5, "PWRAP_SPI0_CK2"),
++              "H11", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO5"),
++              MTK_FUNCTION(1, "PWRAP_SPICK2_I")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"),
++              "G11", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO6"),
++              MTK_FUNCTION(1, "PWRAP_SPICS2_B_I")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(7, "SPI1_CSN"),
++              "G19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO7"),
++              MTK_FUNCTION(1, "SPI1_CS")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(8, "SPI1_MI"),
++              "F19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO8"),
++              MTK_FUNCTION(1, "SPI1_MI"),
++              MTK_FUNCTION(2, "SPI1_MO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(9, "SPI1_MO"),
++              "G20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO9"),
++              MTK_FUNCTION(1, "SPI1_MO"),
++              MTK_FUNCTION(2, "SPI1_MI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(10, "RTC32K_CK"),
++              "A13", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO10"),
++              MTK_FUNCTION(1, "RTC32K_CK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(11, "WATCHDOG"),
++              "D14", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO11"),
++              MTK_FUNCTION(1, "WATCHDOG")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(12, "SRCLKENA"),
++              "C13", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO12"),
++              MTK_FUNCTION(1, "SRCLKENA")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(13, "SRCLKENAI"),
++              "B13", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO13"),
++              MTK_FUNCTION(1, "SRCLKENAI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(14, "GPIO14"),
++              "E18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO14"),
++              MTK_FUNCTION(1, "URXD2"),
++              MTK_FUNCTION(2, "UTXD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(15, "GPIO15"),
++              "E17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO15"),
++              MTK_FUNCTION(1, "UTXD2"),
++              MTK_FUNCTION(2, "URXD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(16, "GPIO16"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO16")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(17, "GPIO17"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO17")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(18, "PCM_CLK"),
++              "C19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO18"),
++              MTK_FUNCTION(1, "PCM_CLK0"),
++              MTK_FUNCTION(6, "AP_PCM_CLKO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(19, "PCM_SYNC"),
++              "D19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO19"),
++              MTK_FUNCTION(1, "PCM_SYNC"),
++              MTK_FUNCTION(6, "AP_PCM_SYNC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(20, "PCM_RX"),
++              "D18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO20"),
++              MTK_FUNCTION(1, "PCM_RX"),
++              MTK_FUNCTION(4, "PCM_TX"),
++              MTK_FUNCTION(6, "AP_PCM_RX")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(21, "PCM_TX"),
++              "C18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO21"),
++              MTK_FUNCTION(1, "PCM_TX"),
++              MTK_FUNCTION(4, "PCM_RX"),
++              MTK_FUNCTION(6, "AP_PCM_TX")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(22, "EINT0"),
++              "H15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO22"),
++              MTK_FUNCTION(1, "UCTS0"),
++              MTK_FUNCTION(2, "PCIE0_PERST_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(23, "EINT1"),
++              "J16", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO23"),
++              MTK_FUNCTION(1, "URTS0"),
++              MTK_FUNCTION(2, "PCIE1_PERST_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(24, "EINT2"),
++              "H16", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO24"),
++              MTK_FUNCTION(1, "UCTS1"),
++              MTK_FUNCTION(2, "PCIE2_PERST_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(25, "EINT3"),
++              "K15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO25"),
++              MTK_FUNCTION(1, "URTS1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(26, "EINT4"),
++              "G15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO26"),
++              MTK_FUNCTION(1, "UCTS3"),
++              MTK_FUNCTION(6, "PCIE2_WAKE_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(27, "EINT5"),
++              "F15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO27"),
++              MTK_FUNCTION(1, "URTS3"),
++              MTK_FUNCTION(6, "PCIE1_WAKE_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(28, "EINT6"),
++              "J15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO28"),
++              MTK_FUNCTION(1, "DRV_VBUS"),
++              MTK_FUNCTION(6, "PCIE0_WAKE_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(29, "EINT7"),
++              "E15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO29"),
++              MTK_FUNCTION(1, "IDDIG"),
++              MTK_FUNCTION(2, "MSDC1_WP"),
++              MTK_FUNCTION(6, "PCIE2_PERST_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(30, "GPIO30"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO30")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(31, "GPIO31"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO31")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(32, "GPIO32"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO32")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(33, "I2S1_DATA"),
++              "Y18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO33"),
++              MTK_FUNCTION(1, "I2S1_DATA"),
++              MTK_FUNCTION(3, "PCM_TX"),
++              MTK_FUNCTION(6, "AP_PCM_TX")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(34, "I2S1_DATA_IN"),
++              "Y17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO34"),
++              MTK_FUNCTION(1, "I2S1_DATA_IN"),
++              MTK_FUNCTION(3, "PCM_RX"),
++              MTK_FUNCTION(6, "AP_PCM_RX")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(35, "I2S1_BCK"),
++              "V17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO35"),
++              MTK_FUNCTION(1, "I2S1_BCK"),
++              MTK_FUNCTION(3, "PCM_CLK0"),
++              MTK_FUNCTION(6, "AP_PCM_CLKO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(36, "I2S1_LRCK"),
++              "W17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO36"),
++              MTK_FUNCTION(1, "I2S1_LRCK"),
++              MTK_FUNCTION(3, "PCM_SYNC"),
++              MTK_FUNCTION(6, "AP_PCM_SYNC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(37, "I2S1_MCLK"),
++              "AA18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO37"),
++              MTK_FUNCTION(1, "I2S1_MCLK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(38, "GPIO38"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO38")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(39, "JTMS"),
++              "G21", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO39"),
++              MTK_FUNCTION(1, "JTMS")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(40, "JTCK"),
++              "J20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO40"),
++              MTK_FUNCTION(1, "JTCK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(41, "JTDI"),
++              "H22", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO41"),
++              MTK_FUNCTION(1, "JTDI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(42, "JTDO"),
++              "H21", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO42"),
++              MTK_FUNCTION(1, "JTDO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(43, "NCLE"),
++              "C7", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO43"),
++              MTK_FUNCTION(1, "NCLE"),
++              MTK_FUNCTION(2, "EXT_XCS2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(44, "NCEB1"),
++              "C6", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO44"),
++              MTK_FUNCTION(1, "NCEB1"),
++              MTK_FUNCTION(2, "IDDIG")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(45, "NCEB0"),
++              "D7", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO45"),
++              MTK_FUNCTION(1, "NCEB0"),
++              MTK_FUNCTION(2, "DRV_VBUS")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(46, "IR"),
++              "D15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO46"),
++              MTK_FUNCTION(1, "IR")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(47, "NREB"),
++              "A6", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO47"),
++              MTK_FUNCTION(1, "NREB")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(48, "NRNB"),
++              "B6", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO48"),
++              MTK_FUNCTION(1, "NRNB")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(49, "I2S0_DATA"),
++              "AB18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO49"),
++              MTK_FUNCTION(1, "I2S0_DATA"),
++              MTK_FUNCTION(3, "PCM_TX"),
++              MTK_FUNCTION(6, "AP_I2S_DO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(50, "GPIO50"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO50")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(51, "GPIO51"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO51")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(52, "GPIO52"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO52")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(53, "SPI0_CSN"),
++              "E7", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO53"),
++              MTK_FUNCTION(1, "SPI0_CS"),
++              MTK_FUNCTION(5, "PWM1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(54, "SPI0_CK"),
++              "F7", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO54"),
++              MTK_FUNCTION(1, "SPI0_CK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(55, "SPI0_MI"),
++              "E6", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO55"),
++              MTK_FUNCTION(1, "SPI0_MI"),
++              MTK_FUNCTION(2, "SPI0_MO"),
++              MTK_FUNCTION(3, "MSDC1_WP"),
++              MTK_FUNCTION(5, "PWM2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(56, "SPI0_MO"),
++              "G7", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO56"),
++              MTK_FUNCTION(1, "SPI0_MO"),
++              MTK_FUNCTION(2, "SPI0_MI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(57, "GPIO57"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO57")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(58, "GPIO58"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO58")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(59, "GPIO59"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO59")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(60, "WB_RSTB"),
++              "Y21", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO60"),
++              MTK_FUNCTION(1, "WB_RSTB")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(61, "GPIO61"),
++              "AA21", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO61"),
++              MTK_FUNCTION(1, "TEST_FD")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(62, "GPIO62"),
++              "AB22", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO62"),
++              MTK_FUNCTION(1, "TEST_FC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(63, "WB_SCLK"),
++              "AC23", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO63"),
++              MTK_FUNCTION(1, "WB_SCLK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(64, "WB_SDATA"),
++              "AB21", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO64"),
++              MTK_FUNCTION(1, "WB_SDATA")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(65, "WB_SEN"),
++              "AB24", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO65"),
++              MTK_FUNCTION(1, "WB_SEN")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(66, "WB_CRTL0"),
++              "AB20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO66"),
++              MTK_FUNCTION(1, "WB_CRTL0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(67, "WB_CRTL1"),
++              "AC20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO67"),
++              MTK_FUNCTION(1, "WB_CRTL1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(68, "WB_CRTL2"),
++              "AB19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO68"),
++              MTK_FUNCTION(1, "WB_CRTL2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(69, "WB_CRTL3"),
++              "AC19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO69"),
++              MTK_FUNCTION(1, "WB_CRTL3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(70, "WB_CRTL4"),
++              "AD19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO70"),
++              MTK_FUNCTION(1, "WB_CRTL4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(71, "WB_CRTL5"),
++              "AE19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO71"),
++              MTK_FUNCTION(1, "WB_CRTL5")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(72, "I2S0_DATA_IN"),
++              "AA20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO72"),
++              MTK_FUNCTION(1, "I2S0_DATA_IN"),
++              MTK_FUNCTION(3, "PCM_RX"),
++              MTK_FUNCTION(4, "PWM0"),
++              MTK_FUNCTION(5, "DISP_PWM"),
++              MTK_FUNCTION(6, "AP_I2S_DI")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(73, "I2S0_LRCK"),
++              "Y20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO73"),
++              MTK_FUNCTION(1, "I2S0_LRCK"),
++              MTK_FUNCTION(3, "PCM_SYNC"),
++              MTK_FUNCTION(6, "AP_I2S_LRCK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(74, "I2S0_BCK"),
++              "Y19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO74"),
++              MTK_FUNCTION(1, "I2S0_BCK"),
++              MTK_FUNCTION(3, "PCM_CLK0"),
++              MTK_FUNCTION(6, "AP_I2S_BCK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(75, "SDA0"),
++              "K19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO75"),
++              MTK_FUNCTION(1, "SDA0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(76, "SCL0"),
++              "K20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO76"),
++              MTK_FUNCTION(1, "SCL0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(77, "GPIO77"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO77")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(78, "GPIO78"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO78")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(79, "GPIO79"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO79")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(80, "GPIO80"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO80")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(81, "GPIO81"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO81")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(82, "GPIO82"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO82")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(83, "LCM_RST"),
++              "V16", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO83"),
++              MTK_FUNCTION(1, "LCM_RST")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(84, "DSI_TE"),
++              "V14", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO84"),
++              MTK_FUNCTION(1, "DSI_TE")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(85, "GPIO85"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO85")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(86, "GPIO86"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO86")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(87, "GPIO87"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO87")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(88, "GPIO88"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO88")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(89, "GPIO89"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO89")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(90, "GPIO90"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO90")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(91, "GPIO91"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO91")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(92, "GPIO92"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO92")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(93, "GPIO93"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO93")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(94, "GPIO94"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO94")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(95, "MIPI_TCN"),
++              "AB14", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO95"),
++              MTK_FUNCTION(1, "TCN")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(96, "MIPI_TCP"),
++              "AC14", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO96"),
++              MTK_FUNCTION(1, "TCP")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(97, "MIPI_TDN1"),
++              "AE15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO97"),
++              MTK_FUNCTION(1, "TDN1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(98, "MIPI_TDP1"),
++              "AD15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO98"),
++              MTK_FUNCTION(1, "TDP1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(99, "MIPI_TDN0"),
++              "AB15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO99"),
++              MTK_FUNCTION(1, "TDN0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(100, "MIPI_TDP0"),
++              "AC15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO100"),
++              MTK_FUNCTION(1, "TDP0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(101, "GPIO101"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO101")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(102, "GPIO102"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO102")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(103, "GPIO103"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO103")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(104, "GPIO104"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO104")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(105, "MSDC1_CMD"),
++              "AD2", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO105"),
++              MTK_FUNCTION(1, "MSDC1_CMD"),
++              MTK_FUNCTION(3, "SDA1"),
++              MTK_FUNCTION(6, "I2SOUT_BCK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(106, "MSDC1_CLK"),
++              "AD3", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO106"),
++              MTK_FUNCTION(1, "MSDC1_CLK"),
++              MTK_FUNCTION(3, "SCL1"),
++              MTK_FUNCTION(6, "I2SOUT_LRCK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(107, "MSDC1_DAT0"),
++              "AE2", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO107"),
++              MTK_FUNCTION(1, "MSDC1_DAT0"),
++              MTK_FUNCTION(5, "UTXD0"),
++              MTK_FUNCTION(6, "I2SOUT_DATA_OUT")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(108, "MSDC1_DAT1"),
++              "AC1", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO108"),
++              MTK_FUNCTION(1, "MSDC1_DAT1"),
++              MTK_FUNCTION(3, "PWM0"),
++              MTK_FUNCTION(5, "URXD0"),
++              MTK_FUNCTION(6, "PWM1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(109, "MSDC1_DAT2"),
++              "AC3", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO109"),
++              MTK_FUNCTION(1, "MSDC1_DAT2"),
++              MTK_FUNCTION(3, "SDA2"),
++              MTK_FUNCTION(5, "UTXD1"),
++              MTK_FUNCTION(6, "PWM2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(110, "MSDC1_DAT3"),
++              "AC4", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO110"),
++              MTK_FUNCTION(1, "MSDC1_DAT3"),
++              MTK_FUNCTION(3, "SCL2"),
++              MTK_FUNCTION(5, "URXD1"),
++              MTK_FUNCTION(6, "PWM3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(111, "MSDC0_DAT7"),
++              "A2", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO111"),
++              MTK_FUNCTION(1, "MSDC0_DAT7"),
++              MTK_FUNCTION(4, "NLD7")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(112, "MSDC0_DAT6"),
++              "B3", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO112"),
++              MTK_FUNCTION(1, "MSDC0_DAT6"),
++              MTK_FUNCTION(4, "NLD6")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(113, "MSDC0_DAT5"),
++              "C4", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO113"),
++              MTK_FUNCTION(1, "MSDC0_DAT5"),
++              MTK_FUNCTION(4, "NLD5")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(114, "MSDC0_DAT4"),
++              "A4", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO114"),
++              MTK_FUNCTION(1, "MSDC0_DAT4"),
++              MTK_FUNCTION(4, "NLD4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(115, "MSDC0_RSTB"),
++              "C5", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO115"),
++              MTK_FUNCTION(1, "MSDC0_RSTB"),
++              MTK_FUNCTION(4, "NLD8")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(116, "MSDC0_CMD"),
++              "D5", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO116"),
++              MTK_FUNCTION(1, "MSDC0_CMD"),
++              MTK_FUNCTION(4, "NALE")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(117, "MSDC0_CLK"),
++              "B1", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO117"),
++              MTK_FUNCTION(1, "MSDC0_CLK"),
++              MTK_FUNCTION(4, "NWEB")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(118, "MSDC0_DAT3"),
++              "D6", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO118"),
++              MTK_FUNCTION(1, "MSDC0_DAT3"),
++              MTK_FUNCTION(4, "NLD3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(119, "MSDC0_DAT2"),
++              "B2", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO119"),
++              MTK_FUNCTION(1, "MSDC0_DAT2"),
++              MTK_FUNCTION(4, "NLD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(120, "MSDC0_DAT1"),
++              "A3", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO120"),
++              MTK_FUNCTION(1, "MSDC0_DAT1"),
++              MTK_FUNCTION(4, "NLD1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(121, "MSDC0_DAT0"),
++              "B4", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO121"),
++              MTK_FUNCTION(1, "MSDC0_DAT0"),
++              MTK_FUNCTION(4, "NLD0"),
++              MTK_FUNCTION(5, "WATCHDOG")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(122, "GPIO122"),
++              "H17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO122"),
++              MTK_FUNCTION(1, "TEST"),
++              MTK_FUNCTION(4, "SDA2"),
++              MTK_FUNCTION(5, "URXD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(123, "GPIO123"),
++              "F17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO123"),
++              MTK_FUNCTION(1, "TEST"),
++              MTK_FUNCTION(4, "SCL2"),
++              MTK_FUNCTION(5, "UTXD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(124, "GPIO124"),
++              "H18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO124"),
++              MTK_FUNCTION(1, "TEST"),
++              MTK_FUNCTION(4, "SDA1"),
++              MTK_FUNCTION(5, "PWM3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(125, "GPIO125"),
++              "G17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO125"),
++              MTK_FUNCTION(1, "TEST"),
++              MTK_FUNCTION(4, "SCL1"),
++              MTK_FUNCTION(5, "PWM4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(126, "I2S0_MCLK"),
++              "AA19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO126"),
++              MTK_FUNCTION(1, "I2S0_MCLK"),
++              MTK_FUNCTION(6, "AP_I2S_MCLK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(127, "GPIO127"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO127")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(128, "GPIO128"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO128")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(129, "GPIO129"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO129")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(130, "GPIO130"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO130")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(131, "GPIO131"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO131")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(132, "GPIO132"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO132")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(133, "GPIO133"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO133")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(134, "GPIO134"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO134")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(135, "GPIO135"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO135")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(136, "GPIO136"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO136")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(137, "GPIO137"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO137")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(138, "GPIO138"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO138")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(139, "GPIO139"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO139")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(140, "GPIO140"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO140")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(141, "GPIO141"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO141")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(142, "GPIO142"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO142")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(143, "GPIO143"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO143")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(144, "GPIO144"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO144")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(145, "GPIO145"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO145")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(146, "GPIO146"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO146")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(147, "GPIO147"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO147")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(148, "GPIO148"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO148")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(149, "GPIO149"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO149")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(150, "GPIO150"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO150")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(151, "GPIO151"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO151")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(152, "GPIO152"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO152")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(153, "GPIO153"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO153")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(154, "GPIO154"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO154")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(155, "GPIO155"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO155")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(156, "GPIO156"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO156")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(157, "GPIO157"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO157")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(158, "GPIO158"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO158")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(159, "GPIO159"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO159")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(160, "GPIO160"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO160")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(161, "GPIO161"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO161")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(162, "GPIO162"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO162")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(163, "GPIO163"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO163")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(164, "GPIO164"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO164")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(165, "GPIO165"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO165")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(166, "GPIO166"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO166")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(167, "GPIO167"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO167")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(168, "GPIO168"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO168")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(169, "GPIO169"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO169")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(170, "GPIO170"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO170")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(171, "GPIO171"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO171")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(172, "GPIO172"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO172")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(173, "GPIO173"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO173")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(174, "GPIO174"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO174")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(175, "GPIO175"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO175")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(176, "GPIO176"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO176")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(177, "GPIO177"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO177")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(178, "GPIO178"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO178")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(179, "GPIO179"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO179")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(180, "GPIO180"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO180")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(181, "GPIO181"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO181")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(182, "GPIO182"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO182")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(183, "GPIO183"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO183")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(184, "GPIO184"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO184")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(185, "GPIO185"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO185")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(186, "GPIO186"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO186")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(187, "GPIO187"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO187")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(188, "GPIO188"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO188")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(189, "GPIO189"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO189")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(190, "GPIO190"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO190")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(191, "GPIO191"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO191")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(192, "GPIO192"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO192")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(193, "GPIO193"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO193")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(194, "GPIO194"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO194")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(195, "GPIO195"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO195")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(196, "GPIO196"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO196")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(197, "GPIO197"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO197")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(198, "GPIO198"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO198")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(199, "SPI1_CK"),
++              "E19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO199"),
++              MTK_FUNCTION(1, "SPI1_CK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(200, "URXD2"),
++              "K18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO200"),
++              MTK_FUNCTION(6, "URXD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(201, "UTXD2"),
++              "L18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO201"),
++              MTK_FUNCTION(6, "UTXD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(202, "GPIO202"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO202")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(203, "PWM0"),
++              "AA16", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO203"),
++              MTK_FUNCTION(1, "PWM0"),
++              MTK_FUNCTION(2, "DISP_PWM")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(204, "PWM1"),
++              "Y16", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO204"),
++              MTK_FUNCTION(1, "PWM1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(205, "PWM2"),
++              "AA15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO205"),
++              MTK_FUNCTION(1, "PWM2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(206, "PWM3"),
++              "AA17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO206"),
++              MTK_FUNCTION(1, "PWM3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(207, "PWM4"),
++              "Y15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO207"),
++              MTK_FUNCTION(1, "PWM4")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(208, "AUD_EXT_CK1"),
++              "W14", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO208"),
++              MTK_FUNCTION(1, "AUD_EXT_CK1"),
++              MTK_FUNCTION(2, "PWM0"),
++              MTK_FUNCTION(3, "PCIE0_PERST_N"),
++              MTK_FUNCTION(5, "DISP_PWM")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(209, "AUD_EXT_CK2"),
++              "V15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO209"),
++              MTK_FUNCTION(1, "AUD_EXT_CK2"),
++              MTK_FUNCTION(2, "MSDC1_WP"),
++              MTK_FUNCTION(3, "PCIE1_PERST_N"),
++              MTK_FUNCTION(5, "PWM1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(210, "GPIO210"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO210")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(211, "GPIO211"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO211")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(212, "GPIO212"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO212")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(213, "GPIO213"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO213")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(214, "GPIO214"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO214")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(215, "GPIO215"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO215")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(216, "GPIO216"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO216")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(217, "GPIO217"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO217")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(218, "GPIO218"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO218")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(219, "GPIO219"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO219")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(220, "GPIO220"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO220")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(221, "GPIO221"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO221")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(222, "GPIO222"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO222")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(223, "GPIO223"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO223")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(224, "GPIO224"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO224")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(225, "GPIO225"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO225")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(226, "GPIO226"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO226")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(227, "GPIO227"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO227")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(228, "GPIO228"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO228")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(229, "GPIO229"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO229")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(230, "GPIO230"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO230")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(231, "GPIO231"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO231")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(232, "GPIO232"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO232")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(233, "GPIO233"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO233")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(234, "GPIO234"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO234")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(235, "GPIO235"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO235")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(236, "EXT_SDIO3"),
++              "A8", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO236"),
++              MTK_FUNCTION(1, "EXT_SDIO3"),
++              MTK_FUNCTION(2, "IDDIG")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(237, "EXT_SDIO2"),
++              "D8", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO237"),
++              MTK_FUNCTION(1, "EXT_SDIO2"),
++              MTK_FUNCTION(2, "DRV_VBUS")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(238, "EXT_SDIO1"),
++              "D9", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO238"),
++              MTK_FUNCTION(1, "EXT_SDIO1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(239, "EXT_SDIO0"),
++              "B8", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO239"),
++              MTK_FUNCTION(1, "EXT_SDIO0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(240, "EXT_XCS"),
++              "C9", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO240"),
++              MTK_FUNCTION(1, "EXT_XCS")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(241, "EXT_SCK"),
++              "C8", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO241"),
++              MTK_FUNCTION(1, "EXT_SCK")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(242, "URTS2"),
++              "G18", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO242"),
++              MTK_FUNCTION(1, "URTS2"),
++              MTK_FUNCTION(2, "UTXD3"),
++              MTK_FUNCTION(3, "URXD3"),
++              MTK_FUNCTION(4, "SCL1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(243, "UCTS2"),
++              "H19", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO243"),
++              MTK_FUNCTION(1, "UCTS2"),
++              MTK_FUNCTION(2, "URXD3"),
++              MTK_FUNCTION(3, "UTXD3"),
++              MTK_FUNCTION(4, "SDA1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(244, "GPIO244"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO244")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(245, "GPIO245"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO245")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(246, "GPIO246"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO246")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(247, "GPIO247"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO247")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(248, "GPIO248"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO248")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(249, "GPIO249"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO249")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(250, "GPIO250"),
++              "A15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO250"),
++              MTK_FUNCTION(1, "TEST_MD7"),
++              MTK_FUNCTION(6, "PCIE0_CLKREQ_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(251, "GPIO251"),
++              "B15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO251"),
++              MTK_FUNCTION(1, "TEST_MD6"),
++              MTK_FUNCTION(6, "PCIE0_WAKE_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(252, "GPIO252"),
++              "C16", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO252"),
++              MTK_FUNCTION(1, "TEST_MD5"),
++              MTK_FUNCTION(6, "PCIE1_CLKREQ_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(253, "GPIO253"),
++              "D17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO253"),
++              MTK_FUNCTION(1, "TEST_MD4"),
++              MTK_FUNCTION(6, "PCIE1_WAKE_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(254, "GPIO254"),
++              "D16", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO254"),
++              MTK_FUNCTION(1, "TEST_MD3"),
++              MTK_FUNCTION(6, "PCIE2_CLKREQ_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(255, "GPIO255"),
++              "C17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO255"),
++              MTK_FUNCTION(1, "TEST_MD2"),
++              MTK_FUNCTION(6, "PCIE2_WAKE_N")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(256, "GPIO256"),
++              "B17", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO256"),
++              MTK_FUNCTION(1, "TEST_MD1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(257, "GPIO257"),
++              "C15", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO257"),
++              MTK_FUNCTION(1, "TEST_MD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(258, "GPIO258"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO258")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(259, "GPIO259"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO259")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(260, "GPIO260"),
++              "N/C", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),            MTK_FUNCTION(0, "GPIO260")
++
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(261, "MSDC1_INS"),
++              "AD1", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO261"),
++              MTK_FUNCTION(1, "MSDC1_INS")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(262, "G2_TXEN"),
++              "A23", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO262"),
++              MTK_FUNCTION(1, "G2_TXEN")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(263, "G2_TXD3"),
++              "N/A", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO263"),
++              MTK_FUNCTION(1, "G2_TXD3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(264, "G2_TXD2"),
++              "C24", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO264"),
++              MTK_FUNCTION(1, "G2_TXD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(265, "G2_TXD1"),
++              "B25", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO265"),
++              MTK_FUNCTION(1, "G2_TXD1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(266, "G2_TXD0"),
++              "A24", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO266"),
++              MTK_FUNCTION(1, "G2_TXD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(267, "G2_TXCLK"),
++              "C23", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO267"),
++              MTK_FUNCTION(1, "G2_TXC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(268, "G2_RXCLK"),
++              "B23", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO268"),
++              MTK_FUNCTION(1, "G2_RXC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(269, "G2_RXD0"),
++              "D21", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO269"),
++              MTK_FUNCTION(1, "G2_RXD0")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(270, "G2_RXD1"),
++              "B22", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO270"),
++              MTK_FUNCTION(1, "G2_RXD1")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(271, "G2_RXD2"),
++              "A22", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO271"),
++              MTK_FUNCTION(1, "G2_RXD2")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(272, "G2_RXD3"),
++              "C22", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO272"),
++              MTK_FUNCTION(1, "G2_RXD3")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(273, "D2D_ESW_INT"),
++              "N/A", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO273"),
++              MTK_FUNCTION(1, "ESW_INT")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(274, "G2_RXDV"),
++              "C21", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO274"),
++              MTK_FUNCTION(1, "G2_RXDV")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(275, "G2_MDC"),
++              "N/A", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO275"),
++              MTK_FUNCTION(1, "MDC")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(276, "G2_MDIO"),
++              "N/A", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO276"),
++              MTK_FUNCTION(1, "MDIO")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(277, "D2D_ESW_RSTN"),
++              "N/A", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO277"),
++              MTK_FUNCTION(1, "ESW_RST")
++      ),
++      MTK_PIN(
++              PINCTRL_PIN(278, "JTAG_RESET"),
++              "H20", "mt7623",
++              MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
++              MTK_FUNCTION(0, "GPIO278"),
++              MTK_FUNCTION(1, "JTAG_RESET")
++      ),
++};
++
++#endif /* __PINCTRL_MTK_MT7623_H */
+\ No newline at end of file
+diff --git a/include/dt-bindings/pinctrl/mt7623-pinfunc.h b/include/dt-bindings/pinctrl/mt7623-pinfunc.h
+new file mode 100644
+index 0000000..826835c
+--- /dev/null
++++ b/include/dt-bindings/pinctrl/mt7623-pinfunc.h
+@@ -0,0 +1,526 @@
++#ifndef __DTS_MT7623_PINFUNC_H
++#define __DTS_MT7623_PINFUNC_H
++
++#include <dt-bindings/pinctrl/mt65xx.h>
++
++#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
++#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_PWRAP_SPIDO (MTK_PIN_NO(0) | 1)
++#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_PWRAP_SPIDI (MTK_PIN_NO(0) | 2)
++
++#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
++#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_PWRAP_SPIDI (MTK_PIN_NO(1) | 1)
++#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_PWRAP_SPIDO (MTK_PIN_NO(1) | 2)
++
++#define MT7623_PIN_2_PWRAP_INT_FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
++#define MT7623_PIN_2_PWRAP_INT_FUNC_PWRAP_INT (MTK_PIN_NO(2) | 1)
++
++#define MT7623_PIN_3_PWRAP_SPI0_CK_FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
++#define MT7623_PIN_3_PWRAP_SPI0_CK_FUNC_PWRAP_SPICK_I (MTK_PIN_NO(3) | 1)
++
++#define MT7623_PIN_4_PWRAP_SPI0_CSN_FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
++#define MT7623_PIN_4_PWRAP_SPI0_CSN_FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(4) | 1)
++
++#define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
++#define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1)
++
++#define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
++#define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1)
++
++#define MT7623_PIN_7_SPI1_CSN_FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
++#define MT7623_PIN_7_SPI1_CSN_FUNC_SPI1_CS (MTK_PIN_NO(7) | 1)
++
++#define MT7623_PIN_8_SPI1_MI_FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
++#define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MI (MTK_PIN_NO(8) | 1)
++#define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MO (MTK_PIN_NO(8) | 2)
++
++#define MT7623_PIN_9_SPI1_MO_FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
++#define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MO (MTK_PIN_NO(9) | 1)
++#define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MI (MTK_PIN_NO(9) | 2)
++
++#define MT7623_PIN_10_RTC32K_CK_FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
++#define MT7623_PIN_10_RTC32K_CK_FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1)
++
++#define MT7623_PIN_11_WATCHDOG_FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
++#define MT7623_PIN_11_WATCHDOG_FUNC_WATCHDOG (MTK_PIN_NO(11) | 1)
++
++#define MT7623_PIN_12_SRCLKENA_FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
++#define MT7623_PIN_12_SRCLKENA_FUNC_SRCLKENA (MTK_PIN_NO(12) | 1)
++
++#define MT7623_PIN_13_SRCLKENAI_FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
++#define MT7623_PIN_13_SRCLKENAI_FUNC_SRCLKENAI (MTK_PIN_NO(13) | 1)
++
++#define MT7623_PIN_14_GPIO14_FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
++#define MT7623_PIN_14_GPIO14_FUNC_URXD2 (MTK_PIN_NO(14) | 1)
++#define MT7623_PIN_14_GPIO14_FUNC_UTXD2 (MTK_PIN_NO(14) | 2)
++
++#define MT7623_PIN_15_GPIO15_FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
++#define MT7623_PIN_15_GPIO15_FUNC_UTXD2 (MTK_PIN_NO(15) | 1)
++#define MT7623_PIN_15_GPIO15_FUNC_URXD2 (MTK_PIN_NO(15) | 2)
++
++#define MT7623_PIN_18_PCM_CLK_FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
++#define MT7623_PIN_18_PCM_CLK_FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1)
++#define MT7623_PIN_18_PCM_CLK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(18) | 6)
++
++#define MT7623_PIN_19_PCM_SYNC_FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
++#define MT7623_PIN_19_PCM_SYNC_FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1)
++#define MT7623_PIN_19_PCM_SYNC_FUNC_AP_PCM_SYNC (MTK_PIN_NO(19) | 6)
++
++#define MT7623_PIN_20_PCM_RX_FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
++#define MT7623_PIN_20_PCM_RX_FUNC_PCM_RX (MTK_PIN_NO(20) | 1)
++#define MT7623_PIN_20_PCM_RX_FUNC_PCM_TX (MTK_PIN_NO(20) | 4)
++#define MT7623_PIN_20_PCM_RX_FUNC_AP_PCM_RX (MTK_PIN_NO(20) | 6)
++
++#define MT7623_PIN_21_PCM_TX_FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
++#define MT7623_PIN_21_PCM_TX_FUNC_PCM_TX (MTK_PIN_NO(21) | 1)
++#define MT7623_PIN_21_PCM_TX_FUNC_PCM_RX (MTK_PIN_NO(21) | 4)
++#define MT7623_PIN_21_PCM_TX_FUNC_AP_PCM_TX (MTK_PIN_NO(21) | 6)
++
++#define MT7623_PIN_22_EINT0_FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
++#define MT7623_PIN_22_EINT0_FUNC_UCTS0 (MTK_PIN_NO(22) | 1)
++#define MT7623_PIN_22_EINT0_FUNC_PCIE0_PERST_N (MTK_PIN_NO(22) | 2)
++
++#define MT7623_PIN_23_EINT1_FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
++#define MT7623_PIN_23_EINT1_FUNC_URTS0 (MTK_PIN_NO(23) | 1)
++#define MT7623_PIN_23_EINT1_FUNC_PCIE1_PERST_N (MTK_PIN_NO(23) | 2)
++
++#define MT7623_PIN_24_EINT2_FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
++#define MT7623_PIN_24_EINT2_FUNC_UCTS1 (MTK_PIN_NO(24) | 1)
++#define MT7623_PIN_24_EINT2_FUNC_PCIE2_PERST_N (MTK_PIN_NO(24) | 2)
++
++#define MT7623_PIN_25_EINT3_FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
++#define MT7623_PIN_25_EINT3_FUNC_URTS1 (MTK_PIN_NO(25) | 1)
++
++#define MT7623_PIN_26_EINT4_FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
++#define MT7623_PIN_26_EINT4_FUNC_UCTS3 (MTK_PIN_NO(26) | 1)
++#define MT7623_PIN_26_EINT4_FUNC_PCIE2_WAKE_N (MTK_PIN_NO(26) | 6)
++
++#define MT7623_PIN_27_EINT5_FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
++#define MT7623_PIN_27_EINT5_FUNC_URTS3 (MTK_PIN_NO(27) | 1)
++#define MT7623_PIN_27_EINT5_FUNC_PCIE1_WAKE_N (MTK_PIN_NO(27) | 6)
++
++#define MT7623_PIN_28_EINT6_FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
++#define MT7623_PIN_28_EINT6_FUNC_DRV_VBUS (MTK_PIN_NO(28) | 1)
++#define MT7623_PIN_28_EINT6_FUNC_PCIE0_WAKE_N (MTK_PIN_NO(28) | 6)
++
++#define MT7623_PIN_29_EINT7_FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
++#define MT7623_PIN_29_EINT7_FUNC_IDDIG (MTK_PIN_NO(29) | 1)
++#define MT7623_PIN_29_EINT7_FUNC_MSDC1_WP (MTK_PIN_NO(29) | 2)
++#define MT7623_PIN_29_EINT7_FUNC_PCIE2_PERST_N (MTK_PIN_NO(29) | 6)
++
++#define MT7623_PIN_33_I2S1_DATA_FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
++#define MT7623_PIN_33_I2S1_DATA_FUNC_I2S1_DATA (MTK_PIN_NO(33) | 1)
++#define MT7623_PIN_33_I2S1_DATA_FUNC_PCM_TX (MTK_PIN_NO(33) | 3)
++#define MT7623_PIN_33_I2S1_DATA_FUNC_AP_PCM_TX (MTK_PIN_NO(33) | 6)
++
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_I2S1_DATA_IN (MTK_PIN_NO(34) | 1)
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_PCM_RX (MTK_PIN_NO(34) | 3)
++#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_AP_PCM_RX (MTK_PIN_NO(34) | 6)
++
++#define MT7623_PIN_35_I2S1_BCK_FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
++#define MT7623_PIN_35_I2S1_BCK_FUNC_I2S1_BCK (MTK_PIN_NO(35) | 1)
++#define MT7623_PIN_35_I2S1_BCK_FUNC_PCM_CLK0 (MTK_PIN_NO(35) | 3)
++#define MT7623_PIN_35_I2S1_BCK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(35) | 6)
++
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_I2S1_LRCK (MTK_PIN_NO(36) | 1)
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_PCM_SYNC (MTK_PIN_NO(36) | 3)
++#define MT7623_PIN_36_I2S1_LRCK_FUNC_AP_PCM_SYNC (MTK_PIN_NO(36) | 6)
++
++#define MT7623_PIN_37_I2S1_MCLK_FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
++#define MT7623_PIN_37_I2S1_MCLK_FUNC_I2S1_MCLK (MTK_PIN_NO(37) | 1)
++
++#define MT7623_PIN_39_JTMS_FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
++#define MT7623_PIN_39_JTMS_FUNC_JTMS (MTK_PIN_NO(39) | 1)
++
++#define MT7623_PIN_40_JTCK_FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
++#define MT7623_PIN_40_JTCK_FUNC_JTCK (MTK_PIN_NO(40) | 1)
++
++#define MT7623_PIN_41_JTDI_FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
++#define MT7623_PIN_41_JTDI_FUNC_JTDI (MTK_PIN_NO(41) | 1)
++
++#define MT7623_PIN_42_JTDO_FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
++#define MT7623_PIN_42_JTDO_FUNC_JTDO (MTK_PIN_NO(42) | 1)
++
++#define MT7623_PIN_43_NCLE_FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
++#define MT7623_PIN_43_NCLE_FUNC_NCLE (MTK_PIN_NO(43) | 1)
++#define MT7623_PIN_43_NCLE_FUNC_EXT_XCS2 (MTK_PIN_NO(43) | 2)
++
++#define MT7623_PIN_44_NCEB1_FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
++#define MT7623_PIN_44_NCEB1_FUNC_NCEB1 (MTK_PIN_NO(44) | 1)
++#define MT7623_PIN_44_NCEB1_FUNC_IDDIG (MTK_PIN_NO(44) | 2)
++
++#define MT7623_PIN_45_NCEB0_FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
++#define MT7623_PIN_45_NCEB0_FUNC_NCEB0 (MTK_PIN_NO(45) | 1)
++#define MT7623_PIN_45_NCEB0_FUNC_DRV_VBUS (MTK_PIN_NO(45) | 2)
++
++#define MT7623_PIN_46_IR_FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
++#define MT7623_PIN_46_IR_FUNC_IR (MTK_PIN_NO(46) | 1)
++
++#define MT7623_PIN_47_NREB_FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
++#define MT7623_PIN_47_NREB_FUNC_NREB (MTK_PIN_NO(47) | 1)
++
++#define MT7623_PIN_48_NRNB_FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
++#define MT7623_PIN_48_NRNB_FUNC_NRNB (MTK_PIN_NO(48) | 1)
++
++#define MT7623_PIN_49_I2S0_DATA_FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
++#define MT7623_PIN_49_I2S0_DATA_FUNC_I2S0_DATA (MTK_PIN_NO(49) | 1)
++#define MT7623_PIN_49_I2S0_DATA_FUNC_PCM_TX (MTK_PIN_NO(49) | 3)
++#define MT7623_PIN_49_I2S0_DATA_FUNC_AP_I2S_DO (MTK_PIN_NO(49) | 6)
++
++#define MT7623_PIN_53_SPI0_CSN_FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
++#define MT7623_PIN_53_SPI0_CSN_FUNC_SPI0_CS (MTK_PIN_NO(53) | 1)
++#define MT7623_PIN_53_SPI0_CSN_FUNC_PWM1 (MTK_PIN_NO(53) | 5)
++
++#define MT7623_PIN_54_SPI0_CK_FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
++#define MT7623_PIN_54_SPI0_CK_FUNC_SPI0_CK (MTK_PIN_NO(54) | 1)
++
++#define MT7623_PIN_55_SPI0_MI_FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
++#define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MI (MTK_PIN_NO(55) | 1)
++#define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MO (MTK_PIN_NO(55) | 2)
++#define MT7623_PIN_55_SPI0_MI_FUNC_MSDC1_WP (MTK_PIN_NO(55) | 3)
++#define MT7623_PIN_55_SPI0_MI_FUNC_PWM2 (MTK_PIN_NO(55) | 5)
++
++#define MT7623_PIN_56_SPI0_MO_FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
++#define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO (MTK_PIN_NO(56) | 1)
++#define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MI (MTK_PIN_NO(56) | 2)
++
++#define MT7623_PIN_60_WB_RSTB_FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
++#define MT7623_PIN_60_WB_RSTB_FUNC_WB_RSTB (MTK_PIN_NO(60) | 1)
++
++#define MT7623_PIN_61_GPIO61_FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
++#define MT7623_PIN_61_GPIO61_FUNC_TEST_FD (MTK_PIN_NO(61) | 1)
++
++#define MT7623_PIN_62_GPIO62_FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
++#define MT7623_PIN_62_GPIO62_FUNC_TEST_FC (MTK_PIN_NO(62) | 1)
++
++#define MT7623_PIN_63_WB_SCLK_FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
++#define MT7623_PIN_63_WB_SCLK_FUNC_WB_SCLK (MTK_PIN_NO(63) | 1)
++
++#define MT7623_PIN_64_WB_SDATA_FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
++#define MT7623_PIN_64_WB_SDATA_FUNC_WB_SDATA (MTK_PIN_NO(64) | 1)
++
++#define MT7623_PIN_65_WB_SEN_FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
++#define MT7623_PIN_65_WB_SEN_FUNC_WB_SEN (MTK_PIN_NO(65) | 1)
++
++#define MT7623_PIN_66_WB_CRTL0_FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
++#define MT7623_PIN_66_WB_CRTL0_FUNC_WB_CRTL0 (MTK_PIN_NO(66) | 1)
++
++#define MT7623_PIN_67_WB_CRTL1_FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
++#define MT7623_PIN_67_WB_CRTL1_FUNC_WB_CRTL1 (MTK_PIN_NO(67) | 1)
++
++#define MT7623_PIN_68_WB_CRTL2_FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
++#define MT7623_PIN_68_WB_CRTL2_FUNC_WB_CRTL2 (MTK_PIN_NO(68) | 1)
++
++#define MT7623_PIN_69_WB_CRTL3_FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
++#define MT7623_PIN_69_WB_CRTL3_FUNC_WB_CRTL3 (MTK_PIN_NO(69) | 1)
++
++#define MT7623_PIN_70_WB_CRTL4_FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
++#define MT7623_PIN_70_WB_CRTL4_FUNC_WB_CRTL4 (MTK_PIN_NO(70) | 1)
++
++#define MT7623_PIN_71_WB_CRTL5_FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
++#define MT7623_PIN_71_WB_CRTL5_FUNC_WB_CRTL5 (MTK_PIN_NO(71) | 1)
++
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_I2S0_DATA_IN (MTK_PIN_NO(72) | 1)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_PCM_RX (MTK_PIN_NO(72) | 3)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_PWM0 (MTK_PIN_NO(72) | 4)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_DISP_PWM (MTK_PIN_NO(72) | 5)
++#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_AP_I2S_DI (MTK_PIN_NO(72) | 6)
++
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_I2S0_LRCK (MTK_PIN_NO(73) | 1)
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_PCM_SYNC (MTK_PIN_NO(73) | 3)
++#define MT7623_PIN_73_I2S0_LRCK_FUNC_AP_I2S_LRCK (MTK_PIN_NO(73) | 6)
++
++#define MT7623_PIN_74_I2S0_BCK_FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
++#define MT7623_PIN_74_I2S0_BCK_FUNC_I2S0_BCK (MTK_PIN_NO(74) | 1)
++#define MT7623_PIN_74_I2S0_BCK_FUNC_PCM_CLK0 (MTK_PIN_NO(74) | 3)
++#define MT7623_PIN_74_I2S0_BCK_FUNC_AP_I2S_BCK (MTK_PIN_NO(74) | 6)
++
++#define MT7623_PIN_75_SDA0_FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
++#define MT7623_PIN_75_SDA0_FUNC_SDA0 (MTK_PIN_NO(75) | 1)
++
++#define MT7623_PIN_76_SCL0_FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
++#define MT7623_PIN_76_SCL0_FUNC_SCL0 (MTK_PIN_NO(76) | 1)
++
++#define MT7623_PIN_83_LCM_RST_FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
++#define MT7623_PIN_83_LCM_RST_FUNC_LCM_RST (MTK_PIN_NO(83) | 1)
++
++#define MT7623_PIN_84_DSI_TE_FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
++#define MT7623_PIN_84_DSI_TE_FUNC_DSI_TE (MTK_PIN_NO(84) | 1)
++
++#define MT7623_PIN_95_MIPI_TCN_FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
++#define MT7623_PIN_95_MIPI_TCN_FUNC_TCN (MTK_PIN_NO(95) | 1)
++
++#define MT7623_PIN_96_MIPI_TCP_FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
++#define MT7623_PIN_96_MIPI_TCP_FUNC_TCP (MTK_PIN_NO(96) | 1)
++
++#define MT7623_PIN_97_MIPI_TDN1_FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
++#define MT7623_PIN_97_MIPI_TDN1_FUNC_TDN1 (MTK_PIN_NO(97) | 1)
++
++#define MT7623_PIN_98_MIPI_TDP1_FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
++#define MT7623_PIN_98_MIPI_TDP1_FUNC_TDP1 (MTK_PIN_NO(98) | 1)
++
++#define MT7623_PIN_99_MIPI_TDN0_FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
++#define MT7623_PIN_99_MIPI_TDN0_FUNC_TDN0 (MTK_PIN_NO(99) | 1)
++
++#define MT7623_PIN_100_MIPI_TDP0_FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
++#define MT7623_PIN_100_MIPI_TDP0_FUNC_TDP0 (MTK_PIN_NO(100) | 1)
++
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD (MTK_PIN_NO(105) | 1)
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_SDA1 (MTK_PIN_NO(105) | 3)
++#define MT7623_PIN_105_MSDC1_CMD_FUNC_I2SOUT_BCK (MTK_PIN_NO(105) | 6)
++
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK (MTK_PIN_NO(106) | 1)
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_SCL1 (MTK_PIN_NO(106) | 3)
++#define MT7623_PIN_106_MSDC1_CLK_FUNC_I2SOUT_LRCK (MTK_PIN_NO(106) | 6)
++
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_MSDC1_DAT0 (MTK_PIN_NO(107) | 1)
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_UTXD0 (MTK_PIN_NO(107) | 5)
++#define MT7623_PIN_107_MSDC1_DAT0_FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(107) | 6)
++
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_MSDC1_DAT1 (MTK_PIN_NO(108) | 1)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_PWM0 (MTK_PIN_NO(108) | 3)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_URXD0 (MTK_PIN_NO(108) | 5)
++#define MT7623_PIN_108_MSDC1_DAT1_FUNC_PWM1 (MTK_PIN_NO(108) | 6)
++
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_MSDC1_DAT2 (MTK_PIN_NO(109) | 1)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_SDA2 (MTK_PIN_NO(109) | 3)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_UTXD1 (MTK_PIN_NO(109) | 5)
++#define MT7623_PIN_109_MSDC1_DAT2_FUNC_PWM2 (MTK_PIN_NO(109) | 6)
++
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3 (MTK_PIN_NO(110) | 1)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_SCL2 (MTK_PIN_NO(110) | 3)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_URXD1 (MTK_PIN_NO(110) | 5)
++#define MT7623_PIN_110_MSDC1_DAT3_FUNC_PWM3 (MTK_PIN_NO(110) | 6)
++
++#define MT7623_PIN_111_MSDC0_DAT7_FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
++#define MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7 (MTK_PIN_NO(111) | 1)
++#define MT7623_PIN_111_MSDC0_DAT7_FUNC_NLD7 (MTK_PIN_NO(111) | 4)
++
++#define MT7623_PIN_112_MSDC0_DAT6_FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
++#define MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6 (MTK_PIN_NO(112) | 1)
++#define MT7623_PIN_112_MSDC0_DAT6_FUNC_NLD6 (MTK_PIN_NO(112) | 4)
++
++#define MT7623_PIN_113_MSDC0_DAT5_FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
++#define MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5 (MTK_PIN_NO(113) | 1)
++#define MT7623_PIN_113_MSDC0_DAT5_FUNC_NLD5 (MTK_PIN_NO(113) | 4)
++
++#define MT7623_PIN_114_MSDC0_DAT4_FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
++#define MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4 (MTK_PIN_NO(114) | 1)
++#define MT7623_PIN_114_MSDC0_DAT4_FUNC_NLD4 (MTK_PIN_NO(114) | 4)
++
++#define MT7623_PIN_115_MSDC0_RSTB_FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
++#define MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB (MTK_PIN_NO(115) | 1)
++#define MT7623_PIN_115_MSDC0_RSTB_FUNC_NLD8 (MTK_PIN_NO(115) | 4)
++
++#define MT7623_PIN_116_MSDC0_CMD_FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
++#define MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD (MTK_PIN_NO(116) | 1)
++#define MT7623_PIN_116_MSDC0_CMD_FUNC_NALE (MTK_PIN_NO(116) | 4)
++
++#define MT7623_PIN_117_MSDC0_CLK_FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
++#define MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK (MTK_PIN_NO(117) | 1)
++#define MT7623_PIN_117_MSDC0_CLK_FUNC_NWEB (MTK_PIN_NO(117) | 4)
++
++#define MT7623_PIN_118_MSDC0_DAT3_FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
++#define MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3 (MTK_PIN_NO(118) | 1)
++#define MT7623_PIN_118_MSDC0_DAT3_FUNC_NLD3 (MTK_PIN_NO(118) | 4)
++
++#define MT7623_PIN_119_MSDC0_DAT2_FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
++#define MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2 (MTK_PIN_NO(119) | 1)
++#define MT7623_PIN_119_MSDC0_DAT2_FUNC_NLD2 (MTK_PIN_NO(119) | 4)
++
++#define MT7623_PIN_120_MSDC0_DAT1_FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
++#define MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1 (MTK_PIN_NO(120) | 1)
++#define MT7623_PIN_120_MSDC0_DAT1_FUNC_NLD1 (MTK_PIN_NO(120) | 4)
++
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0 (MTK_PIN_NO(121) | 1)
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_NLD0 (MTK_PIN_NO(121) | 4)
++#define MT7623_PIN_121_MSDC0_DAT0_FUNC_WATCHDOG (MTK_PIN_NO(121) | 5)
++
++#define MT7623_PIN_122_GPIO122_FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
++#define MT7623_PIN_122_GPIO122_FUNC_TEST (MTK_PIN_NO(122) | 1)
++#define MT7623_PIN_122_GPIO122_FUNC_SDA2 (MTK_PIN_NO(122) | 4)
++#define MT7623_PIN_122_GPIO122_FUNC_URXD0 (MTK_PIN_NO(122) | 5)
++
++#define MT7623_PIN_123_GPIO123_FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
++#define MT7623_PIN_123_GPIO123_FUNC_TEST (MTK_PIN_NO(123) | 1)
++#define MT7623_PIN_123_GPIO123_FUNC_SCL2 (MTK_PIN_NO(123) | 4)
++#define MT7623_PIN_123_GPIO123_FUNC_UTXD0 (MTK_PIN_NO(123) | 5)
++
++#define MT7623_PIN_124_GPIO124_FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
++#define MT7623_PIN_124_GPIO124_FUNC_TEST (MTK_PIN_NO(124) | 1)
++#define MT7623_PIN_124_GPIO124_FUNC_SDA1 (MTK_PIN_NO(124) | 4)
++#define MT7623_PIN_124_GPIO124_FUNC_PWM3 (MTK_PIN_NO(124) | 5)
++
++#define MT7623_PIN_125_GPIO125_FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
++#define MT7623_PIN_125_GPIO125_FUNC_TEST (MTK_PIN_NO(125) | 1)
++#define MT7623_PIN_125_GPIO125_FUNC_SCL1 (MTK_PIN_NO(125) | 4)
++#define MT7623_PIN_125_GPIO125_FUNC_PWM4 (MTK_PIN_NO(125) | 5)
++
++#define MT7623_PIN_126_I2S0_MCLK_FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
++#define MT7623_PIN_126_I2S0_MCLK_FUNC_I2S0_MCLK (MTK_PIN_NO(126) | 1)
++#define MT7623_PIN_126_I2S0_MCLK_FUNC_AP_I2S_MCLK (MTK_PIN_NO(126) | 6)
++
++#define MT7623_PIN_199_SPI1_CK_FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
++#define MT7623_PIN_199_SPI1_CK_FUNC_SPI1_CK (MTK_PIN_NO(199) | 1)
++
++#define MT7623_PIN_200_URXD2_FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
++#define MT7623_PIN_200_URXD2_FUNC_URXD2 (MTK_PIN_NO(200) | 6)
++
++#define MT7623_PIN_201_UTXD2_FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
++#define MT7623_PIN_201_UTXD2_FUNC_UTXD2 (MTK_PIN_NO(201) | 6)
++
++#define MT7623_PIN_203_PWM0_FUNC_GPIO203 (MTK_PIN_NO(203) | 0)
++#define MT7623_PIN_203_PWM0_FUNC_PWM0 (MTK_PIN_NO(203) | 1)
++#define MT7623_PIN_203_PWM0_FUNC_DISP_PWM (MTK_PIN_NO(203) | 2)
++
++#define MT7623_PIN_204_PWM1_FUNC_GPIO204 (MTK_PIN_NO(204) | 0)
++#define MT7623_PIN_204_PWM1_FUNC_PWM1 (MTK_PIN_NO(204) | 1)
++
++#define MT7623_PIN_205_PWM2_FUNC_GPIO205 (MTK_PIN_NO(205) | 0)
++#define MT7623_PIN_205_PWM2_FUNC_PWM2 (MTK_PIN_NO(205) | 1)
++
++#define MT7623_PIN_206_PWM3_FUNC_GPIO206 (MTK_PIN_NO(206) | 0)
++#define MT7623_PIN_206_PWM3_FUNC_PWM3 (MTK_PIN_NO(206) | 1)
++
++#define MT7623_PIN_207_PWM4_FUNC_GPIO207 (MTK_PIN_NO(207) | 0)
++#define MT7623_PIN_207_PWM4_FUNC_PWM4 (MTK_PIN_NO(207) | 1)
++
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_GPIO208 (MTK_PIN_NO(208) | 0)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_AUD_EXT_CK1 (MTK_PIN_NO(208) | 1)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_PWM0 (MTK_PIN_NO(208) | 2)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N (MTK_PIN_NO(208) | 3)
++#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_DISP_PWM (MTK_PIN_NO(208) | 5)
++
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_GPIO209 (MTK_PIN_NO(209) | 0)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_AUD_EXT_CK2 (MTK_PIN_NO(209) | 1)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_MSDC1_WP (MTK_PIN_NO(209) | 2)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N (MTK_PIN_NO(209) | 3)
++#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_PWM1 (MTK_PIN_NO(209) | 5)
++
++#define MT7623_PIN_236_EXT_SDIO3_FUNC_GPIO236 (MTK_PIN_NO(236) | 0)
++#define MT7623_PIN_236_EXT_SDIO3_FUNC_EXT_SDIO3 (MTK_PIN_NO(236) | 1)
++#define MT7623_PIN_236_EXT_SDIO3_FUNC_IDDIG (MTK_PIN_NO(236) | 2)
++
++#define MT7623_PIN_237_EXT_SDIO2_FUNC_GPIO237 (MTK_PIN_NO(237) | 0)
++#define MT7623_PIN_237_EXT_SDIO2_FUNC_EXT_SDIO2 (MTK_PIN_NO(237) | 1)
++#define MT7623_PIN_237_EXT_SDIO2_FUNC_DRV_VBUS (MTK_PIN_NO(237) | 2)
++
++#define MT7623_PIN_238_EXT_SDIO1_FUNC_GPIO238 (MTK_PIN_NO(238) | 0)
++#define MT7623_PIN_238_EXT_SDIO1_FUNC_EXT_SDIO1 (MTK_PIN_NO(238) | 1)
++
++#define MT7623_PIN_239_EXT_SDIO0_FUNC_GPIO239 (MTK_PIN_NO(239) | 0)
++#define MT7623_PIN_239_EXT_SDIO0_FUNC_EXT_SDIO0 (MTK_PIN_NO(239) | 1)
++
++#define MT7623_PIN_240_EXT_XCS_FUNC_GPIO240 (MTK_PIN_NO(240) | 0)
++#define MT7623_PIN_240_EXT_XCS_FUNC_EXT_XCS (MTK_PIN_NO(240) | 1)
++
++#define MT7623_PIN_241_EXT_SCK_FUNC_GPIO241 (MTK_PIN_NO(241) | 0)
++#define MT7623_PIN_241_EXT_SCK_FUNC_EXT_SCK (MTK_PIN_NO(241) | 1)
++
++#define MT7623_PIN_242_URTS2_FUNC_GPIO242 (MTK_PIN_NO(242) | 0)
++#define MT7623_PIN_242_URTS2_FUNC_URTS2 (MTK_PIN_NO(242) | 1)
++#define MT7623_PIN_242_URTS2_FUNC_UTXD3 (MTK_PIN_NO(242) | 2)
++#define MT7623_PIN_242_URTS2_FUNC_URXD3 (MTK_PIN_NO(242) | 3)
++#define MT7623_PIN_242_URTS2_FUNC_SCL1 (MTK_PIN_NO(242) | 4)
++
++#define MT7623_PIN_243_UCTS2_FUNC_GPIO243 (MTK_PIN_NO(243) | 0)
++#define MT7623_PIN_243_UCTS2_FUNC_UCTS2 (MTK_PIN_NO(243) | 1)
++#define MT7623_PIN_243_UCTS2_FUNC_URXD3 (MTK_PIN_NO(243) | 2)
++#define MT7623_PIN_243_UCTS2_FUNC_UTXD3 (MTK_PIN_NO(243) | 3)
++#define MT7623_PIN_243_UCTS2_FUNC_SDA1 (MTK_PIN_NO(243) | 4)
++
++#define MT7623_PIN_250_GPIO250_FUNC_GPIO250 (MTK_PIN_NO(250) | 0)
++#define MT7623_PIN_250_GPIO250_FUNC_TEST_MD7 (MTK_PIN_NO(250) | 1)
++#define MT7623_PIN_250_GPIO250_FUNC_PCIE0_CLKREQ_N (MTK_PIN_NO(250) | 6)
++
++#define MT7623_PIN_251_GPIO251_FUNC_GPIO251 (MTK_PIN_NO(251) | 0)
++#define MT7623_PIN_251_GPIO251_FUNC_TEST_MD6 (MTK_PIN_NO(251) | 1)
++#define MT7623_PIN_251_GPIO251_FUNC_PCIE0_WAKE_N (MTK_PIN_NO(251) | 6)
++
++#define MT7623_PIN_252_GPIO252_FUNC_GPIO252 (MTK_PIN_NO(252) | 0)
++#define MT7623_PIN_252_GPIO252_FUNC_TEST_MD5 (MTK_PIN_NO(252) | 1)
++#define MT7623_PIN_252_GPIO252_FUNC_PCIE1_CLKREQ_N (MTK_PIN_NO(252) | 6)
++
++#define MT7623_PIN_253_GPIO253_FUNC_GPIO253 (MTK_PIN_NO(253) | 0)
++#define MT7623_PIN_253_GPIO253_FUNC_TEST_MD4 (MTK_PIN_NO(253) | 1)
++#define MT7623_PIN_253_GPIO253_FUNC_PCIE1_WAKE_N (MTK_PIN_NO(253) | 6)
++
++#define MT7623_PIN_254_GPIO254_FUNC_GPIO254 (MTK_PIN_NO(254) | 0)
++#define MT7623_PIN_254_GPIO254_FUNC_TEST_MD3 (MTK_PIN_NO(254) | 1)
++#define MT7623_PIN_254_GPIO254_FUNC_PCIE2_CLKREQ_N (MTK_PIN_NO(254) | 6)
++
++#define MT7623_PIN_255_GPIO255_FUNC_GPIO255 (MTK_PIN_NO(255) | 0)
++#define MT7623_PIN_255_GPIO255_FUNC_TEST_MD2 (MTK_PIN_NO(255) | 1)
++#define MT7623_PIN_255_GPIO255_FUNC_PCIE2_WAKE_N (MTK_PIN_NO(255) | 6)
++
++#define MT7623_PIN_256_GPIO256_FUNC_GPIO256 (MTK_PIN_NO(256) | 0)
++#define MT7623_PIN_256_GPIO256_FUNC_TEST_MD1 (MTK_PIN_NO(256) | 1)
++
++#define MT7623_PIN_257_GPIO257_FUNC_GPIO257 (MTK_PIN_NO(257) | 0)
++#define MT7623_PIN_257_GPIO257_FUNC_TEST_MD0 (MTK_PIN_NO(257) | 1)
++
++#define MT7623_PIN_261_MSDC1_INS_FUNC_GPIO261 (MTK_PIN_NO(261) | 0)
++#define MT7623_PIN_261_MSDC1_INS_FUNC_MSDC1_INS (MTK_PIN_NO(261) | 1)
++
++#define MT7623_PIN_262_G2_TXEN_FUNC_GPIO262 (MTK_PIN_NO(262) | 0)
++#define MT7623_PIN_262_G2_TXEN_FUNC_G2_TXEN (MTK_PIN_NO(262) | 1)
++
++#define MT7623_PIN_263_G2_TXD3_FUNC_GPIO263 (MTK_PIN_NO(263) | 0)
++#define MT7623_PIN_263_G2_TXD3_FUNC_G2_TXD3 (MTK_PIN_NO(263) | 1)
++
++#define MT7623_PIN_264_G2_TXD2_FUNC_GPIO264 (MTK_PIN_NO(264) | 0)
++#define MT7623_PIN_264_G2_TXD2_FUNC_G2_TXD2 (MTK_PIN_NO(264) | 1)
++
++#define MT7623_PIN_265_G2_TXD1_FUNC_GPIO265 (MTK_PIN_NO(265) | 0)
++#define MT7623_PIN_265_G2_TXD1_FUNC_G2_TXD1 (MTK_PIN_NO(265) | 1)
++
++#define MT7623_PIN_266_G2_TXD0_FUNC_GPIO266 (MTK_PIN_NO(266) | 0)
++#define MT7623_PIN_266_G2_TXD0_FUNC_G2_TXD0 (MTK_PIN_NO(266) | 1)
++
++#define MT7623_PIN_267_G2_TXCLK_FUNC_GPIO267 (MTK_PIN_NO(267) | 0)
++#define MT7623_PIN_267_G2_TXCLK_FUNC_G2_TXC (MTK_PIN_NO(267) | 1)
++
++#define MT7623_PIN_268_G2_RXCLK_FUNC_GPIO268 (MTK_PIN_NO(268) | 0)
++#define MT7623_PIN_268_G2_RXCLK_FUNC_G2_RXC (MTK_PIN_NO(268) | 1)
++
++#define MT7623_PIN_269_G2_RXD0_FUNC_GPIO269 (MTK_PIN_NO(269) | 0)
++#define MT7623_PIN_269_G2_RXD0_FUNC_G2_RXD0 (MTK_PIN_NO(269) | 1)
++
++#define MT7623_PIN_270_G2_RXD1_FUNC_GPIO270 (MTK_PIN_NO(270) | 0)
++#define MT7623_PIN_270_G2_RXD1_FUNC_G2_RXD1 (MTK_PIN_NO(270) | 1)
++
++#define MT7623_PIN_271_G2_RXD2_FUNC_GPIO271 (MTK_PIN_NO(271) | 0)
++#define MT7623_PIN_271_G2_RXD2_FUNC_G2_RXD2 (MTK_PIN_NO(271) | 1)
++
++#define MT7623_PIN_272_G2_RXD3_FUNC_GPIO272 (MTK_PIN_NO(272) | 0)
++#define MT7623_PIN_272_G2_RXD3_FUNC_G2_RXD3 (MTK_PIN_NO(272) | 1)
++
++#define MT7623_PIN_273_D2D_ESW_INT_FUNC_GPIO273 (MTK_PIN_NO(273) | 0)
++#define MT7623_PIN_273_D2D_ESW_INT_FUNC_ESW_INT (MTK_PIN_NO(273) | 1)
++
++#define MT7623_PIN_274_G2_RXDV_FUNC_GPIO274 (MTK_PIN_NO(274) | 0)
++#define MT7623_PIN_274_G2_RXDV_FUNC_G2_RXDV (MTK_PIN_NO(274) | 1)
++
++#define MT7623_PIN_275_G2_MDC_FUNC_GPIO275 (MTK_PIN_NO(275) | 0)
++#define MT7623_PIN_275_G2_MDC_FUNC_MDC (MTK_PIN_NO(275) | 1)
++
++#define MT7623_PIN_276_G2_MDIO_FUNC_GPIO276 (MTK_PIN_NO(276) | 0)
++#define MT7623_PIN_276_G2_MDIO_FUNC_MDIO (MTK_PIN_NO(276) | 1)
++
++#define MT7623_PIN_277_D2D_ESW_RSTN_FUNC_GPIO277 (MTK_PIN_NO(277) | 0)
++#define MT7623_PIN_277_D2D_ESW_RSTN_FUNC_ESW_RST (MTK_PIN_NO(277) | 1)
++
++#define MT7623_PIN_278_JTAG_RESET_FUNC_GPIO278 (MTK_PIN_NO(278) | 0)
++#define MT7623_PIN_278_JTAG_RESET_FUNC_JTAG_RESET (MTK_PIN_NO(278) | 1)
++
++#endif /* __DTS_MT7623_PINFUNC_H */
+\ No newline at end of file
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch b/target/linux/mediatek/patches/0063-arm-mediatek-add-SDK-ethernet.patch
new file mode 100644 (file)
index 0000000..7263bb2
--- /dev/null
@@ -0,0 +1,20654 @@
+From e3aece79d5003b6879298b05551e113117d5cdd8 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:13:36 +0200
+Subject: [PATCH 63/76] arm: mediatek: add SDK ethernet
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/ethernet/Kconfig                      |    1 +
+ drivers/net/ethernet/Makefile                     |    1 +
+ drivers/net/ethernet/raeth/Kconfig                |  415 ++
+ drivers/net/ethernet/raeth/Makefile               |   67 +
+ drivers/net/ethernet/raeth/Makefile.release       |   60 +
+ drivers/net/ethernet/raeth/csr_netlink.h          |   27 +
+ drivers/net/ethernet/raeth/dvt/pkt_gen.c          |   88 +
+ drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c |  138 +
+ drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c |  191 +
+ drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c | 1527 +++++
+ drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h |   75 +
+ drivers/net/ethernet/raeth/ethtool_readme.txt     |   44 +
+ drivers/net/ethernet/raeth/mcast.c                |  187 +
+ drivers/net/ethernet/raeth/mii_mgr.c              |  603 ++
+ drivers/net/ethernet/raeth/ra2882ethreg.h         | 1985 +++++++
+ drivers/net/ethernet/raeth/ra_ethtool.c           |  515 ++
+ drivers/net/ethernet/raeth/ra_ethtool.h           |   13 +
+ drivers/net/ethernet/raeth/ra_ioctl.h             |  102 +
+ drivers/net/ethernet/raeth/ra_mac.c               | 2645 +++++++++
+ drivers/net/ethernet/raeth/ra_mac.h               |   57 +
+ drivers/net/ethernet/raeth/ra_netlink.c           |  142 +
+ drivers/net/ethernet/raeth/ra_netlink.h           |   10 +
+ drivers/net/ethernet/raeth/ra_qos.c               |  655 +++
+ drivers/net/ethernet/raeth/ra_qos.h               |   18 +
+ drivers/net/ethernet/raeth/ra_rfrw.c              |   66 +
+ drivers/net/ethernet/raeth/ra_rfrw.h              |    6 +
+ drivers/net/ethernet/raeth/raether.c              | 6401 +++++++++++++++++++++
+ drivers/net/ethernet/raeth/raether.h              |  126 +
+ drivers/net/ethernet/raeth/raether_hwlro.c        |  347 ++
+ drivers/net/ethernet/raeth/raether_pdma.c         | 1121 ++++
+ drivers/net/ethernet/raeth/raether_qdma.c         | 1407 +++++
+ drivers/net/ethernet/raeth/raether_qdma_mt7623.c  | 1020 ++++
+ drivers/net/ethernet/raeth/smb_hook.c             |   17 +
+ drivers/net/ethernet/raeth/smb_nf.c               |  177 +
+ drivers/net/ethernet/raeth/sync_write.h           |  103 +
+ 35 files changed, 20357 insertions(+)
+ create mode 100644 drivers/net/ethernet/raeth/Kconfig
+ create mode 100644 drivers/net/ethernet/raeth/Makefile
+ create mode 100644 drivers/net/ethernet/raeth/Makefile.release
+ create mode 100644 drivers/net/ethernet/raeth/csr_netlink.h
+ create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c
+ create mode 100755 drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h
+ create mode 100644 drivers/net/ethernet/raeth/ethtool_readme.txt
+ create mode 100644 drivers/net/ethernet/raeth/mcast.c
+ create mode 100644 drivers/net/ethernet/raeth/mii_mgr.c
+ create mode 100644 drivers/net/ethernet/raeth/ra2882ethreg.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_ethtool.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_ethtool.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_ioctl.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_mac.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_mac.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_netlink.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_netlink.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_qos.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_qos.h
+ create mode 100644 drivers/net/ethernet/raeth/ra_rfrw.c
+ create mode 100644 drivers/net/ethernet/raeth/ra_rfrw.h
+ create mode 100644 drivers/net/ethernet/raeth/raether.c
+ create mode 100644 drivers/net/ethernet/raeth/raether.h
+ create mode 100755 drivers/net/ethernet/raeth/raether_hwlro.c
+ create mode 100755 drivers/net/ethernet/raeth/raether_pdma.c
+ create mode 100644 drivers/net/ethernet/raeth/raether_qdma.c
+ create mode 100644 drivers/net/ethernet/raeth/raether_qdma_mt7623.c
+ create mode 100644 drivers/net/ethernet/raeth/smb_hook.c
+ create mode 100644 drivers/net/ethernet/raeth/smb_nf.c
+ create mode 100644 drivers/net/ethernet/raeth/sync_write.h
+
+diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
+index eadcb05..627e1d4 100644
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -17,6 +17,7 @@ config MDIO
+ config SUNGEM_PHY
+       tristate
++source "drivers/net/ethernet/raeth/Kconfig"
+ source "drivers/net/ethernet/3com/Kconfig"
+ source "drivers/net/ethernet/adaptec/Kconfig"
+ source "drivers/net/ethernet/aeroflex/Kconfig"
+diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
+index 1367afc..abdd636 100644
+--- a/drivers/net/ethernet/Makefile
++++ b/drivers/net/ethernet/Makefile
+@@ -84,3 +84,4 @@ obj-$(CONFIG_NET_VENDOR_VIA) += via/
+ obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
+ obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
+ obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
++obj-$(CONFIG_RAETH) += raeth/
+diff --git a/drivers/net/ethernet/raeth/Kconfig b/drivers/net/ethernet/raeth/Kconfig
+new file mode 100644
+index 0000000..c252c85
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/Kconfig
+@@ -0,0 +1,415 @@
++config ARCH_MT7623
++      bool
++      default y
++
++config RA_NAT_NONE
++      bool
++      default y
++
++config RAETH
++        tristate "Ralink GMAC"
++      ---help---
++          This driver supports Ralink gigabit ethernet family of
++          adapters.
++
++config PDMA_NEW
++        bool
++      default y if  (RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623)
++        depends on RAETH
++
++config RAETH_SCATTER_GATHER_RX_DMA
++        bool
++      default y if (RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623)
++        depends on RAETH
++
++
++choice
++      prompt "Network BottomHalves"   
++        depends on RAETH
++      default RA_NETWORK_WORKQUEUE_BH
++
++      config RA_NETWORK_TASKLET_BH
++      bool "Tasklet"
++
++      config RA_NETWORK_WORKQUEUE_BH
++      bool "Work Queue"
++
++      config RAETH_NAPI
++        bool "NAPI"
++
++endchoice
++
++#config TASKLET_WORKQUEUE_SW
++#        bool "Tasklet and Workqueue switch"
++#        depends on RA_NETWORK_TASKLET_BH
++
++config RAETH_SKB_RECYCLE_2K
++        bool "SKB Recycling"
++        depends on RAETH
++
++config RAETH_SPECIAL_TAG
++        bool "Ralink Special Tag (0x810x)"
++        depends on RAETH && RT_3052_ESW
++
++#config RAETH_JUMBOFRAME
++#        bool "Jumbo Frame up to 4K bytes"
++#        depends on RAETH && !(RALINK_RT3052 || RALINK_RT3352 || RALINK_RT5350 || RALINK_MT7628)
++
++config RAETH_CHECKSUM_OFFLOAD
++        bool "TCP/UDP/IP checksum offload"
++      default y
++        depends on RAETH && !RALINK_RT2880
++
++#config RAETH_SW_FC
++#        bool "When TX ring is full, inform kernel stop transmit and stop RX handler"
++#      default n
++#        depends on RAETH
++
++#config RAETH_8023AZ_EEE
++#        bool "Enable Embeded Switch EEE"
++#      default n
++#        depends on RAETH && (RALINK_MT7620 || RALINK_MT7621 || RALINK_MT7628)
++
++
++
++config 32B_DESC
++        bool "32bytes TX/RX description"
++      default n
++        depends on RAETH && (RALINK_MT7620 || RALINK_MT7621)
++        ---help---
++          At this moment, you cannot enable 32B description with Multiple RX ring at the same time.
++
++config RAETH_LRO
++        bool "LRO (Large Receive Offload )"
++      select INET_LRO
++        depends on RAETH && (RALINK_RT6855A || RALINK_MT7620 || RALINK_MT7621 || ARCH_MT7623)
++
++config RAETH_HW_LRO
++        bool "HW LRO (Large Receive Offload)"
++      default n
++        depends on RAETH
++
++config RAETH_HW_LRO_DBG
++        bool "HW LRO Debug"
++      default n
++      depends on RAETH_HW_LRO
++
++config RAETH_HW_LRO_AUTO_ADJ_DBG
++        bool "HW LRO Auto Adjustment Debug"
++      default y
++      depends on RAETH_HW_LRO
++
++config RAETH_HW_LRO_REASON_DBG
++        bool "HW LRO Flush Reason Debug"
++      default n
++      depends on RAETH_HW_LRO
++
++config RAETH_HW_VLAN_TX
++        bool "Transmit VLAN HW (DoubleVLAN is not supported)"
++        depends on RAETH && !(RALINK_RT5350 || RALINK_MT7628)
++        ---help---
++          Please disable HW_VLAN_TX if you need double vlan
++
++config RAETH_HW_VLAN_RX
++        bool "Receive VLAN HW (DoubleVLAN is not supported)"
++        depends on RAETH && RALINK_MT7621
++        ---help---
++          Please disable HW_VLAN_RX if you need double vlan
++
++config RAETH_TSO
++        bool "TSOV4 (Tcp Segmentaton Offload)"
++      depends on (RAETH_HW_VLAN_TX && (RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620))||((RALINK_MT7621 || ARCH_MT7623) &&(RAETH_HW_VLAN_TX || RAETH_GMAC2 ))
++
++config RAETH_TSOV6
++        bool "TSOV6 (Tcp Segmentaton Offload)"
++      depends on RAETH_TSO
++
++config RAETH_RW_PDMAPTR_FROM_VAR
++      bool
++      default y if RALINK_RT6855A || RALINK_MT7620
++        depends on RAETH
++
++config MTK_SMB_HOOK
++        bool "Samba Speedup Module"
++      depends on RAETH
++
++config SPLICE_NET_SUPPORT
++      default y if MTK_SMB_HOOK
++      depends on MTK_SMB_HOOK
++      bool
++
++
++config RAETH_DVT
++        bool "RAETH DVT"
++      depends on RAETH && (RALINK_MT7621 || ARCH_MT7623)
++      
++config RAETH_PDMA_DVT
++        bool "PDMA DVT"
++      depends on RAETH_DVT
++
++config RAETH_PDMA_LEGACY_MODE
++        bool "PDMA legacy mode"
++      depends on RAETH_PDMA_DVT
++
++#config RAETH_QOS
++#        bool "QoS Feature"
++#        depends on RAETH && !RALINK_RT2880 && !RALINK_MT7620 && !RALINK_MT7621 && !RAETH_TSO
++
++choice
++        prompt "QoS Type"
++        depends on RAETH_QOS
++        default DSCP_QOS_DSCP
++
++config  RAETH_QOS_DSCP_BASED
++        bool "DSCP-based"
++        depends on RAETH_QOS 
++
++config  RAETH_QOS_VPRI_BASED
++        bool "VPRI-based"
++        depends on RAETH_QOS
++
++endchoice
++
++config RAETH_QDMA
++        bool "Choose QDMA instead PDMA"
++      default n
++        depends on RAETH && (RALINK_MT7621 || ARCH_MT7623)
++
++config RAETH_QDMATX_QDMARX
++        bool "Choose QDMA RX instead PDMA RX"
++      default n
++        depends on RAETH_QDMA && !RALINK_MT7621
++
++   
++
++choice
++        prompt "GMAC is connected to"
++        depends on RAETH
++        default GE1_RGMII_FORCE_1000
++
++config  GE1_MII_FORCE_100
++        bool "MII_FORCE_100 (10/100M Switch)"
++        depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621) 
++
++config  GE1_MII_AN
++        bool "MII_AN (100Phy)"
++        depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621) 
++
++config  GE1_RVMII_FORCE_100
++        bool "RvMII_FORCE_100 (CPU)"
++        depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621) 
++
++config  GE1_RGMII_FORCE_1000
++        bool "RGMII_FORCE_1000 (GigaSW, CPU)"
++        depends on (RALINK_RT2880 || RALINK_RT3883)
++      select RALINK_SPI
++
++config  GE1_RGMII_FORCE_1000
++        bool "RGMII_FORCE_1000 (GigaSW, CPU)"
++        depends on (RALINK_MT7621 || ARCH_MT7623)
++      select RT_3052_ESW
++
++config  GE1_TRGMII_FORCE_1200
++        bool "TRGMII_FORCE_1200 (GigaSW, CPU)"
++        depends on (RALINK_MT7621)
++      select RT_3052_ESW
++
++config  GE1_TRGMII_FORCE_2000
++        bool "TRGMII_FORCE_2000 (GigaSW, CPU, for MT7623 and MT7683)"
++        depends on (ARCH_MT7623)
++        select RT_3052_ESW
++
++config  GE1_TRGMII_FORCE_2600
++        bool "TRGMII_FORCE_2600 (GigaSW, CPU, MT7623 only)"
++        depends on (ARCH_MT7623)
++        select RT_3052_ESW
++
++config  GE1_RGMII_AN
++        bool "RGMII_AN (GigaPhy)"
++        depends on (RALINK_RT2880 || RALINK_RT3883 || RALINK_MT7621 || ARCH_MT7623) 
++
++config  GE1_RGMII_NONE
++        bool "NONE (NO CONNECT)"
++        depends on (RALINK_MT7621 || ARCH_MT7623)
++
++endchoice
++
++config HW_SFQ
++        bool "HW_SFQ"
++      default n
++        depends on RAETH_QDMA && (ARCH_MT7623)
++        
++        
++config  RT_3052_ESW
++        bool "Ralink Embedded Switch"
++      default y
++        depends on RAETH && (RALINK_RT3052 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620 || RALINK_MT7621 || RALINK_MT7628 || ARCH_MT7623)
++
++config LAN_WAN_SUPPORT
++        bool "LAN/WAN Partition"
++        depends on RAETH && (RAETH_ROUTER || RT_3052_ESW)
++
++config ETH_MEMORY_OPTIMIZATION
++      bool "Ethernet memory optimization"
++      depends on RALINK_MT7628
++
++config ETH_ONE_PORT_ONLY
++      bool "One Port Only"
++      depends on RALINK_MT7628
++
++choice
++        prompt "Switch Board Layout Type"
++        depends on LAN_WAN_SUPPORT || P5_RGMII_TO_MAC_MODE ||  GE1_RGMII_FORCE_1000 || GE1_TRGMII_FORCE_1200 || GE2_RGMII_FORCE_1000
++      default WAN_AT_P0
++
++      config  WAN_AT_P4
++              bool "LLLL/W"
++              
++      config  WAN_AT_P0
++              bool "W/LLLL"
++endchoice
++
++config        RALINK_VISTA_BASIC
++      bool 'Vista Basic Logo for IC+ 175C'
++        depends on LAN_WAN_SUPPORT && (RALINK_RT2880 || RALINK_RT3883)
++
++config        ESW_DOUBLE_VLAN_TAG
++      bool
++      default y if RT_3052_ESW
++
++config RAETH_HAS_PORT4
++        bool "Port 4 Support"
++        depends on RAETH && RALINK_MT7620
++choice
++        prompt "Target Mode"
++        depends on RAETH_HAS_PORT4
++      default P4_RGMII_TO_MAC_MODE
++
++      config P4_MAC_TO_PHY_MODE
++              bool "Giga_Phy (RGMII)"
++      config  GE_RGMII_MT7530_P0_AN
++              bool "GE_RGMII_MT7530_P0_AN (MT7530 Internal GigaPhy)"
++      config  GE_RGMII_MT7530_P4_AN
++              bool "GE_RGMII_MT7530_P4_AN (MT7530 Internal GigaPhy)"
++      config P4_RGMII_TO_MAC_MODE
++              bool "Giga_SW/iNIC (RGMII)"
++      config P4_MII_TO_MAC_MODE
++              bool "External_CPU (MII_RvMII)"
++      config P4_RMII_TO_MAC_MODE
++              bool "External_CPU (RvMII_MII)"
++endchoice
++
++config  MAC_TO_GIGAPHY_MODE_ADDR2
++        hex "Port4 Phy Address"
++      default 0x4
++        depends on P4_MAC_TO_PHY_MODE
++
++config RAETH_HAS_PORT5
++        bool "Port 5 Support"
++        depends on RAETH && (RALINK_RT3052 || RALINK_RT3352 || RALINK_RT6855 || RALINK_RT6855A || RALINK_MT7620)
++choice
++        prompt "Target Mode"
++        depends on RAETH_HAS_PORT5
++      default P5_RGMII_TO_MAC_MODE
++
++      config P5_MAC_TO_PHY_MODE
++              bool "Giga_Phy (RGMII)"
++      config P5_RGMII_TO_MAC_MODE
++              bool "Giga_SW/iNIC (RGMII)"
++      config P5_RGMII_TO_MT7530_MODE
++              bool "MT7530 Giga_SW (RGMII)"
++              depends on RALINK_MT7620
++      config P5_MII_TO_MAC_MODE
++              bool "External_CPU (MII_RvMII)"
++      config P5_RMII_TO_MAC_MODE
++              bool "External_CPU (RvMII_MII)"
++endchoice
++
++config  MAC_TO_GIGAPHY_MODE_ADDR
++        hex "GE1 Phy Address"
++      default 0x1F
++        depends on GE1_MII_AN || GE1_RGMII_AN
++
++config  MAC_TO_GIGAPHY_MODE_ADDR
++        hex "Port5 Phy Address"
++      default 0x5
++        depends on P5_MAC_TO_PHY_MODE
++
++config RAETH_GMAC2
++        bool "GMAC2 Support"
++        depends on RAETH && (RALINK_RT3883 || RALINK_MT7621 || ARCH_MT7623)
++
++choice
++        prompt "GMAC2 is connected to"
++        depends on RAETH_GMAC2
++        default GE2_RGMII_AN
++
++config  GE2_MII_FORCE_100
++        bool "MII_FORCE_100 (10/100M Switch)"
++        depends on RAETH_GMAC2
++
++config  GE2_MII_AN
++        bool "MII_AN (100Phy)"
++        depends on RAETH_GMAC2
++
++config  GE2_RVMII_FORCE_100
++        bool "RvMII_FORCE_100 (CPU)"
++        depends on RAETH_GMAC2
++
++config  GE2_RGMII_FORCE_1000
++        bool "RGMII_FORCE_1000 (GigaSW, CPU)"
++        depends on RAETH_GMAC2
++      select RALINK_SPI
++
++config  GE2_RGMII_AN
++        bool "RGMII_AN (External GigaPhy)"
++        depends on RAETH_GMAC2
++
++config  GE2_INTERNAL_GPHY
++        bool "RGMII_AN (Internal GigaPny)"
++        depends on RAETH_GMAC2
++      select LAN_WAN_SUPPORT
++
++endchoice
++
++config  GE_RGMII_INTERNAL_P0_AN
++      bool
++        depends on GE2_INTERNAL_GPHY
++      default y if WAN_AT_P0
++
++config  GE_RGMII_INTERNAL_P4_AN
++      bool
++        depends on GE2_INTERNAL_GPHY
++      default y if WAN_AT_P4
++
++config  MAC_TO_GIGAPHY_MODE_ADDR2
++        hex
++      default 0 if GE_RGMII_INTERNAL_P0_AN
++      default 4 if GE_RGMII_INTERNAL_P4_AN
++        depends on GE_RGMII_INTERNAL_P0_AN || GE_RGMII_INTERNAL_P4_AN
++
++config  MAC_TO_GIGAPHY_MODE_ADDR2
++        hex "GE2 Phy Address"
++      default 0x1E
++        depends on GE2_MII_AN || GE2_RGMII_AN
++
++#force 100M
++config RAETH_ROUTER
++bool
++default y if GE1_MII_FORCE_100 || GE2_MII_FORCE_100 || GE1_RVMII_FORCE_100 || GE2_RVMII_FORCE_100
++
++#force 1000M
++config MAC_TO_MAC_MODE
++bool
++default y if GE1_RGMII_FORCE_1000 || GE2_RGMII_FORCE_1000
++depends on (RALINK_RT2880 || RALINK_RT3883) 
++
++#AN
++config GIGAPHY
++bool
++default y if GE1_RGMII_AN || GE2_RGMII_AN
++
++#AN
++config 100PHY
++bool
++default y if GE1_MII_AN || GE2_MII_AN
+diff --git a/drivers/net/ethernet/raeth/Makefile b/drivers/net/ethernet/raeth/Makefile
+new file mode 100644
+index 0000000..563af05
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/Makefile
+@@ -0,0 +1,67 @@
++obj-$(CONFIG_RAETH) += raeth.o
++raeth-objs := ra_mac.o mii_mgr.o ra_rfrw.o
++
++ifeq ($(CONFIG_MTK_SMB_HOOK),y)
++obj-y += smb_hook.o
++obj-m += smb.o
++smb-objs := smb_nf.o
++endif
++
++#EXTRA_CFLAGS   += -DCONFIG_RAETH_MULTIPLE_RX_RING
++
++ifeq ($(CONFIG_RAETH_QOS),y)
++raeth-objs += ra_qos.o
++endif
++
++ifeq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_qdma.o
++endif
++
++ifneq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_pdma.o
++endif
++
++raeth-objs += raether.o
++
++ifeq ($(CONFIG_ETHTOOL),y)
++raeth-objs += ra_ethtool.o
++endif
++
++ifeq ($(CONFIG_RALINK_RT3052_MP2),y)
++raeth-objs += mcast.o
++endif
++
++ifeq ($(CONFIG_RAETH_NETLINK),y)
++raeth-objs += ra_netlink.o
++endif
++
++ifeq ($(CONFIG_RAETH_PDMA_DVT),y)
++raeth-objs += dvt/raether_pdma_dvt.o
++obj-m += dvt/pkt_gen.o
++obj-m += dvt/pkt_gen_udp_frag.o
++obj-m += dvt/pkt_gen_tcp_frag.o
++endif
++
++ifeq ($(CONFIG_RAETH_HW_LRO),y)
++raeth-objs += raether_hwlro.o
++endif
++
++ifeq ($(CONFIG_RAETH_GMAC2),y)
++EXTRA_CFLAGS += -DCONFIG_PSEUDO_SUPPORT
++endif
++
++ifeq ($(CONFIG_ETH_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS   += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS   += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y)
++EXTRA_CFLAGS   += -DWORKQUEUE_BH
++endif
++
++ifeq ($(CONFIG_TASKLET_WORKQUEUE_SW),y)
++EXTRA_CFLAGS   += -DTASKLET_WORKQUEUE_SW
++endif
+diff --git a/drivers/net/ethernet/raeth/Makefile.release b/drivers/net/ethernet/raeth/Makefile.release
+new file mode 100644
+index 0000000..ecdeeda
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/Makefile.release
+@@ -0,0 +1,60 @@
++obj-$(CONFIG_RAETH) += raeth.o
++raeth-objs := ra_mac.o mii_mgr.o ra_rfrw.o
++
++ifeq ($(CONFIG_MTK_SMB_HOOK),y)
++obj-y += smb_hook.o
++obj-m += smb.o
++smb-objs := smb_nf.o
++endif
++
++#EXTRA_CFLAGS   += -DCONFIG_RAETH_MULTIPLE_RX_RING
++
++ifeq ($(CONFIG_RAETH_QOS),y)
++raeth-objs += ra_qos.o
++endif
++
++ifeq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_qdma.o
++endif
++
++ifneq ($(CONFIG_RAETH_QDMA),y)
++raeth-objs += raether_pdma.o
++endif
++
++raeth-objs += raether.o
++
++ifeq ($(CONFIG_ETHTOOL),y)
++raeth-objs += ra_ethtool.o
++endif
++
++ifeq ($(CONFIG_RALINK_RT3052_MP2),y)
++raeth-objs += mcast.o
++endif
++
++ifeq ($(CONFIG_RAETH_NETLINK),y)
++raeth-objs += ra_netlink.o
++endif
++
++ifeq ($(CONFIG_RAETH_HW_LRO),y)
++raeth-objs += raether_hwlro.o
++endif
++
++ifeq ($(CONFIG_RAETH_GMAC2),y)
++EXTRA_CFLAGS += -DCONFIG_PSEUDO_SUPPORT
++endif
++
++ifeq ($(CONFIG_ETH_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS   += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RT2860V2_AP_MEMORY_OPTIMIZATION),y)
++EXTRA_CFLAGS   += -DMEMORY_OPTIMIZATION
++endif
++
++ifeq ($(CONFIG_RA_NETWORK_WORKQUEUE_BH),y)
++EXTRA_CFLAGS   += -DWORKQUEUE_BH
++endif
++
++ifeq ($(CONFIG_TASKLET_WORKQUEUE_SW),y)
++EXTRA_CFLAGS   += -DTASKLET_WORKQUEUE_SW
++endif
+diff --git a/drivers/net/ethernet/raeth/csr_netlink.h b/drivers/net/ethernet/raeth/csr_netlink.h
+new file mode 100644
+index 0000000..add7745
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/csr_netlink.h
+@@ -0,0 +1,27 @@
++#ifndef       CSR_NETLINK_H
++#define CSR_NETLINK_H
++
++#define       CSR_NETLINK     30
++#define       CSR_READ        0
++#define       CSR_WRITE       1
++#define       CSR_TEST        2
++
++#define RALINK_CSR_GROUP       2882   
++
++typedef struct rt2880_csr_msg {
++      int     enable;
++      char    reg_name[32];
++      unsigned long address;
++      unsigned long default_value;
++      unsigned long reserved_bits;    /* 1 : not reserved, 0 : reserved */
++      unsigned long write_mask;
++      unsigned long write_value;
++      int     status;
++} CSR_MSG;
++
++int csr_msg_send(CSR_MSG* msg);
++int csr_msg_recv(void);
++
++// static CSR_MSG     input_csr_msg;
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen.c b/drivers/net/ethernet/raeth/dvt/pkt_gen.c
+new file mode 100755
+index 0000000..b351b21
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen.c
+@@ -0,0 +1,88 @@
++//#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <asm/uaccess.h>
++#include <linux/moduleparam.h>
++
++char *ifname="eth3";
++
++static int32_t PktGenInitMod(void)
++{
++
++    struct net_dev *dev;
++    struct sk_buff *skb;
++    int i=0;
++
++    unsigned char pkt[]={
++      //0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // dest bcast mac
++      0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest macA
++      //0x00, 0x30, 0xdb, 0x02, 0x02, 0x01, // dest macB
++      0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++      0x81, 0x00, // vlan tag
++      //0x81, 0x10, // vlan tag
++      //0x87, 0x39, // do not learn
++      //0xc1, 0x03, // vlan tag SA=0, VID=2, LV=1
++      0x00, 0x03, // pri=0, vlan=3
++      0x08, 0x00, // eth type=ip
++      0x45, 0x00, 0x00, 0x30, 0x12, 0x34, 0x40, 0x00, 0xff, 0x06,
++      0x40, 0x74, 0x0a, 0x0a, 0x1e, 0x0a, 0x0a, 0x0a, 0x1e, 0x0b,
++      0x00, 0x1e, 0x00, 0x28, 0x00, 0x1c, 0x81, 0x06, 0x00, 0x00,
++      0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
++
++    skb = alloc_skb(256, GFP_ATOMIC);
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++    if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++    if((dev=dev_get_by_name(ifname))){
++#endif
++
++
++
++      skb->dev=dev;
++      skb_put(skb,sizeof(pkt));
++      memcpy(skb->data, pkt, sizeof(pkt));
++
++      printk("send pkt(len=%d) to %s\n", skb->len, skb->dev->name);
++
++
++      for(i=0;i<sizeof(pkt);i++){
++          if(i%16==0) {
++              printk("\n");
++          }
++          printk("%02X-",skb->data[i]);
++      }
++
++      dev_queue_xmit(skb);
++    }else{
++      printk("interface %s not found\n",ifname);
++      return 1;
++    }
++
++    return 0;
++}
++
++static void PktGenCleanupMod(void)
++{
++}
++
++module_init(PktGenInitMod);
++module_exit(PktGenCleanupMod);
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
++MODULE_PARM (ifname, "s");
++#else
++module_param (ifname, charp, 0);
++#endif
++
++MODULE_DESCRIPTION("Ralink PktGen Module");
++MODULE_AUTHOR("Steven Liu");
++MODULE_LICENSE("Proprietary");
++MODULE_PARM_DESC (ifname, "interface name");
++
+diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c b/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c
+new file mode 100755
+index 0000000..e78c65a
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen_tcp_frag.c
+@@ -0,0 +1,138 @@
++//#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <asm/uaccess.h>
++#include <linux/moduleparam.h>
++
++char *ifname="eth3";
++
++
++static int32_t PktGenInitMod(void)
++{
++    unsigned char pkt_1[]={
++    0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++    0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++    0x08, 0x00, // type: ip
++    0x45, 0x00, 0x00, 0x34, // ip: ..., total len (0x034 = 52)
++    0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset
++    0x80, 0x06, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++    0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++    0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++    0x0d, 0xd5,  //tcp src port
++    0x13, 0x89,  //tcp dst port
++    0x40, 0xf5, 0x15, 0x04,  //tcp sequence number
++    0xf6, 0x4f, 0x1e, 0x31,  //tcp ack number
++    0x50, 0x10, 0xfc, 0x00,  //tcp flags, win size
++    0xf1, 0xfe, 0x00, 0x00,  //tcp checksum (0xf1fe)
++    0x01, 0x02, 0x03, 0x04, 0x05,  //payload (12 bytes)
++    0x06, 0x07, 0x08, 0x09, 0x0a,
++    0x0b, 0x0c
++    };
++    
++    unsigned char pkt_2[]={
++    0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++    0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++    0x08, 0x00, // type: ip
++    0x45, 0x00, 0x00, 0x20, // ip: ..., total len (0x020 = 32)
++    0xa1, 0x78, 0x00, 0x04, // ip: id, frag, frag offset (32)
++    0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++    0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++    0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++    0x11, 0x12, 0x13, 0x14, 0x15,  //payload (12 bytes)
++    0x16, 0x17, 0x18, 0x19, 0x1a,
++    0x1b, 0x1c
++    };
++
++    struct net_dev *dev;
++    struct sk_buff *skb_1;
++    struct sk_buff *skb_2;
++    int i=0;
++
++    skb_1 = alloc_skb(256, GFP_ATOMIC);
++    skb_2 = alloc_skb(256, GFP_ATOMIC);
++
++
++#if 1
++/* send packet 1 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++    if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++    if((dev=dev_get_by_name(ifname))){
++#endif
++
++      skb_1->dev=dev;
++      skb_put(skb_1,sizeof(pkt_1));
++      memcpy(skb_1->data, pkt_1, sizeof(pkt_1));
++
++      printk("send pkt(len=%d) to %s\n", skb_1->len, skb_1->dev->name);
++
++
++      for(i=0;i<sizeof(pkt_1);i++){
++          if(i%16==0) {
++              printk("\n");
++          }
++          printk("%02X-",skb_1->data[i]);
++      }
++
++      dev_queue_xmit(skb_1);
++    }else{
++      printk("interface %s not found\n",ifname);
++      return 1;
++    }
++#endif
++
++#if 1
++/* send packet 2 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++        if((dev=dev_get_by_name(ifname))){
++#endif
++
++      skb_2->dev=dev;
++      skb_put(skb_2,sizeof(pkt_2));
++      memcpy(skb_2->data, pkt_2, sizeof(pkt_2));
++
++      printk("send pkt(len=%d) to %s\n", skb_2->len, skb_2->dev->name);
++
++
++      for(i=0;i<sizeof(pkt_2);i++){
++          if(i%16==0) {
++              printk("\n");
++          }
++          printk("%02X-",skb_2->data[i]);
++      }
++
++      dev_queue_xmit(skb_2);
++    }else{
++      printk("interface %s not found\n",ifname);
++      return 1;
++    }
++#endif
++
++    return 0;
++}
++
++static void PktGenCleanupMod(void)
++{
++}
++
++module_init(PktGenInitMod);
++module_exit(PktGenCleanupMod);
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
++MODULE_PARM (ifname, "s");
++#else
++module_param (ifname, charp, 0);
++#endif
++
++MODULE_DESCRIPTION("Ralink PktGen Module");
++MODULE_AUTHOR("Steven Liu");
++MODULE_LICENSE("Proprietary");
++MODULE_PARM_DESC (ifname, "interface name");
++
+diff --git a/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c b/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c
+new file mode 100755
+index 0000000..917e7ad
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/pkt_gen_udp_frag.c
+@@ -0,0 +1,191 @@
++//#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <linux/types.h>
++#include <asm/uaccess.h>
++#include <linux/moduleparam.h>
++
++char *ifname="eth3";
++
++
++static int32_t PktGenInitMod(void)
++{
++#if 0
++    unsigned char pkt_0[]={
++//    0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac
++    0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++    0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++    0x08, 0x00, // type: ip
++    0x45, 0x00, 0x00, 0x26, // ip: ..., total len (0x026 = 38)
++//    0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset
++    0xa1, 0x78, 0x40, 0x00, // ip: id, frag, frag offset
++    0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++    0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++//    0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3)
++    0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++    0xca, 0x7b,  //udp src port
++    0x13, 0x89,  //udp dst port
++    0x00, 0x12,  //udp len (0x01c = 18) 
++    0x2f, 0x96,  //udp checksum (0x2f96)
++    0x01, 0x02, 0x03, 0x04, 0x05,  //payload (10 bytes)
++    0x06, 0x07, 0x08, 0x09, 0x0a
++    };
++#endif
++
++    unsigned char pkt_1[]={
++//    0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac
++    0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++    0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++    0x08, 0x00, // type: ip
++    0x45, 0x00, 0x00, 0x24, // ip: ..., total len (0x024 = 36)
++    0xa1, 0x78, 0x20, 0x00, // ip: id, frag, frag offset
++//    0xa1, 0x78, 0x40, 0x00, // ip: id, frag, frag offset
++    0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++    0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++//    0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3)
++    0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++    0xca, 0x7b,  //udp src port
++    0x13, 0x89,  //udp dst port
++    0x00, 0x1a,  //udp len (0x01a = 26) 
++    0x2f, 0x96,  //udp checksum (0x2f96)
++    0x01, 0x02, 0x03, 0x04, 0x05,  //payload (8 bytes)
++    0x06, 0x07, 0x08
++    };
++    
++    unsigned char pkt_2[]={
++//    0x00, 0x21, 0x86, 0xee, 0xe3, 0x95, // dest mac
++    0x00, 0x21, 0x86, 0xee, 0xe3, 0x90, // dest mac
++    0x00, 0x0c, 0x43, 0x28, 0x80, 0x33, // src mac
++    0x08, 0x00, // type: ip
++    0x45, 0x00, 0x00, 0x1e, // ip: ..., total len (0x01e = 30)
++    0xa1, 0x78, 0x00, 0x02, // ip: id, frag, frag offset (16)
++    0x40, 0x11, 0x63, 0x07, // ip: ttl, protocol, hdr checksum (0x6307)
++    0x0a, 0x0a, 0x1e, 0x7b, // src ip (10.10.30.123)
++//   0x0a, 0x0a, 0x1e, 0x03, // dst ip (10.10.30.3)
++    0x0a, 0x0a, 0x1e, 0x05, // dst ip (10.10.30.5)
++    0x11, 0x12, 0x13, 0x14, 0x15,  //payload (10 bytes)
++    0x16, 0x17, 0x18, 0x19, 0x1a
++    };
++
++    struct net_dev *dev;
++//    struct sk_buff *skb_0;
++    struct sk_buff *skb_1;
++    struct sk_buff *skb_2;
++    int i=0;
++
++//    skb_0 = alloc_skb(256, GFP_ATOMIC);
++    skb_1 = alloc_skb(256, GFP_ATOMIC);
++    skb_2 = alloc_skb(256, GFP_ATOMIC);
++
++#if 0
++/* send packet 0 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++    if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++    if((dev=dev_get_by_name(ifname))){
++#endif
++
++      skb_0->dev=dev;
++      skb_put(skb_0,sizeof(pkt_0));
++      memcpy(skb_0->data, pkt_0, sizeof(pkt_0));
++
++      printk("send pkt(len=%d) to %s\n", skb_0->len, skb_0->dev->name);
++
++
++      for(i=0;i<sizeof(pkt_0);i++){
++          if(i%16==0) {
++              printk("\n");
++          }
++          printk("%02X-",skb_0->data[i]);
++      }
++
++      dev_queue_xmit(skb_0);
++    }else{
++      printk("interface %s not found\n",ifname);
++      return 1;
++    }
++#endif
++
++#if 1
++/* send packet 1 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++    if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++    if((dev=dev_get_by_name(ifname))){
++#endif
++
++      skb_1->dev=dev;
++      skb_put(skb_1,sizeof(pkt_1));
++      memcpy(skb_1->data, pkt_1, sizeof(pkt_1));
++
++      printk("send pkt(len=%d) to %s\n", skb_1->len, skb_1->dev->name);
++
++
++      for(i=0;i<sizeof(pkt_1);i++){
++          if(i%16==0) {
++              printk("\n");
++          }
++          printk("%02X-",skb_1->data[i]);
++      }
++
++      dev_queue_xmit(skb_1);
++    }else{
++      printk("interface %s not found\n",ifname);
++      return 1;
++    }
++#endif
++
++#if 1
++/* send packet 2 */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        if((dev=dev_get_by_name(&init_net,ifname))){
++#else
++        if((dev=dev_get_by_name(ifname))){
++#endif
++
++      skb_2->dev=dev;
++      skb_put(skb_2,sizeof(pkt_2));
++      memcpy(skb_2->data, pkt_2, sizeof(pkt_2));
++
++      printk("send pkt(len=%d) to %s\n", skb_2->len, skb_2->dev->name);
++
++
++      for(i=0;i<sizeof(pkt_2);i++){
++          if(i%16==0) {
++              printk("\n");
++          }
++          printk("%02X-",skb_2->data[i]);
++      }
++
++      dev_queue_xmit(skb_2);
++    }else{
++      printk("interface %s not found\n",ifname);
++      return 1;
++    }
++#endif
++
++    return 0;
++}
++
++static void PktGenCleanupMod(void)
++{
++}
++
++module_init(PktGenInitMod);
++module_exit(PktGenCleanupMod);
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
++MODULE_PARM (ifname, "s");
++#else
++module_param (ifname, charp, 0);
++#endif
++
++MODULE_DESCRIPTION("Ralink PktGen Module");
++MODULE_AUTHOR("Steven Liu");
++MODULE_LICENSE("Proprietary");
++MODULE_PARM_DESC (ifname, "interface name");
++
+diff --git a/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c
+new file mode 100755
+index 0000000..971a821
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.c
+@@ -0,0 +1,1527 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined(CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#if defined(CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++
++#include "../ra2882ethreg.h"
++#include "../raether.h"
++#include "../ra_mac.h"
++#include "../ra_ioctl.h"
++#include "../ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "../ra_netlink.h"
++#endif
++#if defined(CONFIG_RAETH_QOS)
++#include "../ra_qos.h"
++#endif
++#include "raether_pdma_dvt.h"
++
++/* Global variables */
++static unsigned int g_pdma_dvt_show_config;
++static unsigned int g_pdma_dvt_rx_test_config;
++static unsigned int g_pdma_dvt_tx_test_config;
++static unsigned int g_pdma_dvt_debug_test_config;
++static unsigned int g_pdma_dvt_lro_test_config;
++
++unsigned int g_pdma_dev_lanport = 0;
++unsigned int g_pdma_dev_wanport = 0;
++
++void skb_dump(struct sk_buff *sk)
++{
++      unsigned int i;
++
++      printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n",
++             sk->dev ? sk->dev->name : "ip stack", sk->len, sk->truesize,
++             skb_headroom(sk), skb_tailroom(sk));
++
++      /* for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) { */
++      /* for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) { */
++      for (i = (unsigned int)sk->head; i <= (unsigned int)sk->data + 60; i++) {
++              if ((i % 20) == 0)
++                      printk("\n");
++              if (i == (unsigned int)sk->data)
++                      printk("{");
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 21)
++              if (i == (unsigned int)sk->transport_header)
++                      printk("#");
++              if (i == (unsigned int)sk->network_header)
++                      printk("|");
++              if (i == (unsigned int)sk->mac_header)
++                      printk("*");
++#else
++              if (i == (unsigned int)sk->h.raw)
++                      printk("#");
++              if (i == (unsigned int)sk->nh.raw)
++                      printk("|");
++              if (i == (unsigned int)sk->mac.raw)
++                      printk("*");
++#endif
++              printk("%02X-", *((unsigned char *)i));
++              if (i == (unsigned int)sk->tail)
++                      printk("}");
++      }
++      printk("\n");
++}
++
++#if defined(CONFIG_RAETH_HW_LRO)
++/* PDMA LRO test functions start */
++int pdma_lro_disable_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_lro_disable_dvt()\n");
++
++      /* 1. Invalid LRO ring1~3 */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0);
++
++      /* 2 Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++      }
++
++      /* 3. Disable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal &= ~(PDMA_LRO_EN);
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++#if 0
++      /* 4. Disable non-lro multiple rx */
++      SET_PDMA_NON_LRO_MULTI_EN(0);
++
++      /* 5.1. Set GDM1 to ring0 */
++      SET_GDM_PID1_RXID_SEL(0);
++      /* 5.2. Set GDM2 to ring0 */
++      SET_GDM_PID2_RXID_SEL(0);
++#endif
++
++      return 0;
++}
++
++int pdma_lro_force_aggre_dvt(void)
++{
++      unsigned int regVal = 0;
++      unsigned int ip;
++
++      printk("pdma_lro_force_aggre_dvt()\n");
++
++/* pdma rx ring1 */
++      /* 1. Set RX ring mode to force port */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT);
++
++      /* 2. Configure lro ring */
++      /* 2.1 set src/destination TCP ports */
++      SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 3423);
++      SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 2301);
++      /* 2.2 set src/destination IPs */
++      str_to_ip(&ip, "10.10.10.3");
++      sysRegWrite(LRO_RX_RING1_SIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.100");
++      sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++
++      /* 2.3 Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++
++      /* 2.4 Set AGE timer */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, 0);
++
++      /* 2.5 Set max AGG timer */
++      SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, 0);
++
++      /* 2.6 Set max LRO agg count */
++      SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT);
++
++      /* 3. IPv4 checksum update enable */
++      SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++      /* 4. Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++      }
++
++      /* 5. Enable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal |= PDMA_LRO_EN;
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++      return 0;
++}
++
++int pdma_lro_auto_aggre_dvt(void)
++{
++      unsigned int regVal = 0;
++      unsigned int ip;
++
++      printk("pdma_lro_auto_aggre_dvt()\n");
++
++      /* 1.1 Set my IP_1 */
++      str_to_ip(&ip, "10.10.10.254");
++      sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++      sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1);
++
++      /* 1.2 Set my IP_2 */
++      str_to_ip(&ip, "10.10.20.254");
++      sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++      sysRegWrite(LRO_RX_RING1_DIP_DW1, 0);
++      sysRegWrite(LRO_RX_RING1_DIP_DW2, 0);
++      sysRegWrite(LRO_RX_RING1_DIP_DW3, 0);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++
++      /* 1.3 Set my IP_3 */
++      sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238);
++      sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000);
++      sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000);
++      sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++
++      /* 1.4 Set my IP_4 */
++      sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238);
++      sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000);
++      sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000);
++      sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++
++      /* 2.1 Set RX ring1~3 to auto-learn modes */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++      /* 2.2 Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++      /* 2.3 Set AGE timer */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, 0);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, 0);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, 0);
++
++      /* 2.4 Set max AGG timer */
++      SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, 0);
++      SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, 0);
++      SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, 0);
++
++      /* 2.5 Set max LRO agg count */
++      SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT);
++      SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, HW_LRO_MAX_AGG_CNT);
++      SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, HW_LRO_MAX_AGG_CNT);
++
++      /* 3.0 IPv6 LRO enable */
++      SET_PDMA_LRO_IPV6_EN(1);
++
++      /* 3.1 IPv4 checksum update disable */
++      SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++      /* 3.2 switch priority comparision to byte count mode */
++      SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++      /* 3.3 bandwidth threshold setting */
++      SET_PDMA_LRO_BW_THRESHOLD(0);
++
++      /* 3.4 auto-learn score delta setting */
++      sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++      /* 3.5 Set ALT timer to 20us: (unit: 20us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(HW_LRO_TIMER_UNIT);
++      /* 3.6 Set ALT refresh timer to 1 sec. (unit: 20us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER(HW_LRO_REFRESH_TIME);
++
++      /* 4. Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++      }
++
++      /* 5. Enable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal |= PDMA_LRO_EN;
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++      return 0;
++}
++
++int pdma_lro_auto_ipv6_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_lro_auto_ipv6_dvt()\n");
++
++      /* 1. Set my IP */
++      sysRegWrite(LRO_RX_RING1_DIP_DW3, 0x20010238);
++      sysRegWrite(LRO_RX_RING1_DIP_DW2, 0x08000000);
++      sysRegWrite(LRO_RX_RING1_DIP_DW1, 0x00000000);
++      sysRegWrite(LRO_RX_RING1_DIP_DW0, 0x00000254);
++
++      /* 2.1 Set RX ring1~3 to auto-learn modes */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++      /* 2.2 Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++      /* 2.3 Set AGE timer */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++      /* 3.0 IPv6 LRO enable */
++      SET_PDMA_LRO_IPV6_EN(1);
++
++      /* 3.1 IPv4 checksum update disable */
++      SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++      /* 3.2 switch priority comparision to byte count mode */
++      SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++      /* 3.3 bandwidth threshold setting */
++      SET_PDMA_LRO_BW_THRESHOLD(0);
++
++      /* 3.4 auto-learn score delta setting */
++      sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++      /* 3.5 Set ALT timer to 500us: (unit: 20us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25);
++      /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER(2000);
++
++      /* 3.7 Set max AGG timer: 10 msec. */
++      SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++      /* 4. Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++      }
++
++      /* 5. Enable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal |= PDMA_LRO_EN;
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++      return 0;
++}
++
++int pdma_lro_auto_myIP_dvt(void)
++{
++      unsigned int regVal = 0;
++      unsigned int ip;
++
++      printk("pdma_lro_auto_myIP_dvt()\n");
++
++      /* 1.1 Set my IP_1 */
++      str_to_ip(&ip, "10.10.10.254");
++      sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++      sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1);
++      /* 1.2 Set my IP_2 */
++      str_to_ip(&ip, "10.10.20.254");
++      sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++      sysRegWrite(LRO_RX_RING1_DIP_DW1, 0);
++      sysRegWrite(LRO_RX_RING1_DIP_DW2, 0);
++      sysRegWrite(LRO_RX_RING1_DIP_DW3, 0);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++      /* 1.3 Set my IP_3 */
++      sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238);
++      sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000);
++      sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000);
++      sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++      /* 1.4 Set my IP_4 */
++      sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238);
++      sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000);
++      sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000);
++      sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++
++      /* 2.1 Set RX ring1~3 to auto-learn modes */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++      /* 2.2 Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++      /* 2.3 Set AGE timer */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++      /* 3.0 IPv6 LRO enable */
++      SET_PDMA_LRO_IPV6_EN(1);
++
++      /* 3.1 IPv4 checksum update disable */
++      SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++      /* 3.2 switch priority comparision to byte count mode */
++      SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++      /* 3.3 bandwidth threshold setting */
++      SET_PDMA_LRO_BW_THRESHOLD(0);
++
++      /* 3.4 auto-learn score delta setting */
++      sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++      /* 3.5 Set ALT timer to 500us: (unit: 20us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25);
++      /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER(2000);
++
++      /* 3.7 Set max AGG timer: 10 msec. */
++      SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++      /* 4. Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++      }
++
++      /* 5. Enable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal |= PDMA_LRO_EN;
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++      return 0;
++}
++
++int pdma_lro_dly_int_dvt(int index)
++{
++      unsigned int regVal = 0;
++      unsigned int ip;
++
++      printk("pdma_lro_dly_int_dvt(%d)\n", index);
++
++#if 0
++      /* 1.1 Set my IP_1 */
++      /* str_to_ip( &ip, "10.10.10.254" ); */
++      str_to_ip(&ip, "10.10.10.100");
++      sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++      sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++#else
++      /* 1.1 set src/destination TCP ports */
++      SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 3423);
++      SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 2301);
++      SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING2, 3423);
++      SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING2, 2301);
++      SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING3, 3423);
++      SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING3, 2301);
++      /* 1.2 set src/destination IPs */
++      str_to_ip(&ip, "10.10.10.3");
++      sysRegWrite(LRO_RX_RING1_SIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.100");
++      sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.3");
++      sysRegWrite(LRO_RX_RING2_SIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.100");
++      sysRegWrite(LRO_RX_RING2_DIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.3");
++      sysRegWrite(LRO_RX_RING3_SIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.100");
++      sysRegWrite(LRO_RX_RING3_DIP_DW0, ip);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++#endif
++
++      if (index == 0) {
++              /* 1.2 Disable DLY_INT for lro ring */
++              SET_PDMA_LRO_DLY_INT_EN(0);
++      } else {
++              /* 1.2 Enable DLY_INT for lro ring */
++              SET_PDMA_LRO_DLY_INT_EN(1);
++      }
++
++      /* 1.3 LRO ring DLY_INT setting */
++      if (index == 1) {
++              sysRegWrite(LRO_RX1_DLY_INT, DELAY_INT_INIT);
++      } else if (index == 2) {
++              sysRegWrite(LRO_RX2_DLY_INT, DELAY_INT_INIT);
++      } else if (index == 3) {
++              sysRegWrite(LRO_RX3_DLY_INT, DELAY_INT_INIT);
++      }
++#if 0
++      /* 2.1 Set RX rings to auto-learn modes */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++#else
++      /* 2.0 set rx ring mode */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_FORCE_PORT);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_FORCE_PORT);
++
++      /* 2.1 IPv4 force port mode */
++      SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING1, 1);
++      SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING2, 1);
++      SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING3, 1);
++#endif
++
++      /* 2.2 Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++      if ((index == 0) || (index == 1)) {
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0);
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0);
++      } else if (index == 2) {
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0);
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 0);
++      } else {
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 0);
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 0);
++              SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++      }
++
++      /* 2.3 Set AGE timer */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++      /* 3.1 IPv4 checksum update enable */
++      SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++      /* 3.2 switch priority comparision to byte count mode */
++      SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE);
++
++      /* 3.3 bandwidth threshold setting */
++      SET_PDMA_LRO_BW_THRESHOLD(0);
++
++      /* 3.4 auto-learn score delta setting */
++      sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++      /* 3.5 Set ALT timer to 500us: (unit: 20us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(25);
++      /* 3.6 Set ALT refresh timer to 1 sec. (unit: 500us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER(2000);
++
++      /* 3.7 Set max AGG timer */
++      SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++      /* 4. Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH) {;
++      }
++
++      /* 5. Enable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal |= PDMA_LRO_EN;
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++      return 0;
++}
++
++int pdma_lro_dly_int0_dvt(void)
++{
++      return pdma_lro_dly_int_dvt(0);
++}
++
++int pdma_lro_dly_int1_dvt(void)
++{
++      return pdma_lro_dly_int_dvt(1);
++}
++
++int pdma_lro_dly_int2_dvt(void)
++{
++      return pdma_lro_dly_int_dvt(2);
++}
++
++int pdma_lro_dly_int3_dvt(void)
++{
++      return pdma_lro_dly_int_dvt(3);
++}
++
++#endif /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++int pdma_gdm_rxid_config(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_gdm_rxid_config()\n");
++
++      /* 1. Set RX ring1~3 to pse modes */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_PSE_MODE);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_PSE_MODE);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_PSE_MODE);
++
++      /* 2. Enable non-lro multiple rx */
++      SET_PDMA_NON_LRO_MULTI_EN(1);
++
++      return 0;
++}
++
++int pdma_non_lro_portid_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_non_lro_portid_dvt()\n");
++
++      /* 1. Set GDM1 to ring3 */
++      SET_GDM_PID1_RXID_SEL(3);
++#if 0
++      /* 2. Set GDM2 to ring1 */
++      SET_GDM_PID2_RXID_SEL(1);
++#endif
++
++      /* 3. Set priority rule: pid */
++      SET_GDM_RXID_PRI_SEL(GDM_PRI_PID);
++
++      /* PDMA multi-rx enable */
++      pdma_gdm_rxid_config();
++
++      return 0;
++}
++
++int pdma_non_lro_stag_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_non_lro_stag_dvt()\n");
++
++      /* 1. Set STAG4 to ring0 */
++      GDM_STAG_RXID_SEL(4, 0);
++      /* 2. Set STAG3 to ring1 */
++      GDM_STAG_RXID_SEL(3, 1);
++      /* 3. Set STAG2 to ring2 */
++      GDM_STAG_RXID_SEL(2, 2);
++      /* 4. Set STAG1 to ring3 */
++      GDM_STAG_RXID_SEL(1, 3);
++
++      /* 5. Set priority rule: stag/pid */
++      SET_GDM_RXID_PRI_SEL(GDM_PRI_PID);
++
++      /* PDMA multi-rx enable */
++      pdma_gdm_rxid_config();
++
++      return 0;
++}
++
++int pdma_non_lro_vlan_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_non_lro_vlan_dvt()\n");
++
++      /* 1. Set vlan priority=3 to ring1 */
++      SET_GDM_VLAN_PRI_RXID_SEL(3, 1);
++      /* 2. Set vlan priority=2 to ring2 */
++      SET_GDM_VLAN_PRI_RXID_SEL(2, 2);
++      /* 3. Set vlan priority=1 to ring3 */
++      SET_GDM_VLAN_PRI_RXID_SEL(1, 3);
++      /* 4. Set vlan priority=0 to ring3 */
++      SET_GDM_VLAN_PRI_RXID_SEL(0, 3);
++
++      /* 1. Set vlan priority=4 to ring1 */
++      SET_GDM_VLAN_PRI_RXID_SEL(4, 1);
++      /* 2. Set vlan priority=5 to ring2 */
++      SET_GDM_VLAN_PRI_RXID_SEL(5, 2);
++      /* 3. Set vlan priority=6 to ring3 */
++      SET_GDM_VLAN_PRI_RXID_SEL(6, 3);
++      /* 4. Set vlan priority=7 to ring3 */
++      SET_GDM_VLAN_PRI_RXID_SEL(7, 3);
++
++      /* 4. Set priority rule: vlan > pid */
++      SET_GDM_RXID_PRI_SEL(GDM_PRI_VLAN_PID);
++
++      /* PDMA multi-rx enable */
++      pdma_gdm_rxid_config();
++
++      return 0;
++}
++
++int pdma_non_lro_tcpack_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_non_lro_tcpack_dvt()\n");
++
++      /* 1. Enable TCP ACK with zero payload check */
++      SET_GDM_TCP_ACK_WZPC(1);
++      /* 2. Set TCP ACK to ring3 */
++      SET_GDM_TCP_ACK_RXID_SEL(3);
++
++      /* 3. Set priority rule: ack > pid */
++      SET_GDM_RXID_PRI_SEL(GDM_PRI_ACK_PID);
++
++      /* PDMA multi-rx enable */
++      pdma_gdm_rxid_config();
++
++      return 0;
++}
++
++int pdma_non_lro_pri1_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_non_lro_pri1_dvt()\n");
++
++      /* 1. Set GDM1 to ring0 */
++      SET_GDM_PID1_RXID_SEL(0);
++
++      /* 2.1 Disable TCP ACK with zero payload check */
++      SET_GDM_TCP_ACK_WZPC(0);
++      /* 2.2 Set TCP ACK to ring1 */
++      SET_GDM_TCP_ACK_RXID_SEL(1);
++
++      /* 3. Set vlan priority=1 to ring2 */
++      SET_GDM_VLAN_PRI_RXID_SEL(1, 2);
++
++      /* 4. Set priority rule: vlan > ack > pid */
++      SET_GDM_RXID_PRI_SEL(GDM_PRI_VLAN_ACK_PID);
++
++      /* PDMA multi-rx enable */
++      pdma_gdm_rxid_config();
++
++      return 0;
++}
++
++int pdma_non_lro_pri2_dvt(void)
++{
++      unsigned int regVal = 0;
++
++      printk("pdma_non_lro_pri2_dvt()\n");
++
++      /* 1. Set GDM1 to ring0 */
++      SET_GDM_PID1_RXID_SEL(0);
++
++      /* 2.1 Disable TCP ACK with zero payload check */
++      SET_GDM_TCP_ACK_WZPC(0);
++      /* 2.2 Set TCP ACK to ring1 */
++      SET_GDM_TCP_ACK_RXID_SEL(1);
++
++      /* 3. Set vlan priority=1 to ring2 */
++      SET_GDM_VLAN_PRI_RXID_SEL(1, 2);
++
++      /* 4. Set priority rule: ack > vlan > pid */
++      SET_GDM_RXID_PRI_SEL(GDM_PRI_ACK_VLAN_PID);
++
++      /* PDMA multi-rx enable */
++      pdma_gdm_rxid_config();
++
++      return 0;
++}
++#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */
++const static PDMA_LRO_DVT_FUNC pdma_dvt_lro_func[] = {
++#if defined(CONFIG_RAETH_HW_LRO)
++      [0] = pdma_lro_disable_dvt,     /* PDMA_TEST_LRO_DISABLE */
++      [1] = pdma_lro_force_aggre_dvt, /* PDMA_TEST_LRO_FORCE_PORT */
++      [2] = pdma_lro_auto_aggre_dvt,  /* PDMA_TEST_LRO_AUTO_LEARN */
++      [3] = pdma_lro_auto_ipv6_dvt,   /* PDMA_TEST_LRO_AUTO_IPV6 */
++      [4] = pdma_lro_auto_myIP_dvt,   /* PDMA_TEST_LRO_AUTO_MYIP */
++      [5] = pdma_lro_force_aggre_dvt, /* PDMA_TEST_LRO_FORCE_AGGREGATE */
++#endif /* CONFIG_RAETH_HW_LRO */
++#if defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++      [6] = pdma_non_lro_portid_dvt,  /* PDMA_TEST_NON_LRO_PORT_ID */
++      [7] = pdma_non_lro_stag_dvt,    /* PDMA_TEST_NON_LRO_STAG */
++      [8] = pdma_non_lro_vlan_dvt,    /* PDMA_TEST_NON_LRO_VLAN */
++      [9] = pdma_non_lro_tcpack_dvt,  /* PDMA_TEST_NON_LRO_TCP_ACK */
++      [10] = pdma_non_lro_pri1_dvt,   /* PDMA_TEST_NON_LRO_PRI1 */
++      [11] = pdma_non_lro_pri2_dvt,   /* PDMA_TEST_NON_LRO_PRI2 */
++#endif /* CONFIG_RAETH_MULTIPLE_RX_RING */
++#if defined(CONFIG_RAETH_HW_LRO)
++      [12] = pdma_lro_dly_int0_dvt,   /* PDMA_TEST_LRO_DLY_INT0 */
++      [13] = pdma_lro_dly_int1_dvt,   /* PDMA_TEST_LRO_DLY_INT1 */
++      [14] = pdma_lro_dly_int2_dvt,   /* PDMA_TEST_LRO_DLY_INT2 */
++      [15] = pdma_lro_dly_int3_dvt,   /* PDMA_TEST_LRO_DLY_INT3 */
++#endif /* CONFIG_RAETH_HW_LRO */
++};
++
++/* PDMA LRO test functions end */
++
++#if defined(CONFIG_RAETH_HW_LRO) || defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++void raeth_pdma_lro_dvt(int rx_ring_no, END_DEVICE *ei_local,
++                      int rx_dma_owner_idx0)
++{
++      if (pdma_dvt_get_show_config() & PDMA_SHOW_RX_DESC) {
++              if (rx_ring_no == 1) {
++                      printk("------- rt2880_eth_recv (ring1) --------\n");
++                      printk("rx_info1=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info1);
++                      printk("rx_info2=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2);
++                      printk("rx_info3=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info3);
++                      printk("rx_info4=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4);
++                      printk("-------------------------------\n");
++              } else if (rx_ring_no == 2) {
++                      printk("------- rt2880_eth_recv (ring2) --------\n");
++                      printk("rx_info1=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info1);
++                      printk("rx_info2=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2);
++                      printk("rx_info3=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info3);
++                      printk("rx_info4=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4);
++                      printk("-------------------------------\n");
++              } else if (rx_ring_no == 3) {
++                      printk("------- rt2880_eth_recv (ring3) --------\n");
++                      printk("rx_info1=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info1);
++                      printk("rx_info2=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2);
++                      printk("rx_info3=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info3);
++                      printk("rx_info4=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4);
++                      printk("-------------------------------\n");
++              }
++#if 0
++              else {
++                      printk("------- rt2880_eth_recv (ring0) --------\n");
++                      printk("rx_info1=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info1);
++                      printk("rx_info2=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2);
++                      printk("rx_info3=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info3);
++                      printk("rx_info4=0x%x\n",
++                             *(unsigned int *)
++                             &ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4);
++                      printk("-------------------------------\n");
++              }
++#endif
++      }
++      if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_RX_DESC) ||
++          (pdma_dvt_get_lro_test_config()==PDMA_TEST_LRO_FORCE_PORT)) {
++              if (rx_ring_no == 1) {
++                      printk("------- rt2880_eth_recv (ring1) --------\n");
++                      printk("rx_info1.PDP0=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info1.PDP0);
++                      printk("rx_info2.DDONE_bit=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.DDONE_bit);
++                      printk("rx_info2.LS0=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.LS0);
++                      printk("rx_info2.PLEN0=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.PLEN0);
++                      printk("rx_info2.TAG=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++                      printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.LRO_AGG_CNT);
++                      printk("rx_info2.REV=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.REV);
++#else
++                      printk("rx_info2.LS1=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++                      printk("rx_info2.PLEN1=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info2.PLEN1);
++                      printk("rx_info3.TPID=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info3.TPID);
++                      printk("rx_info3.VID=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info3.VID);
++                      printk("rx_info4.IP6=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.IP6);
++                      printk("rx_info4.IP4=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.IP4);
++                      printk("rx_info4.IP4F=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.IP4F);
++                      printk("rx_info4.TACK=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.TACK);
++                      printk("rx_info4.L4VLD=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.L4VLD);
++                      printk("rx_info4.L4F=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.L4F);
++                      printk("rx_info4.SPORT=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.SP);
++                      printk("rx_info4.CRSN=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.CRSN);
++                      printk("rx_info4.FOE_Entry=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info4.FOE_Entry);
++                      printk("-------------------------------\n");
++              } else if (rx_ring_no == 2) {
++                      printk("------- rt2880_eth_recv (ring2) --------\n");
++                      printk("rx_info1.PDP0=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info1.PDP0);
++                      printk("rx_info2.DDONE_bit=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.DDONE_bit);
++                      printk("rx_info2.LS0=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.LS0);
++                      printk("rx_info2.PLEN0=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.PLEN0);
++                      printk("rx_info2.TAG=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++                      printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.LRO_AGG_CNT);
++                      printk("rx_info2.REV=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.REV);
++#else
++                      printk("rx_info2.LS1=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++                      printk("rx_info2.PLEN1=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info2.PLEN1);
++                      printk("rx_info3.TPID=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info3.TPID);
++                      printk("rx_info3.VID=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info3.VID);
++                      printk("rx_info4.IP6=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.IP6);
++                      printk("rx_info4.IP4=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.IP4);
++                      printk("rx_info4.IP4F=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.IP4F);
++                      printk("rx_info4.TACK=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.TACK);
++                      printk("rx_info4.L4VLD=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.L4VLD);
++                      printk("rx_info4.L4F=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.L4F);
++                      printk("rx_info4.SPORT=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.SP);
++                      printk("rx_info4.CRSN=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.CRSN);
++                      printk("rx_info4.FOE_Entry=0x%x\n",
++                             ei_local->rx_ring2[rx_dma_owner_idx0].
++                             rxd_info4.FOE_Entry);
++                      printk("-------------------------------\n");
++              } else if (rx_ring_no == 3) {
++                      printk("------- rt2880_eth_recv (ring3) --------\n");
++                      printk("rx_info1.PDP0=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info1.PDP0);
++                      printk("rx_info2.DDONE_bit=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.DDONE_bit);
++                      printk("rx_info2.LS0=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.LS0);
++                      printk("rx_info2.PLEN0=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.PLEN0);
++                      printk("rx_info2.TAG=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++                      printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.LRO_AGG_CNT);
++                      printk("rx_info2.REV=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.REV);
++#else
++                      printk("rx_info2.LS1=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++                      printk("rx_info2.PLEN1=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info2.PLEN1);
++                      printk("rx_info3.TPID=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info3.TPID);
++                      printk("rx_info3.VID=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info3.VID);
++                      printk("rx_info4.IP6=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.IP6);
++                      printk("rx_info4.IP4=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.IP4);
++                      printk("rx_info4.IP4F=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.IP4F);
++                      printk("rx_info4.TACK=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.TACK);
++                      printk("rx_info4.L4VLD=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.L4VLD);
++                      printk("rx_info4.L4F=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.L4F);
++                      printk("rx_info4.SPORT=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.SP);
++                      printk("rx_info4.CRSN=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.CRSN);
++                      printk("rx_info4.FOE_Entry=0x%x\n",
++                             ei_local->rx_ring3[rx_dma_owner_idx0].
++                             rxd_info4.FOE_Entry);
++                      printk("-------------------------------\n");
++              }
++#if 0
++              else {
++                      printk("------- rt2880_eth_recv (ring0) --------\n");
++                      printk("rx_info1.PDP0=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info1.PDP0);
++                      printk("rx_info2.DDONE_bit=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2.DDONE_bit);
++                      printk("rx_info2.LS0=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2.LS0);
++                      printk("rx_info2.PLEN0=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2.PLEN0);
++                      printk("rx_info2.TAG=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2.TAG);
++                      printk("rx_info2.LS1=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2.LS1);
++                      printk("rx_info2.PLEN1=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2.PLEN1);
++                      printk("rx_info3.TPID=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info3.TPID);
++                      printk("rx_info3.VID=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info3.VID);
++                      printk("rx_info4.IP6=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.IP6);
++                      printk("rx_info4.IP4=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.IP4);
++                      printk("rx_info4.IP4F=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.IP4F);
++                      printk("rx_info4.TACK=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.TACK);
++                      printk("rx_info4.L4VLD=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.L4VLD);
++                      printk("rx_info4.L4F=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.L4F);
++                      printk("rx_info4.SPORT=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.SP);
++                      printk("rx_info4.CRSN=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.CRSN);
++                      printk("rx_info4.FOE_Entry=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.FOE_Entry);
++                      printk("-------------------------------\n");
++              }
++#endif
++      }
++      if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_FORCE_AGGREGATE) {
++              if (rx_ring_no == 1) {
++                      printk("PASS!!! => RING1: rxd_info1.PDP0=0x%x\n",
++                             ei_local->rx_ring1[rx_dma_owner_idx0].
++                             rxd_info1.PDP0);
++                      skb_dump(ei_local->netrx1_skbuf[rx_dma_owner_idx0]);
++                      pdma_dvt_reset_config();
++              }
++      }
++}
++#endif
++
++int pdma_dvt_show_ctrl(int par1, int par2)
++{
++      if (par2 == 0)
++              g_pdma_dvt_show_config = 0;
++      else
++              g_pdma_dvt_show_config |= (1 << par2);
++
++      return 0;
++}
++
++int pdma_dvt_test_rx_ctrl(int par1, int par2)
++{
++      if (par2 == 0)
++              g_pdma_dvt_rx_test_config = 0;
++      else
++              g_pdma_dvt_rx_test_config |= (1 << par2);
++
++      return 0;
++}
++
++int pdma_dvt_test_tx_ctrl(int par1, int par2)
++{
++      if (par2 == 0)
++              g_pdma_dvt_tx_test_config = 0;
++      else
++              g_pdma_dvt_tx_test_config |= (1 << par2);
++
++      return 0;
++}
++
++int pdma_dvt_test_debug_ctrl(int par1, int par2)
++{
++      if (par2 == 0)
++              g_pdma_dvt_debug_test_config = 0;
++      else
++              g_pdma_dvt_debug_test_config |= (1 << par2);
++
++      return 0;
++}
++
++int pdma_dvt_test_lro_ctrl(int par1, int par2)
++{
++      g_pdma_dvt_lro_test_config = par2;
++
++#if defined(CONFIG_RAETH_HW_LRO) || defined(CONFIG_RAETH_MULTIPLE_RX_RING)
++      if (pdma_dvt_lro_func[par2])
++              (*pdma_dvt_lro_func[par2]) ();
++#endif /* #if defined (CONFIG_RAETH_HW_LRO) */
++
++      return 0;
++}
++
++unsigned int pdma_dvt_get_show_config()
++{
++      return g_pdma_dvt_show_config;
++}
++
++unsigned int pdma_dvt_get_rx_test_config()
++{
++      return g_pdma_dvt_rx_test_config;
++}
++
++unsigned int pdma_dvt_get_tx_test_config()
++{
++      return g_pdma_dvt_tx_test_config;
++}
++
++unsigned int pdma_dvt_get_debug_test_config()
++{
++      return g_pdma_dvt_debug_test_config;
++}
++
++unsigned int pdma_dvt_get_lro_test_config()
++{
++      return g_pdma_dvt_lro_test_config;
++}
++
++void pdma_dvt_reset_config()
++{
++      g_pdma_dvt_show_config = 0;
++      g_pdma_dvt_rx_test_config = 0;
++      g_pdma_dvt_tx_test_config = 0;
++      g_pdma_dvt_lro_test_config = 0;
++}
++
++void raeth_pdma_rx_desc_dvt(END_DEVICE *ei_local, int rx_dma_owner_idx0)
++{
++#if 0
++      unsigned int udf = 0;
++#endif
++
++      if (pdma_dvt_get_show_config() & PDMA_SHOW_RX_DESC) {
++              printk("------- rt2880_eth_recv --------\n");
++              printk("rx_info1=0x%x\n",
++                     *(unsigned int *)&ei_local->
++                     rx_ring0[rx_dma_owner_idx0].rxd_info1);
++              printk("rx_info2=0x%x\n",
++                     *(unsigned int *)&ei_local->
++                     rx_ring0[rx_dma_owner_idx0].rxd_info2);
++              printk("rx_info3=0x%x\n",
++                     *(unsigned int *)&ei_local->
++                     rx_ring0[rx_dma_owner_idx0].rxd_info3);
++              printk("rx_info4=0x%x\n",
++                     *(unsigned int *)&ei_local->
++                     rx_ring0[rx_dma_owner_idx0].rxd_info4);
++              printk("-------------------------------\n");
++      }
++      if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_RX_DESC) ||
++          pdma_dvt_get_rx_test_config()) {
++#if 0
++              udf = ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6 << 5 |
++                  ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4 << 4 |
++                  ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F << 3 |
++                  ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.TACK << 2 |
++                  ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD << 1 |
++                  ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F;
++#endif
++              printk("------- rt2880_eth_recv --------\n");
++              printk("rx_info1.PDP0=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info1.PDP0);
++              printk("rx_info2.DDONE_bit=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].
++                     rxd_info2.DDONE_bit);
++              printk("rx_info2.LS0=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.LS0);
++              printk("rx_info2.PLEN0=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.PLEN0);
++              printk("rx_info2.TAG=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.TAG);
++#if defined(CONFIG_ARCH_MT7623)
++              printk("rx_info2.LRO_AGG_CNT=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].
++                     rxd_info2.LRO_AGG_CNT);
++#else
++              printk("rx_info2.LS1=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.LS1);
++#endif /* CONFIG_RAETH_HW_LRO */
++              printk("rx_info2.PLEN1=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.PLEN1);
++              printk("rx_info3.TPID=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.TPID);
++              printk("rx_info3.VID=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID);
++#if 0
++              printk("rx_info4.UDF=0x%x\n", udf);
++#endif
++              printk("rx_info4.IP6=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6);
++              printk("rx_info4.IP4=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4);
++              printk("rx_info4.IP4F=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F);
++              printk("rx_info4.TACK=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.TACK);
++              printk("rx_info4.L4VLD=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD);
++              printk("rx_info4.L4F=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F);
++              printk("rx_info4.SPORT=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP);
++              printk("rx_info4.CRSN=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.CRSN);
++              printk("rx_info4.FOE_Entry=0x%x\n",
++                     ei_local->rx_ring0[rx_dma_owner_idx0].
++                     rxd_info4.FOE_Entry);
++              printk("-------------------------------\n");
++      }
++      if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV6)) {
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP6) {
++                      printk("PASS!!! => rx_info4.IP6=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.IP6);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV4)) {
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4) {
++                      printk("PASS!!! => rx_info4.IP4=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.IP4);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_IPV4F)) {
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.IP4F) {
++                      printk("PASS!!! => rx_info4.IP4F=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.IP4F);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_L4VLD)) {
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4VLD) {
++                      printk("PASS!!! => rx_info4.L4VLD=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.L4VLD);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_L4F)) {
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.L4F) {
++                      printk("PASS!!! => rx_info4.L4F=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info4.L4F);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_SPORT)) {
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP == 1) {
++                      g_pdma_dev_lanport++;
++              } else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info4.SP ==
++                         2) {
++                      g_pdma_dev_wanport++;
++              }
++              if (g_pdma_dev_lanport && g_pdma_dev_wanport) {
++                      printk
++                          ("PASS!!! => g_pdma_dev_lanport=0x%x, g_pdma_dev_wanport=0x%x",
++                           g_pdma_dev_lanport, g_pdma_dev_wanport);
++
++                      g_pdma_dev_lanport = 0;
++                      g_pdma_dev_wanport = 0;
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_VID_OFF)) {
++              if (!ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID) {
++                      printk("PASS!!! => rxd_info3.VID=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info3.VID);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_rx_test_config() & PDMA_TEST_RX_VID_ON)) {
++              printk("RX data: (PDP0=%x)\n",
++                     (unsigned int)ei_local->
++                     netrx0_skbuf[rx_dma_owner_idx0]->data);
++
++              skb_dump(ei_local->netrx0_skbuf[rx_dma_owner_idx0]);
++
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info3.VID &&
++                  ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.TAG) {
++                      printk("PASS!!! => rxd_info2.TAG=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info2.TAG);
++                      printk("PASS!!! => rxd_info3.VID=0x%x\n",
++                             ei_local->rx_ring0[rx_dma_owner_idx0].
++                             rxd_info3.VID);
++                      pdma_dvt_reset_config();
++              }
++      }
++}
++
++void raeth_pdma_tx_vlan_dvt(END_DEVICE *ei_local,
++                          unsigned long tx_cpu_owner_idx0)
++{
++      if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ON)) {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0xE007;    /* VLAN_TAG = 0x1E007 */
++      } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ZERO)) {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0x0000;    /* VLAN_TAG = 0x10000 */
++      } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_MAX)) {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | 0xFFFF;    /* VLAN_TAG = 0x1FFFF */
++      }
++}
++
++void raeth_pdma_tx_desc_dvt(END_DEVICE *ei_local,
++                          unsigned long tx_cpu_owner_idx0)
++{
++      if (PDMA_TEST_RX_UDF == pdma_dvt_get_rx_test_config()) {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4;      /* PPE */
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.UDF = 0x2F;
++      }
++      if (pdma_dvt_get_show_config() & PDMA_SHOW_TX_DESC) {
++              printk("------- rt2880_eth_send --------\n");
++              printk("tx_info1=%x\n",
++                     *(unsigned int *)&ei_local->
++                     tx_ring0[tx_cpu_owner_idx0].txd_info1);
++              printk("tx_info2=%x\n",
++                     *(unsigned int *)&ei_local->
++                     tx_ring0[tx_cpu_owner_idx0].txd_info2);
++              printk("tx_info3=%x\n",
++                     *(unsigned int *)&ei_local->
++                     tx_ring0[tx_cpu_owner_idx0].txd_info3);
++              printk("tx_info4=%x\n",
++                     *(unsigned int *)&ei_local->
++                     tx_ring0[tx_cpu_owner_idx0].txd_info4);
++              printk("--------------------------------\n");
++      }
++      if ((pdma_dvt_get_show_config() & PDMA_SHOW_DETAIL_TX_DESC) ||
++          pdma_dvt_get_tx_test_config()) {
++              printk("------- rt2880_eth_send --------\n");
++              printk("tx_info1.SDP0=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0);
++              printk("tx_info2.DDONE_bit=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].
++                     txd_info2.DDONE_bit);
++              printk("tx_info2.LS0_bit=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit);
++              printk("tx_info2.SDL0=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0);
++              printk("tx_info2.BURST_bit=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].
++                     txd_info2.BURST_bit);
++              printk("tx_info2.LS1_bit=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit);
++              printk("tx_info2.SDL1=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL1);
++              printk("tx_info3.SDP1=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1);
++              printk("tx_info4.TUI_CO=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO);
++              printk("tx_info4.TSO=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TSO);
++              printk("tx_info4.FPORT=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT);
++              printk("tx_info4.UDF=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.UDF);
++              printk("tx_info4.RESV=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.RESV);
++              printk("tx_info4.VLAN_TAG=%x\n",
++                     ei_local->tx_ring0[tx_cpu_owner_idx0].
++                     txd_info4.VLAN_TAG);
++              printk("--------------------------------\n");
++      }
++      if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_LAN_SPORT)) {
++              if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT == 1) {
++                      printk("PASS!!! => txd_info4.FPORT=0x%x\n",
++                             ei_local->tx_ring0[tx_cpu_owner_idx0].
++                             txd_info4.FPORT);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_WAN_SPORT)) {
++              if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT == 2) {
++                      printk("PASS!!! => txd_info4.FPORT=0x%x\n",
++                             ei_local->tx_ring0[tx_cpu_owner_idx0].
++                             txd_info4.FPORT);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ON)) {
++              if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++                      printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++                             ei_local->tx_ring0[tx_cpu_owner_idx0].
++                             txd_info4.VLAN_TAG);
++                      /* pdma_dvt_reset_config(); */
++              }
++      } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_OFF)) {
++              if (!ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++                      printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++                             ei_local->tx_ring0[tx_cpu_owner_idx0].
++                             txd_info4.VLAN_TAG);
++                      pdma_dvt_reset_config();
++              }
++      } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_ZERO)) {
++              if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++                      printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++                             ei_local->tx_ring0[tx_cpu_owner_idx0].
++                             txd_info4.VLAN_TAG);
++                      /* pdma_dvt_reset_config(); */
++              }
++      } else if ((pdma_dvt_get_tx_test_config() & PDMA_TEST_TX_VLAN_MAX)) {
++              if (ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG) {
++                      printk("PASS!!! => txd_info4.VLAN_TAG=0x%x\n",
++                             ei_local->tx_ring0[tx_cpu_owner_idx0].
++                             txd_info4.VLAN_TAG);
++                      /* pdma_dvt_reset_config(); */
++              }
++      }
++}
++
++void raeth_pdma_lro_dly_int_dvt(void)
++{
++      unsigned int reg_int_val;
++
++      reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
++
++      if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT0) {
++              if ((reg_int_val & RX_DLY_INT)) {
++                      printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++                      pdma_dvt_reset_config();
++              }
++      } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT1) {
++              if ((reg_int_val & RING1_RX_DLY_INT)) {
++                      printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++                      pdma_dvt_reset_config();
++              }
++      } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT2) {
++              if ((reg_int_val & RING2_RX_DLY_INT)) {
++                      printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++                      pdma_dvt_reset_config();
++              }
++      } else if (pdma_dvt_get_lro_test_config() == PDMA_TEST_LRO_DLY_INT3) {
++              if ((reg_int_val & RING3_RX_DLY_INT)) {
++                      printk("PASS!!! => reg_int_val=0x%x\n", reg_int_val);
++                      pdma_dvt_reset_config();
++              }
++      }
++}
++
++void pdma_dvt_set_dma_mode(void)
++{
++#if defined(CONFIG_RAETH_PDMA_LEGACY_MODE)
++      unsigned int regVal;
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW3);
++      regVal &= ~(BIT(15));
++      sysRegWrite(ADMA_LRO_CTRL_DW3, regVal);
++#endif  /* CONFIG_RAETH_PDMA_DVT */   
++}
++
+diff --git a/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h
+new file mode 100755
+index 0000000..600aab7
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/dvt/raether_pdma_dvt.h
+@@ -0,0 +1,75 @@
++/* Show controls */
++#define PDMA_SHOW_RX_DESC   (1 << 1)
++#define PDMA_SHOW_TX_DESC   (1 << 2)
++#define PDMA_SHOW_DETAIL_RX_DESC   (1 << 3)
++#define PDMA_SHOW_DETAIL_TX_DESC   (1 << 4)
++
++/* Rx test controls */
++#define PDMA_TEST_RX_UDF     (1 << 1)
++#define PDMA_TEST_RX_IPV6    (1 << 2)
++#define PDMA_TEST_RX_IPV4    (1 << 3)
++#define PDMA_TEST_RX_IPV4F   (1 << 4)
++#define PDMA_TEST_RX_L4VLD   (1 << 5)
++#define PDMA_TEST_RX_L4F     (1 << 6)
++#define PDMA_TEST_RX_SPORT   (1 << 7)
++#define PDMA_TEST_RX_VID_ON  (1 << 8)
++#define PDMA_TEST_RX_VID_OFF (1 << 9)
++
++/* Tx test controls */
++#define PDMA_TEST_TX_LAN_SPORT   (1 << 1)
++#define PDMA_TEST_TX_WAN_SPORT   (1 << 2)
++#define PDMA_TEST_TX_VLAN_ON     (1 << 3)
++#define PDMA_TEST_TX_VLAN_OFF    (1 << 4)
++#define PDMA_TEST_TX_VLAN_ZERO   (1 << 5)
++#define PDMA_TEST_TX_VLAN_MAX    (1 << 6)
++#define PDMA_TEST_TX_PDMA_LPK    (1 << 31)
++
++/* Debug controls */
++#define PDMA_TEST_TSO_DEBUG      (1 << 1)
++
++/* LRO test controls */
++typedef int (*PDMA_LRO_DVT_FUNC) (void);
++
++#define PDMA_TEST_LRO_DISABLE           (0)
++#define PDMA_TEST_LRO_FORCE_PORT        (1)
++#define PDMA_TEST_LRO_AUTO_LEARN        (2)
++#define PDMA_TEST_LRO_AUTO_IPV6         (3)
++#define PDMA_TEST_LRO_AUTO_MYIP         (4)
++#define PDMA_TEST_LRO_FORCE_AGGREGATE   (5)
++#define PDMA_TEST_NON_LRO_PORT_ID       (6)
++#define PDMA_TEST_NON_LRO_STAG          (7)
++#define PDMA_TEST_NON_LRO_VLAN          (8)
++#define PDMA_TEST_NON_LRO_TCP_ACK       (9)
++#define PDMA_TEST_NON_LRO_PRI1          (10)
++#define PDMA_TEST_NON_LRO_PRI2          (11)
++#define PDMA_TEST_LRO_DLY_INT0          (12)
++#define PDMA_TEST_LRO_DLY_INT1          (13)
++#define PDMA_TEST_LRO_DLY_INT2          (14)
++#define PDMA_TEST_LRO_DLY_INT3          (15)
++
++void skb_dump(struct sk_buff *sk);
++
++int pdma_dvt_show_ctrl(int par1, int par2);
++int pdma_dvt_test_rx_ctrl(int par1, int par2);
++int pdma_dvt_test_tx_ctrl(int par1, int par2);
++int pdma_dvt_test_debug_ctrl(int par1, int par2);
++int pdma_dvt_test_lro_ctrl(int par1, int par2);
++
++unsigned int pdma_dvt_get_show_config(void);
++unsigned int pdma_dvt_get_rx_test_config(void);
++unsigned int pdma_dvt_get_tx_test_config(void);
++unsigned int pdma_dvt_get_debug_test_config(void);
++unsigned int pdma_dvt_get_lro_test_config(void);
++void pdma_dvt_reset_config(void);
++
++void raeth_pdma_rx_desc_dvt(END_DEVICE *ei_local, int rx_dma_owner_idx0);
++void raeth_pdma_tx_vlan_dvt(END_DEVICE *ei_local,
++                          unsigned long tx_cpu_owner_idx0);
++void raeth_pdma_tx_desc_dvt(END_DEVICE *ei_local,
++                          unsigned long tx_cpu_owner_idx0);
++
++void raeth_pdma_lro_dvt(int rx_ring_no, END_DEVICE *ei_local,
++                      int rx_dma_owner_idx0);
++void raeth_pdma_lro_dly_int_dvt(void);
++void pdma_dvt_set_dma_mode(void);
++
+diff --git a/drivers/net/ethernet/raeth/ethtool_readme.txt b/drivers/net/ethernet/raeth/ethtool_readme.txt
+new file mode 100644
+index 0000000..10e918b
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ethtool_readme.txt
+@@ -0,0 +1,44 @@
++
++Ethtool readme for selecting different PHY address.
++
++Before doing any ethtool command you should make sure the current PHY
++address is expected. The default PHY address is 1(port 1).
++
++You can change current PHY address to X(0~4) by doing follow command:
++# echo X > /proc/rt2880/gmac
++
++Ethtool command also would show the current PHY address as following.
++
++# ethtool  eth2
++Settings for eth2:
++        Supported ports: [ TP MII ]
++        Supported link modes:   10baseT/Half 10baseT/Full
++                                100baseT/Half 100baseT/Full
++        Supports auto-negotiation: Yes
++        Advertised link modes:  10baseT/Half 10baseT/Full
++                                100baseT/Half 100baseT/Full
++        Advertised auto-negotiation: No
++        Speed: 10Mb/s
++        Duplex: Full
++        Port: MII
++        PHYAD: 1
++        Transceiver: internal
++        Auto-negotiation: off
++        Current message level: 0x00000000 (0)
++        Link detected: no
++
++
++The "PHYAD" field shows the current PHY address.
++
++
++
++Usage example
++1) show port1 info
++# echo 1 > /proc/rt2880/gmac          # change phy address to 1
++# ethtool eth2
++
++2) show port0 info
++# echo 0 > /proc/rt2880/gmac          # change phy address to 0
++# ethtool eth2
++
++
+diff --git a/drivers/net/ethernet/raeth/mcast.c b/drivers/net/ethernet/raeth/mcast.c
+new file mode 100644
+index 0000000..d796b03
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/mcast.c
+@@ -0,0 +1,187 @@
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/if_vlan.h>
++
++
++#define MAX_MCAST_ENTRY           16
++#define AGEING_TIME       5  //Unit: Sec
++#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2], \
++    ((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
++
++//#define MCAST_DEBUG
++#ifdef MCAST_DEBUG
++#define MCAST_PRINT(fmt, args...) printk(KERN_INFO fmt, ## args)
++#else
++#define MCAST_PRINT(fmt, args...) { }
++#endif
++
++typedef struct {
++    uint8_t   src_mac[6];
++    uint8_t   dst_mac[6];
++    uint16_t    vlan_id;
++    uint32_t  valid;
++    uint32_t  use_count;
++    unsigned long ageout;
++} mcast_entry;
++
++mcast_entry mcast_tbl[MAX_MCAST_ENTRY];
++atomic_t mcast_entry_num=ATOMIC_INIT(0);
++DECLARE_MUTEX(mtbl_lock);
++
++uint32_t inline is_multicast_pkt(uint8_t *mac)
++{
++    if(mac[0]==0x01 && mac[1]==0x00 && mac[2]==0x5E) {
++      return 1;
++    }else{
++      return 0;
++    }
++}
++
++int32_t inline mcast_entry_get(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac) 
++{
++    int i=0;
++
++    for(i=0;i<MAX_MCAST_ENTRY;i++) {
++      if( (mcast_tbl[i].vlan_id == vlan_id) &&
++          memcmp(mcast_tbl[i].src_mac,src_mac, 6)==0 &&
++          memcmp(mcast_tbl[i].dst_mac, dst_mac, 6)==0 &&
++              mcast_tbl[i].valid == 1) {
++          return i;
++      }
++    }
++    return -1;
++}
++
++int inline __add_mcast_entry(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac)
++{
++    int i=0;
++
++    // use empty or ageout entry
++    for(i=0;i<MAX_MCAST_ENTRY;i++) {
++      if( mcast_tbl[i].valid==0 ||
++              time_after(jiffies, mcast_tbl[i].ageout)) {
++
++          if(mcast_tbl[i].valid==0) {
++              atomic_inc(&mcast_entry_num);
++          }
++          mcast_tbl[i].vlan_id = vlan_id;
++          memcpy(mcast_tbl[i].src_mac, src_mac, 6);
++          memcpy(mcast_tbl[i].dst_mac, dst_mac, 6);
++          mcast_tbl[i].valid=1;
++          mcast_tbl[i].use_count=1;
++          mcast_tbl[i].ageout=jiffies + AGEING_TIME * HZ;
++         
++          return 1;
++      }
++    }
++
++    MCAST_PRINT("RAETH: Multicast Table is FULL!!\n");
++    return 0;
++}
++
++int inline mcast_entry_ins(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac) 
++{
++    int entry_num=0, ret=0;
++
++    down(&mtbl_lock);
++    if((entry_num = mcast_entry_get(vlan_id, src_mac, dst_mac)) >=0) {
++      mcast_tbl[entry_num].use_count++;
++      mcast_tbl[entry_num].ageout=jiffies + AGEING_TIME * HZ;
++      MCAST_PRINT("%s: Update %0X:%0X:%0X:%0X:%0X:%0X's use_count=%d\n" \
++              ,__FUNCTION__, MAC_ARG(dst_mac), mcast_tbl[entry_num].use_count);
++      ret = 1;
++    }else { //if entry not found, create new entry.
++      MCAST_PRINT("%s: Create new entry %0X:%0X:%0X:%0X:%0X:%0X\n", \
++              __FUNCTION__, MAC_ARG(dst_mac));
++      ret = __add_mcast_entry(vlan_id, src_mac,dst_mac);
++    }
++    
++    up(&mtbl_lock);
++    return ret;
++
++}
++
++
++/*
++ * Return:
++ *        0: entry found
++ *        1: entry not found
++ */
++int inline mcast_entry_del(uint16_t vlan_id, uint8_t *src_mac, uint8_t *dst_mac) 
++{
++    int entry_num;
++
++    down(&mtbl_lock);
++    if((entry_num = mcast_entry_get(vlan_id, src_mac, dst_mac)) >=0) {
++      if((--mcast_tbl[entry_num].use_count)==0) {
++          MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X (entry_num=%d)\n", \
++                  __FUNCTION__, MAC_ARG(dst_mac), entry_num);
++          mcast_tbl[entry_num].valid=0;
++          atomic_dec(&mcast_entry_num);
++      }
++      up(&mtbl_lock);
++      return 0;
++    }else { 
++      /* this multicast packet was not sent by meself, just ignore it */
++      up(&mtbl_lock);
++      return 1;
++    }
++}
++
++/* 
++ * Return
++ *        0: drop packet
++ *        1: continue
++ */
++int32_t mcast_rx(struct sk_buff * skb)
++{
++    struct vlan_ethhdr *eth = (struct vlan_ethhdr *)(skb->data-ETH_HLEN);
++
++    /* if we do not send multicast packet before, 
++     * we don't need to check re-inject multicast packet.
++     */
++    if (atomic_read(&mcast_entry_num)==0) {
++      return 1;
++    }
++
++
++    if(is_multicast_pkt(eth->h_dest)) {
++      MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X\n", __FUNCTION__, \
++              MAC_ARG(eth->h_dest));
++
++      if(ntohs(eth->h_vlan_proto)==0x8100) {
++          return mcast_entry_del(eth->h_vlan_TCI, eth->h_source, eth->h_dest);
++      } else {
++          return mcast_entry_del(0, eth->h_source, eth->h_dest);
++      }
++    }
++
++    return 1;
++}
++
++
++int32_t mcast_tx(struct sk_buff *skb)
++{
++    struct vlan_ethhdr *eth = (struct vlan_ethhdr *)(skb->data);
++
++
++    if(is_multicast_pkt(eth->h_dest)) {
++      MCAST_PRINT("%s: %0X:%0X:%0X:%0X:%0X:%0X\n", __FUNCTION__,\
++              MAC_ARG(eth->h_dest));
++
++      if(ntohs(eth->h_vlan_proto)==0x8100) {
++          mcast_entry_ins(eth->h_vlan_TCI, eth->h_source, eth->h_dest);
++      } else {
++          mcast_entry_ins(0, eth->h_source, eth->h_dest);
++      }
++    }
++
++    return 1;
++}
++
+diff --git a/drivers/net/ethernet/raeth/mii_mgr.c b/drivers/net/ethernet/raeth/mii_mgr.c
+new file mode 100644
+index 0000000..77a47f1
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/mii_mgr.c
+@@ -0,0 +1,603 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/netdevice.h>
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define PHY_CONTROL_0                 0xC0   
++#define PHY_CONTROL_1                 0xC4   
++#define MDIO_PHY_CONTROL_0    (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define MDIO_PHY_CONTROL_1    (RALINK_ETH_SW_BASE + PHY_CONTROL_1)
++
++#define GPIO_MDIO_BIT         (1<<7)
++#define GPIO_PURPOSE_SELECT   0x60
++#define GPIO_PRUPOSE          (RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT)
++
++#elif defined (CONFIG_RALINK_RT6855)  || defined (CONFIG_RALINK_RT6855A)
++
++#define PHY_CONTROL_0                 0x7004   
++#define MDIO_PHY_CONTROL_0    (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define enable_mdio(x)
++
++#elif defined (CONFIG_RALINK_MT7620)
++
++#define PHY_CONTROL_0                 0x7004   
++#define MDIO_PHY_CONTROL_0    (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define enable_mdio(x)
++
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#define PHY_CONTROL_0                 0x0004   
++#define MDIO_PHY_CONTROL_0    (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
++#define enable_mdio(x)
++
++#else 
++#define PHY_CONTROL_0         0x00
++#define PHY_CONTROL_1         0x04
++#define MDIO_PHY_CONTROL_0    (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_0)
++#define MDIO_PHY_CONTROL_1    (RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_1)
++#define enable_mdio(x)
++#endif
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++void enable_mdio(int enable)
++{
++#if !defined (CONFIG_P5_MAC_TO_PHY_MODE) && !defined(CONFIG_GE1_RGMII_AN) && !defined(CONFIG_GE2_RGMII_AN) && \
++    !defined (CONFIG_GE1_MII_AN) && !defined (CONFIG_GE2_MII_AN) && !defined (CONFIG_RALINK_MT7628)
++      u32 data = sysRegRead(GPIO_PRUPOSE);
++      if (enable)
++              data &= ~GPIO_MDIO_BIT;
++      else
++              data |= GPIO_MDIO_BIT;
++      sysRegWrite(GPIO_PRUPOSE, data);
++#endif
++}
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A)
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++      u32 volatile status = 0;
++      u32 rc = 0;
++      unsigned long volatile t_start = jiffies;
++      u32 volatile data = 0;
++
++      /* We enable mdio gpio purpose register, and disable it when exit. */
++      enable_mdio(1);
++
++      // make sure previous read operation is complete
++      while (1) {
++                      // 0 : Read/write operation complete
++              if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing !!\n");
++                      return rc;
++              }
++      }
++
++      data  = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++
++      // make sure read operation is complete
++      t_start = jiffies;
++      while (1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++                      status = sysRegRead(MDIO_PHY_CONTROL_0);
++                      *read_data = (u32)(status & 0x0000FFFF);
++
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start+5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing and Time Out!!\n");
++                      return 0;
++              }
++      }
++}
++
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++      unsigned long volatile t_start=jiffies;
++      u32 volatile data;
++
++      enable_mdio(1);
++
++      // make sure previous write operation is complete
++      while(1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation ongoing\n");
++                      return 0;
++              }
++      }
++
++      data = (0x01 << 16)| (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data;
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation
++      //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++      t_start = jiffies;
++
++      // make sure write operation is complete
++      while (1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++              {
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation Time Out\n");
++                      return 0;
++              }
++      }
++}
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT7623)
++
++u32 __mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++      u32 volatile status = 0;
++      u32 rc = 0;
++      unsigned long volatile t_start = jiffies;
++      u32 volatile data = 0;
++
++      /* We enable mdio gpio purpose register, and disable it when exit. */
++      enable_mdio(1);
++
++      // make sure previous read operation is complete
++      while (1) {
++                      // 0 : Read/write operation complete
++              if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing !!\n");
++                      return rc;
++              }
++      }
++
++      data  = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      //printk("\n Set Command [0x%08X] = [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0, data);
++
++
++      // make sure read operation is complete
++      t_start = jiffies;
++      while (1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++                      status = sysRegRead(MDIO_PHY_CONTROL_0);
++                      *read_data = (u32)(status & 0x0000FFFF);
++
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start+5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing and Time Out!!\n");
++                      return 0;
++              }
++      }
++}
++
++u32 __mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++      unsigned long volatile t_start=jiffies;
++      u32 volatile data;
++
++      enable_mdio(1);
++
++      // make sure previous write operation is complete
++      while(1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation ongoing\n");
++                      return 0;
++              }
++      }
++
++      data = (0x01 << 16)| (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data;
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation
++      //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++      t_start = jiffies;
++
++      // make sure write operation is complete
++      while (1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++              {
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation Time Out\n");
++                      return 0;
++              }
++      }
++}
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++        u32 low_word;
++        u32 high_word;
++        u32 an_status = 0;
++        
++      if(phy_addr==31) 
++      {
++              an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1<<31));
++              if(an_status){
++                      *(unsigned long *)(ESW_PHY_POLLING) &= ~(1<<31);//(AN polling off)
++              }
++              //phase1: write page address phase
++                if(__mii_mgr_write(phy_addr, 0x1f, ((phy_register >> 6) & 0x3FF))) {
++                        //phase2: write address & read low word phase
++                        if(__mii_mgr_read(phy_addr, (phy_register >> 2) & 0xF, &low_word)) {
++                                //phase3: write address & read high word phase
++                                if(__mii_mgr_read(phy_addr, (0x1 << 4), &high_word)) {
++                                        *read_data = (high_word << 16) | (low_word & 0xFFFF);
++                                      if(an_status){
++                                              *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++                                      }
++                                      return 1;
++                                }
++                        }
++                }
++              if(an_status){
++                      *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++              }
++        } else 
++#endif
++      {
++                if(__mii_mgr_read(phy_addr, phy_register, read_data)) {
++                        return 1;
++                }
++        }
++
++        return 0;
++}
++
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++      u32 an_status = 0;
++        
++      if(phy_addr == 31) 
++      {
++              an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1<<31));
++              if(an_status){
++                      *(unsigned long *)(ESW_PHY_POLLING) &= ~(1<<31);//(AN polling off)
++              }
++              //phase1: write page address phase
++                if(__mii_mgr_write(phy_addr, 0x1f, (phy_register >> 6) & 0x3FF)) {
++                        //phase2: write address & read low word phase
++                        if(__mii_mgr_write(phy_addr, ((phy_register >> 2) & 0xF), write_data & 0xFFFF)) {
++                                //phase3: write address & read high word phase
++                                if(__mii_mgr_write(phy_addr, (0x1 << 4), write_data >> 16)) {
++                                      if(an_status){
++                                              *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++                                      }
++                                  return 1;
++                                }
++                        }
++                }
++              if(an_status){
++                      *(unsigned long *)(ESW_PHY_POLLING) |= (1<<31);//(AN polling on)
++              }
++        } else 
++#endif
++      {
++                if(__mii_mgr_write(phy_addr, phy_register, write_data)) {
++                        return 1;
++                }
++        }
++
++        return 0;
++}
++
++u32 mii_mgr_cl45_set_address(u32 port_num, u32 dev_addr, u32 reg_addr)
++{
++      u32 rc = 0;
++      unsigned long volatile t_start = jiffies;
++      u32 volatile data = 0;
++
++      enable_mdio(1);
++
++      while (1) {
++              if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing !!\n");
++                      return rc;
++              }
++      }
++      data = (dev_addr << 25) | (port_num << 20) | (0x00 << 18) | (0x00 << 16) | reg_addr;
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++
++      t_start = jiffies;
++      while (1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++              {
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation Time Out\n");
++                      return 0;
++              }
++      }
++
++}
++
++
++u32 mii_mgr_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *read_data)
++{
++      u32 volatile status = 0;
++      u32 rc = 0;
++      unsigned long volatile t_start = jiffies;
++      u32 volatile data = 0;
++
++        // set address first
++      mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr);
++      //udelay(10);
++
++      enable_mdio(1);
++
++      while (1) {
++              if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing !!\n");
++                      return rc;
++              }
++      }
++      data = (dev_addr << 25) | (port_num << 20) | (0x03 << 18) | (0x00 << 16) | reg_addr;
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      t_start = jiffies;
++      while (1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++                      *read_data = (sysRegRead(MDIO_PHY_CONTROL_0) & 0x0000FFFF);
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start+5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n Set Operation: MDIO Read operation is ongoing and Time Out!!\n");
++                      return 0;
++              }
++              status = sysRegRead(MDIO_PHY_CONTROL_0);
++      }
++
++}
++
++u32 mii_mgr_write_cl45        (u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data)
++{
++      u32 rc = 0;
++      unsigned long volatile t_start = jiffies;
++      u32 volatile data = 0;
++
++      // set address first
++      mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr);
++      //udelay(10);
++
++      enable_mdio(1);
++      while (1) {
++              if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing !!\n");
++                      return rc;
++              }
++      }
++
++      data = (dev_addr << 25) | (port_num << 20) | (0x01 << 18) | (0x00 << 16) | write_data;
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++
++      t_start = jiffies;
++
++      while (1) {
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
++              {
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation Time Out\n");
++                      return 0;
++              }
++
++      }
++}
++
++#else // not rt6855
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
++{
++      u32 volatile status = 0;
++      u32 rc = 0;
++      unsigned long volatile t_start = jiffies;
++#if !defined (CONFIG_RALINK_RT3052) && !defined (CONFIG_RALINK_RT3352) && !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++      u32 volatile data = 0;
++#endif
++
++      /* We enable mdio gpio purpose register, and disable it when exit. */
++      enable_mdio(1);
++
++      // make sure previous read operation is complete
++      while (1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++              // rd_rdy: read operation is complete
++              if(!( sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1))) 
++#else
++                      // 0 : Read/write operation complet
++              if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
++#endif
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing !!\n");
++                      return rc;
++              }
++      }
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++      sysRegWrite(MDIO_PHY_CONTROL_0 , (1<<14) | (phy_register << 8) | (phy_addr));
++#else
++      data  = (phy_addr << 24) | (phy_register << 16);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++#endif
++      //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++
++      // make sure read operation is complete
++      t_start = jiffies;
++      while (1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++              if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1)) {
++                      status = sysRegRead(MDIO_PHY_CONTROL_1);
++                      *read_data = (u32)(status >>16);
++
++                      enable_mdio(0);
++                      return 1;
++              }
++#else
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
++                      status = sysRegRead(MDIO_PHY_CONTROL_0);
++                      *read_data = (u32)(status & 0x0000FFFF);
++
++                      enable_mdio(0);
++                      return 1;
++              }
++#endif
++              else if (time_after(jiffies, t_start+5*HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Read operation is ongoing and Time Out!!\n");
++                      return 0;
++              }
++      }
++}
++
++
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
++{
++      unsigned long volatile t_start=jiffies;
++      u32 volatile data;
++
++      enable_mdio(1);
++
++      // make sure previous write operation is complete
++      while(1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++              if (!(sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0)))
++#else
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
++#endif
++              {
++                      break;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation ongoing\n");
++                      return 0;
++              }
++      }
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++      data = ((write_data & 0xFFFF) << 16);
++      data |= (phy_register << 8) | (phy_addr);
++      data |= (1<<13);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++#else
++      data = (1<<30) | (phy_addr << 24) | (phy_register << 16) | write_data;
++      sysRegWrite(MDIO_PHY_CONTROL_0, data);
++      data |= (1<<31);
++      sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation
++#endif
++      //printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
++
++      t_start = jiffies;
++
++      // make sure write operation is complete
++      while (1) {
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++              if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0)) //wt_done ?= 1
++#else
++              if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
++#endif
++              {
++                      enable_mdio(0);
++                      return 1;
++              }
++              else if (time_after(jiffies, t_start + 5 * HZ)) {
++                      enable_mdio(0);
++                      printk("\n MDIO Write operation Time Out\n");
++                      return 0;
++              }
++      }
++}
++
++
++
++
++#endif
++
++
++
++
++EXPORT_SYMBOL(mii_mgr_write);
++EXPORT_SYMBOL(mii_mgr_read);
+diff --git a/drivers/net/ethernet/raeth/ra2882ethreg.h b/drivers/net/ethernet/raeth/ra2882ethreg.h
+new file mode 100644
+index 0000000..c67a042
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra2882ethreg.h
+@@ -0,0 +1,1985 @@
++#ifndef RA2882ETHREG_H
++#define RA2882ETHREG_H
++
++#include <linux/mii.h>                // for struct mii_if_info in ra2882ethreg.h
++#include <linux/version.h>    /* check linux version for 2.4 and 2.6 compatibility */
++#include <linux/interrupt.h>  /* for "struct tasklet_struct" in linux-3.10.14 */
++#if defined (CONFIG_HW_SFQ)
++#include <linux/ip.h>  
++#include <linux/ipv6.h>
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#endif
++#include "raether.h"
++
++#ifdef WORKQUEUE_BH
++#include <linux/workqueue.h>
++#endif // WORKQUEUE_BH //
++#ifdef CONFIG_RAETH_LRO
++#include <linux/inet_lro.h>
++#endif
++
++#define MAX_PACKET_SIZE       1514
++#define       MIN_PACKET_SIZE 60
++#define MAX_TXD_LEN 0x3fff
++
++#if defined (CONFIG_ARCH_MT7623)
++#define phys_to_bus(a) (a)
++#else
++#define phys_to_bus(a) (a & 0x1FFFFFFF)
++#endif
++
++
++
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++#define BIT(x)            ((1 << x))
++#endif
++/* bits range: for example BITS(16,23) = 0xFF0000
++ *   ==>  (BIT(m)-1)   = 0x0000FFFF     ~(BIT(m)-1)   => 0xFFFF0000
++ *   ==>  (BIT(n+1)-1) = 0x00FFFFFF
++ */
++#define BITS(m,n)   (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n)))
++
++#define ETHER_ADDR_LEN  6
++
++/*  Phy Vender ID list */
++
++#define EV_ICPLUS_PHY_ID0 0x0243  
++#define EV_ICPLUS_PHY_ID1 0x0D90  
++#define EV_MARVELL_PHY_ID0 0x0141  
++#define EV_MARVELL_PHY_ID1 0x0CC2  
++#define EV_VTSS_PHY_ID0 0x0007
++#define EV_VTSS_PHY_ID1 0x0421
++
++/*
++     FE_INT_STATUS
++*/
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || \
++    defined (CONFIG_ARCH_MT7623)
++
++#define RX_COHERENT      BIT(31)
++#define RX_DLY_INT       BIT(30)
++#define TX_COHERENT      BIT(29)
++#define TX_DLY_INT       BIT(28)
++#define RING3_RX_DLY_INT    BIT(27)
++#define RING2_RX_DLY_INT    BIT(26)
++#define RING1_RX_DLY_INT    BIT(25)
++
++#define ALT_RPLC_INT3    BIT(23)
++#define ALT_RPLC_INT2    BIT(22)
++#define ALT_RPLC_INT1    BIT(21)
++
++#define RX_DONE_INT3     BIT(19)
++#define RX_DONE_INT2     BIT(18)
++#define RX_DONE_INT1     BIT(17)
++#define RX_DONE_INT0     BIT(16)
++
++#define TX_DONE_INT3     BIT(3)
++#define TX_DONE_INT2     BIT(2)
++#define TX_DONE_INT1     BIT(1)
++#define TX_DONE_INT0     BIT(0)
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define RLS_COHERENT     BIT(29)
++#define RLS_DLY_INT      BIT(28)
++#define RLS_DONE_INT     BIT(0)
++#endif
++
++#else
++//#define CNT_PPE_AF       BIT(31)     
++//#define CNT_GDM_AF       BIT(29)
++#define PSE_P2_FC      BIT(26)
++#define GDM_CRC_DROP     BIT(25)
++#define PSE_BUF_DROP     BIT(24)
++#define GDM_OTHER_DROP         BIT(23)
++#define PSE_P1_FC        BIT(22)
++#define PSE_P0_FC        BIT(21)
++#define PSE_FQ_EMPTY     BIT(20)
++#define GE1_STA_CHG      BIT(18)
++#define TX_COHERENT      BIT(17)
++#define RX_COHERENT      BIT(16)
++
++#define TX_DONE_INT3     BIT(11)
++#define TX_DONE_INT2     BIT(10)
++#define TX_DONE_INT1     BIT(9)
++#define TX_DONE_INT0     BIT(8)
++#define RX_DONE_INT1     RX_DONE_INT0
++#define RX_DONE_INT0     BIT(2)
++#define TX_DLY_INT       BIT(1)
++#define RX_DLY_INT       BIT(0)
++#endif
++
++#define FE_INT_ALL            (TX_DONE_INT3 | TX_DONE_INT2 | \
++                               TX_DONE_INT1 | TX_DONE_INT0 | \
++                               RX_DONE_INT0 | RX_DONE_INT1 | \
++                               RX_DONE_INT2 | RX_DONE_INT3)
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define QFE_INT_ALL           (RLS_DONE_INT | RX_DONE_INT0 | RX_DONE_INT1)
++#define QFE_INT_DLY_INIT      (RLS_DLY_INT | RX_DLY_INT)
++
++#define NUM_QDMA_PAGE     512 
++#define QDMA_PAGE_SIZE      2048
++#endif
++/*
++ * SW_INT_STATUS
++ */
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define PORT0_QUEUE_FULL        BIT(14) //port0 queue full
++#define PORT1_QUEUE_FULL        BIT(15) //port1 queue full
++#define PORT2_QUEUE_FULL        BIT(16) //port2 queue full
++#define PORT3_QUEUE_FULL        BIT(17) //port3 queue full
++#define PORT4_QUEUE_FULL        BIT(18) //port4 queue full
++#define PORT5_QUEUE_FULL        BIT(19) //port5 queue full
++#define PORT6_QUEUE_FULL        BIT(20) //port6 queue full
++#define SHARED_QUEUE_FULL       BIT(23) //shared queue full
++#define QUEUE_EXHAUSTED         BIT(24) //global queue is used up and all packets are dropped
++#define BC_STROM                BIT(25) //the device is undergoing broadcast storm
++#define PORT_ST_CHG             BIT(26) //Port status change
++#define UNSECURED_ALERT         BIT(27) //Intruder alert
++#define ABNORMAL_ALERT          BIT(28) //Abnormal
++
++#define ESW_ISR                       (RALINK_ETH_SW_BASE + 0x00)
++#define ESW_IMR                       (RALINK_ETH_SW_BASE + 0x04)
++#define ESW_INT_ALL           (PORT_ST_CHG)
++
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++      defined (CONFIG_RALINK_MT7620)
++#define MIB_INT                 BIT(25)
++#define ACL_INT                       BIT(24)
++#define P5_LINK_CH            BIT(5)
++#define P4_LINK_CH            BIT(4)
++#define P3_LINK_CH            BIT(3)
++#define P2_LINK_CH            BIT(2)
++#define P1_LINK_CH            BIT(1)
++#define P0_LINK_CH            BIT(0)
++
++#define RX_GOCT_CNT           BIT(4)
++#define RX_GOOD_CNT           BIT(6)
++#define TX_GOCT_CNT           BIT(17)
++#define TX_GOOD_CNT           BIT(19)
++
++#define MSK_RX_GOCT_CNT               BIT(4)
++#define MSK_RX_GOOD_CNT               BIT(6)
++#define MSK_TX_GOCT_CNT               BIT(17)
++#define MSK_TX_GOOD_CNT               BIT(19)
++#define MSK_CNT_INT_ALL               (MSK_RX_GOCT_CNT | MSK_RX_GOOD_CNT | MSK_TX_GOCT_CNT | MSK_TX_GOOD_CNT) 
++//#define MSK_CNT_INT_ALL             (MSK_RX_GOOD_CNT | MSK_TX_GOOD_CNT) 
++
++
++#define ESW_IMR                       (RALINK_ETH_SW_BASE + 0x7000 + 0x8)
++#define ESW_ISR                       (RALINK_ETH_SW_BASE + 0x7000 + 0xC)
++#define ESW_INT_ALL           (P0_LINK_CH | P1_LINK_CH | P2_LINK_CH | P3_LINK_CH | P4_LINK_CH | P5_LINK_CH | ACL_INT | MIB_INT)
++#define ESW_AISR              (RALINK_ETH_SW_BASE + 0x8)
++#define ESW_P0_IntSn          (RALINK_ETH_SW_BASE + 0x4004)
++#define ESW_P1_IntSn          (RALINK_ETH_SW_BASE + 0x4104)
++#define ESW_P2_IntSn          (RALINK_ETH_SW_BASE + 0x4204)
++#define ESW_P3_IntSn          (RALINK_ETH_SW_BASE + 0x4304)
++#define ESW_P4_IntSn          (RALINK_ETH_SW_BASE + 0x4404)
++#define ESW_P5_IntSn          (RALINK_ETH_SW_BASE + 0x4504)
++#define ESW_P6_IntSn          (RALINK_ETH_SW_BASE + 0x4604)
++#define ESW_P0_IntMn          (RALINK_ETH_SW_BASE + 0x4008)
++#define ESW_P1_IntMn          (RALINK_ETH_SW_BASE + 0x4108)
++#define ESW_P2_IntMn          (RALINK_ETH_SW_BASE + 0x4208)
++#define ESW_P3_IntMn          (RALINK_ETH_SW_BASE + 0x4308)
++#define ESW_P4_IntMn          (RALINK_ETH_SW_BASE + 0x4408)
++#define ESW_P5_IntMn          (RALINK_ETH_SW_BASE + 0x4508)
++#define ESW_P6_IntMn          (RALINK_ETH_SW_BASE + 0x4608)
++
++#if defined (CONFIG_RALINK_MT7620) 
++#define ESW_P7_IntSn          (RALINK_ETH_SW_BASE + 0x4704)
++#define ESW_P7_IntMn          (RALINK_ETH_SW_BASE + 0x4708)
++#endif
++
++
++#define ESW_PHY_POLLING               (RALINK_ETH_SW_BASE + 0x7000)
++
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#define ESW_PHY_POLLING               (RALINK_ETH_SW_BASE + 0x0000)
++
++#define P5_LINK_CH            BIT(5)
++#define P4_LINK_CH            BIT(4)
++#define P3_LINK_CH            BIT(3)
++#define P2_LINK_CH            BIT(2)
++#define P1_LINK_CH            BIT(1)
++#define P0_LINK_CH            BIT(0)
++
++
++#endif // CONFIG_RALINK_RT3052 || CONFIG_RALINK_RT3352 || CONFIG_RALINK_RT5350 || defined (CONFIG_RALINK_MT7628)//
++
++#define RX_BUF_ALLOC_SIZE     2000
++#define FASTPATH_HEADROOM     64
++
++#define ETHER_BUFFER_ALIGN    32              ///// Align on a cache line
++
++#define ETHER_ALIGNED_RX_SKB_ADDR(addr) \
++        ((((unsigned long)(addr) + ETHER_BUFFER_ALIGN - 1) & \
++        ~(ETHER_BUFFER_ALIGN - 1)) - (unsigned long)(addr))
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++typedef struct _PSEUDO_ADAPTER {
++    struct net_device *RaethDev;
++    struct net_device *PseudoDev;
++    struct net_device_stats stat;
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++      struct mii_if_info      mii_info;
++#endif
++
++} PSEUDO_ADAPTER, PPSEUDO_ADAPTER;
++
++#define MAX_PSEUDO_ENTRY               1
++#endif
++
++
++
++/* Register Categories Definition */
++#define RAFRAMEENGINE_OFFSET  0x0000
++#define RAGDMA_OFFSET         0x0020
++#define RAPSE_OFFSET          0x0040
++#define RAGDMA2_OFFSET                0x0060
++#define RACDMA_OFFSET         0x0080
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || \
++    defined (CONFIG_ARCH_MT7623)
++
++#define RAPDMA_OFFSET         0x0800
++#define SDM_OFFSET            0x0C00
++#else
++#define RAPDMA_OFFSET         0x0100
++#endif
++#define RAPPE_OFFSET          0x0200
++#define RACMTABLE_OFFSET      0x0400
++#define RAPOLICYTABLE_OFFSET  0x1000
++
++
++/* Register Map Detail */
++/* RT3883 */
++#define SYSCFG1                       (RALINK_SYSCTL_BASE + 0x14)
++
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++
++/* 1. PDMA */
++#define TX_BASE_PTR0          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x000)
++#define TX_MAX_CNT0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x004)
++#define TX_CTX_IDX0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x008)
++#define TX_DTX_IDX0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x00C)
++
++#define TX_BASE_PTR1          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x010)
++#define TX_MAX_CNT1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x014)
++#define TX_CTX_IDX1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x018)
++#define TX_DTX_IDX1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x01C)
++
++#define TX_BASE_PTR2          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x020)
++#define TX_MAX_CNT2           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x024)
++#define TX_CTX_IDX2           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x028)
++#define TX_DTX_IDX2           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x02C)
++
++#define TX_BASE_PTR3          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x030)
++#define TX_MAX_CNT3           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x034)
++#define TX_CTX_IDX3           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x038)
++#define TX_DTX_IDX3           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x03C)
++
++#define RX_BASE_PTR0          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x100)
++#define RX_MAX_CNT0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x104)
++#define RX_CALC_IDX0          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x108)
++#define RX_DRX_IDX0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x10C)
++
++#define RX_BASE_PTR1          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x110)
++#define RX_MAX_CNT1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x114)
++#define RX_CALC_IDX1          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x118)
++#define RX_DRX_IDX1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x11C)
++
++#define PDMA_INFO             (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x200)
++#define PDMA_GLO_CFG          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x204)
++#define PDMA_RST_IDX          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x208)
++#define PDMA_RST_CFG          (PDMA_RST_IDX)
++#define DLY_INT_CFG           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x20C)
++#define FREEQ_THRES           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x210)
++#define INT_STATUS            (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x220)
++#define FE_INT_STATUS         (INT_STATUS)
++#define INT_MASK              (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x228)
++#define FE_INT_ENABLE         (INT_MASK)
++#define PDMA_WRR              (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x280)
++#define PDMA_SCH_CFG          (PDMA_WRR)
++
++#define SDM_CON                       (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x00)  //Switch DMA configuration
++#define SDM_RRING             (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x04)  //Switch DMA Rx Ring
++#define SDM_TRING             (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x08)  //Switch DMA Tx Ring
++#define SDM_MAC_ADRL          (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x0C)  //Switch MAC address LSB
++#define SDM_MAC_ADRH          (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x10)  //Switch MAC Address MSB
++#define SDM_TPCNT             (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x100) //Switch DMA Tx packet count
++#define SDM_TBCNT             (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x104) //Switch DMA Tx byte count
++#define SDM_RPCNT             (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x108) //Switch DMA rx packet count
++#define SDM_RBCNT             (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x10C) //Switch DMA rx byte count
++#define SDM_CS_ERR            (RALINK_FRAME_ENGINE_BASE+SDM_OFFSET+0x110) //Switch DMA rx checksum error count
++
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++      defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || \
++      defined (CONFIG_ARCH_MT7623)
++
++/* Old FE with New PDMA */
++#define PDMA_RELATED            0x0800
++/* 1. PDMA */
++#define TX_BASE_PTR0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x000)
++#define TX_MAX_CNT0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x004)
++#define TX_CTX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x008)
++#define TX_DTX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x00C)
++
++#define TX_BASE_PTR1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x010)
++#define TX_MAX_CNT1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x014)
++#define TX_CTX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x018)
++#define TX_DTX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x01C)
++
++#define TX_BASE_PTR2            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x020)
++#define TX_MAX_CNT2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x024)
++#define TX_CTX_IDX2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x028)
++#define TX_DTX_IDX2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x02C)
++
++#define TX_BASE_PTR3            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x030)
++#define TX_MAX_CNT3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x034)
++#define TX_CTX_IDX3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x038)
++#define TX_DTX_IDX3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x03C)
++
++#define RX_BASE_PTR0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x100)
++#define RX_MAX_CNT0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x104)
++#define RX_CALC_IDX0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x108)
++#define RX_DRX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x10C)
++
++#define RX_BASE_PTR1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x110)
++#define RX_MAX_CNT1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x114)
++#define RX_CALC_IDX1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x118)
++#define RX_DRX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x11C)
++
++#define RX_BASE_PTR2            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x120)
++#define RX_MAX_CNT2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x124)
++#define RX_CALC_IDX2            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x128)
++#define RX_DRX_IDX12            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x12C)
++
++#define RX_BASE_PTR3            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x130)
++#define RX_MAX_CNT3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x134)
++#define RX_CALC_IDX3            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x138)
++#define RX_DRX_IDX3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x13C)
++
++#define PDMA_INFO               (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x200)
++#define PDMA_GLO_CFG            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x204)
++#define PDMA_RST_IDX            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x208)
++#define PDMA_RST_CFG            (PDMA_RST_IDX)
++#define DLY_INT_CFG             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x20C)
++#define FREEQ_THRES             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x210)
++#define INT_STATUS              (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x220)
++#define FE_INT_STATUS         (INT_STATUS)
++#define INT_MASK                (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x228)
++#define FE_INT_ENABLE         (INT_MASK)
++#define SCH_Q01_CFG           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x280)
++#define SCH_Q23_CFG           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x284)
++
++#define FE_GLO_CFG          RALINK_FRAME_ENGINE_BASE + 0x00
++#define FE_RST_GL           RALINK_FRAME_ENGINE_BASE + 0x04
++#define FE_INT_STATUS2            RALINK_FRAME_ENGINE_BASE + 0x08
++#define FE_INT_ENABLE2            RALINK_FRAME_ENGINE_BASE + 0x0c
++//#define FC_DROP_STA         RALINK_FRAME_ENGINE_BASE + 0x18
++#define FOE_TS_T            RALINK_FRAME_ENGINE_BASE + 0x10
++
++#if defined (CONFIG_RALINK_MT7620)
++#define GDMA1_RELATED       0x0600
++#define GDMA1_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
++#define GDMA1_SHPR_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
++#define GDMA1_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
++#define GDMA1_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDMA1_RELATED       0x0500
++#define GDMA1_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
++#define GDMA1_SHPR_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
++#define GDMA1_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
++#define GDMA1_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
++
++#define GDMA2_RELATED       0x1500
++#define GDMA2_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00)
++#define GDMA2_SHPR_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04)
++#define GDMA2_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08)
++#define GDMA2_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C)
++#else
++#define GDMA1_RELATED       0x0020
++#define GDMA1_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
++#define GDMA1_SCH_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
++#define GDMA1_SHPR_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
++#define GDMA1_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
++#define GDMA1_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x10)
++
++#define GDMA2_RELATED       0x0060
++#define GDMA2_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00)
++#define GDMA2_SCH_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04)
++#define GDMA2_SHPR_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08)
++#define GDMA2_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C)
++#define GDMA2_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x10)
++#endif
++
++#if defined (CONFIG_RALINK_MT7620)
++#define PSE_RELATED         0x0500
++#define PSE_FQFC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00)
++#define PSE_IQ_CFG          (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04)
++#define PSE_QUE_STA         (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08)
++#else
++#define PSE_RELATED         0x0040
++#define PSE_FQ_CFG          (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00)
++#define CDMA_FC_CFG         (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04)
++#define GDMA1_FC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08)
++#define GDMA2_FC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x0C)
++#define CDMA_OQ_STA         (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x10)
++#define GDMA1_OQ_STA        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x14)
++#define GDMA2_OQ_STA        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x18)
++#define PSE_IQ_STA          (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x1C)
++#endif
++
++
++#if defined (CONFIG_RALINK_MT7620)
++#define CDMA_RELATED        0x0400
++#define CDMA_CSG_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
++#define SMACCR0                   (RALINK_ETH_SW_BASE + 0x3FE4)
++#define SMACCR1                   (RALINK_ETH_SW_BASE + 0x3FE8)
++#define CKGCR               (RALINK_ETH_SW_BASE + 0x3FF0)
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define CDMA_RELATED        0x0400
++#define CDMA_CSG_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00) //fake definition
++#define CDMP_IG_CTRL        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
++#define CDMP_EG_CTRL        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04)
++#else
++#define CDMA_RELATED        0x0080
++#define CDMA_CSG_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
++#define CDMA_SCH_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04)
++#define SMACCR0                   (RALINK_ETH_SW_BASE + 0x30E4)
++#define SMACCR1                   (RALINK_ETH_SW_BASE + 0x30E8)
++#define CKGCR               (RALINK_ETH_SW_BASE + 0x30F0)
++#endif
++
++#define PDMA_FC_CFG       (RALINK_FRAME_ENGINE_BASE+0x100)
++
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++/*kurtis: add QDMA define*/
++
++#define CLK_CFG_0             (RALINK_SYSCTL_BASE + 0x2C)
++#define PAD_RGMII2_MDIO_CFG     (RALINK_SYSCTL_BASE + 0x58)
++
++#define QDMA_RELATED            0x1800
++#define  QTX_CFG_0          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x000)
++#define  QTX_SCH_0          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x004)
++#define  QTX_HEAD_0         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x008)
++#define  QTX_TAIL_0         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x00C)
++#define  QTX_CFG_1          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x010)
++#define  QTX_SCH_1          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x014)
++#define  QTX_HEAD_1         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x018)
++#define  QTX_TAIL_1         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x01C)
++#define  QTX_CFG_2          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x020)
++#define  QTX_SCH_2          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x024)
++#define  QTX_HEAD_2         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x028)
++#define  QTX_TAIL_2         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x02C)
++#define  QTX_CFG_3          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x030)
++#define  QTX_SCH_3          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x034)
++#define  QTX_HEAD_3         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x038)
++#define  QTX_TAIL_3         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x03C)
++#define  QTX_CFG_4          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x040)
++#define  QTX_SCH_4          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x044)
++#define  QTX_HEAD_4         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x048)
++#define  QTX_TAIL_4         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x04C)
++#define  QTX_CFG_5          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x050)
++#define  QTX_SCH_5          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x054)
++#define  QTX_HEAD_5         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x058)
++#define  QTX_TAIL_5         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x05C)
++#define  QTX_CFG_6          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x060)
++#define  QTX_SCH_6          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x064)
++#define  QTX_HEAD_6         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x068)
++#define  QTX_TAIL_6         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x06C)
++#define  QTX_CFG_7          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x070)
++#define  QTX_SCH_7          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x074)
++#define  QTX_HEAD_7         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x078)
++#define  QTX_TAIL_7         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x07C)
++#define  QTX_CFG_8          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x080)
++#define  QTX_SCH_8          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x084)
++#define  QTX_HEAD_8         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x088)
++#define  QTX_TAIL_8         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x08C)
++#define  QTX_CFG_9          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x090)
++#define  QTX_SCH_9          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x094)
++#define  QTX_HEAD_9         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x098)
++#define  QTX_TAIL_9         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x09C)
++#define  QTX_CFG_10         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A0)
++#define  QTX_SCH_10         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A4)
++#define  QTX_HEAD_10        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0A8)
++#define  QTX_TAIL_10        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0AC)
++#define  QTX_CFG_11         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B0)
++#define  QTX_SCH_11         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B4)
++#define  QTX_HEAD_11        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0B8)
++#define  QTX_TAIL_11        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0BC)
++#define  QTX_CFG_12         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C0)
++#define  QTX_SCH_12         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C4)
++#define  QTX_HEAD_12        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0C8)
++#define  QTX_TAIL_12        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0CC)
++#define  QTX_CFG_13         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D0)
++#define  QTX_SCH_13         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D4)
++#define  QTX_HEAD_13        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0D8)
++#define  QTX_TAIL_13        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0DC)
++#define  QTX_CFG_14         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E0)
++#define  QTX_SCH_14         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E4)
++#define  QTX_HEAD_14        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0E8)
++#define  QTX_TAIL_14        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0EC)
++#define  QTX_CFG_15         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F0)
++#define  QTX_SCH_15         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F4)
++#define  QTX_HEAD_15        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0F8)
++#define  QTX_TAIL_15        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x0FC)
++#define  QRX_BASE_PTR_0     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x100)
++#define  QRX_MAX_CNT_0      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x104)
++#define  QRX_CRX_IDX_0      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x108)
++#define  QRX_DRX_IDX_0      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x10C)
++#define  QRX_BASE_PTR_1     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x110)
++#define  QRX_MAX_CNT_1      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x114)
++#define  QRX_CRX_IDX_1      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x118)
++#define  QRX_DRX_IDX_1      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x11C)
++#if defined (CONFIG_ARCH_MT7623)
++#define  VQTX_TB_BASE_0     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x180)
++#define  VQTX_TB_BASE_1     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x184)
++#define  VQTX_TB_BASE_2     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x188)
++#define  VQTX_TB_BASE_3     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x18C)
++#endif
++#define  QDMA_INFO          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x200)
++#define  QDMA_GLO_CFG       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x204)
++#define  QDMA_RST_IDX       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x208)
++#define  QDMA_RST_CFG       (QDMA_RST_IDX)
++#define  QDMA_DELAY_INT     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x20C)
++#define  QDMA_FC_THRES      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x210)
++#define  QDMA_TX_SCH        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x214)
++#define  QDMA_INT_STS       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x218)
++#define  QFE_INT_STATUS                 (QDMA_INT_STS)
++#define  QDMA_INT_MASK      (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x21C)
++#define  QFE_INT_ENABLE                 (QDMA_INT_MASK)
++#define  QDMA_TRTCM         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x220)
++#define  QDMA_DATA0         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x224)
++#define  QDMA_DATA1         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x228)
++#define  QDMA_RED_THRES     (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x22C)
++#define  QDMA_TEST          (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x230)
++#define  QDMA_DMA           (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x234)
++#define  QDMA_BMU           (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x238)
++#define  QDMA_HRED1         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x240)
++#define  QDMA_HRED2         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x244)
++#define  QDMA_SRED1         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x248)
++#define  QDMA_SRED2         (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x24C)
++#define  QTX_CTX_PTR        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x300)
++#define  QTX_DTX_PTR        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x304)
++#define  QTX_FWD_CNT        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x308)
++#define  QTX_CRX_PTR        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x310)
++#define  QTX_DRX_PTR        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x314)
++#define  QTX_RLS_CNT        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x318)
++#define  QDMA_FQ_HEAD       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x320)
++#define  QDMA_FQ_TAIL       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x324)
++#define  QDMA_FQ_CNT        (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x328)
++#define  QDMA_FQ_BLEN       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x32C)
++#define  QTX_Q0MIN_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x350)
++#define  QTX_Q1MIN_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x354)
++#define  QTX_Q2MIN_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x358)
++#define  QTX_Q3MIN_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x35C)
++#define  QTX_Q0MAX_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x360)
++#define  QTX_Q1MAX_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x364)
++#define  QTX_Q2MAX_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x368)
++#define  QTX_Q3MAX_BK       (RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + 0x36C)
++
++
++#endif/*MT7621 QDMA*/
++
++#else
++
++/* 1. Frame Engine Global Registers */
++#define MDIO_ACCESS           (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x00)
++#define MDIO_CFG              (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x04)
++#define FE_GLO_CFG            (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x08)
++#define FE_RST_GL             (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x0C)
++#define FE_INT_STATUS         (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x10)
++#define FE_INT_ENABLE         (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x14)
++#define MDIO_CFG2             (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x18) //Original:FC_DROP_STA
++#define FOC_TS_T              (RALINK_FRAME_ENGINE_BASE+RAFRAMEENGINE_OFFSET+0x1C)
++
++
++/* 2. GDMA Registers */
++#define       GDMA1_FWD_CFG           (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x00)
++#define GDMA1_SCH_CFG         (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x04)
++#define GDMA1_SHPR_CFG                (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x08)
++#define GDMA1_MAC_ADRL                (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x0C)
++#define GDMA1_MAC_ADRH                (RALINK_FRAME_ENGINE_BASE+RAGDMA_OFFSET+0x10)
++
++#define       GDMA2_FWD_CFG           (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x00)
++#define GDMA2_SCH_CFG         (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x04)
++#define GDMA2_SHPR_CFG                (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x08)
++#define GDMA2_MAC_ADRL                (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x0C)
++#define GDMA2_MAC_ADRH                (RALINK_FRAME_ENGINE_BASE+RAGDMA2_OFFSET+0x10)
++
++/* 3. PSE */
++#define PSE_FQ_CFG            (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x00)
++#define CDMA_FC_CFG           (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x04)
++#define GDMA1_FC_CFG          (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x08)
++#define GDMA2_FC_CFG          (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x0C)
++#define PDMA_FC_CFG           (RALINK_FRAME_ENGINE_BASE+0x1f0)
++
++/* 4. CDMA */
++#define CDMA_CSG_CFG          (RALINK_FRAME_ENGINE_BASE+RACDMA_OFFSET+0x00)
++#define CDMA_SCH_CFG          (RALINK_FRAME_ENGINE_BASE+RACDMA_OFFSET+0x04)
++/* skip ppoe sid and vlan id definition */
++
++
++/* 5. PDMA */
++#define PDMA_GLO_CFG          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x00)
++#define PDMA_RST_CFG          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x04)
++#define PDMA_SCH_CFG          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x08)
++
++#define DLY_INT_CFG           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x0C)
++
++#define TX_BASE_PTR0          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x10)
++#define TX_MAX_CNT0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x14)
++#define TX_CTX_IDX0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x18)
++#define TX_DTX_IDX0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x1C)
++
++#define TX_BASE_PTR1          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x20)
++#define TX_MAX_CNT1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x24)
++#define TX_CTX_IDX1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x28)
++#define TX_DTX_IDX1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x2C)
++
++#define TX_BASE_PTR2          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x40)
++#define TX_MAX_CNT2           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x44)
++#define TX_CTX_IDX2           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x48)
++#define TX_DTX_IDX2           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x4C)
++
++#define TX_BASE_PTR3          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x50)
++#define TX_MAX_CNT3           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x54)
++#define TX_CTX_IDX3           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x58)
++#define TX_DTX_IDX3           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x5C)
++
++#define RX_BASE_PTR0          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x30)
++#define RX_MAX_CNT0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x34)
++#define RX_CALC_IDX0          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x38)
++#define RX_DRX_IDX0           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x3C)
++
++#define RX_BASE_PTR1          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x40)
++#define RX_MAX_CNT1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x44)
++#define RX_CALC_IDX1          (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x48)
++#define RX_DRX_IDX1           (RALINK_FRAME_ENGINE_BASE+RAPDMA_OFFSET+0x4C)
++
++#endif
++
++#define DELAY_INT_INIT                0x84048404
++#define FE_INT_DLY_INIT               (TX_DLY_INT | RX_DLY_INT)
++
++
++#if !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++
++/* 6. Counter and Meter Table */
++#define PPE_AC_BCNT0          (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x000) /* PPE Accounting Group 0 Byte Cnt */
++#define PPE_AC_PCNT0          (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x004) /* PPE Accounting Group 0 Packet Cnt */
++/* 0 ~ 63 */
++
++#define PPE_MTR_CNT0          (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x200) /* 0 ~ 63 */
++/* skip... */
++#define PPE_MTR_CNT63         (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x2FC)
++
++#define GDMA_TX_GBCNT0                (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x300) /* Transmit good byte cnt for GEport */
++#define GDMA_TX_GPCNT0                (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x304) /* Transmit good pkt cnt for GEport */
++#define GDMA_TX_SKIPCNT0      (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x308) /* Transmit skip cnt for GEport */
++#define GDMA_TX_COLCNT0               (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x30C) /* Transmit collision cnt for GEport */
++
++/* update these address mapping to fit data sheet v0.26, by bobtseng, 2007.6.14 */
++#define GDMA_RX_GBCNT0                (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x320)
++#define GDMA_RX_GPCNT0                (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x324)
++#define GDMA_RX_OERCNT0               (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x328)
++#define GDMA_RX_FERCNT0       (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x32C)
++#define GDMA_RX_SERCNT0               (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x330)
++#define GDMA_RX_LERCNT0               (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x334)
++#define GDMA_RX_CERCNT0               (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x338)
++#define GDMA_RX_FCCNT1                (RALINK_FRAME_ENGINE_BASE+RACMTABLE_OFFSET+0x33C)
++
++#endif
++
++/* LRO global control */ 
++/* Bits [15:0]:LRO_ALT_RFSH_TIMER, Bits [20:16]:LRO_ALT_TICK_TIMER */
++#define LRO_ALT_REFRESH_TIMER   (RALINK_FRAME_ENGINE_BASE+0x001C)
++
++/* LRO auto-learn table info */
++#define PDMA_FE_ALT_CF8               (RALINK_FRAME_ENGINE_BASE+0x0300)
++#define PDMA_FE_ALT_SGL_CFC   (RALINK_FRAME_ENGINE_BASE+0x0304)
++#define PDMA_FE_ALT_SEQ_CFC   (RALINK_FRAME_ENGINE_BASE+0x0308)
++
++/* LRO controls */
++#define ADMA_LRO_CTRL_OFFSET    0x0980
++/* 
++ * Bit [0]:LRO_EN, Bit [1]:LRO_IPv6_EN, Bit [2]:MULTIPLE_NON_LRO_RX_RING_EN, Bit [3]:MULTIPLE_RXD_PREFETCH_EN,
++ * Bit [4]:RXD_PREFETCH_EN, Bit [5]:LRO_DLY_INT_EN, Bit [6]:LRO_CRSN_BNW, Bit [7]:L3_CKS_UPD_EN, 
++ * Bit [20]:first_ineligible_pkt_redirect_en, Bit [21]:cr_lro_alt_score_mode, Bit [22]:cr_lro_alt_rplc_mode,
++ * Bit [23]:cr_lro_l4_ctrl_psh_en, Bits [28:26]:LRO_RING_RELINGUISH_REQ, Bits [31:29]:LRO_RING_RELINGUISH_DONE
++ */
++#define ADMA_LRO_CTRL_DW0             (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x00)
++/* Bits [31:0]:LRO_CPU_REASON */
++#define ADMA_LRO_CTRL_DW1             (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x04)
++/* Bits [31:0]:AUTO_LEARN_LRO_ELIGIBLE_THRESHOLD */
++#define ADMA_LRO_CTRL_DW2             (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x08)
++/* 
++ * Bits [7:0]:LRO_MAX_AGGREGATED_CNT, Bits [11:8]:LRO_VLAN_EN, Bits [13:12]:LRO_VLAN_VID_CMP_DEPTH,
++ * Bit [14]:ADMA_FW_RSTN_REQ, Bit [15]:ADMA_MODE, Bits [31:16]:LRO_MIN_RXD_SDL0
++ */
++#define ADMA_LRO_CTRL_DW3       (RALINK_FRAME_ENGINE_BASE+ADMA_LRO_CTRL_OFFSET+0x0C)
++
++/* LRO RX delay interrupt configurations */
++#define LRO_RX1_DLY_INT        (RALINK_FRAME_ENGINE_BASE+0x0a70)
++#define LRO_RX2_DLY_INT        (RALINK_FRAME_ENGINE_BASE+0x0a74)
++#define LRO_RX3_DLY_INT        (RALINK_FRAME_ENGINE_BASE+0x0a78)
++
++/* LRO auto-learn configurations */
++#define PDMA_LRO_ATL_OVERFLOW_ADJ_OFFSET    0x0990
++#define PDMA_LRO_ATL_OVERFLOW_ADJ   (RALINK_FRAME_ENGINE_BASE+PDMA_LRO_ATL_OVERFLOW_ADJ_OFFSET)
++#define LRO_ALT_SCORE_DELTA   (RALINK_FRAME_ENGINE_BASE+0x0a4c)
++
++/* LRO agg timer configurations */
++#define LRO_MAX_AGG_TIME       (RALINK_FRAME_ENGINE_BASE+0x0a5c)
++
++/* LRO configurations of RX ring #0 */
++#define LRO_RXRING0_OFFSET          0x0b00
++#define LRO_RX_RING0_DIP_DW0          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x04)
++#define LRO_RX_RING0_DIP_DW1          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x08)
++#define LRO_RX_RING0_DIP_DW2          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x0C)
++#define LRO_RX_RING0_DIP_DW3          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x10)
++#define LRO_RX_RING0_CTRL_DW1         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x28)
++/* Bit [8]:RING0_VLD, Bit [9]:RING0_MYIP_VLD */
++#define LRO_RX_RING0_CTRL_DW2         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x2C)
++#define LRO_RX_RING0_CTRL_DW3         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING0_OFFSET+0x30)
++/* LRO configurations of RX ring #1 */
++#define LRO_RXRING1_OFFSET          0x0b40
++#define LRO_RX_RING1_STP_DTP_DW               (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x00)
++#define LRO_RX_RING1_DIP_DW0          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x04)
++#define LRO_RX_RING1_DIP_DW1          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x08)
++#define LRO_RX_RING1_DIP_DW2          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x0C)
++#define LRO_RX_RING1_DIP_DW3          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x10)
++#define LRO_RX_RING1_SIP_DW0          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x14)
++#define LRO_RX_RING1_SIP_DW1          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x18)
++#define LRO_RX_RING1_SIP_DW2          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x1C)
++#define LRO_RX_RING1_SIP_DW3          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x20)
++#define LRO_RX_RING1_CTRL_DW0         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x24)
++#define LRO_RX_RING1_CTRL_DW1         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x28)
++#define LRO_RX_RING1_CTRL_DW2         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x2C)
++#define LRO_RX_RING1_CTRL_DW3         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING1_OFFSET+0x30)
++#define LRO_RXRING2_OFFSET          0x0b80
++#define LRO_RX_RING2_STP_DTP_DW               (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x00)
++#define LRO_RX_RING2_DIP_DW0          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x04)
++#define LRO_RX_RING2_DIP_DW1          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x08)
++#define LRO_RX_RING2_DIP_DW2          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x0C)
++#define LRO_RX_RING2_DIP_DW3          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x10)
++#define LRO_RX_RING2_SIP_DW0          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x14)
++#define LRO_RX_RING2_SIP_DW1          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x18)
++#define LRO_RX_RING2_SIP_DW2          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x1C)
++#define LRO_RX_RING2_SIP_DW3          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x20)
++#define LRO_RX_RING2_CTRL_DW0         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x24)
++#define LRO_RX_RING2_CTRL_DW1         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x28)
++#define LRO_RX_RING2_CTRL_DW2         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x2C)
++#define LRO_RX_RING2_CTRL_DW3         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING2_OFFSET+0x30)
++#define LRO_RXRING3_OFFSET          0x0bc0
++#define LRO_RX_RING3_STP_DTP_DW               (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x00)
++#define LRO_RX_RING3_DIP_DW0          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x04)
++#define LRO_RX_RING3_DIP_DW1          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x08)
++#define LRO_RX_RING3_DIP_DW2          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x0C)
++#define LRO_RX_RING3_DIP_DW3          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x10)
++#define LRO_RX_RING3_SIP_DW0          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x14)
++#define LRO_RX_RING3_SIP_DW1          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x18)
++#define LRO_RX_RING3_SIP_DW2          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x1C)
++#define LRO_RX_RING3_SIP_DW3          (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x20)
++#define LRO_RX_RING3_CTRL_DW0         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x24)
++#define LRO_RX_RING3_CTRL_DW1         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x28)
++#define LRO_RX_RING3_CTRL_DW2         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x2C)
++#define LRO_RX_RING3_CTRL_DW3         (RALINK_FRAME_ENGINE_BASE+LRO_RXRING3_OFFSET+0x30)
++
++/* LRO RX ring mode */
++#define PDMA_RX_NORMAL_MODE         (0x0)
++#define PDMA_RX_PSE_MODE            (0x1)
++#define PDMA_RX_FORCE_PORT          (0x2)
++#define PDMA_RX_AUTO_LEARN          (0x3)
++
++#define ADMA_RX_RING0   (0)
++#define ADMA_RX_RING1   (1)
++#define ADMA_RX_RING2   (2)
++#define ADMA_RX_RING3   (3)
++
++#define ADMA_RX_LEN0_MASK   (0x3fff)
++#define ADMA_RX_LEN1_MASK   (0x3)
++
++#define PDMA_LRO_EN             BIT(0)
++#define PDMA_LRO_IPV6_EN        BIT(1)
++#define PDMA_LRO_IPV4_CSUM_UPDATE_EN    BIT(7)
++#define PDMA_LRO_IPV4_CTRL_PUSH_EN    BIT(23)
++#define PDMA_LRO_RXD_PREFETCH_EN        BITS(3,4)
++#define PDMA_NON_LRO_MULTI_EN   BIT(2)
++#define PDMA_LRO_DLY_INT_EN             BIT(5)
++#define PDMA_LRO_FUSH_REQ               BITS(26,28)
++#define PDMA_LRO_RELINGUISH     BITS(29,31)
++#define PDMA_LRO_FREQ_PRI_ADJ   BITS(16,19)
++#define PDMA_LRO_TPUT_PRE_ADJ           BITS(8,11)
++#define PDMA_LRO_TPUT_PRI_ADJ           BITS(12,15)
++#define PDMA_LRO_ALT_SCORE_MODE         BIT(21)
++#define PDMA_LRO_RING_AGE1      BITS(22,31)
++#define PDMA_LRO_RING_AGE2      BITS(0,5)
++#define PDMA_LRO_RING_AGG               BITS(10,25)
++#define PDMA_LRO_RING_AGG_CNT1          BITS(26,31)
++#define PDMA_LRO_RING_AGG_CNT2          BITS(0,1)
++#define PDMA_LRO_ALT_TICK_TIMER         BITS(16,20)
++#define PDMA_LRO_LRO_MIN_RXD_SDL0       BITS(16,31)
++
++#define PDMA_LRO_DLY_INT_EN_OFFSET          (5)
++#define PDMA_LRO_TPUT_PRE_ADJ_OFFSET        (8)
++#define PDMA_LRO_FREQ_PRI_ADJ_OFFSET    (16)
++#define PDMA_LRO_LRO_MIN_RXD_SDL0_OFFSET    (16)
++#define PDMA_LRO_TPUT_PRI_ADJ_OFFSET        (12)
++#define PDMA_LRO_ALT_SCORE_MODE_OFFSET      (21)
++#define PDMA_LRO_FUSH_REQ_OFFSET            (26)
++#define PDMA_NON_LRO_MULTI_EN_OFFSET        (2)
++#define PDMA_LRO_IPV6_EN_OFFSET             (1)
++#define PDMA_LRO_RXD_PREFETCH_EN_OFFSET     (3)
++#define PDMA_LRO_IPV4_CSUM_UPDATE_EN_OFFSET (7)
++#define PDMA_LRO_IPV4_CTRL_PUSH_EN_OFFSET   (23)
++#define PDMA_LRO_ALT_TICK_TIMER_OFFSET      (16)
++
++#define PDMA_LRO_TPUT_OVERFLOW_ADJ  BITS(12,31)
++#define PDMA_LRO_CNT_OVERFLOW_ADJ   BITS(0,11)
++
++#define PDMA_LRO_TPUT_OVERFLOW_ADJ_OFFSET   (12)
++#define PDMA_LRO_CNT_OVERFLOW_ADJ_OFFSET    (0)
++
++#define PDMA_LRO_ALT_BYTE_CNT_MODE  (0)
++#define PDMA_LRO_ALT_PKT_CNT_MODE   (1)
++
++/* LRO_RX_RING1_CTRL_DW1 offsets  */
++#define PDMA_LRO_AGE_H_OFFSET           (10)
++#define PDMA_LRO_RING_AGE1_OFFSET       (22)
++#define PDMA_LRO_RING_AGG_CNT1_OFFSET   (26)
++/* LRO_RX_RING1_CTRL_DW2 offsets  */
++#define PDMA_RX_MODE_OFFSET             (6)
++#define PDMA_RX_PORT_VALID_OFFSET       (8)
++#define PDMA_RX_MYIP_VALID_OFFSET       (9)
++#define PDMA_LRO_RING_AGE2_OFFSET       (0)
++#define PDMA_LRO_RING_AGG_OFFSET        (10)
++#define PDMA_LRO_RING_AGG_CNT2_OFFSET   (0)
++/* LRO_RX_RING1_CTRL_DW3 offsets  */
++#define PDMA_LRO_AGG_CNT_H_OFFSET       (6)
++/* LRO_RX_RING1_STP_DTP_DW offsets */
++#define PDMA_RX_TCP_SRC_PORT_OFFSET     (16)
++#define PDMA_RX_TCP_DEST_PORT_OFFSET    (0)
++/* LRO_RX_RING1_CTRL_DW0 offsets */
++#define PDMA_RX_IPV4_FORCE_OFFSET       (1)
++#define PDMA_RX_IPV6_FORCE_OFFSET       (0)
++
++#define SET_ADMA_RX_LEN0(x)    ((x)&ADMA_RX_LEN0_MASK)
++#define SET_ADMA_RX_LEN1(x)    ((x)&ADMA_RX_LEN1_MASK)
++
++#define SET_PDMA_LRO_MAX_AGG_CNT(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW3; \
++        *addr &= ~0xff;   \
++        *addr |= ((x) & 0xff);  \
++    }
++#define SET_PDMA_LRO_FLUSH_REQ(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_FUSH_REQ;   \
++        *addr |= ((x) & 0x7)<<PDMA_LRO_FUSH_REQ_OFFSET;  \
++    }
++#define SET_PDMA_LRO_IPV6_EN(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_IPV6_EN;   \
++        *addr |= ((x) & 0x1)<<PDMA_LRO_IPV6_EN_OFFSET;  \
++    }
++#if defined(CONFIG_RAETH_HW_LRO_PREFETCH)
++#define SET_PDMA_LRO_RXD_PREFETCH_EN(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_RXD_PREFETCH_EN;   \
++        *addr |= ((x) & 0x3)<<PDMA_LRO_RXD_PREFETCH_EN_OFFSET;  \
++    }
++#else
++#define SET_PDMA_LRO_RXD_PREFETCH_EN(x)
++#endif
++#define SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_IPV4_CSUM_UPDATE_EN;   \
++        *addr |= ((x) & 0x1)<<PDMA_LRO_IPV4_CSUM_UPDATE_EN_OFFSET;  \
++    }
++#define SET_PDMA_LRO_IPV4_CTRL_PUSH_EN(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_IPV4_CTRL_PUSH_EN;   \
++        *addr |= ((x) & 0x1)<<PDMA_LRO_IPV4_CTRL_PUSH_EN_OFFSET;  \
++    }
++#define SET_PDMA_NON_LRO_MULTI_EN(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~(PDMA_NON_LRO_MULTI_EN);   \
++        *addr |= ((x) & 0x1)<<PDMA_NON_LRO_MULTI_EN_OFFSET;  \
++    }
++#define SET_PDMA_LRO_FREQ_PRI_ADJ(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_FREQ_PRI_ADJ;   \
++        *addr |= ((x) & 0xf)<<PDMA_LRO_FREQ_PRI_ADJ_OFFSET;  \
++    }
++#define SET_PDMA_LRO_TPUT_PRE_ADJ(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_TPUT_PRE_ADJ;   \
++        *addr |= ((x) & 0xf)<<PDMA_LRO_TPUT_PRE_ADJ_OFFSET;  \
++    }
++#define SET_PDMA_LRO_TPUT_PRI_ADJ(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_TPUT_PRI_ADJ;   \
++        *addr |= ((x) & 0xf)<<PDMA_LRO_TPUT_PRI_ADJ_OFFSET;  \
++    }
++#define SET_PDMA_LRO_ALT_SCORE_MODE(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_ALT_SCORE_MODE;   \
++        *addr |= ((x) & 0x1)<<PDMA_LRO_ALT_SCORE_MODE_OFFSET;  \
++    }
++#define SET_PDMA_LRO_DLY_INT_EN(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW0; \
++        *addr &= ~PDMA_LRO_DLY_INT_EN;   \
++        *addr |= ((x) & 0x1)<<PDMA_LRO_DLY_INT_EN_OFFSET;  \
++    }
++#define SET_PDMA_LRO_BW_THRESHOLD(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW2; \
++        *addr = (x);  \
++    }
++#define SET_PDMA_LRO_MIN_RXD_SDL(x) \
++    { volatile unsigned int *addr = (unsigned int*)ADMA_LRO_CTRL_DW3; \
++        *addr &= ~PDMA_LRO_LRO_MIN_RXD_SDL0;   \
++        *addr |= ((x) & 0xffff)<<PDMA_LRO_LRO_MIN_RXD_SDL0_OFFSET;  \
++    }
++#define SET_PDMA_LRO_TPUT_OVERFLOW_ADJ(x) \
++    { volatile unsigned int *addr = (unsigned int*)PDMA_LRO_ATL_OVERFLOW_ADJ; \
++        *addr &= ~PDMA_LRO_TPUT_OVERFLOW_ADJ;   \
++        *addr |= ((x) & 0xfffff)<<PDMA_LRO_TPUT_OVERFLOW_ADJ_OFFSET;  \
++    }
++#define SET_PDMA_LRO_CNT_OVERFLOW_ADJ(x) \
++    { volatile unsigned int *addr = (unsigned int*)PDMA_LRO_ATL_OVERFLOW_ADJ; \
++        *addr &= ~PDMA_LRO_CNT_OVERFLOW_ADJ;   \
++        *addr |= ((x) & 0xfff)<<PDMA_LRO_CNT_OVERFLOW_ADJ_OFFSET;  \
++    }
++#define SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(x) \
++    { volatile unsigned int *addr = (unsigned int*)LRO_ALT_REFRESH_TIMER; \
++        *addr &= ~PDMA_LRO_ALT_TICK_TIMER;   \
++        *addr |= ((x) & 0x1f)<<PDMA_LRO_ALT_TICK_TIMER_OFFSET;  \
++    }
++#define SET_PDMA_LRO_ALT_REFRESH_TIMER(x) \
++    { volatile unsigned int *addr = (unsigned int*)LRO_ALT_REFRESH_TIMER; \
++        *addr &= ~0xffff;   \
++        *addr |= ((x) & 0xffff);  \
++    }
++#define SET_PDMA_LRO_MAX_AGG_TIME(x) \
++    { volatile unsigned int *addr = (unsigned int*)LRO_MAX_AGG_TIME; \
++        *addr &= ~0xffff;   \
++        *addr |= ((x) & 0xffff);  \
++    }
++#define SET_PDMA_RXRING_MODE(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++        *addr &= ~(0x3<<PDMA_RX_MODE_OFFSET);   \
++        *addr |= (y)<<PDMA_RX_MODE_OFFSET;  \
++    }
++#define SET_PDMA_RXRING_MYIP_VALID(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++        *addr &= ~(0x1<<PDMA_RX_MYIP_VALID_OFFSET); \
++        *addr |= ((y)&0x1)<<PDMA_RX_MYIP_VALID_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_VALID(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++        *addr &= ~(0x1<<PDMA_RX_PORT_VALID_OFFSET); \
++        *addr |= ((y)&0x1)<<PDMA_RX_PORT_VALID_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_TCP_SRC_PORT(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_STP_DTP_DW + (((x)-1) << 6)); \
++        *addr &= ~(0xffff<<PDMA_RX_TCP_SRC_PORT_OFFSET);    \
++        *addr |= (y)<<PDMA_RX_TCP_SRC_PORT_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_TCP_DEST_PORT(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_STP_DTP_DW + (((x)-1) << 6)); \
++        *addr &= ~(0xffff<<PDMA_RX_TCP_DEST_PORT_OFFSET);    \
++        *addr |= (y)<<PDMA_RX_TCP_DEST_PORT_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_IPV4_FORCE_MODE(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_CTRL_DW0 + (((x)-1) << 6)); \
++        *addr &= ~(0x1<<PDMA_RX_IPV4_FORCE_OFFSET);    \
++        *addr |= (y)<<PDMA_RX_IPV4_FORCE_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_IPV6_FORCE_MODE(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING1_CTRL_DW0 + (((x)-1) << 6)); \
++        *addr &= ~(0x1<<PDMA_RX_IPV6_FORCE_OFFSET);    \
++        *addr |= (y)<<PDMA_RX_IPV6_FORCE_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_AGE_TIME(x,y) \
++    { volatile unsigned int *addr1 = (unsigned int*)(LRO_RX_RING0_CTRL_DW1 + ((x) << 6)); \
++      volatile unsigned int *addr2 = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++        *addr1 &= ~PDMA_LRO_RING_AGE1;    \
++        *addr2 &= ~PDMA_LRO_RING_AGE2;    \
++        *addr1 |= ((y) & 0x3ff)<<PDMA_LRO_RING_AGE1_OFFSET;    \
++        *addr2 |= (((y)>>PDMA_LRO_AGE_H_OFFSET) & 0x03f)<<PDMA_LRO_RING_AGE2_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_AGG_TIME(x,y) \
++    { volatile unsigned int *addr = (unsigned int*)(LRO_RX_RING0_CTRL_DW2 + ((x) << 6)); \
++        *addr &= ~PDMA_LRO_RING_AGG;    \
++        *addr |= ((y) & 0xffff)<<PDMA_LRO_RING_AGG_OFFSET;    \
++    }
++#define SET_PDMA_RXRING_MAX_AGG_CNT(x,y) \
++    { volatile unsigned int *addr1 = (unsigned int*)(LRO_RX_RING1_CTRL_DW2 + (((x)-1) << 6)); \
++      volatile unsigned int *addr2 = (unsigned int*)(LRO_RX_RING1_CTRL_DW3 + (((x)-1) << 6)); \
++        *addr1 &= ~PDMA_LRO_RING_AGG_CNT1;    \
++        *addr2 &= ~PDMA_LRO_RING_AGG_CNT2;    \
++        *addr1 |= ((y) & 0x3f)<<PDMA_LRO_RING_AGG_CNT1_OFFSET;    \
++        *addr2 |= (((y)>>PDMA_LRO_AGG_CNT_H_OFFSET) & 0x03)<<PDMA_LRO_RING_AGG_CNT2_OFFSET;    \
++    }
++
++typedef struct _PDMA_LRO_AUTO_TLB_INFO0_    PDMA_LRO_AUTO_TLB_INFO0_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO1_    PDMA_LRO_AUTO_TLB_INFO1_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO2_    PDMA_LRO_AUTO_TLB_INFO2_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO3_    PDMA_LRO_AUTO_TLB_INFO3_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO4_    PDMA_LRO_AUTO_TLB_INFO4_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO5_    PDMA_LRO_AUTO_TLB_INFO5_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO6_    PDMA_LRO_AUTO_TLB_INFO6_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO7_    PDMA_LRO_AUTO_TLB_INFO7_T;
++typedef struct _PDMA_LRO_AUTO_TLB_INFO8_    PDMA_LRO_AUTO_TLB_INFO8_T;
++
++struct _PDMA_LRO_AUTO_TLB_INFO0_
++{
++    unsigned int    DTP         : 16;
++    unsigned int    STP         : 16;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO1_
++{
++    unsigned int    SIP0        : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO2_
++{
++    unsigned int    SIP1        : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO3_
++{
++    unsigned int    SIP2        : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO4_
++{
++    unsigned int    SIP3        : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO5_
++{
++    unsigned int    VLAN_VID0   : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO6_
++{
++    unsigned int    VLAN_VID1       : 16;
++    unsigned int    VLAN_VID_VLD    : 4;
++    unsigned int    CNT             : 12;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO7_
++{
++    unsigned int    DW_LEN          : 32;
++};
++struct _PDMA_LRO_AUTO_TLB_INFO8_
++{
++    unsigned int    DIP_ID          : 2;
++    unsigned int    IPV6            : 1;
++    unsigned int    IPV4            : 1;
++    unsigned int    RESV            : 27;
++    unsigned int    VALID           : 1;
++};
++struct PDMA_LRO_AUTO_TLB_INFO {
++      PDMA_LRO_AUTO_TLB_INFO0_T auto_tlb_info0;
++      PDMA_LRO_AUTO_TLB_INFO1_T auto_tlb_info1;
++      PDMA_LRO_AUTO_TLB_INFO2_T auto_tlb_info2;
++      PDMA_LRO_AUTO_TLB_INFO3_T auto_tlb_info3;
++    PDMA_LRO_AUTO_TLB_INFO4_T auto_tlb_info4;
++    PDMA_LRO_AUTO_TLB_INFO5_T auto_tlb_info5;
++    PDMA_LRO_AUTO_TLB_INFO6_T auto_tlb_info6;
++    PDMA_LRO_AUTO_TLB_INFO7_T auto_tlb_info7;
++    PDMA_LRO_AUTO_TLB_INFO8_T auto_tlb_info8;
++};
++
++#if defined (CONFIG_HW_SFQ)
++#define VQTX_TB_BASE0 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1980)
++#define VQTX_TB_BASE1 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1984)
++#define VQTX_TB_BASE2 (ETHDMASYS_FRAME_ENGINE_BASE + 0x1988)
++#define VQTX_TB_BASE3 (ETHDMASYS_FRAME_ENGINE_BASE + 0x198C)
++#define SFQ_OFFSET 0x1A80
++#define VQTX_GLO (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET)
++#define VQTX_INVLD_PTR (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x0C)
++#define VQTX_NUM (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x10)
++#define VQTX_SCH (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x18)
++#define VQTX_HASH_CFG (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x20)
++#define VQTX_HASH_SD (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x24)
++#define VQTX_VLD_CFG (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x30)
++#define VQTX_MIB_IF (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x3C)
++#define VQTX_MIB_PCNT (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x40)
++#define VQTX_MIB_BCNT0 (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x44)
++#define VQTX_MIB_BCNT1 (ETHDMASYS_FRAME_ENGINE_BASE + SFQ_OFFSET + 0x48)
++
++#define VQTX_MIB_EN (1<<17) 
++#define VQTX_NUM_0  (4<<0)
++#define VQTX_NUM_1  (4<<4)
++#define VQTX_NUM_2  (4<<8)
++#define VQTX_NUM_3  (4<<12)
++
++/*=========================================
++      SFQ Table Format define
++=========================================*/
++typedef struct _SFQ_INFO1_  SFQ_INFO1_T;
++
++struct _SFQ_INFO1_
++{
++    unsigned int    VQHPTR;
++};
++//-------------------------------------------------
++typedef struct _SFQ_INFO2_    SFQ_INFO2_T;
++
++struct _SFQ_INFO2_
++{
++    unsigned int    VQTPTR;
++};
++//-------------------------------------------------
++typedef struct _SFQ_INFO3_  SFQ_INFO3_T;
++
++struct _SFQ_INFO3_
++{
++    unsigned int    QUE_DEPTH:16;
++    unsigned int    DEFICIT_CNT:16;
++};
++//-------------------------------------------------
++typedef struct _SFQ_INFO4_    SFQ_INFO4_T;
++
++struct _SFQ_INFO4_
++{
++      unsigned int    RESV; 
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO5_    SFQ_INFO5_T;
++
++struct _SFQ_INFO5_
++{
++      unsigned int    PKT_CNT; 
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO6_    SFQ_INFO6_T;
++
++struct _SFQ_INFO6_
++{
++      unsigned int    BYTE_CNT; 
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO7_    SFQ_INFO7_T;
++
++struct _SFQ_INFO7_
++{
++      unsigned int    BYTE_CNT; 
++};
++//-------------------------------------------------
++
++typedef struct _SFQ_INFO8_    SFQ_INFO8_T;
++
++struct _SFQ_INFO8_
++{
++              unsigned int    RESV; 
++};
++
++
++struct SFQ_table {
++      SFQ_INFO1_T sfq_info1;
++      SFQ_INFO2_T sfq_info2;
++      SFQ_INFO3_T sfq_info3;
++      SFQ_INFO4_T sfq_info4;
++  SFQ_INFO5_T sfq_info5;
++      SFQ_INFO6_T sfq_info6;
++      SFQ_INFO7_T sfq_info7;
++      SFQ_INFO8_T sfq_info8;
++
++};
++#endif
++#if defined (CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#define FE_GDM_RXID1_OFFSET        (0x0130)
++#define FE_GDM_RXID1               (RALINK_FRAME_ENGINE_BASE+FE_GDM_RXID1_OFFSET)
++#define GDM_VLAN_PRI7_RXID_SEL     BITS(30,31)
++#define GDM_VLAN_PRI6_RXID_SEL     BITS(28,29)
++#define GDM_VLAN_PRI5_RXID_SEL     BITS(26,27)
++#define GDM_VLAN_PRI4_RXID_SEL     BITS(24,25)
++#define GDM_VLAN_PRI3_RXID_SEL     BITS(22,23)
++#define GDM_VLAN_PRI2_RXID_SEL     BITS(20,21)
++#define GDM_VLAN_PRI1_RXID_SEL     BITS(18,19)
++#define GDM_VLAN_PRI0_RXID_SEL     BITS(16,17)
++#define GDM_TCP_ACK_RXID_SEL       BITS(4,5)
++#define GDM_TCP_ACK_WZPC           BIT(3)
++#define GDM_RXID_PRI_SEL           BITS(0,2)
++
++#define FE_GDM_RXID2_OFFSET        (0x0134)
++#define FE_GDM_RXID2               (RALINK_FRAME_ENGINE_BASE+FE_GDM_RXID2_OFFSET)
++#define GDM_STAG7_RXID_SEL         BITS(30,31)
++#define GDM_STAG6_RXID_SEL         BITS(28,29)
++#define GDM_STAG5_RXID_SEL         BITS(26,27)
++#define GDM_STAG4_RXID_SEL         BITS(24,25)
++#define GDM_STAG3_RXID_SEL         BITS(22,23)
++#define GDM_STAG2_RXID_SEL         BITS(20,21)
++#define GDM_STAG1_RXID_SEL         BITS(18,19)
++#define GDM_STAG0_RXID_SEL         BITS(16,17)
++#define GDM_PID2_RXID_SEL          BITS(2,3)
++#define GDM_PID1_RXID_SEL          BITS(0,1)
++
++#define GDM_PRI_PID              (0)
++#define GDM_PRI_VLAN_PID         (1)
++#define GDM_PRI_ACK_PID          (2)
++#define GDM_PRI_VLAN_ACK_PID     (3)
++#define GDM_PRI_ACK_VLAN_PID     (4)
++
++#define SET_GDM_VLAN_PRI_RXID_SEL(x,y) \
++    { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++        *addr &= ~(0x03 << (((x) << 1)+16));    \
++        *addr |= ((y) & 0x3) << (((x) << 1)+16); \
++    }
++#define SET_GDM_TCP_ACK_RXID_SEL(x) \
++    { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++        *addr &= ~(GDM_TCP_ACK_RXID_SEL);    \
++        *addr |= ((x) & 0x3) << 4; \
++    }
++#define SET_GDM_TCP_ACK_WZPC(x) \
++    { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++        *addr &= ~(GDM_TCP_ACK_WZPC);    \
++        *addr |= ((x) & 0x1) << 3; \
++    }
++#define SET_GDM_RXID_PRI_SEL(x) \
++    { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID1; \
++        *addr &= ~(GDM_RXID_PRI_SEL);    \
++        *addr |= (x) & 0x7; \
++    }
++#define GDM_STAG_RXID_SEL(x,y) \
++    { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
++        *addr &= ~(0x03 << (((x) << 1)+16));    \
++        *addr |= ((y) & 0x3) << (((x) << 1)+16); \
++    }
++#define SET_GDM_PID2_RXID_SEL(x) \
++    { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
++        *addr &= ~(GDM_PID2_RXID_SEL);    \
++        *addr |= ((x) & 0x3) << 2; \
++    }
++#define SET_GDM_PID1_RXID_SEL(x) \
++    { volatile unsigned int *addr = (unsigned int *)FE_GDM_RXID2; \
++        *addr &= ~(GDM_PID1_RXID_SEL);    \
++        *addr |= ((x) & 0x3); \
++    }
++#endif  /* CONFIG_RAETH_MULTIPLE_RX_RING */
++/* Per Port Packet Counts in RT3052, added by bobtseng 2009.4.17. */
++#define       PORT0_PKCOUNT           (0xb01100e8)
++#define       PORT1_PKCOUNT           (0xb01100ec)
++#define       PORT2_PKCOUNT           (0xb01100f0)
++#define       PORT3_PKCOUNT           (0xb01100f4)
++#define       PORT4_PKCOUNT           (0xb01100f8)
++#define       PORT5_PKCOUNT           (0xb01100fc)
++
++#if defined (CONFIG_ARCH_MT7623)
++#include "sync_write.h"
++#define sysRegRead(phys)            (*(volatile unsigned int *)((phys)))
++#define sysRegWrite(phys, val)      mt65xx_reg_sync_writel((val), (phys))
++#else
++#define PHYS_TO_K1(physaddr) KSEG1ADDR(physaddr)
++#define sysRegRead(phys)        (*(volatile unsigned int *)PHYS_TO_K1(phys))
++#define sysRegWrite(phys, val)  ((*(volatile unsigned int *)PHYS_TO_K1(phys)) = (val))
++#endif
++
++#define u_long        unsigned long
++#define u32   unsigned int
++#define u16   unsigned short
++
++
++/* ====================================== */
++#define GDM1_DISPAD       BIT(18)
++#define GDM1_DISCRC       BIT(17)
++
++//GDMA1 uni-cast frames destination port
++#define GDM1_ICS_EN              (0x1 << 22)
++#define GDM1_TCS_EN              (0x1 << 21)
++#define GDM1_UCS_EN              (0x1 << 20)
++#define GDM1_JMB_EN              (0x1 << 19)
++#define GDM1_STRPCRC             (0x1 << 16)
++#define GDM1_UFRC_P_CPU     (0 << 12)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_UFRC_P_PPE     (4 << 12)
++#else
++#define GDM1_UFRC_P_PPE     (6 << 12)
++#endif
++
++//GDMA1 broad-cast MAC address frames
++#define GDM1_BFRC_P_CPU     (0 << 8)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_BFRC_P_PPE     (4 << 8)
++#else
++#define GDM1_BFRC_P_PPE     (6 << 8)
++#endif
++
++//GDMA1 multi-cast MAC address frames
++#define GDM1_MFRC_P_CPU     (0 << 4)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_MFRC_P_PPE     (4 << 4)
++#else
++#define GDM1_MFRC_P_PPE     (6 << 4)
++#endif
++
++//GDMA1 other MAC address frames destination port
++#define GDM1_OFRC_P_CPU     (0 << 0)
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define GDM1_OFRC_P_PPE     (4 << 0)
++#else
++#define GDM1_OFRC_P_PPE     (6 << 0)
++#endif
++
++#if defined (CONFIG_RALINK_RT6856) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++/* checksum generator registers are removed */
++#define ICS_GEN_EN          (0 << 2)
++#define UCS_GEN_EN          (0 << 1)
++#define TCS_GEN_EN          (0 << 0)
++#else
++#define ICS_GEN_EN          (1 << 2)
++#define UCS_GEN_EN          (1 << 1)
++#define TCS_GEN_EN          (1 << 0)
++#endif
++
++// MDIO_CFG   bit
++#define MDIO_CFG_GP1_FC_TX    (1 << 11)
++#define MDIO_CFG_GP1_FC_RX    (1 << 10)
++
++/* ====================================== */
++/* ====================================== */
++#define GP1_LNK_DWN     BIT(9) 
++#define GP1_AN_FAIL     BIT(8) 
++/* ====================================== */
++/* ====================================== */
++#define PSE_RESET       BIT(0)
++/* ====================================== */
++#define PST_DRX_IDX3       BIT(19)
++#define PST_DRX_IDX2       BIT(18)
++#define PST_DRX_IDX1       BIT(17)
++#define PST_DRX_IDX0       BIT(16)
++#define PST_DTX_IDX3       BIT(3)
++#define PST_DTX_IDX2       BIT(2)
++#define PST_DTX_IDX1       BIT(1)
++#define PST_DTX_IDX0       BIT(0)
++
++#define RX_2B_OFFSET    BIT(31)
++#define DESC_32B_EN     BIT(8)
++#define TX_WB_DDONE       BIT(6)
++#define RX_DMA_BUSY       BIT(3)
++#define TX_DMA_BUSY       BIT(1)
++#define RX_DMA_EN         BIT(2)
++#define TX_DMA_EN         BIT(0)
++
++#define PDMA_BT_SIZE_4DWORDS     (0<<4)
++#define PDMA_BT_SIZE_8DWORDS     (1<<4)
++#define PDMA_BT_SIZE_16DWORDS    (2<<4)
++#define PDMA_BT_SIZE_32DWORDS    (3<<4)
++
++#define ADMA_RX_BT_SIZE_4DWORDS               (0<<11)
++#define ADMA_RX_BT_SIZE_8DWORDS               (1<<11)
++#define ADMA_RX_BT_SIZE_16DWORDS      (2<<11)
++#define ADMA_RX_BT_SIZE_32DWORDS      (3<<11)
++
++/* Register bits.
++ */
++
++#define MACCFG_RXEN           (1<<2)
++#define MACCFG_TXEN           (1<<3)
++#define MACCFG_PROMISC                (1<<18)
++#define MACCFG_RXMCAST                (1<<19)
++#define MACCFG_FDUPLEX                (1<<20)
++#define MACCFG_PORTSEL                (1<<27)
++#define MACCFG_HBEATDIS               (1<<28)
++
++
++#define DMACTL_SR             (1<<1)  /* Start/Stop Receive */
++#define DMACTL_ST             (1<<13) /* Start/Stop Transmission Command */
++
++#define DMACFG_SWR            (1<<0)  /* Software Reset */
++#define DMACFG_BURST32                (32<<8)
++
++#define DMASTAT_TS            0x00700000      /* Transmit Process State */
++#define DMASTAT_RS            0x000e0000      /* Receive Process State */
++
++#define MACCFG_INIT           0 //(MACCFG_FDUPLEX) // | MACCFG_PORTSEL)
++
++
++
++/* Descriptor bits.
++ */
++#define R_OWN         0x80000000      /* Own Bit */
++#define RD_RER                0x02000000      /* Receive End Of Ring */
++#define RD_LS         0x00000100      /* Last Descriptor */
++#define RD_ES         0x00008000      /* Error Summary */
++#define RD_CHAIN      0x01000000      /* Chained */
++
++/* Word 0 */
++#define T_OWN         0x80000000      /* Own Bit */
++#define TD_ES         0x00008000      /* Error Summary */
++
++/* Word 1 */
++#define TD_LS         0x40000000      /* Last Segment */
++#define TD_FS         0x20000000      /* First Segment */
++#define TD_TER                0x08000000      /* Transmit End Of Ring */
++#define TD_CHAIN      0x01000000      /* Chained */
++
++
++#define TD_SET                0x08000000      /* Setup Packet */
++
++
++#define POLL_DEMAND 1
++
++#define RSTCTL        (0x34)
++#define RSTCTL_RSTENET1       (1<<19)
++#define RSTCTL_RSTENET2       (1<<20)
++
++#define INIT_VALUE_OF_RT2883_PSE_FQ_CFG               0xff908000
++#define INIT_VALUE_OF_PSE_FQFC_CFG            0x80504000
++#define INIT_VALUE_OF_FORCE_100_FD            0x1001BC01
++#define INIT_VALUE_OF_FORCE_1000_FD           0x1F01DC01
++
++// Define Whole FE Reset Register
++#define RSTCTRL                       (RALINK_SYSCTL_BASE + 0x34)
++#define RT2880_AGPIOCFG_REG   (RALINK_SYSCTL_BASE + 0x3C)
++
++/*=========================================
++      PDMA RX Descriptor Format define
++=========================================*/
++
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO1_  PDMA_RXD_INFO1_T;
++
++struct _PDMA_RXD_INFO1_
++{
++    unsigned int    PDP0;
++};
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO2_    PDMA_RXD_INFO2_T;
++
++struct _PDMA_RXD_INFO2_
++{
++#if defined (CONFIG_ARCH_MT7623)
++    unsigned int    PLEN1                 : 2;
++    unsigned int    LRO_AGG_CNT           : 8;
++    unsigned int    REV                   : 5;
++#else
++    unsigned int    PLEN1                 : 14;
++    unsigned int    LS1                   : 1;
++#endif  /* CONFIG_RAETH_HW_LRO */
++    unsigned int    TAG                   : 1;
++    unsigned int    PLEN0                 : 14;
++    unsigned int    LS0                   : 1;
++    unsigned int    DDONE_bit             : 1;
++};
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO3_  PDMA_RXD_INFO3_T;
++
++struct _PDMA_RXD_INFO3_
++{
++    unsigned int    VID:16;
++    unsigned int    TPID:16;
++};
++//-------------------------------------------------
++typedef struct _PDMA_RXD_INFO4_    PDMA_RXD_INFO4_T;
++
++struct _PDMA_RXD_INFO4_
++{
++#if defined (CONFIG_RALINK_MT7620)
++    unsigned int    FOE_Entry           : 14;
++    unsigned int    CRSN              : 5;
++    unsigned int    SPORT             : 3;
++    unsigned int    L4F                       : 1;
++    unsigned int    L4VLD             : 1;
++    unsigned int    TACK              : 1;
++    unsigned int    IP4F              : 1;
++    unsigned int    IP4                       : 1;
++    unsigned int    IP6                       : 1;
++    unsigned int    UN_USE1           : 4;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++    unsigned int    FOE_Entry           : 14;
++    unsigned int    CRSN              : 5;
++    unsigned int    SP                        : 4;
++    unsigned int    L4F                       : 1;
++    unsigned int    L4VLD             : 1;
++    unsigned int    TACK              : 1;
++    unsigned int    IP4F              : 1;
++    unsigned int    IP4                       : 1;
++    unsigned int    IP6                       : 1;
++    unsigned int    UN_USE1           : 3;
++#else
++    unsigned int    FOE_Entry           : 14;
++    unsigned int    FVLD                : 1;
++    unsigned int    UN_USE1             : 1;
++    unsigned int    AI                  : 8;
++    unsigned int    SP                  : 3;
++    unsigned int    AIS                 : 1;
++    unsigned int    L4F                 : 1;
++    unsigned int    IPF                  : 1;
++    unsigned int    L4FVLD_bit           : 1;
++    unsigned int    IPFVLD_bit           : 1;
++#endif
++};
++
++
++struct PDMA_rxdesc {
++      PDMA_RXD_INFO1_T rxd_info1;
++      PDMA_RXD_INFO2_T rxd_info2;
++      PDMA_RXD_INFO3_T rxd_info3;
++      PDMA_RXD_INFO4_T rxd_info4;
++#ifdef CONFIG_32B_DESC
++      unsigned int     rxd_info5;
++      unsigned int     rxd_info6;
++      unsigned int     rxd_info7;
++      unsigned int     rxd_info8;
++#endif
++};
++
++/*=========================================
++      PDMA TX Descriptor Format define
++=========================================*/
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO1_  PDMA_TXD_INFO1_T;
++
++struct _PDMA_TXD_INFO1_
++{
++    unsigned int    SDP0;
++};
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO2_    PDMA_TXD_INFO2_T;
++
++struct _PDMA_TXD_INFO2_
++{
++    unsigned int    SDL1                  : 14;
++    unsigned int    LS1_bit               : 1;
++    unsigned int    BURST_bit             : 1;
++    unsigned int    SDL0                  : 14;
++    unsigned int    LS0_bit               : 1;
++    unsigned int    DDONE_bit             : 1;
++};
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO3_  PDMA_TXD_INFO3_T;
++
++struct _PDMA_TXD_INFO3_
++{
++    unsigned int    SDP1;
++};
++//-------------------------------------------------
++typedef struct _PDMA_TXD_INFO4_    PDMA_TXD_INFO4_T;
++
++struct _PDMA_TXD_INFO4_
++{
++#if defined (CONFIG_RALINK_MT7620)
++    unsigned int    VPRI_VIDX           : 8;
++    unsigned int    SIDX                : 4;
++    unsigned int    INSP                : 1;
++    unsigned int    RESV              : 2;
++    unsigned int    UDF               : 5;
++    unsigned int    FP_BMAP                   : 8;
++    unsigned int    TSO                       : 1;
++    unsigned int    TUI_CO            : 3;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++    unsigned int    VLAN_TAG          :17; // INSV(1)+VPRI(3)+CFI(1)+VID(12)
++    unsigned int    RESV                : 2;
++    unsigned int    UDF                 : 6;
++    unsigned int    FPORT               : 3;
++    unsigned int    TSO                       : 1;
++    unsigned int    TUI_CO            : 3;
++#else
++    unsigned int    VPRI_VIDX           : 8;
++    unsigned int    SIDX                : 4;
++    unsigned int    INSP                : 1;
++    unsigned int    RESV              : 1;
++    unsigned int    UN_USE3             : 2;
++    unsigned int    QN                  : 3;
++    unsigned int    UN_USE2             : 1;
++    unsigned int    UDF                       : 4;
++    unsigned int    PN                  : 3;
++    unsigned int    UN_USE1             : 1;
++    unsigned int    TSO                       : 1;
++    unsigned int    TUI_CO            : 3;
++#endif
++};
++
++
++struct PDMA_txdesc {
++      PDMA_TXD_INFO1_T txd_info1;
++      PDMA_TXD_INFO2_T txd_info2;
++      PDMA_TXD_INFO3_T txd_info3;
++      PDMA_TXD_INFO4_T txd_info4;
++#ifdef CONFIG_32B_DESC
++      unsigned int     txd_info5;
++      unsigned int     txd_info6;
++      unsigned int     txd_info7;
++      unsigned int     txd_info8;
++#endif
++};
++
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++/*=========================================
++      QDMA TX Descriptor Format define
++=========================================*/
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO1_  QDMA_TXD_INFO1_T;
++
++struct _QDMA_TXD_INFO1_
++{
++    unsigned int    SDP;
++};
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO2_    QDMA_TXD_INFO2_T;
++
++struct _QDMA_TXD_INFO2_
++{
++    unsigned int    NDP;
++};
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO3_  QDMA_TXD_INFO3_T;
++
++struct _QDMA_TXD_INFO3_
++{
++    unsigned int    QID                   : 4;
++#if defined (CONFIG_HW_SFQ)
++    //unsigned int    VQID                  : 10;  
++    unsigned int    PROT                   : 3;
++    unsigned int    IPOFST                   : 7;             
++#else
++    unsigned int    RESV                  : 10;
++#endif
++    unsigned int    SWC_bit               : 1;        
++    unsigned int    BURST_bit             : 1;
++    unsigned int    SDL                   : 14;
++    unsigned int    LS_bit               : 1;
++    unsigned int    OWN_bit             : 1;
++};
++//-------------------------------------------------
++typedef struct _QDMA_TXD_INFO4_    QDMA_TXD_INFO4_T;
++
++struct _QDMA_TXD_INFO4_
++{
++    unsigned int    VLAN_TAG          :17; // INSV(1)+VPRI(3)+CFI(1)+VID(12)
++#if defined (CONFIG_RALINK_MT7621)
++    unsigned int    RESV                : 2;
++    unsigned int    UDF                 : 6;
++#elif defined(CONFIG_ARCH_MT7623)
++        unsigned int    VQID0               : 1;
++        unsigned int    RESV                : 7;
++#endif
++    unsigned int    FPORT               : 3;
++    unsigned int    TSO                       : 1;
++    unsigned int    TUI_CO            : 3;
++};
++
++
++struct QDMA_txdesc {
++      QDMA_TXD_INFO1_T txd_info1;
++      QDMA_TXD_INFO2_T txd_info2;
++      QDMA_TXD_INFO3_T txd_info3;
++      QDMA_TXD_INFO4_T txd_info4;
++#ifdef CONFIG_32B_DESC
++      unsigned int     txd_info5;
++      unsigned int     txd_info6;
++      unsigned int     txd_info7;
++      unsigned int     txd_info8;
++#endif
++};
++#endif
++
++#if defined (CONFIG_ARCH_MT7623)
++#define phys_to_bus(a) (a)
++#else
++#define phys_to_bus(a) (a & 0x1FFFFFFF)
++#endif
++
++#define PHY_Enable_Auto_Nego          0x1000
++#define PHY_Restart_Auto_Nego         0x0200
++
++/* PHY_STAT_REG = 1; */
++#define PHY_Auto_Neco_Comp    0x0020
++#define PHY_Link_Status               0x0004
++
++/* PHY_AUTO_NEGO_REG = 4; */
++#define PHY_Cap_10_Half  0x0020
++#define PHY_Cap_10_Full  0x0040
++#define       PHY_Cap_100_Half 0x0080
++#define       PHY_Cap_100_Full 0x0100
++
++/* proc definition */
++
++#if !defined (CONFIG_RALINK_RT6855) && !defined(CONFIG_RALINK_RT6855A) && \
++    !defined (CONFIG_RALINK_MT7620) && !defined (CONFIG_RALINK_MT7621) && \
++    !defined (CONFIG_ARCH_MT7623)
++#define CDMA_OQ_STA   (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x4c)
++#define GDMA1_OQ_STA  (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x50)
++#define PPE_OQ_STA    (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x54)
++#define PSE_IQ_STA    (RALINK_FRAME_ENGINE_BASE+RAPSE_OFFSET+0x58)
++#endif
++
++#define PROCREG_CONTROL_FILE      "/var/run/procreg_control"
++#if defined (CONFIG_RALINK_RT2880)
++#define PROCREG_DIR             "rt2880"
++#elif defined (CONFIG_RALINK_RT3052)
++#define PROCREG_DIR             "rt3052"
++#elif defined (CONFIG_RALINK_RT3352)
++#define PROCREG_DIR             "rt3352"
++#elif defined (CONFIG_RALINK_RT5350)
++#define PROCREG_DIR             "rt5350"
++#elif defined (CONFIG_RALINK_RT2883)
++#define PROCREG_DIR             "rt2883"
++#elif defined (CONFIG_RALINK_RT3883)
++#define PROCREG_DIR             "rt3883"
++#elif defined (CONFIG_RALINK_RT6855)
++#define PROCREG_DIR             "rt6855"
++#elif defined (CONFIG_RALINK_MT7620)
++#define PROCREG_DIR             "mt7620"
++#elif defined (CONFIG_RALINK_MT7621)
++#define PROCREG_DIR             "mt7621"
++#elif defined (CONFIG_ARCH_MT7623)
++#define PROCREG_DIR             "mt7623"
++#elif defined (CONFIG_RALINK_MT7628)
++#define PROCREG_DIR             "mt7628"
++#elif defined (CONFIG_RALINK_RT6855A)
++#define PROCREG_DIR             "rt6855a"
++#else
++#define PROCREG_DIR             "rt2880"
++#endif
++#define PROCREG_SKBFREE               "skb_free"
++#define PROCREG_TXRING                "tx_ring"
++#define PROCREG_RXRING                "rx_ring"
++#define PROCREG_RXRING1               "rx_ring1"
++#define PROCREG_RXRING2               "rx_ring2"
++#define PROCREG_RXRING3               "rx_ring3"
++#define PROCREG_NUM_OF_TXD    "num_of_txd"
++#define PROCREG_TSO_LEN               "tso_len"
++#define PROCREG_LRO_STATS     "lro_stats"
++#define PROCREG_HW_LRO_STATS  "hw_lro_stats"
++#define PROCREG_HW_LRO_AUTO_TLB       "hw_lro_auto_tlb"
++#define PROCREG_GMAC          "gmac"
++#define PROCREG_GMAC2           "gmac2"
++#define PROCREG_CP0           "cp0"
++#define PROCREG_RAQOS         "qos"
++#define PROCREG_READ_VAL      "regread_value"
++#define PROCREG_WRITE_VAL     "regwrite_value"
++#define PROCREG_ADDR          "reg_addr"
++#define PROCREG_CTL           "procreg_control"
++#define PROCREG_RXDONE_INTR   "rxdone_intr_count"
++#define PROCREG_ESW_INTR      "esw_intr_count"
++#define PROCREG_ESW_CNT               "esw_cnt"
++#define PROCREG_SNMP          "snmp"
++#if defined (TASKLET_WORKQUEUE_SW)
++#define PROCREG_SCHE          "schedule"
++#endif
++#define PROCREG_QDMA            "qdma"
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#define PROCREG_PDMA_DVT              "pdma_dvt"
++#endif  //#if defined(CONFIG_RAETH_PDMA_DVT)
++struct rt2880_reg_op_data {
++  char        name[64];
++  unsigned int reg_addr;
++  unsigned int op;
++  unsigned int reg_value;
++};        
++
++#ifdef CONFIG_RAETH_LRO
++struct lro_counters {
++        u32 lro_aggregated;
++        u32 lro_flushed;
++        u32 lro_no_desc;
++};
++
++struct lro_para_struct {
++      unsigned int lan_ip1;
++};
++
++#endif // CONFIG_RAETH_LRO //
++
++
++#if defined (CONFIG_HW_SFQ)
++typedef struct {
++      //layer2 header
++      uint8_t dmac[6];
++      uint8_t smac[6];
++
++      //vlan header 
++      uint16_t vlan_tag;
++      uint16_t vlan1_gap;
++      uint16_t vlan1;
++      uint16_t vlan2_gap;
++      uint16_t vlan2;
++      uint16_t vlan_layer;
++
++      //pppoe header
++      uint32_t pppoe_gap;
++      uint16_t ppp_tag;
++      uint16_t pppoe_sid;
++
++      //layer3 header
++      uint16_t eth_type;
++      struct iphdr iph;
++      struct ipv6hdr ip6h;
++
++      //layer4 header
++      struct tcphdr th;
++      struct udphdr uh;
++
++      uint32_t pkt_type;
++      uint8_t is_mcast;
++
++} ParseResult;
++#endif
++typedef struct end_device
++{
++
++    unsigned int        tx_cpu_owner_idx0;
++    unsigned int        rx_cpu_owner_idx0;
++    unsigned int        fe_int_status;
++    unsigned int        tx_full; 
++    
++#if !defined (CONFIG_RAETH_QDMA)
++    unsigned int      phy_tx_ring0;
++#else
++    /* QDMA Tx  PTR */
++    struct sk_buff *free_skb[NUM_TX_DESC];
++    unsigned int tx_dma_ptr;
++    unsigned int tx_cpu_ptr;
++    unsigned int free_txd_num;
++    unsigned int free_txd_head;
++    unsigned int free_txd_tail;       
++    struct QDMA_txdesc *txd_pool;
++    dma_addr_t phy_txd_pool;
++    unsigned int txd_pool_info[NUM_TX_DESC];
++    struct QDMA_txdesc *free_head;
++    unsigned int phy_free_head;
++    unsigned int *free_page_head;
++    unsigned int phy_free_page_head;
++    struct PDMA_rxdesc *qrx_ring;
++    unsigned int phy_qrx_ring;
++#ifdef CONFIG_RAETH_PDMATX_QDMARX     /* QDMA RX */
++    unsigned int phy_tx_ring0;
++#endif
++#endif
++
++    unsigned int      phy_rx_ring0, phy_rx_ring1, phy_rx_ring2, phy_rx_ring3;
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || \
++    defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || \
++    defined(CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || \
++    defined(CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628)  || \
++    defined (CONFIG_ARCH_MT7623)
++    //send signal to user application to notify link status changed
++    struct work_struct  kill_sig_wq;
++#endif
++
++    struct work_struct  reset_task;
++#ifdef WORKQUEUE_BH
++    struct work_struct  rx_wq;
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++    struct work_struct  rx_wq;
++#endif
++    struct              tasklet_struct     rx_tasklet;
++    struct              tasklet_struct     tx_tasklet;
++#endif // WORKQUEUE_BH //
++
++#if defined(CONFIG_RAETH_QOS)
++    struct            sk_buff *          skb_free[NUM_TX_RINGS][NUM_TX_DESC];
++    unsigned int      free_idx[NUM_TX_RINGS];
++#else
++    struct            sk_buff*           skb_free[NUM_TX_DESC];
++    unsigned int      free_idx;
++#endif
++
++    struct              net_device_stats stat;  /* The new statistics table. */
++    spinlock_t          page_lock;              /* Page register locks */
++    struct PDMA_txdesc *tx_ring0;
++#if defined(CONFIG_RAETH_QOS)
++    struct PDMA_txdesc *tx_ring1;
++    struct PDMA_txdesc *tx_ring2;
++    struct PDMA_txdesc *tx_ring3;
++#endif
++    struct PDMA_rxdesc *rx_ring0;
++    struct sk_buff     *netrx0_skbuf[NUM_RX_DESC];
++#if defined (CONFIG_RAETH_HW_LRO)
++    struct PDMA_rxdesc *rx_ring3;
++    struct sk_buff     *netrx3_skbuf[NUM_RX_DESC];
++    struct PDMA_rxdesc *rx_ring2;
++    struct sk_buff     *netrx2_skbuf[NUM_RX_DESC];
++    struct PDMA_rxdesc *rx_ring1;
++    struct sk_buff     *netrx1_skbuf[NUM_RX_DESC];
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++    struct PDMA_rxdesc *rx_ring1;
++    struct sk_buff     *netrx1_skbuf[NUM_RX_DESC];
++#if defined(CONFIG_ARCH_MT7623)
++    struct PDMA_rxdesc *rx_ring2;
++    struct sk_buff     *netrx2_skbuf[NUM_RX_DESC];
++    struct PDMA_rxdesc *rx_ring3;
++    struct sk_buff     *netrx3_skbuf[NUM_RX_DESC];
++#endif  /* CONFIG_ARCH_MT7623 */
++#endif
++#ifdef CONFIG_RAETH_NAPI
++    atomic_t irq_sem;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++    struct napi_struct napi;
++#endif
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++    struct net_device *PseudoDev;
++    unsigned int isPseudo;
++#endif
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++      struct mii_if_info      mii_info;
++#endif
++#ifdef CONFIG_RAETH_LRO
++    struct lro_counters lro_counters;
++    struct net_lro_mgr lro_mgr;
++    struct net_lro_desc lro_arr[8];
++#endif
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++    struct vlan_group *vlgrp;
++#endif
++#if defined (CONFIG_RAETH_HW_LRO)
++    struct work_struct hw_lro_wq;
++    unsigned int hw_lro_pkt_interval[3];
++    unsigned int hw_lro_alpha;  /* 0 < packet interval alpha <= 10 */
++    unsigned int hw_lro_fix_setting;  /* 0: dynamical AGG/AGE time, 1: fixed AGG/AGE time */
++#endif  /* CONFIG_RAETH_HW_LRO */
++} END_DEVICE, *pEND_DEVICE;
++
++
++#define RAETH_VERSION "v3.1"
++
++#endif
++
++#define DMA_GLO_CFG PDMA_GLO_CFG
++
++#if defined(CONFIG_RAETH_QDMATX_QDMARX) 
++#define GDMA1_FWD_PORT 0x5555
++#define GDMA2_FWD_PORT 0x5555
++#elif defined(CONFIG_RAETH_PDMATX_QDMARX)
++#define GDMA1_FWD_PORT 0x5555
++#define GDMA2_FWD_PORT 0x5555
++#else
++#define GDMA1_FWD_PORT 0x0000
++#define GDMA2_FWD_PORT 0x0000
++#endif
++
++#if defined(CONFIG_RAETH_QDMATX_QDMARX) 
++#define RAETH_RX_CALC_IDX0 QRX_CRX_IDX_0
++#define RAETH_RX_CALC_IDX1 QRX_CRX_IDX_1
++#elif defined(CONFIG_RAETH_PDMATX_QDMARX) 
++#define RAETH_RX_CALC_IDX0 QRX_CRX_IDX_0
++#define RAETH_RX_CALC_IDX1 QRX_CRX_IDX_1
++#else
++#define RAETH_RX_CALC_IDX0 RX_CALC_IDX0
++#define RAETH_RX_CALC_IDX1 RX_CALC_IDX1
++#endif
++#define RAETH_RX_CALC_IDX2 RX_CALC_IDX2
++#define RAETH_RX_CALC_IDX3 RX_CALC_IDX3
++#define RAETH_FE_INT_STATUS FE_INT_STATUS
++#define RAETH_FE_INT_ALL FE_INT_ALL
++#define RAETH_FE_INT_ENABLE FE_INT_ENABLE
++#define RAETH_FE_INT_DLY_INIT FE_INT_DLY_INIT
++#define RAETH_FE_INT_SETTING RX_DONE_INT0 | RX_DONE_INT1 | TX_DONE_INT0 | TX_DONE_INT1 | TX_DONE_INT2 | TX_DONE_INT3
++#define QFE_INT_SETTING RX_DONE_INT0 | RX_DONE_INT1 | TX_DONE_INT0 | TX_DONE_INT1 | TX_DONE_INT2 | TX_DONE_INT3
++#define RAETH_TX_DLY_INT TX_DLY_INT
++#define RAETH_TX_DONE_INT0 TX_DONE_INT0
++#define RAETH_DLY_INT_CFG DLY_INT_CFG
+diff --git a/drivers/net/ethernet/raeth/ra_ethtool.c b/drivers/net/ethernet/raeth/ra_ethtool.c
+new file mode 100644
+index 0000000..ff13e59
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_ethtool.c
+@@ -0,0 +1,515 @@
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/if_ether.h>
++#include <linux/ethtool.h>
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ethtool.h"
++
++#define RAETHER_DRIVER_NAME           "raether"
++#define RA_NUM_STATS                  4
++
++
++static struct {
++    const char str[ETH_GSTRING_LEN];
++} ethtool_stats_keys[] = {
++    { "statistic1" },
++    { "statistic2" },
++    { "statistic3" },
++    { "statistic4" },
++};
++
++unsigned char get_current_phy_address(void)
++{
++      struct net_device *cur_dev_p;
++      END_DEVICE *ei_local;
++#if 0
++      for(cur_dev_p=dev_base; cur_dev_p!=NULL; cur_dev_p=cur_dev_p->next){
++              if (strncmp(cur_dev_p->name, DEV_NAME /* "eth2" usually */, 4) == 0)
++                      break;
++      }
++#else
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      cur_dev_p = dev_get_by_name(&init_net, DEV_NAME);
++#else
++      cur_dev_p = dev_get_by_name(DEV_NAME);
++#endif
++#endif        
++      if(!cur_dev_p)
++              return 0;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      ei_local = netdev_priv(cur_dev_p);
++#else
++      ei_local = cur_dev_p->priv;
++#endif        
++      return ei_local->mii_info.phy_id;
++}
++#if 0
++static u32 et_get_tx_csum(struct net_device *dev)
++{
++      return (sysRegRead(GDMA1_FWD_CFG) & GDM1_DISCRC) ? 0 : 1;       // a pitfall here, "0" means to enable.
++}
++
++static u32 et_get_rx_csum(struct net_device *dev)
++{
++      return (sysRegRead(GDMA1_FWD_CFG) & GDM1_STRPCRC) ? 1 : 0;
++}
++
++static int et_set_tx_csum(struct net_device *dev, u32 data)
++{
++      int value;
++      //printk("et_set_tx_csum(): data = %d\n", data);
++
++      value = sysRegRead(GDMA1_FWD_CFG);
++      if(data)
++              value |= GDM1_DISCRC;
++      else
++              value &= ~GDM1_DISCRC;
++
++      sysRegWrite(GDMA1_FWD_CFG, value);
++    return 0;
++}
++
++static int et_set_rx_csum(struct net_device *dev, u32 data)
++{
++      int value;
++      //printk("et_set_rx_csum(): data = %d\n", data);
++
++      value = sysRegRead(GDMA1_FWD_CFG);
++      if(data)
++              value |= GDM1_STRPCRC;
++      else
++              value &= ~GDM1_STRPCRC;
++
++      sysRegWrite(GDMA1_FWD_CFG, value);
++    return 0;
++}
++#endif
++
++#define MII_CR_ADDR                   0x00
++#define MII_CR_MR_AUTONEG_ENABLE      (1 << 12)
++#define MII_CR_MR_RESTART_NEGOTIATION (1 << 9)
++
++#define AUTO_NEGOTIATION_ADVERTISEMENT        0x04
++#define AN_PAUSE                      (1 << 10)
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static void et_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++      int mii_an_reg;
++      int mdio_cfg_reg;
++      END_DEVICE *ei_local = dev->priv;
++
++      // get mii auto-negotiation register
++      mii_mgr_read(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++      epause->autoneg = (mii_an_reg & AN_PAUSE) ? 1 : 0; //get autonet_enable flag bit
++      
++      mdio_cfg_reg = sysRegRead(MDIO_CFG);
++      epause->tx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_TX) ? 1 : 0;
++      epause->rx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_RX) ? 1 : 0;
++
++      //printk("et_get_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++}
++
++static int et_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++      int mdio_cfg_reg;
++      int mii_an_reg;
++      END_DEVICE *ei_local = dev->priv;
++
++      //printk("et_set_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++
++      // auto-neg pause
++      mii_mgr_read(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++      if(epause->autoneg)
++              mii_an_reg |= AN_PAUSE;
++      else
++              mii_an_reg &= ~AN_PAUSE;
++      mii_mgr_write(ei_local->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, mii_an_reg);
++
++      // tx/rx pause
++      mdio_cfg_reg = sysRegRead(MDIO_CFG);
++      if(epause->tx_pause)
++              mdio_cfg_reg |= MDIO_CFG_GP1_FC_TX;
++      else
++              mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_TX;
++      if(epause->rx_pause)
++              mdio_cfg_reg |= MDIO_CFG_GP1_FC_RX;
++      else
++              mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_RX;
++      sysRegWrite(MDIO_CFG, mdio_cfg_reg);
++
++      return 0;
++}
++
++static int et_nway_reset(struct net_device *dev)
++{
++      END_DEVICE *ei_local = dev->priv;
++      return mii_nway_restart(&ei_local->mii_info);
++}
++#endif
++
++static u32 et_get_link(struct net_device *dev)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        END_DEVICE *ei_local = netdev_priv(dev);
++#else 
++      END_DEVICE *ei_local = dev->priv;
++#endif        
++      return mii_link_ok(&ei_local->mii_info);
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static int et_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++      END_DEVICE *ei_local = dev->priv;
++      int rc;
++      rc = mii_ethtool_sset(&ei_local->mii_info, cmd);
++      return rc;
++}
++#endif
++
++static int et_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        END_DEVICE *ei_local = netdev_priv(dev);
++#else
++        END_DEVICE *ei_local = dev->priv;
++#endif
++      mii_ethtool_gset(&ei_local->mii_info, cmd);
++      return 0;
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static u32 et_get_msglevel(struct net_device *dev)
++{
++      return 0;
++}
++
++static void et_set_msglevel(struct net_device *dev, u32 datum)
++{
++      return;
++}
++
++static void et_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++      //END_DEVICE *ei_local = dev->priv;
++      strcpy(info->driver, RAETHER_DRIVER_NAME);
++      strcpy(info->version, RAETH_VERSION);
++      strcpy(info->bus_info, "n/a");
++      info->n_stats = RA_NUM_STATS;
++      info->eedump_len = 0;
++      info->regdump_len = 0;
++}
++
++static int et_get_stats_count(struct net_device *dev)
++{
++      return RA_NUM_STATS;
++}
++
++static void et_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
++{
++//    END_DEVICE *ei_local = dev->priv;
++      data[0] = 0;//np->xstats.early_rx;
++      data[1] = 0;//np->xstats.tx_buf_mapped;
++      data[2] = 0;//np->xstats.tx_timeouts;
++      data[3] = 0;//np->xstats.rx_lost_in_ring;
++}
++
++static void et_get_strings(struct net_device *dev, u32 stringset, u8 *data)
++{
++      memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
++}
++#endif
++
++/*
++ *    mii_mgr_read wrapper for mii.o ethtool
++ */
++int mdio_read(struct net_device *dev, int phy_id, int location)
++{
++      unsigned int result;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        END_DEVICE *ei_local = netdev_priv(dev);
++#else
++        END_DEVICE *ei_local = dev->priv;
++#endif
++      mii_mgr_read( (unsigned int) ei_local->mii_info.phy_id, (unsigned int)location, &result);
++      //printk("\n%s mii.o query= phy_id:%d, address:%d retval:%x\n", dev->name, phy_id, location, result);
++      return (int)result;
++}
++
++/*
++ *    mii_mgr_write wrapper for mii.o ethtool
++ */
++void mdio_write(struct net_device *dev, int phy_id, int location, int value)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++              END_DEVICE *ei_local = netdev_priv(dev);
++#else
++              END_DEVICE *ei_local = dev->priv;
++#endif
++      //printk("mii.o write= phy_id:%d, address:%d value:%x\n", phy_id, location, value);
++      mii_mgr_write( (unsigned int) ei_local->mii_info.phy_id, (unsigned int)location, (unsigned int)value);
++      return;
++}
++
++struct ethtool_ops ra_ethtool_ops = {
++
++      .get_settings           = et_get_settings,
++       .get_link               = et_get_link,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)       
++      .get_drvinfo            = et_get_drvinfo,
++      .set_settings           = et_set_settings,
++      .get_pauseparam         = et_get_pauseparam,
++      .set_pauseparam         = et_set_pauseparam,
++//    .get_rx_csum            = et_get_rx_csum,
++//    .set_rx_csum            = et_set_rx_csum,
++//    .get_tx_csum            = et_get_tx_csum,
++//    .set_tx_csum            = et_set_tx_csum,
++      .nway_reset             = et_nway_reset,
++      .get_msglevel           = et_get_msglevel,
++      .set_msglevel           = et_set_msglevel,
++      .get_strings            = et_get_strings,
++      .get_stats_count        = et_get_stats_count,
++      .get_ethtool_stats      = et_get_ethtool_stats,
++/*    .get_regs_len           = et_get_regs_len,
++      .get_regs               = et_get_regs,
++*/
++#endif        
++};
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++/*
++ * We unable to re-use the Raether functions because it is hard to tell
++ * where the calling from is. From eth2 or eth3?
++ *
++ * These code size is around 950 bytes.
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static void et_virt_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++      // PSEUDO_ADAPTER *pseudo = dev->priv;
++      return et_get_drvinfo(dev, info);
++}
++
++static void et_virt_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++      int mii_an_reg, mdio_cfg_reg;
++      PSEUDO_ADAPTER *pseudo = dev->priv;
++
++      // get mii auto-negotiation register
++      mii_mgr_read(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++      epause->autoneg = (mii_an_reg & AN_PAUSE) ? 1 : 0; //get autonet_enable flag bit
++      
++      mdio_cfg_reg = sysRegRead(MDIO_CFG);
++      epause->tx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_TX) ? 1 : 0;
++      epause->rx_pause = (mdio_cfg_reg & MDIO_CFG_GP1_FC_RX) ? 1 : 0;
++
++      //printk("et_get_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++}
++
++static int et_virt_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++      int mdio_cfg_reg;
++      int mii_an_reg;
++      PSEUDO_ADAPTER *pseudo = dev->priv;
++
++      //printk("et_set_pauseparam(): autoneg=%d, tx_pause=%d, rx_pause=%d\n", epause->autoneg, epause->tx_pause, epause->rx_pause);
++      // auto-neg pause
++      mii_mgr_read(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, &mii_an_reg);
++      if(epause->autoneg)
++              mii_an_reg |= AN_PAUSE;
++      else
++              mii_an_reg &= ~AN_PAUSE;
++      mii_mgr_write(pseudo->mii_info.phy_id, AUTO_NEGOTIATION_ADVERTISEMENT, mii_an_reg);
++
++      // tx/rx pause
++      mdio_cfg_reg = sysRegRead(MDIO_CFG);
++      if(epause->tx_pause)
++              mdio_cfg_reg |= MDIO_CFG_GP1_FC_TX;
++      else
++              mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_TX;
++      if(epause->rx_pause)
++              mdio_cfg_reg |= MDIO_CFG_GP1_FC_RX;
++      else
++              mdio_cfg_reg &= ~MDIO_CFG_GP1_FC_RX;
++      sysRegWrite(MDIO_CFG, mdio_cfg_reg);
++
++      return 0;
++}
++
++static u32 et_virt_get_tx_csum(struct net_device *dev)
++{
++      return (sysRegRead(GDMA2_FWD_CFG) & GDM1_DISCRC) ? 0 : 1;       // a pitfall here, "0" means to enable.
++}
++
++static u32 et_virt_get_rx_csum(struct net_device *dev)
++{
++      return (sysRegRead(GDMA2_FWD_CFG) & GDM1_STRPCRC) ? 1 : 0;
++}
++
++static int et_virt_set_tx_csum(struct net_device *dev, u32 data)
++{
++      int value;
++      //printk("et_set_tx_csum(): data = %d\n", data);
++      value = sysRegRead(GDMA2_FWD_CFG);
++      if(data)
++              value |= GDM1_DISCRC;
++      else
++              value &= ~GDM1_DISCRC;
++      sysRegWrite(GDMA1_FWD_CFG, value);
++      return 0;
++}
++
++static int et_virt_set_rx_csum(struct net_device *dev, u32 data)
++{
++      int value;
++      //printk("et_set_rx_csum(): data = %d\n", data);
++      value = sysRegRead(GDMA2_FWD_CFG);
++      if(data)
++              value |= GDM1_STRPCRC;
++      else
++              value &= ~GDM1_STRPCRC;
++      sysRegWrite(GDMA1_FWD_CFG, value);
++      return 0;
++}
++
++static int et_virt_nway_reset(struct net_device *dev)
++{
++      PSEUDO_ADAPTER *pseudo  = dev->priv;
++      return mii_nway_restart(&pseudo->mii_info);
++}
++#endif
++
++static u32 et_virt_get_link(struct net_device *dev)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        PSEUDO_ADAPTER *pseudo  = netdev_priv(dev);
++#else
++        PSEUDO_ADAPTER *pseudo  = dev->priv;
++#endif
++      return mii_link_ok(&pseudo->mii_info);
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static int et_virt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++      PSEUDO_ADAPTER *pseudo = dev->priv;
++      int rc = mii_ethtool_sset(&pseudo->mii_info, cmd);
++      return rc;
++}
++#endif
++
++static int et_virt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        PSEUDO_ADAPTER *pseudo  = netdev_priv(dev);
++#else
++        PSEUDO_ADAPTER *pseudo  = dev->priv;
++#endif
++      mii_ethtool_gset(&pseudo->mii_info, cmd);
++      return 0;
++}
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++static u32 et_virt_get_msglevel(struct net_device *dev)
++{
++      return 0;
++}
++
++static void et_virt_set_msglevel(struct net_device *dev, u32 datum)
++{
++      return;
++}
++
++static void et_virt_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
++{
++//    PSEUDO_ADAPTER *pseudo = dev->priv;
++      data[0] = 0;//np->xstats.early_rx;
++      data[1] = 0;//np->xstats.tx_buf_mapped;
++      data[2] = 0;//np->xstats.tx_timeouts;
++      data[3] = 0;//np->xstats.rx_lost_in_ring;
++}
++
++/* for virtual interface dedicated */
++#define RA_VIRT_NUM_STATS                     4
++static struct {
++    const char str[ETH_GSTRING_LEN];
++} ethtool_stats_keys_2[] = {
++    { "statistic1" },
++    { "statistic2" },
++    { "statistic3" },
++    { "statistic4" },
++};
++
++static int et_virt_get_stats_count(struct net_device *dev)
++{
++      return RA_VIRT_NUM_STATS;
++}
++
++static void et_virt_get_strings(struct net_device *dev, u32 stringset, u8 *data)
++{
++      memcpy(data, ethtool_stats_keys_2, sizeof(ethtool_stats_keys_2));
++}
++#endif
++
++struct ethtool_ops ra_virt_ethtool_ops = {
++      .get_settings           = et_virt_get_settings,
++      .get_link               = et_virt_get_link,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)       
++      .get_drvinfo            = et_virt_get_drvinfo,
++      .set_settings           = et_virt_set_settings,
++      .get_pauseparam         = et_virt_get_pauseparam,
++      .set_pauseparam         = et_virt_set_pauseparam,
++      .get_rx_csum            = et_virt_get_rx_csum,
++      .set_rx_csum            = et_virt_set_rx_csum,
++      .get_tx_csum            = et_virt_get_tx_csum,
++      .set_tx_csum            = et_virt_set_tx_csum,
++      .nway_reset             = et_virt_nway_reset,
++      .get_msglevel           = et_virt_get_msglevel,
++      .set_msglevel           = et_virt_set_msglevel,
++      .get_strings            = et_virt_get_strings,
++      .get_stats_count        = et_virt_get_stats_count,
++      .get_ethtool_stats      = et_virt_get_ethtool_stats,
++/*    .get_regs_len           = et_virt_get_regs_len,
++      .get_regs               = et_virt_get_regs,
++*/
++#endif        
++};
++
++int mdio_virt_read(struct net_device *dev, int phy_id, int location)
++{
++      unsigned int result;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        PSEUDO_ADAPTER *pseudo  = netdev_priv(dev);
++#else
++        PSEUDO_ADAPTER *pseudo  = dev->priv;
++#endif
++      mii_mgr_read( (unsigned int) pseudo->mii_info.phy_id, (unsigned int)location, &result);
++//    printk("%s mii.o query= phy_id:%d, address:%d retval:%d\n", dev->name, phy_id, location, result);
++      return (int)result;
++}
++
++void mdio_virt_write(struct net_device *dev, int phy_id, int location, int value)
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        PSEUDO_ADAPTER *pseudo  = netdev_priv(dev);
++#else
++        PSEUDO_ADAPTER *pseudo  = dev->priv;
++#endif
++//    printk("mii.o write= phy_id:%d, address:%d value:%d\n", phy_id, location, value);
++      mii_mgr_write( (unsigned int) pseudo->mii_info.phy_id, (unsigned int)location, (unsigned int)value);
++      return;
++}
++
++#endif /* CONFIG_PSEUDO_SUPPORT */
++
++
+diff --git a/drivers/net/ethernet/raeth/ra_ethtool.h b/drivers/net/ethernet/raeth/ra_ethtool.h
+new file mode 100644
+index 0000000..d64a1ab
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_ethtool.h
+@@ -0,0 +1,13 @@
++#ifndef RA_ETHTOOL_H
++#define RA_ETHTOOL_H
++
++/* ethtool related */
++unsigned char get_current_phy_address(void);
++int mdio_read(struct net_device *dev, int phy_id, int location);
++void mdio_write(struct net_device *dev, int phy_id, int location, int value);
++
++/* for pseudo interface */
++int mdio_virt_read(struct net_device *dev, int phy_id, int location);
++void mdio_virt_write(struct net_device *dev, int phy_id, int location, int value);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_ioctl.h b/drivers/net/ethernet/raeth/ra_ioctl.h
+new file mode 100644
+index 0000000..83b806a
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_ioctl.h
+@@ -0,0 +1,102 @@
++#ifndef _RAETH_IOCTL_H
++#define _RAETH_IOCTL_H
++
++/* ioctl commands */
++#define RAETH_ESW_REG_READ            0x89F1
++#define RAETH_ESW_REG_WRITE           0x89F2
++#define RAETH_MII_READ                        0x89F3
++#define RAETH_MII_WRITE                       0x89F4
++#define RAETH_ESW_INGRESS_RATE                0x89F5
++#define RAETH_ESW_EGRESS_RATE         0x89F6
++#define RAETH_ESW_PHY_DUMP            0x89F7
++#define RAETH_QDMA_REG_READ           0x89F8
++#define RAETH_QDMA_REG_WRITE          0x89F9
++#define RAETH_QDMA_QUEUE_MAPPING        0x89FA
++#define RAETH_QDMA_READ_CPU_CLK         0x89FB
++#define RAETH_MII_READ_CL45             0x89FC
++#define RAETH_MII_WRITE_CL45            0x89FD
++#if defined(CONFIG_HW_SFQ)
++#define RAETH_QDMA_SFQ_WEB_ENABLE       0x89FE
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++    defined (CONFIG_ARCH_MT7623)
++
++#define REG_ESW_WT_MAC_MFC              0x10
++#define REG_ESW_ISC                     0x18
++#define REG_ESW_WT_MAC_ATA1             0x74
++#define REG_ESW_WT_MAC_ATA2             0x78
++#define REG_ESW_WT_MAC_ATWD             0x7C
++#define REG_ESW_WT_MAC_ATC              0x80 
++
++#define REG_ESW_TABLE_TSRA1           0x84
++#define REG_ESW_TABLE_TSRA2           0x88
++#define REG_ESW_TABLE_ATRD            0x8C
++
++
++#define REG_ESW_VLAN_VTCR             0x90
++#define REG_ESW_VLAN_VAWD1            0x94
++#define REG_ESW_VLAN_VAWD2            0x98
++
++
++#define REG_ESW_VLAN_ID_BASE          0x100
++
++//#define REG_ESW_VLAN_ID_BASE                0x50
++#define REG_ESW_VLAN_MEMB_BASE                0x70
++#define REG_ESW_TABLE_SEARCH          0x24
++#define REG_ESW_TABLE_STATUS0         0x28
++#define REG_ESW_TABLE_STATUS1         0x2C
++#define REG_ESW_TABLE_STATUS2         0x30
++#define REG_ESW_WT_MAC_AD0            0x34
++#define REG_ESW_WT_MAC_AD1            0x38
++#define REG_ESW_WT_MAC_AD2            0x3C
++
++#else
++/* rt3052 embedded ethernet switch registers */
++#define REG_ESW_VLAN_ID_BASE          0x50
++#define REG_ESW_VLAN_MEMB_BASE                0x70
++#define REG_ESW_TABLE_SEARCH          0x24
++#define REG_ESW_TABLE_STATUS0         0x28
++#define REG_ESW_TABLE_STATUS1         0x2C
++#define REG_ESW_TABLE_STATUS2         0x30
++#define REG_ESW_WT_MAC_AD0            0x34
++#define REG_ESW_WT_MAC_AD1            0x38
++#define REG_ESW_WT_MAC_AD2            0x3C
++#endif
++
++
++#if defined(CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define REG_ESW_MAX                   0x16C
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++      defined (CONFIG_RALINK_MT7620)
++#define REG_ESW_MAX                   0x7FFFF
++#else //RT305x, RT3350
++#define REG_ESW_MAX                   0xFC
++#endif
++#define REG_HQOS_MAX                  0x3FFF
++
++
++typedef struct rt3052_esw_reg {
++      unsigned int off;
++      unsigned int val;
++} esw_reg;
++
++typedef struct ralink_mii_ioctl_data {
++      __u32   phy_id;
++      __u32   reg_num;
++      __u32   val_in;
++      __u32   val_out;
++      __u32   port_num;
++      __u32   dev_addr;
++      __u32   reg_addr;
++} ra_mii_ioctl_data;
++
++typedef struct rt335x_esw_reg {
++      unsigned int on_off;
++      unsigned int port;
++      unsigned int bw;/*Mbps*/
++} esw_rate;
++
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_mac.c b/drivers/net/ethernet/raeth/ra_mac.c
+new file mode 100644
+index 0000000..e8e978d
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_mac.c
+@@ -0,0 +1,2645 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/signal.h>
++#include <linux/irq.h>
++#include <linux/ctype.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,4)
++#include <asm/system.h>
++#include <linux/mca.h>
++#endif
++#include <asm/io.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++
++#include <asm/rt2880/surfboardint.h>  /* for cp0 reg access, added by bobtseng */
++
++#include <linux/errno.h>
++#include <linux/init.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <asm/uaccess.h>
++
++#include <linux/seq_file.h>
++
++
++#if defined(CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ethtool.h"
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#include "dvt/raether_pdma_dvt.h"
++#endif  //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++extern struct net_device *dev_raether;
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620)
++extern unsigned short p0_rx_good_cnt;
++extern unsigned short p0_tx_good_cnt;
++extern unsigned short p1_rx_good_cnt;
++extern unsigned short p1_tx_good_cnt;
++extern unsigned short p2_rx_good_cnt;
++extern unsigned short p2_tx_good_cnt;
++extern unsigned short p3_rx_good_cnt;
++extern unsigned short p3_tx_good_cnt;
++extern unsigned short p4_rx_good_cnt;
++extern unsigned short p4_tx_good_cnt;
++extern unsigned short p5_rx_good_cnt;
++extern unsigned short p5_tx_good_cnt;
++extern unsigned short p6_rx_good_cnt;
++extern unsigned short p6_tx_good_cnt;
++
++extern unsigned short p0_rx_byte_cnt;
++extern unsigned short p1_rx_byte_cnt;
++extern unsigned short p2_rx_byte_cnt;
++extern unsigned short p3_rx_byte_cnt;
++extern unsigned short p4_rx_byte_cnt;
++extern unsigned short p5_rx_byte_cnt;
++extern unsigned short p6_rx_byte_cnt;
++extern unsigned short p0_tx_byte_cnt;
++extern unsigned short p1_tx_byte_cnt;
++extern unsigned short p2_tx_byte_cnt;
++extern unsigned short p3_tx_byte_cnt;
++extern unsigned short p4_tx_byte_cnt;
++extern unsigned short p5_tx_byte_cnt;
++extern unsigned short p6_tx_byte_cnt;
++
++#if defined(CONFIG_RALINK_MT7620)
++extern unsigned short p7_rx_good_cnt;
++extern unsigned short p7_tx_good_cnt;
++extern unsigned short p7_rx_byte_cnt;
++extern unsigned short p7_tx_byte_cnt;
++#endif
++#endif
++
++
++
++#if defined(CONFIG_RAETH_TSO)
++int txd_cnt[MAX_SKB_FRAGS/2 + 1];
++int tso_cnt[16];
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++#define MAX_AGGR 64
++#define MAX_DESC  8
++int lro_stats_cnt[MAX_AGGR + 1];
++int lro_flush_cnt[MAX_AGGR + 1];
++int lro_len_cnt1[16];
++//int lro_len_cnt2[16];
++int aggregated[MAX_DESC];
++int lro_aggregated;
++int lro_flushed;
++int lro_nodesc;
++int force_flush;
++int tot_called1;
++int tot_called2;
++#endif
++
++#if defined(CONFIG_RAETH_HW_LRO)
++#define HW_LRO_RING_NUM 3
++#define MAX_HW_LRO_AGGR 64
++unsigned int hw_lro_agg_num_cnt[HW_LRO_RING_NUM][MAX_HW_LRO_AGGR + 1];
++unsigned int hw_lro_agg_size_cnt[HW_LRO_RING_NUM][16];
++unsigned int hw_lro_tot_agg_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_tot_flush_cnt[HW_LRO_RING_NUM];
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++unsigned int hw_lro_agg_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_age_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_seq_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_timestamp_flush_cnt[HW_LRO_RING_NUM];
++unsigned int hw_lro_norule_flush_cnt[HW_LRO_RING_NUM];
++#endif  /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_QDMA)
++extern unsigned int M2Q_table[64];
++extern struct QDMA_txdesc *free_head; 
++#endif
++#if defined (CONFIG_ARCH_MT7623)
++extern struct SFQ_table *sfq0;
++extern struct SFQ_table *sfq1;
++extern struct SFQ_table *sfq2;
++extern struct SFQ_table *sfq3;
++#endif
++
++#if defined(CONFIG_USER_SNMPD)
++
++static int ra_snmp_seq_show(struct seq_file *seq, void *v)
++{
++#if !defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7620) && !defined (CONFIG_RALINK_MT7628)
++
++      seq_printf(seq, "rx counters: %x %x %x %x %x %x %x\n", sysRegRead(GDMA_RX_GBCNT0), sysRegRead(GDMA_RX_GPCNT0),sysRegRead(GDMA_RX_OERCNT0), sysRegRead(GDMA_RX_FERCNT0), sysRegRead(GDMA_RX_SERCNT0), sysRegRead(GDMA_RX_LERCNT0), sysRegRead(GDMA_RX_CERCNT0));
++
++      seq_printf(seq, "fc config: %x %x %x %x\n", sysRegRead(CDMA_FC_CFG), sysRegRead(GDMA1_FC_CFG), PDMA_FC_CFG, sysRegRead(PDMA_FC_CFG));
++
++      seq_printf(seq, "scheduler: %x %x %x\n", sysRegRead(GDMA1_SCH_CFG), sysRegRead(GDMA2_SCH_CFG), sysRegRead(PDMA_SCH_CFG));
++
++#endif
++      seq_printf(seq, "ports: %x %x %x %x %x %x\n", sysRegRead(PORT0_PKCOUNT), sysRegRead(PORT1_PKCOUNT), sysRegRead(PORT2_PKCOUNT), sysRegRead(PORT3_PKCOUNT), sysRegRead(PORT4_PKCOUNT), sysRegRead(PORT5_PKCOUNT));
++
++      return 0;
++}
++
++static int ra_snmp_seq_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, ra_snmp_seq_show, NULL);
++}
++
++static const struct file_operations ra_snmp_seq_fops = {
++      .owner   = THIS_MODULE,
++      .open    = ra_snmp_seq_open,
++      .read    = seq_read,
++      .llseek  = seq_lseek,
++      .release = single_release
++};
++#endif
++
++
++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_100PHY) || \
++    defined (CONFIG_P5_MAC_TO_PHY_MODE) || defined (CONFIG_RAETH_GMAC2)
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621)  || \
++    defined (CONFIG_ARCH_MT7623)
++void enable_auto_negotiate(int unused)
++{
++      u32 regValue;
++#if !defined (CONFIG_RALINK_MT7621) && !defined (CONFIG_ARCH_MT7623)
++      u32 addr = CONFIG_MAC_TO_GIGAPHY_MODE_ADDR;
++#endif
++
++#if defined (CONFIG_RALINK_MT7621)
++      //enable MDIO mode all the time
++      regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++      regValue &= ~(0x3 << 12);
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++#endif
++      
++      /* FIXME: we don't know how to deal with PHY end addr */
++      regValue = sysRegRead(ESW_PHY_POLLING);
++      regValue |= (1<<31);
++      regValue &= ~(0x1f);
++      regValue &= ~(0x1f<<8);
++#if defined (CONFIG_RALINK_MT7620)
++      regValue |= ((addr-1) << 0);//setup PHY address for auto polling (Start Addr).
++      regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)|| defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) || defined (CONFIG_GE2_RGMII_AN)
++      regValue |= ((CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2-1)&0x1f << 0);//setup PHY address for auto polling (Start Addr).
++      regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 8);// setup PHY address for auto polling (End Addr).
++#else
++      regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR << 0);//setup PHY address for auto polling (Start Addr).
++      regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 8);// setup PHY address for auto polling (End Addr).
++#endif
++#else
++      regValue |= (addr << 0);// setup PHY address for auto polling (start Addr).
++      regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
++#endif
++
++      /*kurtis: AN is strange*/
++      sysRegWrite(ESW_PHY_POLLING, regValue);
++
++#if defined (CONFIG_P4_MAC_TO_PHY_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330;
++#endif
++#if defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x56330;
++#endif
++}
++#elif defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT3883) || \
++      defined (CONFIG_RALINK_RT3052) || defined(CONFIG_RALINK_RT3352)
++
++void enable_auto_negotiate(int ge)
++{
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352)
++        u32 regValue = sysRegRead(0xb01100C8);
++#else
++      u32 regValue;
++      regValue = (ge == 2)? sysRegRead(MDIO_CFG2) : sysRegRead(MDIO_CFG);
++#endif
++
++        regValue &= 0xe0ff7fff;                 // clear auto polling related field:
++                                                // (MD_PHY1ADDR & GP1_FRC_EN).
++        regValue |= 0x20000000;                 // force to enable MDC/MDIO auto polling.
++
++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_GE2_MII_AN)
++      if(ge==2) {
++          regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2 << 24);               // setup PHY address for auto polling.
++      }
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_GE1_MII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      if(ge==1) {
++          regValue |= (CONFIG_MAC_TO_GIGAPHY_MODE_ADDR << 24);               // setup PHY address for auto polling.
++      }
++#endif
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352)
++      sysRegWrite(0xb01100C8, regValue);
++#else
++      if (ge == 2)
++              sysRegWrite(MDIO_CFG2, regValue);
++      else
++              sysRegWrite(MDIO_CFG, regValue);
++#endif
++}
++#endif
++#endif
++void ra2880stop(END_DEVICE *ei_local)
++{
++      unsigned int regValue;
++      printk("ra2880stop()...");
++
++      regValue = sysRegRead(DMA_GLO_CFG);
++      regValue &= ~(TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN);
++      sysRegWrite(DMA_GLO_CFG, regValue);
++      
++      printk("Done\n");       
++      // printk("Done0x%x...\n", readreg(DMA_GLO_CFG));
++}
++
++void ei_irq_clear(void)
++{
++        sysRegWrite(FE_INT_STATUS, 0xFFFFFFFF);
++}
++
++void rt2880_gmac_hard_reset(void)
++{
++#if !defined (CONFIG_RALINK_RT6855A)
++      //FIXME
++      sysRegWrite(RSTCTRL, RALINK_FE_RST);
++      sysRegWrite(RSTCTRL, 0);
++#endif
++}
++
++void ra2880EnableInterrupt()
++{
++      unsigned int regValue = sysRegRead(FE_INT_ENABLE);
++      RAETH_PRINT("FE_INT_ENABLE -- : 0x%08x\n", regValue);
++//    regValue |= (RX_DONE_INT0 | TX_DONE_INT0);
++              
++      sysRegWrite(FE_INT_ENABLE, regValue);
++}
++
++void ra2880MacAddressSet(unsigned char p[6])
++{
++        unsigned long regValue;
++
++      regValue = (p[0] << 8) | (p[1]);
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++        sysRegWrite(SDM_MAC_ADRH, regValue);
++      printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(SDM_MAC_ADRH));
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)
++        sysRegWrite(GDMA1_MAC_ADRH, regValue);
++      printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRH));
++
++      /* To keep the consistence between RT6855 and RT62806, GSW should keep the register. */
++        sysRegWrite(SMACCR1, regValue);
++      printk("SMACCR1 -- : 0x%08x\n", sysRegRead(SMACCR1));
++#elif defined (CONFIG_RALINK_MT7620)
++        sysRegWrite(SMACCR1, regValue);
++      printk("SMACCR1 -- : 0x%08x\n", sysRegRead(SMACCR1));
++#else
++        sysRegWrite(GDMA1_MAC_ADRH, regValue);
++      printk("GMAC1_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRH));
++#endif
++
++        regValue = (p[2] << 24) | (p[3] <<16) | (p[4] << 8) | p[5];
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++        sysRegWrite(SDM_MAC_ADRL, regValue);
++      printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(SDM_MAC_ADRL));           
++#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)
++        sysRegWrite(GDMA1_MAC_ADRL, regValue);
++      printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRL));         
++
++      /* To keep the consistence between RT6855 and RT62806, GSW should keep the register. */
++        sysRegWrite(SMACCR0, regValue);
++      printk("SMACCR0 -- : 0x%08x\n", sysRegRead(SMACCR0));
++#elif defined (CONFIG_RALINK_MT7620)
++        sysRegWrite(SMACCR0, regValue);
++      printk("SMACCR0 -- : 0x%08x\n", sysRegRead(SMACCR0));
++#else
++        sysRegWrite(GDMA1_MAC_ADRL, regValue);
++      printk("GMAC1_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA1_MAC_ADRL));         
++#endif
++
++        return;
++}
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++void ra2880Mac2AddressSet(unsigned char p[6])
++{
++        unsigned long regValue;
++
++      regValue = (p[0] << 8) | (p[1]);
++        sysRegWrite(GDMA2_MAC_ADRH, regValue);
++
++        regValue = (p[2] << 24) | (p[3] <<16) | (p[4] << 8) | p[5];
++        sysRegWrite(GDMA2_MAC_ADRL, regValue);
++
++      printk("GDMA2_MAC_ADRH -- : 0x%08x\n", sysRegRead(GDMA2_MAC_ADRH));
++      printk("GDMA2_MAC_ADRL -- : 0x%08x\n", sysRegRead(GDMA2_MAC_ADRL));         
++        return;
++}
++#endif
++
++/**
++ * hard_init - Called by raeth_probe to inititialize network device
++ * @dev: device pointer
++ *
++ * ethdev_init initilize dev->priv and set to END_DEVICE structure
++ *
++ */
++void ethtool_init(struct net_device *dev)
++{
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++      END_DEVICE *ei_local = netdev_priv(dev);
++
++      // init mii structure
++      ei_local->mii_info.dev = dev;
++      ei_local->mii_info.mdio_read = mdio_read;
++      ei_local->mii_info.mdio_write = mdio_write;
++      ei_local->mii_info.phy_id_mask = 0x1f;
++      ei_local->mii_info.reg_num_mask = 0x1f;
++      ei_local->mii_info.supports_gmii = mii_check_gmii_support(&ei_local->mii_info);
++      // TODO:   phy_id: 0~4
++      ei_local->mii_info.phy_id = 1;
++#endif
++      return;
++}
++
++/*
++ *    Routine Name : get_idx(mode, index)
++ *    Description: calculate ring usage for tx/rx rings
++ *    Mode 1 : Tx Ring 
++ *    Mode 2 : Rx Ring
++ */
++int get_ring_usage(int mode, int i)
++{
++      unsigned long tx_ctx_idx, tx_dtx_idx, tx_usage;
++      unsigned long rx_calc_idx, rx_drx_idx, rx_usage;
++
++      struct PDMA_rxdesc* rxring;
++      struct PDMA_txdesc* txring;
++
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++
++      if (mode == 2 ) {
++              /* cpu point to the next descriptor of rx dma ring */
++              rx_calc_idx = *(unsigned long*)RX_CALC_IDX0;
++              rx_drx_idx = *(unsigned long*)RX_DRX_IDX0;
++              rxring = (struct PDMA_rxdesc*)RX_BASE_PTR0;
++              
++              rx_usage = (rx_drx_idx - rx_calc_idx -1 + NUM_RX_DESC) % NUM_RX_DESC;
++              if ( rx_calc_idx == rx_drx_idx ) {
++                  if ( rxring[rx_drx_idx].rxd_info2.DDONE_bit == 1)
++                      tx_usage = NUM_RX_DESC;
++                  else
++                      tx_usage = 0;
++              }
++              return rx_usage;
++      }
++
++      
++      switch (i) {
++              case 0:
++                              tx_ctx_idx = *(unsigned long*)TX_CTX_IDX0;
++                              tx_dtx_idx = *(unsigned long*)TX_DTX_IDX0;
++                              txring = ei_local->tx_ring0;
++                              break;
++#if defined(CONFIG_RAETH_QOS)
++              case 1:
++                              tx_ctx_idx = *(unsigned long*)TX_CTX_IDX1;
++                              tx_dtx_idx = *(unsigned long*)TX_DTX_IDX1;
++                              txring = ei_local->tx_ring1;
++                              break;
++              case 2:
++                              tx_ctx_idx = *(unsigned long*)TX_CTX_IDX2;
++                              tx_dtx_idx = *(unsigned long*)TX_DTX_IDX2;
++                              txring = ei_local->tx_ring2;
++                              break;
++              case 3:
++                              tx_ctx_idx = *(unsigned long*)TX_CTX_IDX3;
++                              tx_dtx_idx = *(unsigned long*)TX_DTX_IDX3;
++                              txring = ei_local->tx_ring3;
++                              break;
++#endif
++              default:
++                      printk("get_tx_idx failed %d %d\n", mode, i);
++                      return 0;
++      };
++
++      tx_usage = (tx_ctx_idx - tx_dtx_idx + NUM_TX_DESC) % NUM_TX_DESC;
++      if ( tx_ctx_idx == tx_dtx_idx ) {
++              if ( txring[tx_ctx_idx].txd_info2.DDONE_bit == 1)
++                      tx_usage = 0;
++              else
++                      tx_usage = NUM_TX_DESC;
++      }
++      return tx_usage;
++
++}
++
++#if defined(CONFIG_RAETH_QOS)
++void dump_qos(struct seq_file *s)
++{
++      int usage;
++      int i;
++
++      seq_printf(s, "\n-----Raeth QOS -----\n\n");
++
++      for ( i = 0; i < 4; i++)  {
++              usage = get_ring_usage(1,i);
++              seq_printf(s, "Tx Ring%d Usage : %d/%d\n", i, usage, NUM_TX_DESC);
++      }
++
++      usage = get_ring_usage(2,0);
++      seq_printf(s, "RX Usage : %d/%d\n\n", usage, NUM_RX_DESC);
++#if defined  (CONFIG_RALINK_MT7620)
++      seq_printf(s, "PSE_FQFC_CFG(0x%08x)  : 0x%08x\n", PSE_FQFC_CFG, sysRegRead(PSE_FQFC_CFG));
++      seq_printf(s, "PSE_IQ_CFG(0x%08x)  : 0x%08x\n", PSE_IQ_CFG, sysRegRead(PSE_IQ_CFG));
++      seq_printf(s, "PSE_QUE_STA(0x%08x)  : 0x%08x\n", PSE_QUE_STA, sysRegRead(PSE_QUE_STA));
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++
++#else
++      seq_printf(s, "GDMA1_FC_CFG(0x%08x)  : 0x%08x\n", GDMA1_FC_CFG, sysRegRead(GDMA1_FC_CFG));
++      seq_printf(s, "GDMA2_FC_CFG(0x%08x)  : 0x%08x\n", GDMA2_FC_CFG, sysRegRead(GDMA2_FC_CFG));
++      seq_printf(s, "PDMA_FC_CFG(0x%08x)  : 0x%08x\n", PDMA_FC_CFG, sysRegRead(PDMA_FC_CFG));
++      seq_printf(s, "PSE_FQ_CFG(0x%08x)  : 0x%08x\n", PSE_FQ_CFG, sysRegRead(PSE_FQ_CFG));
++#endif
++      seq_printf(s, "\n\nTX_CTX_IDX0    : 0x%08x\n", sysRegRead(TX_CTX_IDX0));        
++      seq_printf(s, "TX_DTX_IDX0    : 0x%08x\n", sysRegRead(TX_DTX_IDX0));
++      seq_printf(s, "TX_CTX_IDX1    : 0x%08x\n", sysRegRead(TX_CTX_IDX1));    
++      seq_printf(s, "TX_DTX_IDX1    : 0x%08x\n", sysRegRead(TX_DTX_IDX1));
++      seq_printf(s, "TX_CTX_IDX2    : 0x%08x\n", sysRegRead(TX_CTX_IDX2));    
++      seq_printf(s, "TX_DTX_IDX2    : 0x%08x\n", sysRegRead(TX_DTX_IDX2));
++      seq_printf(s, "TX_CTX_IDX3    : 0x%08x\n", sysRegRead(TX_CTX_IDX3));
++      seq_printf(s, "TX_DTX_IDX3    : 0x%08x\n", sysRegRead(TX_DTX_IDX3));
++      seq_printf(s, "RX_CALC_IDX0   : 0x%08x\n", sysRegRead(RX_CALC_IDX0));
++      seq_printf(s, "RX_DRX_IDX0    : 0x%08x\n", sysRegRead(RX_DRX_IDX0));
++
++      seq_printf(s, "\n------------------------------\n\n");
++}
++#endif
++
++void dump_reg(struct seq_file *s)
++{
++      int fe_int_enable;
++      int rx_usage;
++      int dly_int_cfg;
++      int rx_base_ptr0;
++      int rx_max_cnt0;
++      int rx_calc_idx0;
++      int rx_drx_idx0;
++#if !defined (CONFIG_RAETH_QDMA)
++      int tx_usage;
++      int tx_base_ptr[4];
++      int tx_max_cnt[4];
++      int tx_ctx_idx[4];
++      int tx_dtx_idx[4];
++      int i;
++#endif
++
++      fe_int_enable = sysRegRead(FE_INT_ENABLE);
++        rx_usage = get_ring_usage(2,0);
++
++      dly_int_cfg = sysRegRead(DLY_INT_CFG);
++      
++#if !defined (CONFIG_RAETH_QDMA)
++      tx_usage = get_ring_usage(1,0);
++
++      tx_base_ptr[0] = sysRegRead(TX_BASE_PTR0);
++      tx_max_cnt[0] = sysRegRead(TX_MAX_CNT0);
++      tx_ctx_idx[0] = sysRegRead(TX_CTX_IDX0);
++      tx_dtx_idx[0] = sysRegRead(TX_DTX_IDX0);
++      
++      tx_base_ptr[1] = sysRegRead(TX_BASE_PTR1);
++      tx_max_cnt[1] = sysRegRead(TX_MAX_CNT1);
++      tx_ctx_idx[1] = sysRegRead(TX_CTX_IDX1);
++      tx_dtx_idx[1] = sysRegRead(TX_DTX_IDX1);
++
++      tx_base_ptr[2] = sysRegRead(TX_BASE_PTR2);
++      tx_max_cnt[2] = sysRegRead(TX_MAX_CNT2);
++      tx_ctx_idx[2] = sysRegRead(TX_CTX_IDX2);
++      tx_dtx_idx[2] = sysRegRead(TX_DTX_IDX2);
++      
++      tx_base_ptr[3] = sysRegRead(TX_BASE_PTR3);
++      tx_max_cnt[3] = sysRegRead(TX_MAX_CNT3);
++      tx_ctx_idx[3] = sysRegRead(TX_CTX_IDX3);
++      tx_dtx_idx[3] = sysRegRead(TX_DTX_IDX3);
++#endif
++
++      rx_base_ptr0 = sysRegRead(RX_BASE_PTR0);
++      rx_max_cnt0 = sysRegRead(RX_MAX_CNT0);
++      rx_calc_idx0 = sysRegRead(RX_CALC_IDX0);
++      rx_drx_idx0 = sysRegRead(RX_DRX_IDX0);
++
++      seq_printf(s, "\n\nFE_INT_ENABLE  : 0x%08x\n", fe_int_enable);
++#if !defined (CONFIG_RAETH_QDMA)
++      seq_printf(s, "TxRing PktCnt: %d/%d\n", tx_usage, NUM_TX_DESC);
++#endif
++      seq_printf(s, "RxRing PktCnt: %d/%d\n\n", rx_usage, NUM_RX_DESC);
++      seq_printf(s, "DLY_INT_CFG    : 0x%08x\n", dly_int_cfg);
++
++#if !defined (CONFIG_RAETH_QDMA)      
++      for(i=0;i<4;i++) {
++              seq_printf(s, "TX_BASE_PTR%d   : 0x%08x\n", i, tx_base_ptr[i]); 
++              seq_printf(s, "TX_MAX_CNT%d    : 0x%08x\n", i, tx_max_cnt[i]);  
++              seq_printf(s, "TX_CTX_IDX%d     : 0x%08x\n", i, tx_ctx_idx[i]);
++              seq_printf(s, "TX_DTX_IDX%d     : 0x%08x\n", i, tx_dtx_idx[i]);
++      }
++#endif
++
++      seq_printf(s, "RX_BASE_PTR0   : 0x%08x\n", rx_base_ptr0);       
++      seq_printf(s, "RX_MAX_CNT0    : 0x%08x\n", rx_max_cnt0);        
++      seq_printf(s, "RX_CALC_IDX0   : 0x%08x\n", rx_calc_idx0);
++      seq_printf(s, "RX_DRX_IDX0    : 0x%08x\n", rx_drx_idx0);
++      
++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER)
++      seq_printf(s, "The current PHY address selected by ethtool is %d\n", get_current_phy_address());
++#endif
++
++#if defined (CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883)
++      seq_printf(s, "GDMA_RX_FCCNT1(0x%08x)     : 0x%08x\n\n", GDMA_RX_FCCNT1, sysRegRead(GDMA_RX_FCCNT1));   
++#endif
++}
++
++#if 0
++void dump_cp0(void)
++{
++      printk("CP0 Register dump --\n");
++      printk("CP0_INDEX\t: 0x%08x\n", read_32bit_cp0_register(CP0_INDEX));
++      printk("CP0_RANDOM\t: 0x%08x\n", read_32bit_cp0_register(CP0_RANDOM));
++      printk("CP0_ENTRYLO0\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO0));
++      printk("CP0_ENTRYLO1\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO1));
++      printk("CP0_CONF\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONF));
++      printk("CP0_CONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONTEXT));
++      printk("CP0_PAGEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_PAGEMASK));
++      printk("CP0_WIRED\t: 0x%08x\n", read_32bit_cp0_register(CP0_WIRED));
++      printk("CP0_INFO\t: 0x%08x\n", read_32bit_cp0_register(CP0_INFO));
++      printk("CP0_BADVADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_BADVADDR));
++      printk("CP0_COUNT\t: 0x%08x\n", read_32bit_cp0_register(CP0_COUNT));
++      printk("CP0_ENTRYHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYHI));
++      printk("CP0_COMPARE\t: 0x%08x\n", read_32bit_cp0_register(CP0_COMPARE));
++      printk("CP0_STATUS\t: 0x%08x\n", read_32bit_cp0_register(CP0_STATUS));
++      printk("CP0_CAUSE\t: 0x%08x\n", read_32bit_cp0_register(CP0_CAUSE));
++      printk("CP0_EPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_EPC));
++      printk("CP0_PRID\t: 0x%08x\n", read_32bit_cp0_register(CP0_PRID));
++      printk("CP0_CONFIG\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONFIG));
++      printk("CP0_LLADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_LLADDR));
++      printk("CP0_WATCHLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHLO));
++      printk("CP0_WATCHHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHHI));
++      printk("CP0_XCONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_XCONTEXT));
++      printk("CP0_FRAMEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_FRAMEMASK));
++      printk("CP0_DIAGNOSTIC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DIAGNOSTIC));
++      printk("CP0_DEBUG\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEBUG));
++      printk("CP0_DEPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEPC));
++      printk("CP0_PERFORMANCE\t: 0x%08x\n", read_32bit_cp0_register(CP0_PERFORMANCE));
++      printk("CP0_ECC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ECC));
++      printk("CP0_CACHEERR\t: 0x%08x\n", read_32bit_cp0_register(CP0_CACHEERR));
++      printk("CP0_TAGLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGLO));
++      printk("CP0_TAGHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGHI));
++      printk("CP0_ERROREPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ERROREPC));
++      printk("CP0_DESAVE\t: 0x%08x\n\n", read_32bit_cp0_register(CP0_DESAVE));
++}
++#endif
++
++struct proc_dir_entry *procRegDir;
++static struct proc_dir_entry *procGmac, *procSysCP0, *procTxRing, *procRxRing, *procSkbFree;
++#if defined(CONFIG_PSEUDO_SUPPORT) && defined(CONFIG_ETHTOOL)
++static struct proc_dir_entry *procGmac2;
++#endif
++#if defined(CONFIG_USER_SNMPD)
++static struct proc_dir_entry *procRaSnmp;
++#endif
++#if defined(CONFIG_RAETH_TSO)
++static struct proc_dir_entry *procNumOfTxd, *procTsoLen;
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++static struct proc_dir_entry *procLroStats;
++#endif
++#if defined(CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static struct proc_dir_entry *procRxRing1, *procRxRing2, *procRxRing3;
++static struct proc_dir_entry *procHwLroStats, *procHwLroAutoTlb;
++const static HWLRO_DBG_FUNC hw_lro_dbg_func[] =
++{
++    [0] = hwlro_agg_cnt_ctrl,
++    [1] = hwlro_agg_time_ctrl,
++    [2] = hwlro_age_time_ctrl,
++    [3] = hwlro_pkt_int_alpha_ctrl,
++    [4] = hwlro_threshold_ctrl,
++    [5] = hwlro_fix_setting_switch_ctrl,
++};
++#endif  /* CONFIG_RAETH_HW_LRO */
++#if defined (TASKLET_WORKQUEUE_SW)
++static struct proc_dir_entry *procSCHE;
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++static struct proc_dir_entry *procPdmaDvt;
++
++const static PDMA_DBG_FUNC pdma_dvt_dbg_func[] =
++{
++    [0] = pdma_dvt_show_ctrl,
++    [1] = pdma_dvt_test_rx_ctrl,
++    [2] = pdma_dvt_test_tx_ctrl,
++    [3] = pdma_dvt_test_debug_ctrl,
++    [4] = pdma_dvt_test_lro_ctrl,
++};
++#endif  //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++int RegReadMain(struct seq_file *seq, void *v)
++{
++      dump_reg(seq);
++      return 0;
++}
++
++static void *seq_SkbFree_start(struct seq_file *seq, loff_t *pos)
++{
++      if (*pos < NUM_TX_DESC)
++              return pos;
++      return NULL;
++}
++
++static void *seq_SkbFree_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      (*pos)++;
++      if (*pos >= NUM_TX_DESC)
++              return NULL;
++      return pos;
++}
++
++static void seq_SkbFree_stop(struct seq_file *seq, void *v)
++{
++      /* Nothing to do */
++}
++
++static int seq_SkbFree_show(struct seq_file *seq, void *v)
++{
++      int i = *(loff_t *) v;
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++      seq_printf(seq, "%d: %08x\n",i,  *(int *)&ei_local->skb_free[i]);
++
++      return 0;
++}
++
++static const struct seq_operations seq_skb_free_ops = {
++      .start = seq_SkbFree_start,
++      .next  = seq_SkbFree_next,
++      .stop  = seq_SkbFree_stop,
++      .show  = seq_SkbFree_show
++};
++
++static int skb_free_open(struct inode *inode, struct file *file)
++{
++      return seq_open(file, &seq_skb_free_ops);
++}
++
++static const struct file_operations skb_free_fops = {
++      .owner          = THIS_MODULE,
++      .open           = skb_free_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = seq_release
++};
++
++#if defined (CONFIG_RAETH_QDMA)
++int QDMARead(struct seq_file *seq, void *v)
++{
++      unsigned int temp,i;
++      unsigned int sw_fq, hw_fq;
++      unsigned int min_en, min_rate, max_en, max_rate, sch, weight;
++      unsigned int queue, tx_des_cnt, hw_resv, sw_resv, queue_head, queue_tail;
++      struct net_device *dev = dev_raether;
++        END_DEVICE *ei_local = netdev_priv(dev);
++
++      seq_printf(seq, "==== General Information ====\n");
++      temp = sysRegRead(QDMA_FQ_CNT);
++      sw_fq = (temp&0xFFFF0000)>>16;
++      hw_fq = (temp&0x0000FFFF);
++      seq_printf(seq, "SW TXD: %d/%d; HW TXD: %d/%d\n", sw_fq, NUM_TX_DESC, hw_fq,NUM_QDMA_PAGE);
++      seq_printf(seq, "SW TXD virtual start address: 0x%08x\n", ei_local->txd_pool);
++      seq_printf(seq, "HW TXD virtual start address: 0x%08x\n\n", free_head);
++
++      seq_printf(seq, "==== Scheduler Information ====\n");
++      temp = sysRegRead(QDMA_TX_SCH);
++      max_en = (temp&0x00000800)>>11;
++      max_rate = (temp&0x000007F0)>>4;
++      for(i=0;i<(temp&0x0000000F);i++)
++              max_rate *= 10;
++      seq_printf(seq, "SCH1 rate control:%d. Rate is %dKbps.\n", max_en, max_rate);
++      max_en = (temp&0x08000000)>>27;
++      max_rate = (temp&0x07F00000)>>20;
++      for(i=0;i<(temp&0x000F0000);i++)
++              max_rate *= 10;
++      seq_printf(seq, "SCH2 rate control:%d. Rate is %dKbps.\n\n", max_en, max_rate);
++
++      seq_printf(seq, "==== Physical Queue Information ====\n");
++      for (queue = 0; queue < 16; queue++){
++              temp = sysRegRead(QTX_CFG_0 + 0x10 * queue);
++              tx_des_cnt = (temp & 0xffff0000) >> 16;
++              hw_resv = (temp & 0xff00) >> 8;
++              sw_resv = (temp & 0xff);
++              temp = sysRegRead(QTX_CFG_0 +(0x10 * queue) + 0x4);
++              sch = (temp >> 31) + 1 ;
++              min_en = (temp & 0x8000000) >> 27;
++              min_rate = (temp & 0x7f00000) >> 20;
++              for (i = 0; i< (temp & 0xf0000) >> 16; i++)
++                      min_rate *= 10;
++              max_en = (temp & 0x800) >> 11;
++              max_rate = (temp & 0x7f0) >> 4;
++              for (i = 0; i< (temp & 0xf); i++)
++                      max_rate *= 10;
++              weight = (temp & 0xf000) >> 12;
++              queue_head = sysRegRead(QTX_HEAD_0 + 0x10 * queue);
++              queue_tail = sysRegRead(QTX_TAIL_0 + 0x10 * queue);
++
++              seq_printf(seq, "Queue#%d Information:\n", queue);
++              seq_printf(seq, "%d packets in the queue; head address is 0x%08x, tail address is 0x%08x.\n", tx_des_cnt, queue_head, queue_tail);
++              seq_printf(seq, "HW_RESV: %d; SW_RESV: %d; SCH: %d; Weighting: %d\n", hw_resv, sw_resv, sch, weight);
++              seq_printf(seq, "Min_Rate_En is %d, Min_Rate is %dKbps; Max_Rate_En is %d, Max_Rate is %dKbps.\n\n", min_en, min_rate, max_en, max_rate);
++      }
++#if defined (CONFIG_ARCH_MT7623) && defined(CONFIG_HW_SFQ)
++      seq_printf(seq, "==== Virtual Queue Information ====\n");
++      seq_printf(seq, "VQTX_TB_BASE_0:0x%08x;VQTX_TB_BASE_1:0x%08x;VQTX_TB_BASE_2:0x%08x;VQTX_TB_BASE_3:0x%08x\n", \
++                      sfq0, sfq1, sfq2, sfq3);
++      temp = sysRegRead(VQTX_NUM);
++      seq_printf(seq, "VQTX_NUM_0:0x%01x;VQTX_NUM_1:0x%01x;VQTX_NUM_2:0x%01x;VQTX_NUM_3:0x%01x\n\n", \
++                      temp&0xF, (temp&0xF0)>>4, (temp&0xF00)>>8, (temp&0xF000)>>12);
++
++#endif
++
++      seq_printf(seq, "==== Flow Control Information ====\n");
++      temp = sysRegRead(QDMA_FC_THRES);
++      seq_printf(seq, "SW_DROP_EN:%x; SW_DROP_FFA:%d; SW_DROP_MODE:%d\n", \
++                      (temp&0x1000000)>>24, (temp&0x200000)>>25, (temp&0x30000000)>>28);
++      seq_printf(seq, "WH_DROP_EN:%x; HW_DROP_FFA:%d; HW_DROP_MODE:%d\n", \
++                      (temp&0x10000)>>16, (temp&0x2000)>>17, (temp&0x300000)>>20);
++#if defined (CONFIG_ARCH_MT7623)
++      seq_printf(seq, "SW_DROP_FSTVQ_MODE:%d;SW_DROP_FSTVQ:%d\n", \
++                      (temp&0xC0000000)>>30, (temp&0x08000000)>>27);
++      seq_printf(seq, "HW_DROP_FSTVQ_MODE:%d;HW_DROP_FSTVQ:%d\n", \
++                      (temp&0xC00000)>>22, (temp&0x080000)>>19);
++#endif
++
++      seq_printf(seq, "\n==== FSM Information\n");
++      temp = sysRegRead(QDMA_DMA);
++#if defined (CONFIG_ARCH_MT7623)
++      seq_printf(seq, "VQTB_FSM:0x%01x\n", (temp&0x0F000000)>>24);
++#endif
++      seq_printf(seq, "FQ_FSM:0x%01x\n", (temp&0x000F0000)>>16);
++      seq_printf(seq, "TX_FSM:0x%01x\n", (temp&0x00000F00)>>12);
++      seq_printf(seq, "RX_FSM:0x%01x\n\n", (temp&0x0000000f));
++
++      seq_printf(seq, "==== M2Q Information ====\n");
++      for (i = 0; i < 64; i+=8){
++              seq_printf(seq, " (%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)\n",
++                              i, M2Q_table[i], i+1, M2Q_table[i+1], i+2, M2Q_table[i+2], i+3, M2Q_table[i+3],
++                              i+4, M2Q_table[i+4], i+5, M2Q_table[i+5], i+6, M2Q_table[i+6], i+7, M2Q_table[i+7]);
++      }
++
++      return 0;
++
++}
++
++static int qdma_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, QDMARead, NULL);
++}
++
++static const struct file_operations qdma_fops = {
++      .owner          = THIS_MODULE,
++      .open           = qdma_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++#endif
++
++int TxRingRead(struct seq_file *seq, void *v)
++{
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++      struct PDMA_txdesc *tx_ring;
++      int i = 0;
++
++      tx_ring = kmalloc(sizeof(struct PDMA_txdesc) * NUM_TX_DESC, GFP_KERNEL);
++        if(tx_ring==NULL){
++              seq_printf(seq, " allocate temp tx_ring fail.\n");
++              return 0;
++      }
++
++      for (i=0; i < NUM_TX_DESC; i++) {
++              tx_ring[i] = ei_local->tx_ring0[i];
++        }
++      
++      for (i=0; i < NUM_TX_DESC; i++) {
++#ifdef CONFIG_32B_DESC
++              seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i,  *(int *)&tx_ring[i].txd_info1, 
++                              *(int *)&tx_ring[i].txd_info2, *(int *)&tx_ring[i].txd_info3, 
++                              *(int *)&tx_ring[i].txd_info4, *(int *)&tx_ring[i].txd_info5, 
++                              *(int *)&tx_ring[i].txd_info6, *(int *)&tx_ring[i].txd_info7,
++                              *(int *)&tx_ring[i].txd_info8);
++#else
++              seq_printf(seq, "%d: %08x %08x %08x %08x\n",i,  *(int *)&tx_ring[i].txd_info1, *(int *)&tx_ring[i].txd_info2, 
++                              *(int *)&tx_ring[i].txd_info3, *(int *)&tx_ring[i].txd_info4);
++#endif
++      }
++
++      kfree(tx_ring);
++      return 0;
++}
++
++static int tx_ring_open(struct inode *inode, struct file *file)
++{
++#if !defined (CONFIG_RAETH_QDMA)
++      return single_open(file, TxRingRead, NULL);
++#else
++      return single_open(file, QDMARead, NULL);
++#endif
++}
++
++static const struct file_operations tx_ring_fops = {
++      .owner          = THIS_MODULE,
++      .open           = tx_ring_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++
++int RxRingRead(struct seq_file *seq, void *v)
++{
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++      struct PDMA_rxdesc *rx_ring;
++      int i = 0;
++
++      rx_ring = kmalloc(sizeof(struct PDMA_rxdesc) * NUM_RX_DESC, GFP_KERNEL);
++      if(rx_ring==NULL){
++              seq_printf(seq, " allocate temp rx_ring fail.\n");
++              return 0;
++      }
++
++      for (i=0; i < NUM_RX_DESC; i++) {
++              memcpy(&rx_ring[i], &ei_local->rx_ring0[i], sizeof(struct PDMA_rxdesc));
++      }
++      
++      for (i=0; i < NUM_RX_DESC; i++) {
++#ifdef CONFIG_32B_DESC
++              seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i,  *(int *)&rx_ring[i].rxd_info1,
++                              *(int *)&rx_ring[i].rxd_info2, *(int *)&rx_ring[i].rxd_info3,
++                              *(int *)&rx_ring[i].rxd_info4, *(int *)&rx_ring[i].rxd_info5,
++                              *(int *)&rx_ring[i].rxd_info6, *(int *)&rx_ring[i].rxd_info7,
++                              *(int *)&rx_ring[i].rxd_info8);
++#else
++              seq_printf(seq, "%d: %08x %08x %08x %08x\n",i,  *(int *)&rx_ring[i].rxd_info1, *(int *)&rx_ring[i].rxd_info2, 
++                              *(int *)&rx_ring[i].rxd_info3, *(int *)&rx_ring[i].rxd_info4);
++#endif
++        }
++
++      kfree(rx_ring);
++      return 0;
++}
++
++static int rx_ring_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, RxRingRead, NULL);
++}
++
++static const struct file_operations rx_ring_fops = {
++      .owner          = THIS_MODULE,
++      .open           = rx_ring_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++
++#if defined(CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++int RxLRORingRead(struct seq_file *seq, void *v, struct PDMA_rxdesc *rx_ring_p)
++{
++      struct PDMA_rxdesc *rx_ring;
++      int i = 0;
++
++      rx_ring = kmalloc(sizeof(struct PDMA_rxdesc) * NUM_LRO_RX_DESC, GFP_KERNEL);
++      if(rx_ring==NULL){
++              seq_printf(seq, " allocate temp rx_ring fail.\n");
++              return 0;
++      }
++
++      for (i=0; i < NUM_LRO_RX_DESC; i++) {
++              memcpy(&rx_ring[i], &rx_ring_p[i], sizeof(struct PDMA_rxdesc));
++      }
++      
++      for (i=0; i < NUM_LRO_RX_DESC; i++) {
++#ifdef CONFIG_32B_DESC
++              seq_printf(seq, "%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",i,  *(int *)&rx_ring[i].rxd_info1,
++                              *(int *)&rx_ring[i].rxd_info2, *(int *)&rx_ring[i].rxd_info3,
++                              *(int *)&rx_ring[i].rxd_info4, *(int *)&rx_ring[i].rxd_info5,
++                              *(int *)&rx_ring[i].rxd_info6, *(int *)&rx_ring[i].rxd_info7,
++                              *(int *)&rx_ring[i].rxd_info8);
++#else
++              seq_printf(seq, "%d: %08x %08x %08x %08x\n",i,  *(int *)&rx_ring[i].rxd_info1, *(int *)&rx_ring[i].rxd_info2, 
++                              *(int *)&rx_ring[i].rxd_info3, *(int *)&rx_ring[i].rxd_info4);
++#endif
++    }
++
++      kfree(rx_ring);
++      return 0;
++}
++
++int RxRing1Read(struct seq_file *seq, void *v)
++{
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++    RxLRORingRead(seq, v, ei_local->rx_ring1);
++
++    return 0;
++}
++
++int RxRing2Read(struct seq_file *seq, void *v)
++{
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++    RxLRORingRead(seq, v, ei_local->rx_ring2);
++
++    return 0;
++}
++
++int RxRing3Read(struct seq_file *seq, void *v)
++{
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++    RxLRORingRead(seq, v, ei_local->rx_ring3);
++
++    return 0;
++}
++
++static int rx_ring1_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, RxRing1Read, NULL);
++}
++
++static int rx_ring2_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, RxRing2Read, NULL);
++}
++
++static int rx_ring3_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, RxRing3Read, NULL);
++}
++
++static const struct file_operations rx_ring1_fops = {
++      .owner          = THIS_MODULE,
++      .open           = rx_ring1_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++
++static const struct file_operations rx_ring2_fops = {
++      .owner          = THIS_MODULE,
++      .open           = rx_ring2_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++
++static const struct file_operations rx_ring3_fops = {
++      .owner          = THIS_MODULE,
++      .open           = rx_ring3_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_TSO)
++
++int NumOfTxdUpdate(int num_of_txd)
++{
++
++      txd_cnt[num_of_txd]++;
++
++      return 0;       
++}
++
++static void *seq_TsoTxdNum_start(struct seq_file *seq, loff_t *pos)
++{
++      seq_printf(seq, "TXD | Count\n");
++      if (*pos < (MAX_SKB_FRAGS/2 + 1))
++              return pos;
++      return NULL;
++}
++
++static void *seq_TsoTxdNum_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      (*pos)++;
++      if (*pos >= (MAX_SKB_FRAGS/2 + 1))
++              return NULL;
++      return pos;
++}
++
++static void seq_TsoTxdNum_stop(struct seq_file *seq, void *v)
++{
++      /* Nothing to do */
++}
++
++static int seq_TsoTxdNum_show(struct seq_file *seq, void *v)
++{
++      int i = *(loff_t *) v;
++      seq_printf(seq, "%d: %d\n",i , txd_cnt[i]);
++
++      return 0;
++}
++
++ssize_t NumOfTxdWrite(struct file *file, const char __user *buffer, 
++                    size_t count, loff_t *data)
++{
++      memset(txd_cnt, 0, sizeof(txd_cnt));
++        printk("clear txd cnt table\n");
++
++      return count;
++}
++
++int TsoLenUpdate(int tso_len)
++{
++
++      if(tso_len > 70000) {
++              tso_cnt[14]++;
++      }else if(tso_len >  65000) {
++              tso_cnt[13]++;
++      }else if(tso_len >  60000) {
++              tso_cnt[12]++;
++      }else if(tso_len >  55000) {
++              tso_cnt[11]++;
++      }else if(tso_len >  50000) {
++              tso_cnt[10]++;
++      }else if(tso_len >  45000) {
++              tso_cnt[9]++;
++      }else if(tso_len > 40000) {
++              tso_cnt[8]++;
++      }else if(tso_len > 35000) {
++              tso_cnt[7]++;
++      }else if(tso_len > 30000) {
++              tso_cnt[6]++;
++      }else if(tso_len > 25000) {
++              tso_cnt[5]++;
++      }else if(tso_len > 20000) {
++              tso_cnt[4]++;
++      }else if(tso_len > 15000) {
++              tso_cnt[3]++;
++      }else if(tso_len > 10000) {
++              tso_cnt[2]++;
++      }else if(tso_len > 5000) {
++              tso_cnt[1]++;
++      }else {
++              tso_cnt[0]++;
++      }
++
++      return 0;       
++}
++
++ssize_t TsoLenWrite(struct file *file, const char __user *buffer,
++                  size_t count, loff_t *data)
++{
++      memset(tso_cnt, 0, sizeof(tso_cnt));
++        printk("clear tso cnt table\n");
++
++      return count;
++}
++
++static void *seq_TsoLen_start(struct seq_file *seq, loff_t *pos)
++{
++      seq_printf(seq, " Length  | Count\n");
++      if (*pos < 15)
++              return pos;
++      return NULL;
++}
++
++static void *seq_TsoLen_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++      (*pos)++;
++      if (*pos >= 15)
++              return NULL;
++      return pos;
++}
++
++static void seq_TsoLen_stop(struct seq_file *seq, void *v)
++{
++      /* Nothing to do */
++}
++
++static int seq_TsoLen_show(struct seq_file *seq, void *v)
++{
++      int i = *(loff_t *) v;
++
++      seq_printf(seq, "%d~%d: %d\n", i*5000, (i+1)*5000, tso_cnt[i]);
++
++      return 0;
++}
++
++static const struct seq_operations seq_tso_txd_num_ops = {
++      .start = seq_TsoTxdNum_start,
++      .next  = seq_TsoTxdNum_next,
++      .stop  = seq_TsoTxdNum_stop,
++      .show  = seq_TsoTxdNum_show
++};
++
++static int tso_txd_num_open(struct inode *inode, struct file *file)
++{
++      return seq_open(file, &seq_tso_txd_num_ops);
++}
++
++static struct file_operations tso_txd_num_fops = {
++      .owner          = THIS_MODULE,
++      .open           = tso_txd_num_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .write          = NumOfTxdWrite,
++      .release        = seq_release
++};
++
++static const struct seq_operations seq_tso_len_ops = {
++      .start = seq_TsoLen_start,
++      .next  = seq_TsoLen_next,
++      .stop  = seq_TsoLen_stop,
++      .show  = seq_TsoLen_show
++};
++
++static int tso_len_open(struct inode *inode, struct file *file)
++{
++      return seq_open(file, &seq_tso_len_ops);
++}
++
++static struct file_operations tso_len_fops = {
++      .owner          = THIS_MODULE,
++      .open           = tso_len_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .write          = TsoLenWrite,
++      .release        = seq_release
++};
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++static int LroLenUpdate(struct net_lro_desc *lro_desc)
++{
++      int len_idx;
++
++      if(lro_desc->ip_tot_len > 65000) {
++              len_idx = 13;
++      }else if(lro_desc->ip_tot_len > 60000) {
++              len_idx = 12;
++      }else if(lro_desc->ip_tot_len > 55000) {
++              len_idx = 11;
++      }else if(lro_desc->ip_tot_len > 50000) {
++              len_idx = 10;
++      }else if(lro_desc->ip_tot_len > 45000) {
++              len_idx = 9;
++      }else if(lro_desc->ip_tot_len > 40000) {
++              len_idx = 8;
++      }else if(lro_desc->ip_tot_len > 35000) {
++              len_idx = 7;
++      }else if(lro_desc->ip_tot_len > 30000) {
++              len_idx = 6;
++      }else if(lro_desc->ip_tot_len > 25000) {
++              len_idx = 5;
++      }else if(lro_desc->ip_tot_len > 20000) {
++              len_idx = 4;
++      }else if(lro_desc->ip_tot_len > 15000) {
++              len_idx = 3;
++      }else if(lro_desc->ip_tot_len > 10000) {
++              len_idx = 2;
++      }else if(lro_desc->ip_tot_len > 5000) {
++              len_idx = 1;
++      }else {
++              len_idx = 0;
++      }
++
++      return len_idx;
++}
++int LroStatsUpdate(struct net_lro_mgr *lro_mgr, bool all_flushed)
++{
++      struct net_lro_desc *tmp;
++      int len_idx;
++      int i, j; 
++      
++      if (all_flushed) {
++              for (i=0; i< MAX_DESC; i++) {
++                      tmp = & lro_mgr->lro_arr[i];
++                      if (tmp->pkt_aggr_cnt !=0) {
++                              for(j=0; j<=MAX_AGGR; j++) {
++                                      if(tmp->pkt_aggr_cnt == j) {
++                                              lro_flush_cnt[j]++;
++                                      }
++                              }
++                              len_idx = LroLenUpdate(tmp);
++                              lro_len_cnt1[len_idx]++;
++                              tot_called1++;
++                      }
++                      aggregated[i] = 0;
++              }
++      } else {
++              if (lro_flushed != lro_mgr->stats.flushed) {
++                      if (lro_aggregated != lro_mgr->stats.aggregated) {
++                              for (i=0; i<MAX_DESC; i++) {
++                                      tmp = &lro_mgr->lro_arr[i];
++                                      if ((aggregated[i]!= tmp->pkt_aggr_cnt) 
++                                                      && (tmp->pkt_aggr_cnt == 0)) {
++                                              aggregated[i] ++;
++                                              for (j=0; j<=MAX_AGGR; j++) {
++                                                      if (aggregated[i] == j) {
++                                                              lro_stats_cnt[j] ++;
++                                                      }
++                                              }
++                                              aggregated[i] = 0;
++                                              //len_idx = LroLenUpdate(tmp);
++                                              //lro_len_cnt2[len_idx]++;
++                                              tot_called2++;
++                                      }
++                              }
++                      } else {
++                              for (i=0; i<MAX_DESC; i++) {
++                                      tmp = &lro_mgr->lro_arr[i];
++                                      if ((aggregated[i] != 0) && (tmp->pkt_aggr_cnt==0)) {
++                                              for (j=0; j<=MAX_AGGR; j++) {
++                                                      if (aggregated[i] == j) {
++                                                              lro_stats_cnt[j] ++;
++                                                      }
++                                              }
++                                              aggregated[i] = 0;
++                                              //len_idx = LroLenUpdate(tmp);
++                                              //lro_len_cnt2[len_idx]++;
++                                              force_flush ++;
++                                              tot_called2++;
++                                      }
++                              }
++                      }
++              } else {
++                      if (lro_aggregated != lro_mgr->stats.aggregated) {
++                              for (i=0; i<MAX_DESC; i++) {
++                                      tmp = &lro_mgr->lro_arr[i];
++                                      if (tmp->active) {
++                                              if (aggregated[i] != tmp->pkt_aggr_cnt)
++                                                      aggregated[i] = tmp->pkt_aggr_cnt;
++                                      } else
++                                              aggregated[i] = 0;
++                              }
++                      } 
++              }
++
++      }
++
++      lro_aggregated = lro_mgr->stats.aggregated;
++      lro_flushed = lro_mgr->stats.flushed;
++      lro_nodesc = lro_mgr->stats.no_desc;
++
++      return 0;
++              
++}
++
++
++ssize_t LroStatsWrite(struct file *file, const char __user *buffer, 
++                    size_t count, loff_t *data)
++{
++      memset(lro_stats_cnt, 0, sizeof(lro_stats_cnt));
++      memset(lro_flush_cnt, 0, sizeof(lro_flush_cnt));
++      memset(lro_len_cnt1, 0, sizeof(lro_len_cnt1));
++      //memset(lro_len_cnt2, 0, sizeof(lro_len_cnt2));
++      memset(aggregated, 0, sizeof(aggregated));
++      lro_aggregated = 0;
++      lro_flushed = 0;
++      lro_nodesc = 0;
++      force_flush = 0;
++      tot_called1 = 0;
++      tot_called2 = 0;
++        printk("clear lro  cnt table\n");
++
++      return count;
++}
++
++int LroStatsRead(struct seq_file *seq, void *v)
++{
++      int i;
++      int tot_cnt=0;
++      int tot_aggr=0;
++      int ave_aggr=0;
++      
++      seq_printf(seq, "LRO statistic dump:\n");
++      seq_printf(seq, "Cnt:   Kernel | Driver\n");
++      for(i=0; i<=MAX_AGGR; i++) {
++              tot_cnt = tot_cnt + lro_stats_cnt[i] + lro_flush_cnt[i];
++              seq_printf(seq, " %d :      %d        %d\n", i, lro_stats_cnt[i], lro_flush_cnt[i]);
++              tot_aggr = tot_aggr + i * (lro_stats_cnt[i] + lro_flush_cnt[i]);
++      }
++      ave_aggr = lro_aggregated/lro_flushed;
++      seq_printf(seq, "Total aggregated pkt: %d\n", lro_aggregated);
++      seq_printf(seq, "Flushed pkt: %d  %d\n", lro_flushed, force_flush);
++      seq_printf(seq, "Average flush cnt:  %d\n", ave_aggr);
++      seq_printf(seq, "No descriptor pkt: %d\n\n\n", lro_nodesc);
++
++      seq_printf(seq, "Driver flush pkt len:\n");
++      seq_printf(seq, " Length  | Count\n");
++      for(i=0; i<15; i++) {
++              seq_printf(seq, "%d~%d: %d\n", i*5000, (i+1)*5000, lro_len_cnt1[i]);
++      }
++      seq_printf(seq, "Kernel flush: %d;  Driver flush: %d\n", tot_called2, tot_called1);
++      return 0;
++}
++
++static int lro_stats_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, LroStatsRead, NULL);
++}
++
++static struct file_operations lro_stats_fops = {
++      .owner          = THIS_MODULE,
++      .open           = lro_stats_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .write          = LroStatsWrite,
++      .release        = single_release
++};
++#endif
++
++int getnext(const char *src, int separator, char *dest)
++{
++    char *c;
++    int len;
++
++    if ( (src == NULL) || (dest == NULL) ) {
++        return -1;
++    }
++
++    c = strchr(src, separator);
++    if (c == NULL) {
++        strcpy(dest, src);
++        return -1;
++    }
++    len = c - src;
++    strncpy(dest, src, len);
++    dest[len] = '\0';
++    return len + 1;
++}
++
++int str_to_ip(unsigned int *ip, const char *str)
++{
++    int len;
++    const char *ptr = str;
++    char buf[128];
++    unsigned char c[4];
++    int i;
++
++    for (i = 0; i < 3; ++i) {
++        if ((len = getnext(ptr, '.', buf)) == -1) {
++            return 1; /* parse error */
++        }
++        c[i] = simple_strtoul(buf, NULL, 10);
++        ptr += len;
++    }
++    c[3] = simple_strtoul(ptr, NULL, 0);
++    *ip = (c[0]<<24) + (c[1]<<16) + (c[2]<<8) + c[3];
++    return 0;
++}
++
++#if defined(CONFIG_RAETH_HW_LRO)
++static int HwLroLenUpdate(unsigned int agg_size)
++{
++      int len_idx;
++
++      if(agg_size > 65000) {
++              len_idx = 13;
++      }else if(agg_size > 60000) {
++              len_idx = 12;
++      }else if(agg_size > 55000) {
++              len_idx = 11;
++      }else if(agg_size > 50000) {
++              len_idx = 10;
++      }else if(agg_size > 45000) {
++              len_idx = 9;
++      }else if(agg_size > 40000) {
++              len_idx = 8;
++      }else if(agg_size > 35000) {
++              len_idx = 7;
++      }else if(agg_size > 30000) {
++              len_idx = 6;
++      }else if(agg_size > 25000) {
++              len_idx = 5;
++      }else if(agg_size > 20000) {
++              len_idx = 4;
++      }else if(agg_size > 15000) {
++              len_idx = 3;
++      }else if(agg_size > 10000) {
++              len_idx = 2;
++      }else if(agg_size > 5000) {
++              len_idx = 1;
++      }else {
++              len_idx = 0;
++      }
++
++      return len_idx;
++}
++
++int HwLroStatsUpdate(unsigned int ring_num, unsigned int agg_cnt, unsigned int agg_size)
++{
++    if( (ring_num > 0) && (ring_num < 4) )
++    {
++        hw_lro_agg_size_cnt[ring_num-1][HwLroLenUpdate(agg_size)]++;
++        hw_lro_agg_num_cnt[ring_num-1][agg_cnt]++;
++        hw_lro_tot_flush_cnt[ring_num-1]++;
++        hw_lro_tot_agg_cnt[ring_num-1] += agg_cnt;
++    }
++
++    return 0;
++}
++
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++int HwLroFlushStatsUpdate(unsigned int ring_num, unsigned int flush_reason)
++{
++    if( (ring_num > 0) && (ring_num < 4) )
++    {
++#if 1
++        if ( (flush_reason & 0x7) == HW_LRO_AGG_FLUSH )
++            hw_lro_agg_flush_cnt[ring_num-1]++;
++        else if ( (flush_reason & 0x7) == HW_LRO_AGE_FLUSH )
++            hw_lro_age_flush_cnt[ring_num-1]++;
++        else if ( (flush_reason & 0x7) == HW_LRO_NOT_IN_SEQ_FLUSH )
++            hw_lro_seq_flush_cnt[ring_num-1]++;
++        else if ( (flush_reason & 0x7) == HW_LRO_TIMESTAMP_FLUSH )
++            hw_lro_timestamp_flush_cnt[ring_num-1]++;
++        else if ( (flush_reason & 0x7) == HW_LRO_NON_RULE_FLUSH )
++            hw_lro_norule_flush_cnt[ring_num-1]++;
++#else
++        if ( flush_reason & BIT(4) )
++            hw_lro_agg_flush_cnt[ring_num-1]++;
++        else if ( flush_reason & BIT(3) )
++            hw_lro_age_flush_cnt[ring_num-1]++;
++        else if ( flush_reason & BIT(2) )
++            hw_lro_seq_flush_cnt[ring_num-1]++;
++        else if ( flush_reason & BIT(1) )
++            hw_lro_timestamp_flush_cnt[ring_num-1]++;
++        else if ( flush_reason & BIT(0) )
++            hw_lro_norule_flush_cnt[ring_num-1]++;
++#endif
++    }
++
++    return 0;
++}
++#endif  /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++
++ssize_t HwLroStatsWrite(struct file *file, const char __user *buffer, 
++                    size_t count, loff_t *data)
++{
++    memset(hw_lro_agg_num_cnt, 0, sizeof(hw_lro_agg_num_cnt));
++    memset(hw_lro_agg_size_cnt, 0, sizeof(hw_lro_agg_size_cnt));
++    memset(hw_lro_tot_agg_cnt, 0, sizeof(hw_lro_tot_agg_cnt));
++    memset(hw_lro_tot_flush_cnt, 0, sizeof(hw_lro_tot_flush_cnt));
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++    memset(hw_lro_agg_flush_cnt, 0, sizeof(hw_lro_agg_flush_cnt));
++    memset(hw_lro_age_flush_cnt, 0, sizeof(hw_lro_age_flush_cnt));
++    memset(hw_lro_seq_flush_cnt, 0, sizeof(hw_lro_seq_flush_cnt));
++    memset(hw_lro_timestamp_flush_cnt, 0, sizeof(hw_lro_timestamp_flush_cnt));
++    memset(hw_lro_norule_flush_cnt, 0, sizeof(hw_lro_norule_flush_cnt));
++#endif  /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++
++    printk("clear hw lro cnt table\n");
++
++      return count;
++}
++
++int HwLroStatsRead(struct seq_file *seq, void *v)
++{
++      int i;
++      
++      seq_printf(seq, "HW LRO statistic dump:\n");
++
++    /* Agg number count */
++      seq_printf(seq, "Cnt:   RING1 | RING2 | RING3 | Total\n");
++      for(i=0; i<=MAX_HW_LRO_AGGR; i++) {
++              seq_printf(seq, " %d :      %d        %d        %d        %d\n", 
++            i, hw_lro_agg_num_cnt[0][i], hw_lro_agg_num_cnt[1][i], hw_lro_agg_num_cnt[2][i],
++            hw_lro_agg_num_cnt[0][i]+hw_lro_agg_num_cnt[1][i]+hw_lro_agg_num_cnt[2][i]);
++      }
++
++    /* Total agg count */
++    seq_printf(seq, "Total agg:   RING1 | RING2 | RING3 | Total\n");
++    seq_printf(seq, "                %d      %d      %d      %d\n", 
++        hw_lro_tot_agg_cnt[0], hw_lro_tot_agg_cnt[1], hw_lro_tot_agg_cnt[2],
++        hw_lro_tot_agg_cnt[0]+hw_lro_tot_agg_cnt[1]+hw_lro_tot_agg_cnt[2]);
++
++    /* Total flush count */
++    seq_printf(seq, "Total flush:   RING1 | RING2 | RING3 | Total\n");
++    seq_printf(seq, "                %d      %d      %d      %d\n", 
++        hw_lro_tot_flush_cnt[0], hw_lro_tot_flush_cnt[1], hw_lro_tot_flush_cnt[2],
++        hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2]);
++
++    /* Avg agg count */
++    seq_printf(seq, "Avg agg:   RING1 | RING2 | RING3 | Total\n");
++    seq_printf(seq, "                %d      %d      %d      %d\n", 
++        (hw_lro_tot_flush_cnt[0]) ? hw_lro_tot_agg_cnt[0]/hw_lro_tot_flush_cnt[0] : 0,
++        (hw_lro_tot_flush_cnt[1]) ? hw_lro_tot_agg_cnt[1]/hw_lro_tot_flush_cnt[1] : 0,
++        (hw_lro_tot_flush_cnt[2]) ? hw_lro_tot_agg_cnt[2]/hw_lro_tot_flush_cnt[2] : 0,
++        (hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2]) ? \
++        ((hw_lro_tot_agg_cnt[0]+hw_lro_tot_agg_cnt[1]+hw_lro_tot_agg_cnt[2])/(hw_lro_tot_flush_cnt[0]+hw_lro_tot_flush_cnt[1]+hw_lro_tot_flush_cnt[2])) : 0
++    );
++
++    /*  Statistics of aggregation size counts */
++      seq_printf(seq, "HW LRO flush pkt len:\n");
++      seq_printf(seq, " Length  | RING1  | RING2  | RING3  | Total\n");
++      for(i=0; i<15; i++) {
++              seq_printf(seq, "%d~%d: %d      %d      %d      %d\n", i*5000, (i+1)*5000, 
++            hw_lro_agg_size_cnt[0][i], hw_lro_agg_size_cnt[1][i], hw_lro_agg_size_cnt[2][i],
++            hw_lro_agg_size_cnt[0][i]+hw_lro_agg_size_cnt[1][i]+hw_lro_agg_size_cnt[2][i]);
++      }
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++    seq_printf(seq, "Flush reason:   RING1 | RING2 | RING3 | Total\n");
++    seq_printf(seq, "AGG timeout:      %d      %d      %d      %d\n", 
++        hw_lro_agg_flush_cnt[0], hw_lro_agg_flush_cnt[1], hw_lro_agg_flush_cnt[2],
++        (hw_lro_agg_flush_cnt[0]+hw_lro_agg_flush_cnt[1]+hw_lro_agg_flush_cnt[2])
++    );
++    seq_printf(seq, "AGE timeout:      %d      %d      %d      %d\n", 
++        hw_lro_age_flush_cnt[0], hw_lro_age_flush_cnt[1], hw_lro_age_flush_cnt[2],
++        (hw_lro_age_flush_cnt[0]+hw_lro_age_flush_cnt[1]+hw_lro_age_flush_cnt[2])
++    );
++    seq_printf(seq, "Not in-sequence:  %d      %d      %d      %d\n", 
++        hw_lro_seq_flush_cnt[0], hw_lro_seq_flush_cnt[1], hw_lro_seq_flush_cnt[2],
++        (hw_lro_seq_flush_cnt[0]+hw_lro_seq_flush_cnt[1]+hw_lro_seq_flush_cnt[2])
++    );
++    seq_printf(seq, "Timestamp:        %d      %d      %d      %d\n", 
++        hw_lro_timestamp_flush_cnt[0], hw_lro_timestamp_flush_cnt[1], hw_lro_timestamp_flush_cnt[2],
++        (hw_lro_timestamp_flush_cnt[0]+hw_lro_timestamp_flush_cnt[1]+hw_lro_timestamp_flush_cnt[2])
++    );
++    seq_printf(seq, "No LRO rule:      %d      %d      %d      %d\n", 
++        hw_lro_norule_flush_cnt[0], hw_lro_norule_flush_cnt[1], hw_lro_norule_flush_cnt[2],
++        (hw_lro_norule_flush_cnt[0]+hw_lro_norule_flush_cnt[1]+hw_lro_norule_flush_cnt[2])
++    );
++#endif  /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++    
++      return 0;
++}
++
++static int hw_lro_stats_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, HwLroStatsRead, NULL);
++}
++
++static struct file_operations hw_lro_stats_fops = {
++      .owner          = THIS_MODULE,
++      .open           = hw_lro_stats_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .write          = HwLroStatsWrite,
++      .release        = single_release
++};
++
++int hwlro_agg_cnt_ctrl(int par1, int par2)
++{
++    SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, par2);
++    SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, par2);
++    SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, par2);
++    return 0;
++}
++
++int hwlro_agg_time_ctrl(int par1, int par2)
++{
++    SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, par2);
++    SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, par2);
++    SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, par2);
++    return 0;
++}
++
++int hwlro_age_time_ctrl(int par1, int par2)
++{
++    SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, par2);
++    SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, par2);
++    SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, par2);
++    return 0;
++}
++
++int hwlro_pkt_int_alpha_ctrl(int par1, int par2)
++{
++    END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++    ei_local->hw_lro_alpha = par2;
++    printk("[hwlro_pkt_int_alpha_ctrl]ei_local->hw_lro_alpha = %d\n", ei_local->hw_lro_alpha);
++
++    return 0;
++}
++
++int hwlro_threshold_ctrl(int par1, int par2)
++{
++    /* bandwidth threshold setting */
++    SET_PDMA_LRO_BW_THRESHOLD(par2);
++    return 0;
++}
++
++int hwlro_fix_setting_switch_ctrl(int par1, int par2)
++{
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++    END_DEVICE *ei_local = netdev_priv(dev_raether);
++
++    ei_local->hw_lro_fix_setting = par2;
++    printk("[hwlro_pkt_int_alpha_ctrl]ei_local->hw_lro_fix_setting = %d\n", ei_local->hw_lro_fix_setting);
++#endif  /* CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG */
++
++    return 0;
++}
++
++ssize_t HwLroAutoTlbWrite(struct file *file, const char __user *buffer, 
++                    size_t count, loff_t *data)
++{
++    char buf[32];
++    char *pBuf;
++    int len = count;
++    int x = 0,y = 0;
++    char *pToken = NULL;
++    char *pDelimiter = " \t";
++
++    printk("[HwLroAutoTlbWrite]write parameter len = %d\n\r", (int)len);
++    if(len >= sizeof(buf)){
++        printk("input handling fail!\n");
++        len = sizeof(buf) - 1;
++        return -1;
++    }
++    
++    if(copy_from_user(buf, buffer, len)){
++        return -EFAULT;
++    }
++    buf[len] = '\0';
++    printk("[HwLroAutoTlbWrite]write parameter data = %s\n\r", buf);
++
++    pBuf = buf;
++    pToken = strsep(&pBuf, pDelimiter);
++    x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++
++    pToken = strsep(&pBuf, "\t\n ");
++    if(pToken != NULL){
++        y = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++        printk("y = 0x%08x \n\r", y);
++    }
++
++    if ( (sizeof(hw_lro_dbg_func)/sizeof(hw_lro_dbg_func[0]) > x) && NULL != hw_lro_dbg_func[x])
++    {
++        (*hw_lro_dbg_func[x])(x, y);
++    }
++
++      return count;
++}
++
++void HwLroAutoTlbDump(struct seq_file *seq, unsigned int index)
++{
++    int i;
++    struct PDMA_LRO_AUTO_TLB_INFO   pdma_lro_auto_tlb;
++    unsigned int tlb_info[9];
++    unsigned int dw_len, cnt, priority;
++    unsigned int entry;
++
++    if( index > 4 )
++        index = index - 1;
++    entry = (index * 9) + 1;
++
++    /* read valid entries of the auto-learn table */
++    sysRegWrite( PDMA_FE_ALT_CF8, entry );
++
++    //seq_printf(seq, "\nEntry = %d\n", entry);
++    for(i=0; i<9; i++){
++        tlb_info[i] = sysRegRead(PDMA_FE_ALT_SEQ_CFC);
++        //seq_printf(seq, "tlb_info[%d] = 0x%x\n", i, tlb_info[i]);
++    }
++    memcpy(&pdma_lro_auto_tlb, tlb_info, sizeof(struct PDMA_LRO_AUTO_TLB_INFO));
++
++    dw_len = pdma_lro_auto_tlb.auto_tlb_info7.DW_LEN;
++    cnt = pdma_lro_auto_tlb.auto_tlb_info6.CNT;
++
++    if ( sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_ALT_SCORE_MODE )  /* packet count */
++        priority = cnt;
++    else    /* byte count */
++        priority = dw_len;
++
++    /* dump valid entries of the auto-learn table */
++    if( index >= 4 )
++        seq_printf(seq, "\n===== TABLE Entry: %d (Act) =====\n", index);
++    else
++        seq_printf(seq, "\n===== TABLE Entry: %d (LRU) =====\n", index);
++    if( pdma_lro_auto_tlb.auto_tlb_info8.IPV4 ){
++        seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv4)\n", 
++            pdma_lro_auto_tlb.auto_tlb_info4.SIP3,
++            pdma_lro_auto_tlb.auto_tlb_info3.SIP2,
++            pdma_lro_auto_tlb.auto_tlb_info2.SIP1,
++            pdma_lro_auto_tlb.auto_tlb_info1.SIP0);
++    }
++    else{        
++        seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv6)\n", 
++            pdma_lro_auto_tlb.auto_tlb_info4.SIP3,
++            pdma_lro_auto_tlb.auto_tlb_info3.SIP2,
++            pdma_lro_auto_tlb.auto_tlb_info2.SIP1,
++            pdma_lro_auto_tlb.auto_tlb_info1.SIP0);
++    }
++    seq_printf(seq, "DIP_ID = %d\n", pdma_lro_auto_tlb.auto_tlb_info8.DIP_ID);
++    seq_printf(seq, "TCP SPORT = %d | TCP DPORT = %d\n", 
++        pdma_lro_auto_tlb.auto_tlb_info0.STP, 
++        pdma_lro_auto_tlb.auto_tlb_info0.DTP);
++    seq_printf(seq, "VLAN1 = %d | VLAN2 = %d | VLAN3 = %d | VLAN4 =%d \n", 
++        pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0,
++        (pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0 << 12),
++        (pdma_lro_auto_tlb.auto_tlb_info5.VLAN_VID0 << 24),
++        pdma_lro_auto_tlb.auto_tlb_info6.VLAN_VID1);
++    seq_printf(seq, "TPUT = %d | FREQ = %d\n", dw_len, cnt);
++    seq_printf(seq, "PRIORITY = %d\n", priority);
++}
++
++int HwLroAutoTlbRead(struct seq_file *seq, void *v)
++{
++      int i;
++    unsigned int regVal;
++    unsigned int regOp1, regOp2, regOp3, regOp4;
++    unsigned int agg_cnt, agg_time, age_time;
++
++    /* Read valid entries of the auto-learn table */
++    sysRegWrite(PDMA_FE_ALT_CF8, 0);
++    regVal = sysRegRead(PDMA_FE_ALT_SEQ_CFC);
++
++    seq_printf(seq, "HW LRO Auto-learn Table: (PDMA_LRO_ALT_CFC_RSEQ_DBG=0x%x)\n", regVal);
++
++    for(i = 7; i >= 0; i--)
++    {
++        if( regVal & (1 << i) )
++            HwLroAutoTlbDump(seq, i);
++    }
++    
++    /* Read the agg_time/age_time/agg_cnt of LRO rings */
++    seq_printf(seq, "\nHW LRO Ring Settings\n");
++    for(i = 1; i <= 3; i++) 
++    {
++        regOp1 = sysRegRead( LRO_RX_RING0_CTRL_DW1 + (i * 0x40) );
++        regOp2 = sysRegRead( LRO_RX_RING0_CTRL_DW2 + (i * 0x40) );
++        regOp3 = sysRegRead( LRO_RX_RING0_CTRL_DW3 + (i * 0x40) );
++        regOp4 = sysRegRead( ADMA_LRO_CTRL_DW2 );
++        agg_cnt = ((regOp3 & 0x03) << PDMA_LRO_AGG_CNT_H_OFFSET) | ((regOp2 >> PDMA_LRO_RING_AGG_CNT1_OFFSET) & 0x3f);
++        agg_time = (regOp2 >> PDMA_LRO_RING_AGG_OFFSET) & 0xffff;
++        age_time = ((regOp2 & 0x03f) << PDMA_LRO_AGE_H_OFFSET) | ((regOp1 >> PDMA_LRO_RING_AGE1_OFFSET) & 0x3ff);
++        seq_printf(seq, "Ring[%d]: MAX_AGG_CNT=%d, AGG_TIME=%d, AGE_TIME=%d, Threshold=%d\n", 
++            i, agg_cnt, agg_time, age_time, regOp4);
++    }
++
++      return 0;
++}
++
++static int hw_lro_auto_tlb_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, HwLroAutoTlbRead, NULL);
++}
++
++static struct file_operations hw_lro_auto_tlb_fops = {
++      .owner          = THIS_MODULE,
++      .open           = hw_lro_auto_tlb_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .write          = HwLroAutoTlbWrite,
++      .release        = single_release
++};
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if defined (CONFIG_MIPS)
++int CP0RegRead(struct seq_file *seq, void *v)
++{
++      seq_printf(seq, "CP0 Register dump --\n");
++      seq_printf(seq, "CP0_INDEX\t: 0x%08x\n", read_32bit_cp0_register(CP0_INDEX));
++      seq_printf(seq, "CP0_RANDOM\t: 0x%08x\n", read_32bit_cp0_register(CP0_RANDOM));
++      seq_printf(seq, "CP0_ENTRYLO0\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO0));
++      seq_printf(seq, "CP0_ENTRYLO1\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYLO1));
++      seq_printf(seq, "CP0_CONF\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONF));
++      seq_printf(seq, "CP0_CONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONTEXT));
++      seq_printf(seq, "CP0_PAGEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_PAGEMASK));
++      seq_printf(seq, "CP0_WIRED\t: 0x%08x\n", read_32bit_cp0_register(CP0_WIRED));
++      seq_printf(seq, "CP0_INFO\t: 0x%08x\n", read_32bit_cp0_register(CP0_INFO));
++      seq_printf(seq, "CP0_BADVADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_BADVADDR));
++      seq_printf(seq, "CP0_COUNT\t: 0x%08x\n", read_32bit_cp0_register(CP0_COUNT));
++      seq_printf(seq, "CP0_ENTRYHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_ENTRYHI));
++      seq_printf(seq, "CP0_COMPARE\t: 0x%08x\n", read_32bit_cp0_register(CP0_COMPARE));
++      seq_printf(seq, "CP0_STATUS\t: 0x%08x\n", read_32bit_cp0_register(CP0_STATUS));
++      seq_printf(seq, "CP0_CAUSE\t: 0x%08x\n", read_32bit_cp0_register(CP0_CAUSE));
++      seq_printf(seq, "CP0_EPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_EPC));
++      seq_printf(seq, "CP0_PRID\t: 0x%08x\n", read_32bit_cp0_register(CP0_PRID));
++      seq_printf(seq, "CP0_CONFIG\t: 0x%08x\n", read_32bit_cp0_register(CP0_CONFIG));
++      seq_printf(seq, "CP0_LLADDR\t: 0x%08x\n", read_32bit_cp0_register(CP0_LLADDR));
++      seq_printf(seq, "CP0_WATCHLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHLO));
++      seq_printf(seq, "CP0_WATCHHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_WATCHHI));
++      seq_printf(seq, "CP0_XCONTEXT\t: 0x%08x\n", read_32bit_cp0_register(CP0_XCONTEXT));
++      seq_printf(seq, "CP0_FRAMEMASK\t: 0x%08x\n", read_32bit_cp0_register(CP0_FRAMEMASK));
++      seq_printf(seq, "CP0_DIAGNOSTIC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DIAGNOSTIC));
++      seq_printf(seq, "CP0_DEBUG\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEBUG));
++      seq_printf(seq, "CP0_DEPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_DEPC));
++      seq_printf(seq, "CP0_PERFORMANCE\t: 0x%08x\n", read_32bit_cp0_register(CP0_PERFORMANCE));
++      seq_printf(seq, "CP0_ECC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ECC));
++      seq_printf(seq, "CP0_CACHEERR\t: 0x%08x\n", read_32bit_cp0_register(CP0_CACHEERR));
++      seq_printf(seq, "CP0_TAGLO\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGLO));
++      seq_printf(seq, "CP0_TAGHI\t: 0x%08x\n", read_32bit_cp0_register(CP0_TAGHI));
++      seq_printf(seq, "CP0_ERROREPC\t: 0x%08x\n", read_32bit_cp0_register(CP0_ERROREPC));
++      seq_printf(seq, "CP0_DESAVE\t: 0x%08x\n\n", read_32bit_cp0_register(CP0_DESAVE));
++
++      return 0;
++}
++
++static int cp0_reg_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, CP0RegRead, NULL);
++}
++
++static const struct file_operations cp0_reg_fops = {
++      .owner          = THIS_MODULE,
++      .open           = cp0_reg_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++#endif
++
++#if defined(CONFIG_RAETH_QOS)
++static struct proc_dir_entry *procRaQOS, *procRaFeIntr, *procRaEswIntr;
++extern uint32_t num_of_rxdone_intr;
++extern uint32_t num_of_esw_intr;
++
++int RaQOSRegRead(struct seq_file *seq, void *v)
++{
++      dump_qos(seq);
++      return 0;
++}
++
++static int raeth_qos_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, RaQOSRegRead, NULL);
++}
++
++static const struct file_operations raeth_qos_fops = {
++      .owner          = THIS_MODULE,
++      .open           = raeth_qos_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++#endif
++
++static struct proc_dir_entry *procEswCnt;
++
++int EswCntRead(struct seq_file *seq, void *v)
++{
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) || defined (CONFIG_ARCH_MT7623)
++      unsigned int pkt_cnt = 0;
++      int i = 0;
++#endif
++      seq_printf(seq, "\n               <<CPU>>                        \n");
++      seq_printf(seq, "                   |                            \n");
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++      seq_printf(seq, "+-----------------------------------------------+\n");
++      seq_printf(seq, "|                <<PDMA>>                      |\n");
++      seq_printf(seq, "+-----------------------------------------------+\n");
++#else
++      seq_printf(seq, "+-----------------------------------------------+\n");
++      seq_printf(seq, "|                <<PSE>>                       |\n");
++      seq_printf(seq, "+-----------------------------------------------+\n");
++      seq_printf(seq, "                  |                             \n");
++      seq_printf(seq, "+-----------------------------------------------+\n");
++      seq_printf(seq, "|                <<GDMA>>                      |\n");
++#if defined (CONFIG_RALINK_MT7620)
++      seq_printf(seq, "| GDMA1_TX_GPCNT  : %010u (Tx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1304));     
++      seq_printf(seq, "| GDMA1_RX_GPCNT  : %010u (Rx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1324));     
++      seq_printf(seq, "|                                              |\n");
++      seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (skip)               |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1308));     
++      seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x130c));     
++      seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1328));     
++      seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x132c));     
++      seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1330));     
++      seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1334));     
++      seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1338)); 
++      seq_printf(seq, "| GDMA1_RX_FCCNT  : %010u (flow control)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x133c));     
++
++      seq_printf(seq, "|                                              |\n");
++      seq_printf(seq, "| GDMA2_TX_GPCNT  : %010u (Tx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1344));     
++      seq_printf(seq, "| GDMA2_RX_GPCNT  : %010u (Rx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1364));     
++      seq_printf(seq, "|                                              |\n");
++      seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip)               |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1348));     
++      seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x134c));     
++      seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1368));     
++      seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x136c));     
++      seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1370));     
++      seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1374));     
++      seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (l3/l4 checksum) |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x1378)); 
++      seq_printf(seq, "| GDMA2_RX_FCCNT  : %010u (flow control)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x137c));     
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++      seq_printf(seq, "| GDMA1_RX_GBCNT  : %010u (Rx Good Bytes)      |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2400));     
++      seq_printf(seq, "| GDMA1_RX_GPCNT  : %010u (Rx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2408));     
++      seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow error)     |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2410));     
++      seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2414));     
++      seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2418));     
++      seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x241C));     
++      seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (checksum error)     |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2420));     
++      seq_printf(seq, "| GDMA1_RX_FCCNT  : %010u (flow control)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2424));     
++      seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (about count)        |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2428));     
++      seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision count)    |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x242C));     
++      seq_printf(seq, "| GDMA1_TX_GBCNT  : %010u (Tx Good Bytes)      |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2430));     
++      seq_printf(seq, "| GDMA1_TX_GPCNT  : %010u (Tx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2438));     
++      seq_printf(seq, "|                                              |\n");
++      seq_printf(seq, "| GDMA2_RX_GBCNT  : %010u (Rx Good Bytes)      |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2440));     
++      seq_printf(seq, "| GDMA2_RX_GPCNT  : %010u (Rx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2448));     
++      seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow error)     |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2450));     
++      seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2454));     
++      seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2458));     
++      seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x245C));     
++      seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (checksum error)     |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2460));     
++      seq_printf(seq, "| GDMA2_RX_FCCNT  : %010u (flow control)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2464));     
++      seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip)               |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2468));     
++      seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x246C));     
++      seq_printf(seq, "| GDMA2_TX_GBCNT  : %010u (Tx Good Bytes)      |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2470));     
++      seq_printf(seq, "| GDMA2_TX_GPCNT  : %010u (Tx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x2478));     
++#else
++      seq_printf(seq, "| GDMA_TX_GPCNT1  : %010u (Tx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x704));      
++      seq_printf(seq, "| GDMA_RX_GPCNT1  : %010u (Rx Good Pkts)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x724));      
++      seq_printf(seq, "|                                              |\n");
++      seq_printf(seq, "| GDMA_TX_SKIPCNT1: %010u (skip)               |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x708));      
++      seq_printf(seq, "| GDMA_TX_COLCNT1 : %010u (collision)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x70c));      
++      seq_printf(seq, "| GDMA_RX_OERCNT1 : %010u (overflow)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x728));      
++      seq_printf(seq, "| GDMA_RX_FERCNT1 : %010u (FCS error)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x72c));      
++      seq_printf(seq, "| GDMA_RX_SERCNT1 : %010u (too short)  |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x730));      
++      seq_printf(seq, "| GDMA_RX_LERCNT1 : %010u (too long)   |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x734));      
++      seq_printf(seq, "| GDMA_RX_CERCNT1 : %010u (l3/l4 checksum)     |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x738));      
++      seq_printf(seq, "| GDMA_RX_FCCNT1  : %010u (flow control)       |\n", sysRegRead(RALINK_FRAME_ENGINE_BASE+0x73c));      
++
++#endif
++      seq_printf(seq, "+-----------------------------------------------+\n");
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620)
++
++      seq_printf(seq, "                      ^                          \n");
++      seq_printf(seq, "                      | Port6 Rx:%010u Good Pkt   \n", ((p6_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4620)&0xFFFF)));
++      seq_printf(seq, "                      | Port6 Rx:%010u Bad Pkt    \n", sysRegRead(RALINK_ETH_SW_BASE+0x4620)>>16);
++      seq_printf(seq, "                      | Port6 Tx:%010u Good Pkt   \n", ((p6_tx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4610)&0xFFFF)));
++      seq_printf(seq, "                      | Port6 Tx:%010u Bad Pkt    \n", sysRegRead(RALINK_ETH_SW_BASE+0x4610)>>16);
++#if defined (CONFIG_RALINK_MT7620)
++
++      seq_printf(seq, "                      | Port7 Rx:%010u Good Pkt   \n", ((p7_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4720)&0xFFFF)));
++      seq_printf(seq, "                      | Port7 Rx:%010u Bad Pkt    \n", sysRegRead(RALINK_ETH_SW_BASE+0x4720)>>16);
++      seq_printf(seq, "                      | Port7 Tx:%010u Good Pkt   \n", ((p7_tx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4710)&0xFFFF)));
++      seq_printf(seq, "                      | Port7 Tx:%010u Bad Pkt    \n", sysRegRead(RALINK_ETH_SW_BASE+0x4710)>>16);
++#endif
++      seq_printf(seq, "+---------------------v-------------------------+\n");
++      seq_printf(seq, "|                    P6                        |\n");
++      seq_printf(seq, "|        <<10/100/1000 Embedded Switch>>        |\n");
++      seq_printf(seq, "|     P0    P1    P2     P3     P4     P5       |\n");
++      seq_printf(seq, "+-----------------------------------------------+\n");
++      seq_printf(seq, "       |     |     |     |       |      |        \n");
++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) 
++      /* no built-in switch */
++#else
++      seq_printf(seq, "                      ^                          \n");
++      seq_printf(seq, "                      | Port6 Rx:%08u Good Pkt   \n", sysRegRead(RALINK_ETH_SW_BASE+0xE0)&0xFFFF);
++      seq_printf(seq, "                      | Port6 Tx:%08u Good Pkt   \n", sysRegRead(RALINK_ETH_SW_BASE+0xE0)>>16);
++      seq_printf(seq, "+---------------------v-------------------------+\n");
++      seq_printf(seq, "|                    P6                        |\n");
++      seq_printf(seq, "|           <<10/100 Embedded Switch>>         |\n");
++      seq_printf(seq, "|     P0    P1    P2     P3     P4     P5       |\n");
++      seq_printf(seq, "+-----------------------------------------------+\n");
++      seq_printf(seq, "       |     |     |     |       |      |        \n");
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620)
++
++      seq_printf(seq, "Port0 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p0_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4020)&0xFFFF)), ((p0_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4010)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4020)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4010)>>16);
++
++      seq_printf(seq, "Port1 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p1_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4120)&0xFFFF)), ((p1_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4110)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4120)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4110)>>16);
++
++      seq_printf(seq, "Port2 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p2_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4220)&0xFFFF)), ((p2_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4210)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4220)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4210)>>16);
++
++      seq_printf(seq, "Port3 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p3_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4320)&0xFFFF)), ((p3_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4310)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4320)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4310)>>16);
++
++      seq_printf(seq, "Port4 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p4_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4420)&0xFFFF)), ((p4_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4410)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4420)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4410)>>16);
++
++      seq_printf(seq, "Port5 Good RX=%010u Tx=%010u (Bad Rx=%010u Tx=%010u)\n", ((p5_rx_good_cnt << 16) | (sysRegRead(RALINK_ETH_SW_BASE+0x4520)&0xFFFF)), ((p5_tx_good_cnt << 16)| (sysRegRead(RALINK_ETH_SW_BASE+0x4510)&0xFFFF)), sysRegRead(RALINK_ETH_SW_BASE+0x4520)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x4510)>>16);
++
++      seq_printf(seq, "Port0 KBytes RX=%010u Tx=%010u \n", ((p0_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4028) >> 10)), ((p0_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4018) >> 10)));
++
++      seq_printf(seq, "Port1 KBytes RX=%010u Tx=%010u \n", ((p1_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4128) >> 10)), ((p1_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4118) >> 10)));
++
++      seq_printf(seq, "Port2 KBytes RX=%010u Tx=%010u \n", ((p2_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4228) >> 10)), ((p2_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4218) >> 10)));
++
++      seq_printf(seq, "Port3 KBytes RX=%010u Tx=%010u \n", ((p3_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4328) >> 10)), ((p3_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4318) >> 10)));
++
++      seq_printf(seq, "Port4 KBytes RX=%010u Tx=%010u \n", ((p4_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4428) >> 10)), ((p4_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4418) >> 10)));
++
++      seq_printf(seq, "Port5 KBytes RX=%010u Tx=%010u \n", ((p5_rx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4528) >> 10)), ((p5_tx_byte_cnt << 22) + (sysRegRead(RALINK_ETH_SW_BASE+0x4518) >> 10)));
++
++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++#define DUMP_EACH_PORT(base)                                  \
++      for(i=0; i < 7;i++) {                                   \
++              mii_mgr_read(31, (base) + (i*0x100), &pkt_cnt); \
++              seq_printf(seq, "%8u ", pkt_cnt);                       \
++      }                                                       \
++      seq_printf(seq, "\n");
++      seq_printf(seq, "========================================[MT7530] READ CLEAR========================\n");
++
++              seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n","Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
++              seq_printf(seq, "Tx Drop Packet      :"); DUMP_EACH_PORT(0x4000);
++              //seq_printf(seq, "Tx CRC Error        :"); DUMP_EACH_PORT(0x4004);
++              seq_printf(seq, "Tx Unicast Packet   :"); DUMP_EACH_PORT(0x4008);
++              seq_printf(seq, "Tx Multicast Packet :"); DUMP_EACH_PORT(0x400C);
++              seq_printf(seq, "Tx Broadcast Packet :"); DUMP_EACH_PORT(0x4010);
++              //seq_printf(seq, "Tx Collision Event  :"); DUMP_EACH_PORT(0x4014);
++              seq_printf(seq, "Tx Pause Packet     :"); DUMP_EACH_PORT(0x402C);
++              seq_printf(seq, "Rx Drop Packet      :"); DUMP_EACH_PORT(0x4060);
++              seq_printf(seq, "Rx Filtering Packet :"); DUMP_EACH_PORT(0x4064);
++              seq_printf(seq, "Rx Unicast Packet   :"); DUMP_EACH_PORT(0x4068);
++              seq_printf(seq, "Rx Multicast Packet :"); DUMP_EACH_PORT(0x406C);
++              seq_printf(seq, "Rx Broadcast Packet :"); DUMP_EACH_PORT(0x4070);
++              seq_printf(seq, "Rx Alignment Error  :"); DUMP_EACH_PORT(0x4074);
++              seq_printf(seq, "Rx CRC Error       :"); DUMP_EACH_PORT(0x4078);
++              seq_printf(seq, "Rx Undersize Error  :"); DUMP_EACH_PORT(0x407C);
++              //seq_printf(seq, "Rx Fragment Error   :"); DUMP_EACH_PORT(0x4080);
++              //seq_printf(seq, "Rx Oversize Error   :"); DUMP_EACH_PORT(0x4084);
++              //seq_printf(seq, "Rx Jabber Error     :"); DUMP_EACH_PORT(0x4088);
++              seq_printf(seq, "Rx Pause Packet     :"); DUMP_EACH_PORT(0x408C);
++              mii_mgr_write(31, 0x4fe0, 0xf0);
++              mii_mgr_write(31, 0x4fe0, 0x800000f0);
++#endif
++
++
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++      seq_printf(seq, "Port0 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xE8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x150)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xE8)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x150)>>16);
++
++      seq_printf(seq, "Port1 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xEC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x154)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xEC)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x154)>>16);
++
++      seq_printf(seq, "Port2 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF0)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x158)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF0)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x158)>>16);
++
++      seq_printf(seq, "Port3 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF4)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x15C)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF4)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x15c)>>16);
++
++      seq_printf(seq, "Port4 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x160)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF8)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x160)>>16);
++
++      seq_printf(seq, "Port5 Good Pkt Cnt: RX=%08u Tx=%08u (Bad Pkt Cnt: Rx=%08u Tx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xFC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0x164)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xFC)>>16, sysRegRead(RALINK_ETH_SW_BASE+0x164)>>16);
++#elif defined (CONFIG_RALINK_RT3883)
++      /* no built-in switch */
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#define DUMP_EACH_PORT(base)                                  \
++      for(i=0; i < 7;i++) {                                   \
++              mii_mgr_read(31, (base) + (i*0x100), &pkt_cnt); \
++              seq_printf(seq, "%8u ", pkt_cnt);                       \
++      }                                                       \
++      seq_printf(seq, "\n");
++
++#if defined (CONFIG_RALINK_MT7621) /* TODO: need to update to use MT7530 compiler flag */
++      if(sysRegRead(0xbe00000c & (1<<16)))//MCM
++#endif
++      {
++              seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n","Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
++              seq_printf(seq, "Tx Drop Packet      :"); DUMP_EACH_PORT(0x4000);
++              seq_printf(seq, "Tx CRC Error        :"); DUMP_EACH_PORT(0x4004);
++              seq_printf(seq, "Tx Unicast Packet   :"); DUMP_EACH_PORT(0x4008);
++              seq_printf(seq, "Tx Multicast Packet :"); DUMP_EACH_PORT(0x400C);
++              seq_printf(seq, "Tx Broadcast Packet :"); DUMP_EACH_PORT(0x4010);
++              seq_printf(seq, "Tx Collision Event  :"); DUMP_EACH_PORT(0x4014);
++              seq_printf(seq, "Tx Pause Packet     :"); DUMP_EACH_PORT(0x402C);
++              seq_printf(seq, "Rx Drop Packet      :"); DUMP_EACH_PORT(0x4060);
++              seq_printf(seq, "Rx Filtering Packet :"); DUMP_EACH_PORT(0x4064);
++              seq_printf(seq, "Rx Unicast Packet   :"); DUMP_EACH_PORT(0x4068);
++              seq_printf(seq, "Rx Multicast Packet :"); DUMP_EACH_PORT(0x406C);
++              seq_printf(seq, "Rx Broadcast Packet :"); DUMP_EACH_PORT(0x4070);
++              seq_printf(seq, "Rx Alignment Error  :"); DUMP_EACH_PORT(0x4074);
++              seq_printf(seq, "Rx CRC Error       :"); DUMP_EACH_PORT(0x4078);
++              seq_printf(seq, "Rx Undersize Error  :"); DUMP_EACH_PORT(0x407C);
++              seq_printf(seq, "Rx Fragment Error   :"); DUMP_EACH_PORT(0x4080);
++              seq_printf(seq, "Rx Oversize Error   :"); DUMP_EACH_PORT(0x4084);
++              seq_printf(seq, "Rx Jabber Error     :"); DUMP_EACH_PORT(0x4088);
++              seq_printf(seq, "Rx Pause Packet     :"); DUMP_EACH_PORT(0x408C);
++              mii_mgr_write(31, 0x4fe0, 0xf0);
++              mii_mgr_write(31, 0x4fe0, 0x800000f0);
++      } 
++#if defined (CONFIG_RALINK_MT7621)    /* TODO: need to update to use MT7530 compiler flag */
++      else {
++              seq_printf(seq, "no built-in switch\n");
++      }
++#endif
++
++#else /* RT305x, RT3352 */
++      seq_printf(seq, "Port0: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xE8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xE8)>>16);
++      seq_printf(seq, "Port1: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xEC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xEC)>>16);
++      seq_printf(seq, "Port2: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF0)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF0)>>16);
++      seq_printf(seq, "Port3: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF4)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF4)>>16);
++      seq_printf(seq, "Port4: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xF8)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xF8)>>16);
++      seq_printf(seq, "Port5: Good Pkt Cnt: RX=%08u (Bad Pkt Cnt: Rx=%08u)\n", sysRegRead(RALINK_ETH_SW_BASE+0xFC)&0xFFFF,sysRegRead(RALINK_ETH_SW_BASE+0xFC)>>16);
++#endif
++      seq_printf(seq, "\n");
++
++      return 0;
++}
++
++static int switch_count_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, EswCntRead, NULL);
++}
++
++static const struct file_operations switch_count_fops = {
++      .owner          = THIS_MODULE,
++      .open           = switch_count_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++/*
++ * proc write procedure
++ */
++static ssize_t change_phyid(struct file *file, const char __user *buffer, 
++                          size_t count, loff_t *data)
++{
++      char buf[32];
++      struct net_device *cur_dev_p;
++      END_DEVICE *ei_local;
++      char if_name[64];
++      unsigned int phy_id;
++
++      if (count > 32)
++              count = 32;
++      memset(buf, 0, 32);
++      if (copy_from_user(buf, buffer, count))
++              return -EFAULT;
++
++      /* determine interface name */
++    strcpy(if_name, DEV_NAME);        /* "eth2" by default */
++    if(isalpha(buf[0]))
++              sscanf(buf, "%s %d", if_name, &phy_id);
++      else
++              phy_id = simple_strtol(buf, 0, 10);
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      cur_dev_p = dev_get_by_name(&init_net, DEV_NAME);
++#else
++      cur_dev_p = dev_get_by_name(DEV_NAME);
++#endif
++      if (cur_dev_p == NULL)
++              return -EFAULT;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      ei_local = netdev_priv(cur_dev_p);
++#else
++      ei_local = cur_dev_p->priv;
++#endif        
++      ei_local->mii_info.phy_id = (unsigned char)phy_id;
++      return count;
++}
++
++#if defined(CONFIG_PSEUDO_SUPPORT)
++static ssize_t change_gmac2_phyid(struct file *file, const char __user *buffer, 
++                                size_t count, loff_t *data)
++{
++      char buf[32];
++      struct net_device *cur_dev_p;
++      PSEUDO_ADAPTER *pPseudoAd;
++      char if_name[64];
++      unsigned int phy_id;
++
++      if (count > 32)
++              count = 32;
++      memset(buf, 0, 32);
++      if (copy_from_user(buf, buffer, count))
++              return -EFAULT;
++      /* determine interface name */
++      strcpy(if_name, DEV2_NAME);  /* "eth3" by default */
++      if(isalpha(buf[0]))
++              sscanf(buf, "%s %d", if_name, &phy_id);
++      else
++              phy_id = simple_strtol(buf, 0, 10);
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      cur_dev_p = dev_get_by_name(&init_net, DEV2_NAME);
++#else
++      cur_dev_p = dev_get_by_name(DEV2_NAMEj);
++#endif
++      if (cur_dev_p == NULL)
++              return -EFAULT;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        pPseudoAd = netdev_priv(cur_dev_p);   
++#else
++      pPseudoAd = cur_dev_p->priv;
++#endif
++      pPseudoAd->mii_info.phy_id = (unsigned char)phy_id;
++      return count;
++}     
++
++static struct file_operations gmac2_fops = {
++      .owner          = THIS_MODULE,
++      .write          = change_gmac2_phyid
++};
++#endif
++#endif
++
++static int gmac_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, RegReadMain, NULL);
++}
++
++static struct file_operations gmac_fops = {
++      .owner          = THIS_MODULE,
++      .open           = gmac_open,
++      .read           = seq_read,
++      .llseek         = seq_lseek,
++#if defined (CONFIG_ETHTOOL)
++      .write          = change_phyid,
++#endif
++      .release        = single_release
++};
++
++#if defined (TASKLET_WORKQUEUE_SW)
++extern int init_schedule;
++extern int working_schedule;
++static int ScheduleRead(struct seq_file *seq, void *v)
++{
++      if (init_schedule == 1)
++              seq_printf(seq, "Initialize Raeth with workqueque<%d>\n", init_schedule);
++      else
++              seq_printf(seq, "Initialize Raeth with tasklet<%d>\n", init_schedule);
++      if (working_schedule == 1)
++              seq_printf(seq, "Raeth is running at workqueque<%d>\n", working_schedule);
++      else
++              seq_printf(seq, "Raeth is running at tasklet<%d>\n", working_schedule);
++
++      return 0;
++}
++
++static ssize_t ScheduleWrite(struct file *file, const char __user *buffer, 
++                    size_t count, loff_t *data)
++{
++      char buf[2];
++      int old;
++      
++      if (copy_from_user(buf, buffer, count))
++              return -EFAULT;
++      old = init_schedule;
++      init_schedule = simple_strtol(buf, 0, 10);
++      printk("Change Raeth initial schedule from <%d> to <%d>\n! Not running schedule at present !\n", 
++              old, init_schedule);
++
++      return count;
++}
++
++static int schedule_switch_open(struct inode *inode, struct file *file)
++{
++      return single_open(file, ScheduleRead, NULL);
++}
++
++static const struct file_operations schedule_sw_fops = {
++      .owner          = THIS_MODULE,
++      .open           = schedule_switch_open,
++      .read           = seq_read,
++      .write          = ScheduleWrite,
++      .llseek         = seq_lseek,
++      .release        = single_release
++};
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++static int PdmaDvtRead(struct seq_file *seq, void *v)
++{
++    seq_printf(seq, "g_pdma_dvt_show_config = 0x%x\n", pdma_dvt_get_show_config());
++    seq_printf(seq, "g_pdma_dvt_rx_test_config = 0x%x\n", pdma_dvt_get_rx_test_config());
++    seq_printf(seq, "g_pdma_dvt_tx_test_config = 0x%x\n", pdma_dvt_get_tx_test_config());
++    
++      return 0;
++}
++
++static int PdmaDvtOpen(struct inode *inode, struct file *file)
++{
++      return single_open(file, PdmaDvtRead, NULL);
++}
++
++static ssize_t PdmaDvtWrite(struct file *file, const char __user *buffer, 
++                    size_t count, loff_t *data)
++{
++      char buf[32];
++    char *pBuf;
++    int len = count;
++    int x = 0,y = 0;
++    char *pToken = NULL;
++    char *pDelimiter = " \t";
++
++    printk("write parameter len = %d\n\r", (int)len);
++    if(len >= sizeof(buf)){
++        printk("input handling fail!\n");
++        len = sizeof(buf) - 1;
++        return -1;
++    }
++    
++    if(copy_from_user(buf, buffer, len)){
++        return -EFAULT;
++    }
++    buf[len] = '\0';
++    printk("write parameter data = %s\n\r", buf);
++
++    pBuf = buf;
++    pToken = strsep(&pBuf, pDelimiter);
++    x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++
++    pToken = strsep(&pBuf, "\t\n ");
++    if(pToken != NULL){
++        y = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0;
++        printk("y = 0x%08x \n\r", y);
++    }
++
++    if ( (sizeof(pdma_dvt_dbg_func)/sizeof(pdma_dvt_dbg_func[0]) > x) && NULL != pdma_dvt_dbg_func[x])
++    {
++        (*pdma_dvt_dbg_func[x])(x, y);
++    }
++    else
++    {
++        printk("no handler defined for command id(0x%08x)\n\r", x);
++    }
++    
++    printk("x(0x%08x), y(0x%08x)\n", x, y);
++
++    return len;
++}
++
++static const struct file_operations pdma_dev_sw_fops = {
++      .owner          = THIS_MODULE,
++      .open       = PdmaDvtOpen,
++      .read           = seq_read,
++      .write          = PdmaDvtWrite
++};
++#endif  //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++int debug_proc_init(void)
++{
++    if (procRegDir == NULL)
++      procRegDir = proc_mkdir(PROCREG_DIR, NULL);
++   
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procGmac = create_proc_entry(PROCREG_GMAC, 0, procRegDir)))
++          procGmac->proc_fops = &gmac_fops;
++    else
++#else
++    if (!(procGmac = proc_create(PROCREG_GMAC, 0, procRegDir, &gmac_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_GMAC);
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++#if defined(CONFIG_PSEUDO_SUPPORT)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procGmac2 = create_proc_entry(PROCREG_GMAC2, 0, procRegDir)))
++          procGmac2->proc_fops = &gmac2_fops;
++    else
++#else
++    if (!(procGmac2 = proc_create(PROCREG_GMAC2, 0, procRegDir, &gmac2_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_GMAC2);
++#endif        
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procSkbFree = create_proc_entry(PROCREG_SKBFREE, 0, procRegDir)))
++          procSkbFree->proc_fops = &skb_free_fops;
++    else
++#else
++    if (!(procSkbFree = proc_create(PROCREG_SKBFREE, 0, procRegDir, &skb_free_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_SKBFREE);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procTxRing = create_proc_entry(PROCREG_TXRING, 0, procRegDir)))
++          procTxRing->proc_fops = &tx_ring_fops;
++    else
++#else
++    if (!(procTxRing = proc_create(PROCREG_TXRING, 0, procRegDir, &tx_ring_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_TXRING);
++    
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procRxRing = create_proc_entry(PROCREG_RXRING, 0, procRegDir)))
++          procRxRing->proc_fops = &rx_ring_fops;
++    else
++#else
++    if (!(procRxRing = proc_create(PROCREG_RXRING, 0, procRegDir, &rx_ring_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING);
++
++#if defined (CONFIG_RAETH_HW_LRO) || defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procRxRing1 = create_proc_entry(PROCREG_RXRING1, 0, procRegDir)))
++          procRxRing1->proc_fops = &rx_ring1_fops;
++    else
++#else
++    if (!(procRxRing1 = proc_create(PROCREG_RXRING1, 0, procRegDir, &rx_ring1_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING1);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procRxRing2 = create_proc_entry(PROCREG_RXRING2, 0, procRegDir)))
++          procRxRing2->proc_fops = &rx_ring2_fops;
++    else
++#else
++    if (!(procRxRing2 = proc_create(PROCREG_RXRING2, 0, procRegDir, &rx_ring2_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING2);
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procRxRing3 = create_proc_entry(PROCREG_RXRING3, 0, procRegDir)))
++          procRxRing3->proc_fops = &rx_ring3_fops;
++    else
++#else
++    if (!(procRxRing3 = proc_create(PROCREG_RXRING3, 0, procRegDir, &rx_ring3_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_RXRING3);
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if defined (CONFIG_MIPS)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procSysCP0 = create_proc_entry(PROCREG_CP0, 0, procRegDir)))
++          procSysCP0->proc_fops = &cp0_reg_fops;
++    else
++#else
++    if (!(procSysCP0 = proc_create(PROCREG_CP0, 0, procRegDir, &cp0_reg_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_CP0);
++#endif
++
++#if defined(CONFIG_RAETH_TSO)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procNumOfTxd = create_proc_entry(PROCREG_NUM_OF_TXD, 0, procRegDir)))
++          procNumOfTxd->proc_fops = &tso_txd_num_fops;
++    else
++#else
++    if (!(procNumOfTxd = proc_create(PROCREG_NUM_OF_TXD, 0, procRegDir, &tso_txd_num_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_NUM_OF_TXD);
++    
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procTsoLen = create_proc_entry(PROCREG_TSO_LEN, 0, procRegDir)))
++          procTsoLen->proc_fops = &tso_len_fops;
++    else
++#else
++    if (!(procTsoLen = proc_create(PROCREG_TSO_LEN, 0, procRegDir, &tso_len_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_TSO_LEN);
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procLroStats = create_proc_entry(PROCREG_LRO_STATS, 0, procRegDir)))
++          procLroStats->proc_fops = &lro_stats_fops;
++    else
++#else
++    if (!(procLroStats = proc_create(PROCREG_LRO_STATS, 0, procRegDir, &lro_stats_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_LRO_STATS);
++#endif
++
++#if defined(CONFIG_RAETH_HW_LRO)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procHwLroStats = create_proc_entry(PROCREG_HW_LRO_STATS, 0, procRegDir)))
++          procHwLroStats->proc_fops = &hw_lro_stats_fops;
++    else
++#else
++    if (!(procHwLroStats = proc_create(PROCREG_HW_LRO_STATS, 0, procRegDir, &hw_lro_stats_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_STATS);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procHwLroAutoTlb = create_proc_entry(PROCREG_HW_LRO_AUTO_TLB, 0, procRegDir)))
++          procHwLroAutoTlb->proc_fops = &hw_lro_auto_tlb_fops;
++    else
++#else
++    if (!(procHwLroAutoTlb = proc_create(PROCREG_HW_LRO_AUTO_TLB, 0, procRegDir, &hw_lro_auto_tlb_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_AUTO_TLB);
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RAETH_QOS)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procRaQOS = create_proc_entry(PROCREG_RAQOS, 0, procRegDir)))
++          procRaQOS->proc_fops = &raeth_qos_fops;
++    else
++#else
++    if (!(procRaQOS = proc_create(PROCREG_RAQOS, 0, procRegDir, &raeth_qos_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_RAQOS);
++#endif
++
++#if defined(CONFIG_USER_SNMPD)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procRaSnmp = create_proc_entry(PROCREG_SNMP, S_IRUGO, procRegDir)))
++          procRaSnmp->proc_fops = &ra_snmp_seq_fops;
++    else
++#else
++    if (!(procRaSnmp = proc_create(PROCREG_SNMP, S_IRUGO, procRegDir, &ra_snmp_seq_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_SNMP);
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procEswCnt = create_proc_entry(PROCREG_ESW_CNT, 0, procRegDir)))
++          procEswCnt->proc_fops = &switch_count_fops;
++    else
++#else
++    if (!(procEswCnt = proc_create(PROCREG_ESW_CNT, 0, procRegDir, &switch_count_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT);
++
++#if defined (TASKLET_WORKQUEUE_SW)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procSCHE = create_proc_entry(PROCREG_SCHE, 0, procRegDir)))
++          procSCHE->proc_fops = &schedule_sw_fops;
++    else
++#else
++    if (!(procSCHE = proc_create(PROCREG_SCHE, 0, procRegDir, &schedule_sw_fops)))
++#endif
++          printk("!! FAIL to create %s PROC !!\n", PROCREG_SCHE);
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
++    if ((procPdmaDvt = create_proc_entry(PROCREG_PDMA_DVT, 0, procRegDir)))
++        procPdmaDvt->proc_fops = &pdma_dev_sw_fops;
++    else
++#else
++    if (!(procPdmaDvt = proc_create(PROCREG_PDMA_DVT, 0, procRegDir, &pdma_dev_sw_fops )))
++#endif
++        printk("!! FAIL to create %s PROC !!\n", PROCREG_PDMA_DVT);
++#endif  //#if defined(CONFIG_RAETH_PDMA_DVT)
++
++    printk(KERN_ALERT "PROC INIT OK!\n");
++    return 0;
++}
++
++void debug_proc_exit(void)
++{
++
++    if (procSysCP0)
++      remove_proc_entry(PROCREG_CP0, procRegDir);
++
++    if (procGmac)
++      remove_proc_entry(PROCREG_GMAC, procRegDir);
++#if defined(CONFIG_PSEUDO_SUPPORT) && defined(CONFIG_ETHTOOL)
++    if (procGmac)
++        remove_proc_entry(PROCREG_GMAC, procRegDir);
++#endif
++    if (procSkbFree)
++      remove_proc_entry(PROCREG_SKBFREE, procRegDir);
++
++    if (procTxRing)
++      remove_proc_entry(PROCREG_TXRING, procRegDir);
++    
++    if (procRxRing)
++      remove_proc_entry(PROCREG_RXRING, procRegDir);
++   
++#if defined(CONFIG_RAETH_TSO)
++    if (procNumOfTxd)
++      remove_proc_entry(PROCREG_NUM_OF_TXD, procRegDir);
++    
++    if (procTsoLen)
++      remove_proc_entry(PROCREG_TSO_LEN, procRegDir);
++#endif
++
++#if defined(CONFIG_RAETH_LRO)
++    if (procLroStats)
++      remove_proc_entry(PROCREG_LRO_STATS, procRegDir);
++#endif
++
++#if defined(CONFIG_RAETH_QOS)
++    if (procRaQOS)
++      remove_proc_entry(PROCREG_RAQOS, procRegDir);
++    if (procRaFeIntr)
++      remove_proc_entry(PROCREG_RXDONE_INTR, procRegDir);
++    if (procRaEswIntr)
++      remove_proc_entry(PROCREG_ESW_INTR, procRegDir);
++#endif
++
++#if defined(CONFIG_USER_SNMPD)
++    if (procRaSnmp)
++      remove_proc_entry(PROCREG_SNMP, procRegDir);
++#endif
++
++    if (procEswCnt)
++      remove_proc_entry(PROCREG_ESW_CNT, procRegDir);
++    
++    //if (procRegDir)
++      //remove_proc_entry(PROCREG_DIR, 0);
++      
++    printk(KERN_ALERT "proc exit\n");
++}
++EXPORT_SYMBOL(procRegDir);
+diff --git a/drivers/net/ethernet/raeth/ra_mac.h b/drivers/net/ethernet/raeth/ra_mac.h
+new file mode 100644
+index 0000000..66b32d3
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_mac.h
+@@ -0,0 +1,57 @@
++#ifndef RA_MAC_H
++#define RA_MAC_H
++
++void ra2880stop(END_DEVICE *ei_local);
++void ra2880MacAddressSet(unsigned char p[6]);
++void ra2880Mac2AddressSet(unsigned char p[6]);
++void ethtool_init(struct net_device *dev);
++
++void ra2880EnableInterrupt(void);
++
++void dump_qos(void);
++void dump_reg(struct seq_file *s);
++void dump_cp0(void);
++
++int debug_proc_init(void);
++void debug_proc_exit(void);
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++           defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621)
++void enable_auto_negotiate(int unused);
++#else
++void enable_auto_negotiate(int ge);
++#endif
++
++void rt2880_gmac_hard_reset(void);
++
++int TsoLenUpdate(int tso_len);
++int NumOfTxdUpdate(int num_of_txd);
++
++#ifdef CONFIG_RAETH_LRO
++int LroStatsUpdate(struct net_lro_mgr *lro_mgr, bool all_flushed);
++#endif
++#ifdef CONFIG_RAETH_HW_LRO
++int HwLroStatsUpdate(unsigned int ring_num, unsigned int agg_cnt, unsigned int agg_size);
++#if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++#define HW_LRO_AGG_FLUSH        (1)
++#define HW_LRO_AGE_FLUSH        (2)
++#define HW_LRO_NOT_IN_SEQ_FLUSH (3)
++#define HW_LRO_TIMESTAMP_FLUSH  (4)
++#define HW_LRO_NON_RULE_FLUSH   (5)
++int HwLroFlushStatsUpdate(unsigned int ring_num, unsigned int flush_reason);
++#endif  /* CONFIG_RAETH_HW_LRO_REASON_DBG */
++typedef int (*HWLRO_DBG_FUNC)(int par1, int par2);
++int hwlro_agg_cnt_ctrl(int par1, int par2);
++int hwlro_agg_time_ctrl(int par1, int par2);
++int hwlro_age_time_ctrl(int par1, int par2);
++int hwlro_pkt_int_alpha_ctrl(int par1, int par2);
++int hwlro_threshold_ctrl(int par1, int par2);
++int hwlro_fix_setting_switch_ctrl(int par1, int par2);
++#endif  /* CONFIG_RAETH_HW_LRO */
++int getnext(const char *src, int separator, char *dest);
++int str_to_ip(unsigned int *ip, const char *str);
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++typedef int (*PDMA_DBG_FUNC)(int par1, int par2);
++#endif  //#if defined(CONFIG_RAETH_PDMA_DVT)
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_netlink.c b/drivers/net/ethernet/raeth/ra_netlink.c
+new file mode 100644
+index 0000000..f7c3650
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_netlink.c
+@@ -0,0 +1,142 @@
++// for netlink header
++#include <asm/types.h>
++#include <net/sock.h>
++#include <linux/socket.h>
++#include <linux/netlink.h>
++#include <linux/skbuff.h>
++#include <linux/net.h>
++#include <linux/version.h>
++
++#include "csr_netlink.h"
++#include "ra2882ethreg.h"
++#include "ra_netlink.h"
++
++static struct sock *csr_msg_socket = NULL; // synchronize socket for netlink use
++unsigned int flags;
++
++void rt2880_csr_receiver(struct sock *sk, int len)
++{
++      struct sk_buff *skb;
++      int err;
++      struct nlmsghdr *nlh;
++      unsigned int reg_value = 0;
++      CSR_MSG *csrmsg;
++      RAETH_PRINT("csr netlink receiver!\n");
++      skb = skb_recv_datagram(sk, 0, 1, &err);
++
++      RAETH_PRINT("error no : %d\n", err);
++      
++      if (skb == NULL) {
++              printk("rt2880_csr_receiver(): No data received, error!\n");
++              return;
++      }
++      
++      nlh = (struct nlmsghdr*)skb->data;
++      
++      csrmsg = NLMSG_DATA(nlh);
++
++      if (csrmsg->enable == CSR_READ ) {
++              reg_value = sysRegRead(csrmsg->address);
++#if 0
++              printk("raeth -- 0x%08x: 0x%08x\n", csrmsg->address, reg_value);
++#endif
++      } else if ( csrmsg->enable == CSR_WRITE ) {
++              sysRegWrite(csrmsg->address, csrmsg->default_value);
++              reg_value = sysRegRead(csrmsg->address);
++      } else if ( csrmsg->enable == CSR_TEST ) {
++              reg_value = sysRegRead(csrmsg->address);
++              printk("0x%08x: 0x%08x\n", (unsigned int)csrmsg->address, reg_value);   
++      }
++      else
++              printk("drv: Command format error!\n");
++
++      csrmsg->default_value = reg_value;
++              
++      RAETH_PRINT("drv: rt2880_csr_msgsend() - msg to send!\n");              
++      
++      err = rt2880_csr_msgsend(csrmsg);       
++      
++      if ( err == -2 )
++              printk("drv: msg send error!\n");
++
++      skb_free_datagram(sk, skb);
++}
++
++int rt2880_csr_msgsend(CSR_MSG* csrmsg)
++{
++      struct sk_buff *skb;
++      struct nlmsghdr *nlh = NULL;
++      size_t size = 0;
++      struct sock *send_syncnl = csr_msg_socket;
++
++      CSR_MSG* csr_reg;
++      if (send_syncnl == NULL) {
++              printk("drv: netlink_kernel_create() failed!\n");
++              return -1;
++      }
++              
++      size = NLMSG_SPACE(sizeof(CSR_MSG));
++      skb = alloc_skb(size, GFP_ATOMIC);
++      
++      if(!skb)
++      {
++              printk("rt2880_csr_msgsend() : error! msg structure not available\n");
++              return -1;
++      }
++      
++      nlh = NLMSG_PUT(skb, 0, 0, RALINK_CSR_GROUP, size - sizeof(struct nlmsghdr));
++      
++      if (!nlh)
++      {
++              printk("rt2880_csr_msgsend() : error! nlh structure not available\n");
++              return -1;
++      }
++
++      csr_reg = NLMSG_DATA(nlh);
++      if (!csr_reg)
++      {
++              printk("rt2880_csr_msgsend() : error! nlh structure not available\n");
++              return -1;
++      }
++
++      csr_reg->address        = csrmsg->address;
++      csr_reg->default_value  = csrmsg->default_value;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++      NETLINK_CB(skb).dst_group = RALINK_CSR_GROUP;
++#else
++      NETLINK_CB(skb).dst_groups = RALINK_CSR_GROUP;
++#endif
++      netlink_broadcast(send_syncnl, skb, 0, RALINK_CSR_GROUP, GFP_ATOMIC);
++      return 0;
++
++nlmsg_failure:
++      return -2;      
++}
++
++int csr_netlink_init()
++{
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++      csr_msg_socket = netlink_kernel_create(NETLINK_CSR, RALINK_CSR_GROUP, rt2880_csr_receiver, THIS_MODULE);
++#else
++      csr_msg_socket = netlink_kernel_create(NETLINK_CSR, rt2880_csr_receiver);
++#endif
++
++      if ( csr_msg_socket == NULL )
++              printk("unable to create netlink socket!\n");
++      else
++              printk("Netlink init ok!\n");
++      return 0;
++}
++
++void csr_netlink_end()
++{
++      if (csr_msg_socket != NULL){
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++              sock_release(csr_msg_socket->sk_socket);
++#else
++              sock_release(csr_msg_socket->socket);
++#endif
++              printk("Netlink end...\n");
++      }
++}
+diff --git a/drivers/net/ethernet/raeth/ra_netlink.h b/drivers/net/ethernet/raeth/ra_netlink.h
+new file mode 100644
+index 0000000..19ca71f
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_netlink.h
+@@ -0,0 +1,10 @@
++#ifndef RA_NETLINK
++#define RA_NETLINK
++
++#include "csr_netlink.h"
++int rt2880_csr_msgsend(CSR_MSG* csrmsg);
++void rt2880_csr_receiver(struct sock *sk, int len);
++int csr_netlink_init(void);
++void csr_netlink_end(void);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_qos.c b/drivers/net/ethernet/raeth/ra_qos.c
+new file mode 100644
+index 0000000..0a7d9c5
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_qos.c
+@@ -0,0 +1,655 @@
++#include <asm/io.h>
++#include <linux/pci.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include "ra_qos.h"
++#include "raether.h"
++#include "ra2882ethreg.h"
++
++#include <asm/types.h>
++#include <net/sock.h>
++#include <linux/socket.h>
++#include <linux/skbuff.h>
++#include <linux/net.h>
++#include <linux/if_vlan.h>
++#include <linux/ip.h>
++
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++
++#define CONTI_TX_SEND_MAX_SIZE        1440
++
++/* 
++ * set tx queue # to descriptor
++ */
++void rt3052_tx_queue_init(unsigned long data)
++{
++      /* define qos p */
++      
++}
++
++void rt3052_pse_port0_fc_clear(unsigned long data)
++{
++      /* clear FE_INT_STATUS.PSE_P0_FC */
++      
++}
++
++inline int get_tx_ctx_idx(unsigned int ring_no, unsigned long *idx)
++{
++      switch (ring_no) {
++              case RING0:
++                      *idx = *(unsigned long*)TX_CTX_IDX0;
++                      break;
++              case RING1:
++                      *idx = *(unsigned long*)TX_CTX_IDX1;
++                      break;
++              case RING2:
++                      *idx = *(unsigned long*)TX_CTX_IDX2;
++                      break;
++              case RING3:
++                      *idx = *(unsigned long*)TX_CTX_IDX3;
++                      break;
++              default:
++                      printk("set_tx_ctx_idex error\n");
++                      return -1;
++      };
++      return 0;
++}
++
++inline int set_tx_ctx_idx(unsigned int ring_no, unsigned int idx)
++{
++      switch (ring_no ) {
++              case RING0:
++                      *(unsigned long*)TX_CTX_IDX0 = cpu_to_le32((u32)idx);
++                      break;
++              case RING1:
++                      *(unsigned long*)TX_CTX_IDX1 = cpu_to_le32((u32)idx);
++                      break;
++              case RING2:
++                      *(unsigned long*)TX_CTX_IDX2 = cpu_to_le32((u32)idx);
++                      break;
++              case RING3:
++                      *(unsigned long*)TX_CTX_IDX3 = cpu_to_le32((u32)idx);
++                      break;
++              default:
++                      printk("set_tx_ctx_idex error\n");
++                      return -1;
++      };
++
++      return 1;
++}
++
++void get_tx_desc_and_dtx_idx(END_DEVICE* ei_local, int ring_no, unsigned long *tx_dtx_idx, struct PDMA_txdesc **tx_desc)
++{
++      switch (ring_no) {
++              case RING0:
++                      *tx_desc = ei_local->tx_ring0;
++                      *tx_dtx_idx      = *(unsigned long*)TX_DTX_IDX0;
++                      break;
++              case RING1:
++                      *tx_desc = ei_local->tx_ring1;
++                      *tx_dtx_idx      = *(unsigned long*)TX_DTX_IDX1;
++                      break;
++              case RING2:
++                      *tx_desc = ei_local->tx_ring2;
++                      *tx_dtx_idx      = *(unsigned long*)TX_DTX_IDX2;
++                      break;
++              case RING3:
++                      *tx_desc = ei_local->tx_ring3;
++                      *tx_dtx_idx      = *(unsigned long*)TX_DTX_IDX3;
++                      break;
++              default:
++                      printk("ring_no input error... %d\n", ring_no);
++      };
++}
++
++int fe_qos_packet_send(struct net_device *dev, struct sk_buff* skb, unsigned int ring_no, unsigned int qn, unsigned pn)
++{
++      END_DEVICE* ei_local = netdev_priv(dev);
++      struct PDMA_txdesc* tx_desc;
++      unsigned int tx_cpu_owner_idx, tx_dtx_idx;
++
++      unsigned int    length=skb->len;
++      int ret;
++      unsigned long flags;
++
++      //printk("fe_qos_packet_send: ring_no=%d qn=%d pn=%d\n", ring_no, qn, pn);
++
++      switch ( ring_no ) {
++              case 0:
++                      tx_desc = ei_local->tx_ring0;
++                      tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX0;
++                      tx_dtx_idx       = *(unsigned long*)TX_DTX_IDX0;
++                      break;
++              case 1:
++                      tx_desc = ei_local->tx_ring1;
++                      tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX1;
++                      tx_dtx_idx       = *(unsigned long*)TX_DTX_IDX1;
++                      break;
++              case 2:
++                      tx_desc = ei_local->tx_ring2;
++                      tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX2;
++                      tx_dtx_idx       = *(unsigned long*)TX_DTX_IDX2;
++                      break;
++              case 3:
++                      tx_desc = ei_local->tx_ring3;
++                      tx_cpu_owner_idx = *(unsigned long*)TX_CTX_IDX3;
++                      tx_dtx_idx       = *(unsigned long*)TX_DTX_IDX3;
++                      break;
++              default:
++                      printk("ring_no input error... %d\n", ring_no);
++                      return -1;
++      };
++
++      //printk("tx_cpu_owner_idx=%d tx_dtx_idx=%d\n", tx_cpu_owner_idx, tx_dtx_idx);
++
++      if(tx_desc == NULL) {
++              printk("%s : txdesc is NULL\n", dev->name);
++              return -1;
++      }
++
++      tx_desc[tx_cpu_owner_idx].txd_info1.SDP0 = virt_to_phys(skb->data);
++      tx_desc[tx_cpu_owner_idx].txd_info2.SDL0 = length;
++      tx_desc[tx_cpu_owner_idx].txd_info2.DDONE_bit = 0;
++      tx_desc[tx_cpu_owner_idx].txd_info4.PN = pn;
++      tx_desc[tx_cpu_owner_idx].txd_info4.QN = qn;
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++      ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.TCO = 1; 
++      ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.UCO = 1; 
++      ei_local->tx_ring0[tx_cpu_owner_idx].txd_info4.ICO = 1; 
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) 
++      if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++          tx_desc[tx_cpu_owner_idx].txd_info4.PN = 6; /* PPE */
++      } else {
++          tx_desc[tx_cpu_owner_idx].txd_info4.PN = pn; 
++      }
++      
++#endif
++
++      spin_lock_irqsave(&ei_local->page_lock, flags);
++      ei_local->skb_free[ring_no][tx_cpu_owner_idx] = skb;
++      tx_cpu_owner_idx = (tx_cpu_owner_idx +1) % NUM_TX_DESC;
++      ret = set_tx_ctx_idx(ring_no, tx_cpu_owner_idx);
++      spin_unlock_irqrestore(&ei_local->page_lock, flags);
++
++      ei_local->stat.tx_packets++;
++      ei_local->stat.tx_bytes += length;
++
++#ifdef CONFIG_RAETH_NAPI
++      switch ( ring_no ) {
++              case 0:
++                      if ( ei_local->tx0_full == 1) {
++                              ei_local->tx0_full = 0;
++                              netif_wake_queue(dev);
++                      }
++                      break;
++              case 1:
++                      if ( ei_local->tx1_full == 1) {
++                              ei_local->tx1_full = 0;
++                              netif_wake_queue(dev);
++                      }
++                      break;
++              case 2:
++                      if ( ei_local->tx2_full == 1) {
++                              ei_local->tx2_full = 0;
++                              netif_wake_queue(dev);
++                      }
++                      break;
++              case 3:
++                      if ( ei_local->tx3_full == 1) {
++                              ei_local->tx3_full = 0;
++                              netif_wake_queue(dev);
++                      }
++                      break;
++              default :
++                      printk("ring_no input error %d\n", ring_no);
++      };
++#endif
++      return length;
++}
++
++int fe_tx_desc_init(struct net_device *dev, unsigned int ring_no, unsigned int qn, unsigned int pn)
++{
++      END_DEVICE* ei_local = netdev_priv(dev);
++      struct PDMA_txdesc *tx_desc;
++      unsigned int tx_cpu_owner_idx = 0;
++      int i;
++      unsigned int phy_tx_ring;
++
++      // sanity check
++      if ( ring_no > 3 ){
++              printk("%s : ring_no - %d, please under 4...\n", dev->name, ring_no);
++              return 0;
++      }
++
++      if ( pn > 2 ){
++              printk("%s : pn - %d, please under 2...\n", dev->name, pn);
++              return 0;
++      }
++
++      tx_desc = pci_alloc_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), &phy_tx_ring);
++      ei_local->tx_cpu_owner_idx0 = tx_cpu_owner_idx;
++      
++      switch (ring_no) {
++              case 0:
++                      ei_local->tx_ring0 = tx_desc;
++                      ei_local->phy_tx_ring0 = phy_tx_ring;
++                      break;
++              case 1:
++                      ei_local->phy_tx_ring1 = phy_tx_ring;
++                      ei_local->tx_ring1 = tx_desc;
++                      break;
++              case 2:
++                      ei_local->phy_tx_ring2 = phy_tx_ring;
++                      ei_local->tx_ring2 = tx_desc;
++                      break;
++              case 3:
++                      ei_local->phy_tx_ring3 = phy_tx_ring;
++                      ei_local->tx_ring3 = tx_desc;
++                      break;
++              default:
++                      printk("ring_no input error! %d\n", ring_no);
++                      pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), tx_desc, phy_tx_ring);
++                      return 0;
++      };      
++
++      if ( tx_desc == NULL)
++      {
++              printk("tx desc allocation failed!\n");
++              return 0;
++      }
++
++      for( i = 0; i < NUM_TX_DESC; i++) {
++              memset( &tx_desc[i], 0, sizeof(struct PDMA_txdesc));
++              tx_desc[i].txd_info2.LS0_bit = 1;
++              tx_desc[i].txd_info2.DDONE_bit = 1;
++              tx_desc[i].txd_info4.PN = pn;
++              tx_desc[i].txd_info4.QN = qn;
++      }
++
++      switch ( ring_no ) {
++              case 0 :
++                      *(unsigned long*)TX_BASE_PTR0 = phys_to_bus((u32) phy_tx_ring);
++                      *(unsigned long*)TX_MAX_CNT0  = cpu_to_le32((u32)NUM_TX_DESC);
++                      *(unsigned long*)TX_CTX_IDX0  = cpu_to_le32((u32) tx_cpu_owner_idx);
++                      sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX0);
++                      break;
++              case 1 :
++                      *(unsigned long*)TX_BASE_PTR1 = phys_to_bus((u32) phy_tx_ring);
++                      *(unsigned long*)TX_MAX_CNT1  = cpu_to_le32((u32)NUM_TX_DESC);
++                      *(unsigned long*)TX_CTX_IDX1  = cpu_to_le32((u32) tx_cpu_owner_idx);
++                      sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX1);
++                      break;
++              case 2 :
++                      *(unsigned long*)TX_BASE_PTR2 = phys_to_bus((u32) phy_tx_ring);
++                      *(unsigned long*)TX_MAX_CNT2  = cpu_to_le32((u32)NUM_TX_DESC);
++                      *(unsigned long*)TX_CTX_IDX2  = cpu_to_le32((u32) tx_cpu_owner_idx);
++                      sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX2);
++                      break;
++              case 3 :
++                      *(unsigned long*)TX_BASE_PTR3 = phys_to_bus((u32) phy_tx_ring);
++                      *(unsigned long*)TX_MAX_CNT3  = cpu_to_le32((u32)NUM_TX_DESC);
++                      *(unsigned long*)TX_CTX_IDX3  = cpu_to_le32((u32) tx_cpu_owner_idx);
++                      sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX3);
++                      break;
++              default :
++                      printk("tx descriptor init failed %d\n", ring_no);
++                      return 0;
++      };
++      return 1;
++}
++
++/*
++   DSCP | AC | WMM_AC (Access Category)
++   ------+----+--------
++   00-07|  1 |  BE
++   24-31|  1 |  BE
++   08-15|  0 |  BG
++   16-23|  0 |  BG
++   32-39|  2 |  VI
++   40-47|  2 |  VI
++   48-55|  3 |  VO
++   56-63|  3 |  VO 
++
++          |    TOS    |
++     DSCP |(bit5~bit7)|  WMM  
++   -------+-----------+-------
++    0x00  |    000    |   BE
++    0x18  |    011    |   BE
++    0x08  |    001    |   BG
++    0x10  |    010    |   BG
++    0x20  |    100    |   VI
++    0x28  |    101    |   VI
++    0x30  |    110    |   VO
++    0x38  |    111    |   VO
++
++    Notes: BE should be mapped to AC1, but mapped to AC0 in linux kernel.
++
++ */
++
++int  pkt_classifier(struct sk_buff *skb,int gmac_no, int *ring_no, int *queue_no, int *port_no)
++{
++#if defined(CONFIG_RALINK_RT2880)
++    /* RT2880 -- Assume using 1 Ring (Ring0), Queue 0, and Port 0 */
++    *port_no  = 0;
++    *ring_no  = 0;
++    *queue_no         = 0;
++#else
++    unsigned int ac=0;
++    unsigned int bridge_traffic=0, lan_traffic=0;
++    struct iphdr *iph=NULL;
++    struct vlan_ethhdr *veth=NULL;
++    unsigned int vlan_id=0;
++#if defined (CONFIG_RAETH_QOS_DSCP_BASED)
++    static char DscpToAcMap[8]={1,0,0,1,2,2,3,3};
++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED)
++    static char VlanPriToAcMap[8]={1,0,0,1,2,2,3,3};
++#endif
++
++    /* Bridge:: {BG,BE,VI,VO} */
++    /* GateWay:: WAN: {BG,BE,VI,VO}, LAN: {BG,BE,VI,VO} */
++#if defined (CONFIG_RALINK_RT3883) && defined (CONFIG_RAETH_GMAC2)
++    /* 
++     * 1) Bridge: 
++     *    1.1) GMAC1 ONLY:
++     *                 VO/VI->Ring3, BG/BE->Ring2 
++     *    1.2) GMAC1+GMAC2: 
++     *                 GMAC1:: VO/VI->Ring3, BG/BE->Ring2 
++     *                 GMAC2:: VO/VI->Ring1, BG/BE->Ring0 
++     * 2) GateWay:
++     *    2.1) GMAC1 ONLY:
++     *               GMAC1:: LAN:VI/VO->Ring2, BE/BK->Ring2
++     *                       WAN:VI/VO->Ring3, BE/BK->Ring3
++     *    2.2)GMAC1+GMAC2: 
++     *               GMAC1:: LAN:VI/VO/BE/BK->Ring2, WAN:VI/VO/BE/BK->Ring3
++     *               GMAC2:: VI/VO->Ring1, BE/BK->Ring0
++     */
++    static unsigned char AcToRing_BridgeMap[4] = {2, 2, 3, 3}; 
++    static unsigned char AcToRing_GE1Map[2][4] = {{3, 3, 3, 3},{2, 2, 2, 2}}; 
++    static unsigned char AcToRing_GE2Map[4] = {0, 0, 1, 1};
++#elif defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT2883) || \
++      defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || \
++      defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++      defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++      defined (CONFIG_RALINK_MT7628) || \
++     (defined (CONFIG_RALINK_RT3883) && !defined(CONFIG_RAETH_GMAC2))
++    /* 
++     * 1) Bridge: VO->Ring3, VI->Ring2, BG->Ring1, BE->Ring0 
++     * 2) GateWay:
++     *    2.1) GMAC1:: LAN:VI/VO->Ring1, BE/BK->Ring0
++     *                       WAN:VI/VO->Ring3, BE/BK->Ring2
++     */ 
++    static unsigned char AcToRing_BridgeMap[4] = {0, 1, 2, 3}; 
++    static unsigned char AcToRing_GE1Map[2][4] = {{2, 2, 3, 3},{0, 0, 1, 1}}; 
++#endif  // CONFIG_RALINK_RT2883
++
++    /* 
++     * Set queue no - QN field in TX Descriptor
++     * always use queue 3 for the packet from CPU to GMAC 
++     */
++    *queue_no = 3; 
++
++    /* Get access category */
++    veth = (struct vlan_ethhdr *)(skb->data);
++    if(veth->h_vlan_proto == htons(ETH_P_8021Q)) { // VLAN traffic
++      iph= (struct iphdr *)(skb->data + VLAN_ETH_HLEN); 
++
++      vlan_id = ntohs(veth->h_vlan_TCI & VLAN_VID_MASK);
++      if(vlan_id==1) { //LAN
++          lan_traffic = 1;
++      } else { //WAN
++          lan_traffic = 0;
++      }
++
++      if (veth->h_vlan_encapsulated_proto == htons(ETH_P_IP)) { //IPv4 
++#if defined (CONFIG_RAETH_QOS_DSCP_BASED)
++          ac = DscpToAcMap[(iph->tos & 0xe0) >> 5];
++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED)
++          ac = VlanPriToAcMap[skb->priority];
++#endif
++      }else { //Ipv6, ARP ...etc
++          ac = 0;
++      }
++    }else { // non-VLAN traffic
++      if (veth->h_vlan_proto == htons(ETH_P_IP)) { //IPv4
++#if defined (CONFIG_RAETH_QOS_DSCP_BASED)
++          iph= (struct iphdr *)(skb->data + ETH_HLEN);
++          ac = DscpToAcMap[(iph->tos & 0xe0) >> 5];
++#elif defined (CONFIG_RAETH_QOS_VPRI_BASED)
++          ac= VlanPriToAcMap[skb->priority];
++#endif
++      }else { // IPv6, ARP ...etc
++          ac = 0;
++      }
++
++      bridge_traffic=1;
++    }
++    
++
++    /* Set Tx Ring no */
++    if(gmac_no==1) { //GMAC1
++      if(bridge_traffic) { //Bridge Mode
++          *ring_no = AcToRing_BridgeMap[ac];
++      }else { //GateWay Mode
++          *ring_no = AcToRing_GE1Map[lan_traffic][ac];
++      }
++    }else { //GMAC2
++#if defined (CONFIG_RALINK_RT3883) && defined (CONFIG_RAETH_GMAC2)
++      *ring_no = AcToRing_GE2Map[ac];
++#endif
++    }
++
++
++    /* Set Port No - PN field in Tx Descriptor*/
++#if defined(CONFIG_RAETH_GMAC2)
++    *port_no = gmac_no;
++#else
++    if(bridge_traffic) {
++      *port_no = 1;
++    }else {
++      if(lan_traffic==1) { //LAN use VP1
++          *port_no = 1;
++      }else { //WAN use VP2
++          *port_no = 2;
++      }
++    }
++#endif // CONFIG_RAETH_GMAC2 //
++
++#endif
++
++    return 1;
++
++}
++
++
++/*
++ *  Routine Description : 
++ *  Hi/Li Rings and Queues definition for QoS Purpose
++ *
++ *  Related registers: (Detail information refer to pp106 of RT3052_DS_20080226.doc)
++ *  Priority High/Low Definition - PDMA_FC_CFG, GDMA1_FC_CFG, GDMA2_FC_CFG
++ *  Bit 28 -  Allows high priority Q to share low priority Q's reserved pages
++ *  Bit 27:24 -  Px high priority definition bitmap 
++ *  Weight Configuration - GDMA1_SCH_CFG, GDMA2_SCH_CFG, PDMA_SCH_CFG -> default 3210
++ *
++ * Parameter: 
++ *    NONE
++ *    
++*/
++#define PSE_P1_LQ_FULL (1<<2)
++#define PSE_P1_HQ_FULL (1<<3)
++#define PSE_P2_LQ_FULL (1<<4)
++#define PSE_P2_HQ_FULL (1<<5)
++
++#define HIGH_QUEUE(queue)   (1<<(queue))
++#define LOW_QUEUE(queue)    (0<<(queue))
++#define PAGES_SHARING     (1<<28)
++#define RSEV_PAGE_COUNT_HQ  0x10 /* Reserved page count for high priority Q */
++#define RSEV_PAGE_COUNT_LQ  0x10 /* Reserved page count for low priority Q */
++#define VIQ_FC_ASRT       0x10 /* Virtual input Q FC assertion threshold */
++
++#define QUEUE_WEIGHT_1            0
++#define QUEUE_WEIGHT_2            1
++#define QUEUE_WEIGHT_4            2
++#define QUEUE_WEIGHT_8            3
++#define QUEUE_WEIGHT_16     4
++
++#define WRR_SCH                   0 /*WRR */
++#define STRICT_PRI_SCH            1 /* Strict Priority */
++#define MIX_SCH                   2 /* Mixed : Q3>WRR(Q2,Q1,Q0) */
++
++/*
++ *           Ring3  Ring2  Ring1  Ring0
++ *            |  |   |  |  |  |   |  |
++ *            |  |   |  |  |  |   |  |
++ *        --------------------------------
++ *        |         WRR Scheduler        |
++ *        --------------------------------
++ *                       |
++ *    ---------------------------------------
++ *    |                 PDMA                |
++ *    ---------------------------------------
++ *     |Q3||Q2||Q1||Q0|    |Q3||Q2||Q1||Q0|
++ *     |  ||  ||  ||  |    |  ||  ||  ||  |
++ *    ------------------- -------------------
++ *    |      GDMA2      | |     GDMA1       |
++ *    ------------------- -------------------
++ *              |                      |
++ *      ------------------------------------
++ *      |              GMAC                |
++ *      ------------------------------------
++ *                       |
++ *
++ */
++void set_scheduler_weight(void)
++{
++#if !defined (CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++    /* 
++     * STEP1: Queue scheduling configuration 
++     */
++    *(unsigned long *)GDMA1_SCH_CFG = (WRR_SCH << 24) | 
++      (QUEUE_WEIGHT_16 << 12) | /* queue 3 weight */
++      (QUEUE_WEIGHT_8 << 8) |  /* queue 2 weight */
++      (QUEUE_WEIGHT_4  << 4) |  /* queue 1 weight */
++      (QUEUE_WEIGHT_2  << 0);   /* queue 0 weight */
++
++    *(unsigned long *)GDMA2_SCH_CFG = (WRR_SCH << 24) | 
++      (QUEUE_WEIGHT_16 << 12) | /* queue 3 weight */
++      (QUEUE_WEIGHT_8 << 8) |  /* queue 2 weight */
++      (QUEUE_WEIGHT_4  << 4) |  /* queue 1 weight */
++      (QUEUE_WEIGHT_2  << 0);   /* queue 0 weight */
++    
++#endif
++    /* 
++     * STEP2: Ring scheduling configuration 
++     */
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621)
++    /* MIN_RATE_RATIO0=0, MAX_RATE_ULMT0=1, Weight0=1 */
++    *(unsigned long *)SCH_Q01_CFG =  (0 << 10) | (1<<14) | (0 << 12);
++    /* MIN_RATE_RATIO1=0, MAX_RATE_ULMT1=1, Weight1=4 */
++    *(unsigned long *)SCH_Q01_CFG |= (0 << 26) | (1<<30) | (2 << 28);
++
++    /* MIN_RATE_RATIO2=0, MAX_RATE_ULMT2=1, Weight0=1 */
++    *(unsigned long *)SCH_Q23_CFG =  (0 << 10) | (1<<14) | (0 << 12);
++    /* MIN_RATE_RATIO3=0, MAX_RATE_ULMT3=1, Weight1=4 */
++    *(unsigned long *)SCH_Q23_CFG |= (0 << 26) | (1<<30) | (2 << 28);
++#else
++    *(unsigned long *)PDMA_SCH_CFG = (WRR_SCH << 24) | 
++      (QUEUE_WEIGHT_16 << 12) | /* ring 3 weight */
++      (QUEUE_WEIGHT_4 << 8) |  /* ring 2 weight */
++      (QUEUE_WEIGHT_16 << 4) |  /* ring 1 weight */
++      (QUEUE_WEIGHT_4 << 0);   /* ring 0 weight */
++#endif
++}
++
++/*
++ * Routine Description : 
++ *    Bucket size and related information from ASIC Designer, 
++ *    please check Max Lee to update these values
++ *
++ *    Related Registers
++ *      FE_GLO_CFG - initialize clock rate for rate limiting
++ *      PDMA_FC_CFG - Pause mechanism for Rings (Ref to pp116 in datasheet)
++ *      :
++ * Parameter: 
++ *    NONE
++ */
++/*
++ *    Bit 29:24 - Q3 flow control pause condition
++ *    Bit 21:16 - Q2 flow control pause condition
++ *    Bit 13:8  - Q1 flow control pause condition
++ *    Bit 5:0   - Q0 flow control pause condition
++ *
++ *    detail bitmap -
++ *      Bit[5] - Pause Qx when PSE p2 HQ full
++ *      Bit[4] - Pause Qx when PSE p2 LQ full
++ *      Bit[3] - Pause Qx when PSE p1 HQ full
++ *      Bit[2] - Pause Qx when PSE p1 LQ full
++ *      Bit[1] - Pause Qx when PSE p0 HQ full
++ *      Bit[0] - Pause Qx when PSE p0 LQ full
++ */
++void set_schedule_pause_condition(void)
++{
++#if defined (CONFIG_RALINK_MT7620)
++    
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++    *(unsigned long *)SDM_TRING = (0xC << 28) | (0x3 << 24) | (0xC << 4) | 0x3;
++#else
++    /* 
++     * STEP1: Set queue priority is high or low 
++     *
++     * Set queue 3 as high queue in GMAC1/GMAC2 
++     */       
++    *(unsigned long *)GDMA1_FC_CFG = ((HIGH_QUEUE(3)|LOW_QUEUE(2) | 
++                                    LOW_QUEUE(1)|LOW_QUEUE(0))<<24) |
++                                    (RSEV_PAGE_COUNT_HQ << 16) |
++                                    (RSEV_PAGE_COUNT_LQ <<8) |
++                                    VIQ_FC_ASRT | PAGES_SHARING;
++
++    *(unsigned long *)GDMA2_FC_CFG = ((HIGH_QUEUE(3)|LOW_QUEUE(2) | 
++                                    LOW_QUEUE(1)|LOW_QUEUE(0))<<24) |
++                                    (RSEV_PAGE_COUNT_HQ << 16) |
++                                    (RSEV_PAGE_COUNT_LQ <<8) |
++                                    VIQ_FC_ASRT | PAGES_SHARING;
++    
++    /* 
++     * STEP2: Set flow control pause condition 
++     *
++     * CPU always use queue 3, and queue3 is high queue.
++     * If P2(GMAC2) high queue is full, pause ring3/ring2
++     * If P1(GMAC1) high queue is full, pause ring1/ring0
++     */
++    *(unsigned long *)PDMA_FC_CFG =  ( PSE_P2_HQ_FULL << 24 ) | /* queue 3 */
++      ( PSE_P2_HQ_FULL << 16 ) | /* queue 2 */
++      ( PSE_P1_HQ_FULL << 8 ) |  /* queue 1 */
++      ( PSE_P1_HQ_FULL << 0 );  /* queue 0 */
++#endif
++    
++}
++
++
++void set_output_shaper(void)
++{
++#define GDMA1_TOKEN_RATE      16  /* unit=64bits/ms */
++#define GDMA2_TOKEN_RATE      16  /* unit=64bits/ms */
++
++#if 0
++    *(unsigned long *)GDMA1_SHPR_CFG =  (1 << 24) | /* output shaper enable */
++                                      (128 << 16) | /* bucket size (unit=1KB) */
++                                      (GDMA1_TOKEN_RATE << 0); /* token rate (unit=8B/ms) */
++#endif
++
++#if 0
++    *(unsigned long *)GDMA2_SHPR_CFG =  (1 << 24) | /* output shaper enable */
++                                      (128 << 16) | /* bucket size (unit=1KB) */
++                                      (GDMA2_TOKEN_RATE << 0); /* token rate (unit=8B/ms) */
++#endif
++}
+diff --git a/drivers/net/ethernet/raeth/ra_qos.h b/drivers/net/ethernet/raeth/ra_qos.h
+new file mode 100644
+index 0000000..7f2a8a1
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_qos.h
+@@ -0,0 +1,18 @@
++#ifndef RA_QOS_H
++#define       RA_QOS_H
++
++#include "ra2882ethreg.h"
++#define RING0 0
++#define RING1 1
++#define RING2 2
++#define RING3 3
++void get_tx_desc_and_dtx_idx(END_DEVICE* ei_local, int ring_no, unsigned long *tx_dtx_idx, struct PDMA_txdesc **tx_desc);
++int get_tx_ctx_idx(unsigned int ring_no, unsigned long *idx);
++int fe_tx_desc_init(struct net_device *dev, unsigned int ring_no, unsigned int qn, unsigned int pn);
++int fe_qos_packet_send(struct net_device *dev, struct sk_buff* skb, unsigned int ring_no, unsigned int qn, unsigned int pn);
++
++int  pkt_classifier(struct sk_buff *skb,int gmac_no, int *ring_no, int *queue_no, int *port_no);
++void set_schedule_pause_condition(void);
++void set_scheduler_weight(void);
++void set_output_shaper(void);
++#endif
+diff --git a/drivers/net/ethernet/raeth/ra_rfrw.c b/drivers/net/ethernet/raeth/ra_rfrw.c
+new file mode 100644
+index 0000000..d73db01
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_rfrw.c
+@@ -0,0 +1,66 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/signal.h>
++#include <linux/irq.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++
++#define RF_CSR_CFG      0xb0180500
++#define RF_CSR_KICK     (1<<17)
++int rw_rf_reg(int write, int reg, int *data)
++{
++        unsigned long    rfcsr, i = 0;
++
++        while (1) {
++                rfcsr =  sysRegRead(RF_CSR_CFG);
++                if (! (rfcsr & (u32)RF_CSR_KICK) )
++                        break;
++                if (++i > 10000) {
++                        printk("Warning: Abort rw rf register: too busy\n");
++                        return -1;
++                }
++        }
++
++        rfcsr = (u32)(RF_CSR_KICK | ((reg&0x3f) << 8) | (*data & 0xff));
++        if (write)
++                rfcsr |= 0x10000;
++
++         sysRegRead(RF_CSR_CFG) = cpu_to_le32(rfcsr);
++
++        i = 0;
++        while (1) {
++                rfcsr =  sysRegRead(RF_CSR_CFG);
++                if (! (rfcsr & (u32)RF_CSR_KICK) )
++                        break;
++                if (++i > 10000) {
++                        printk("Warning: still busy\n");
++                        return -1;
++                }
++        }
++
++        rfcsr =  sysRegRead(RF_CSR_CFG);
++
++        if (((rfcsr&0x1f00) >> 8) != (reg & 0x1f)) {
++                printk("Error: rw register failed\n");
++                return -1;
++        }
++        *data = (int)(rfcsr & 0xff);
++
++        return 0;
++}
++
+diff --git a/drivers/net/ethernet/raeth/ra_rfrw.h b/drivers/net/ethernet/raeth/ra_rfrw.h
+new file mode 100644
+index 0000000..da5a371
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/ra_rfrw.h
+@@ -0,0 +1,6 @@
++#ifndef RA_RFRW_H
++#define RA_RFRW_H
++
++int rw_rf_reg(int write, int reg, int *data);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/raether.c b/drivers/net/ethernet/raeth/raether.c
+new file mode 100644
+index 0000000..328285a
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether.c
+@@ -0,0 +1,6401 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#include <linux/platform_device.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#if defined (CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++ 
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#include "dvt/raether_pdma_dvt.h"
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++static int fe_irq = 0;
++
++#if defined (TASKLET_WORKQUEUE_SW)
++int init_schedule;
++int working_schedule;
++#endif
++
++#ifdef CONFIG_RAETH_NAPI
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++static int raeth_clean(struct napi_struct *napi, int budget);
++#else
++static int raeth_clean(struct net_device *dev, int *budget);
++#endif
++
++static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do);
++#else
++static int rt2880_eth_recv(struct net_device* dev);
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf) 
++{
++      /* TODO */
++      return 0;
++}
++
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE) || defined (CONFIG_ARCH_MT7623)
++void setup_internal_gsw(void);
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
++void apll_xtal_enable(void);
++#define REGBIT(x, n)              (x << n)
++#endif
++#endif
++
++#if defined (CONFIG_MT7623_FPGA)
++void setup_fpga_gsw(void);
++#endif
++
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#if defined     (CONFIG_ARCH_MT7623)
++#undef DELAY_INT
++#else
++#define DELAY_INT       1
++#endif
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define       MAX_RX_LENGTH   4096
++#else
++#define       MAX_RX_LENGTH   1536
++#endif
++
++struct net_device             *dev_raether;
++
++static int rx_dma_owner_idx; 
++static int rx_dma_owner_idx0;
++#if defined (CONFIG_RAETH_HW_LRO)
++static int rx_dma_owner_lro1;
++static int rx_dma_owner_lro2;
++static int rx_dma_owner_lro3;
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static int rx_dma_owner_idx1;
++#if defined(CONFIG_ARCH_MT7623)
++static int rx_dma_owner_idx2;
++static int rx_dma_owner_idx3;
++#endif  /* CONFIG_ARCH_MT7623 */
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++int rx_calc_idx0;
++#endif
++static int pending_recv;
++static struct PDMA_rxdesc     *rx_ring;
++unsigned long tx_ring_full=0;
++
++#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined(CONFIG_RALINK_MT7620)
++unsigned short p0_rx_good_cnt = 0;
++unsigned short p1_rx_good_cnt = 0;
++unsigned short p2_rx_good_cnt = 0;
++unsigned short p3_rx_good_cnt = 0;
++unsigned short p4_rx_good_cnt = 0;
++unsigned short p5_rx_good_cnt = 0;
++unsigned short p6_rx_good_cnt = 0;
++unsigned short p0_tx_good_cnt = 0;
++unsigned short p1_tx_good_cnt = 0;
++unsigned short p2_tx_good_cnt = 0;
++unsigned short p3_tx_good_cnt = 0;
++unsigned short p4_tx_good_cnt = 0;
++unsigned short p5_tx_good_cnt = 0;
++unsigned short p6_tx_good_cnt = 0;
++
++unsigned short p0_rx_byte_cnt = 0;
++unsigned short p1_rx_byte_cnt = 0;
++unsigned short p2_rx_byte_cnt = 0;
++unsigned short p3_rx_byte_cnt = 0;
++unsigned short p4_rx_byte_cnt = 0;
++unsigned short p5_rx_byte_cnt = 0;
++unsigned short p6_rx_byte_cnt = 0;
++unsigned short p0_tx_byte_cnt = 0;
++unsigned short p1_tx_byte_cnt = 0;
++unsigned short p2_tx_byte_cnt = 0;
++unsigned short p3_tx_byte_cnt = 0;
++unsigned short p4_tx_byte_cnt = 0;
++unsigned short p5_tx_byte_cnt = 0;
++unsigned short p6_tx_byte_cnt = 0;
++
++#if defined(CONFIG_RALINK_MT7620)
++unsigned short p7_rx_good_cnt = 0;
++unsigned short p7_tx_good_cnt = 0;
++
++unsigned short p7_rx_byte_cnt = 0;
++unsigned short p7_tx_byte_cnt = 0;
++#endif
++#endif
++
++
++
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++#include "ra_ethtool.h"
++extern struct ethtool_ops     ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops     ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++unsigned int M2Q_table[64] = {0};
++unsigned int lan_wan_separate = 0;
++
++#if defined(CONFIG_HW_SFQ)
++unsigned int web_sfq_enable = 0;
++EXPORT_SYMBOL(web_sfq_enable);
++#endif
++
++EXPORT_SYMBOL(M2Q_table);
++EXPORT_SYMBOL(lan_wan_separate);
++#if defined (CONFIG_RAETH_LRO)
++unsigned int lan_ip;
++struct lro_para_struct lro_para; 
++int lro_flush_needed;
++extern char const *nvram_get(int index, char *name);
++#endif
++
++#define KSEG1                   0xa0000000
++#if defined (CONFIG_MIPS)
++#define PHYS_TO_VIRT(x)         ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x)         ((unsigned long)(x) & ~KSEG1)
++#else
++#define PHYS_TO_VIRT(x)         phys_to_virt(x)
++#define VIRT_TO_PHYS(x)         virt_to_phys(x)
++#endif
++
++extern int fe_dma_init(struct net_device *dev);
++extern int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no);
++extern void ei_xmit_housekeeping(unsigned long unused);
++extern inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no);
++#if defined (CONFIG_RAETH_HW_LRO)
++extern int fe_hw_lro_init(struct net_device *dev);
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if 0 
++void skb_dump(struct sk_buff* sk) {
++        unsigned int i;
++
++        printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n",
++                sk->dev?sk->dev->name:"ip stack",sk->len,sk->truesize,
++                skb_headroom(sk),skb_tailroom(sk));
++
++        //for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) {
++        for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) {
++                if((i % 20) == 0)
++                        printk("\n");
++                if(i==(unsigned int)sk->data) printk("{");
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
++                if(i==(unsigned int)sk->transport_header) printk("#");
++                if(i==(unsigned int)sk->network_header) printk("|");
++                if(i==(unsigned int)sk->mac_header) printk("*");
++#else
++                if(i==(unsigned int)sk->h.raw) printk("#");
++                if(i==(unsigned int)sk->nh.raw) printk("|");
++                if(i==(unsigned int)sk->mac.raw) printk("*");
++#endif
++                printk("%02X-",*((unsigned char*)i));
++                if(i==(unsigned int)sk->tail) printk("}");
++        }
++        printk("\n");
++}
++#endif
++
++
++
++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++int isICPlusGigaPHY(int ge)
++{
++      u32 phy_id0 = 0, phy_id1 = 0;
++
++#ifdef CONFIG_GE2_RGMII_AN
++      if (ge == 2) {
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
++                      printk("\n Read PhyID 1 is Fail!!\n");
++                      phy_id0 =0;
++              }
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
++                      printk("\n Read PhyID 1 is Fail!!\n");
++                      phy_id1 = 0;
++              }
++      }
++      else
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      {
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
++                      printk("\n Read PhyID 0 is Fail!!\n");
++                      phy_id0 =0;
++              }
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
++                      printk("\n Read PhyID 0 is Fail!!\n");
++                      phy_id1 = 0;
++              }
++      }
++#endif
++
++      if ((phy_id0 == EV_ICPLUS_PHY_ID0) && ((phy_id1 & 0xfff0) == EV_ICPLUS_PHY_ID1))
++              return 1;
++      return 0;
++}
++
++
++int isMarvellGigaPHY(int ge)
++{
++      u32 phy_id0 = 0, phy_id1 = 0;
++
++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
++      if (ge == 2) {
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
++                      printk("\n Read PhyID 1 is Fail!!\n");
++                      phy_id0 =0;
++              }
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
++                      printk("\n Read PhyID 1 is Fail!!\n");
++                      phy_id1 = 0;
++              }
++      }
++      else
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      {
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
++                      printk("\n Read PhyID 0 is Fail!!\n");
++                      phy_id0 =0;
++              }
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
++                      printk("\n Read PhyID 0 is Fail!!\n");
++                      phy_id1 = 0;
++              }
++      }
++#endif
++              ;
++      if ((phy_id0 == EV_MARVELL_PHY_ID0) && (phy_id1 == EV_MARVELL_PHY_ID1))
++              return 1;
++      return 0;
++}
++
++int isVtssGigaPHY(int ge)
++{
++      u32 phy_id0 = 0, phy_id1 = 0;
++
++#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
++      if (ge == 2) {
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
++                      printk("\n Read PhyID 1 is Fail!!\n");
++                      phy_id0 =0;
++              }
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
++                      printk("\n Read PhyID 1 is Fail!!\n");
++                      phy_id1 = 0;
++              }
++      }
++      else
++#endif
++#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      {
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
++                      printk("\n Read PhyID 0 is Fail!!\n");
++                      phy_id0 =0;
++              }
++              if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
++                      printk("\n Read PhyID 0 is Fail!!\n");
++                      phy_id1 = 0;
++              }
++      }
++#endif
++              ;
++      if ((phy_id0 == EV_VTSS_PHY_ID0) && (phy_id1 == EV_VTSS_PHY_ID1))
++              return 1;
++      return 0;
++}
++#endif
++
++/*
++ * Set the hardware MAC address.
++ */
++static int ei_set_mac_addr(struct net_device *dev, void *p)
++{
++      struct sockaddr *addr = p;
++
++      memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++
++      if(netif_running(dev))
++              return -EBUSY;
++
++        ra2880MacAddressSet(addr->sa_data);
++      return 0;
++}
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++static int ei_set_mac2_addr(struct net_device *dev, void *p)
++{
++      struct sockaddr *addr = p;
++
++      memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++
++      if(netif_running(dev))
++              return -EBUSY;
++
++        ra2880Mac2AddressSet(addr->sa_data);
++      return 0;
++}
++#endif
++
++void set_fe_dma_glo_cfg(void)
++{
++        int dma_glo_cfg=0;
++#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
++    defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
++        int fe_glo_cfg=0;
++#endif
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) 
++      dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_32DWORDS);
++#elif defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
++      dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS);
++#elif defined (CONFIG_ARCH_MT7623)
++      dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS | ADMA_RX_BT_SIZE_32DWORDS);
++#else 
++      dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_4DWORDS);
++#endif
++
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++      dma_glo_cfg |= (RX_2B_OFFSET);
++#endif
++
++#if defined (CONFIG_32B_DESC)
++      dma_glo_cfg |= (DESC_32B_EN);
++#endif
++      sysRegWrite(DMA_GLO_CFG, dma_glo_cfg);
++#ifdef CONFIG_RAETH_QDMA      
++      sysRegWrite(QDMA_GLO_CFG, dma_glo_cfg);
++#endif
++
++      /* only the following chipset need to set it */
++#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
++    defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
++      //set 1us timer count in unit of clock cycle
++      fe_glo_cfg = sysRegRead(FE_GLO_CFG);
++      fe_glo_cfg &= ~(0xff << 8); //clear bit8-bit15
++      fe_glo_cfg |= (((get_surfboard_sysclk()/1000000)) << 8);
++      sysRegWrite(FE_GLO_CFG, fe_glo_cfg);
++#endif
++}
++
++int forward_config(struct net_device *dev)
++{
++      
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++
++      /* RT5350: No GDMA, PSE, CDMA, PPE */
++      unsigned int sdmVal;
++      sdmVal = sysRegRead(SDM_CON);
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++      sdmVal |= 0x7<<16; // UDPCS, TCPCS, IPCS=1
++#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++      sdmVal |= 0x1<<20; // TCI_81XX
++#endif // CONFIG_RAETH_SPECIAL_TAG //
++
++      sysRegWrite(SDM_CON, sdmVal);
++
++#else //Non RT5350 chipset
++
++      unsigned int    regVal, regCsg;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      unsigned int    regVal2;
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++#if defined(CONFIG_RALINK_MT7620)
++      /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x430) = 0x00010000;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x434) = 0x00030002;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x438) = 0x00050004;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x43C) = 0x00070006;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x440) = 0x00090008;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x444) = 0x000b000a;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x448) = 0x000d000c;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x44C) = 0x000f000e;
++#else
++      /* 
++       * VLAN_IDX 0 = VLAN_ID 0
++       * .........
++       * VLAN_IDX 15 = VLAN ID 15
++       *
++       */
++      /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xa8) = 0x00010000;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xac) = 0x00030002;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb0) = 0x00050004;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb4) = 0x00070006;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb8) = 0x00090008;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xbc) = 0x000b000a;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc0) = 0x000d000c;
++      *(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc4) = 0x000f000e;
++#endif
++#endif
++
++      regVal = sysRegRead(GDMA1_FWD_CFG);
++      regCsg = sysRegRead(CDMA_CSG_CFG);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      regVal2 = sysRegRead(GDMA2_FWD_CFG);
++#endif
++
++      //set unicast/multicast/broadcast frame to cpu
++#if defined (CONFIG_RALINK_MT7620)
++      /* GDMA1 frames destination port is port0 CPU*/
++      regVal &= ~0x7;
++#else
++      regVal &= ~0xFFFF;
++      regVal |= GDMA1_FWD_PORT;
++#endif
++      regCsg &= ~0x7;
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++      regVal |= (1 << 24); //GDM1_TCI_81xx
++#endif
++
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
++      dev->features |= NETIF_F_HW_VLAN_TX;
++#else
++      dev->features |= NETIF_F_HW_VLAN_CTAG_TX;
++#endif
++#endif
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
++      dev->features |= NETIF_F_HW_VLAN_RX;
++#else
++      dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
++#endif
++#endif
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++      //enable ipv4 header checksum check
++      regVal |= GDM1_ICS_EN;
++      regCsg |= ICS_GEN_EN;
++
++      //enable tcp checksum check
++      regVal |= GDM1_TCS_EN;
++      regCsg |= TCS_GEN_EN;
++
++      //enable udp checksum check
++      regVal |= GDM1_UCS_EN;
++      regCsg |= UCS_GEN_EN;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      regVal2 &= ~0xFFFF;
++      regVal2 |= GDMA2_FWD_PORT;
++  
++      regVal2 |= GDM1_ICS_EN;
++      regVal2 |= GDM1_TCS_EN;
++      regVal2 |= GDM1_UCS_EN;
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO) 
++    dev->features |= NETIF_F_HW_CSUM;
++#else
++      dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
++#endif  /* CONFIG_RAETH_HW_LRO */
++//#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++//    dev->vlan_features |= NETIF_F_IP_CSUM;
++//#endif
++
++#if defined(CONFIG_RALINK_MT7620)
++#if defined (CONFIG_RAETH_TSO)
++      if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++              dev->features |= NETIF_F_SG;
++              dev->features |= NETIF_F_TSO;
++      }
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++      if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++              dev->features |= NETIF_F_TSO6;
++              dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++      }
++#endif // CONFIG_RAETH_TSOV6 //
++#else
++#if defined (CONFIG_RAETH_TSO)
++      dev->features |= NETIF_F_SG;
++      dev->features |= NETIF_F_TSO;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++      dev->features |= NETIF_F_TSO6;
++      dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++#endif // CONFIG_RAETH_TSOV6 //
++#endif // CONFIG_RALINK_MT7620 //
++#else // Checksum offload disabled
++
++      //disable ipv4 header checksum check
++      regVal &= ~GDM1_ICS_EN;
++      regCsg &= ~ICS_GEN_EN;
++
++      //disable tcp checksum check
++      regVal &= ~GDM1_TCS_EN;
++      regCsg &= ~TCS_GEN_EN;
++
++      //disable udp checksum check
++      regVal &= ~GDM1_UCS_EN;
++      regCsg &= ~UCS_GEN_EN;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      regVal2 &= ~GDM1_ICS_EN;
++      regVal2 &= ~GDM1_TCS_EN;
++      regVal2 &= ~GDM1_UCS_EN;
++#endif
++
++      dev->features &= ~NETIF_F_IP_CSUM; /* disable checksum TCP/UDP over IPv4 */
++#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
++
++#ifdef CONFIG_RAETH_JUMBOFRAME
++      regVal |= GDM1_JMB_EN;
++#ifdef CONFIG_PSEUDO_SUPPORT
++      regVal2 |= GDM1_JMB_EN;
++#endif
++#endif
++
++      sysRegWrite(GDMA1_FWD_CFG, regVal);
++      sysRegWrite(CDMA_CSG_CFG, regCsg);
++#ifdef CONFIG_PSEUDO_SUPPORT
++      sysRegWrite(GDMA2_FWD_CFG, regVal2);
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++        dev->vlan_features = dev->features;
++#endif
++
++/*
++ *    PSE_FQ_CFG register definition -
++ *
++ *    Define max free queue page count in PSE. (31:24)
++ *    RT2883/RT3883 - 0xff908000 (255 pages)
++ *    RT3052 - 0x80504000 (128 pages)
++ *    RT2880 - 0x80504000 (128 pages)
++ *
++ *    In each page, there are 128 bytes in each page.
++ *
++ *    23:16 - free queue flow control release threshold
++ *    15:8  - free queue flow control assertion threshold
++ *    7:0   - free queue empty threshold
++ *
++ *    The register affects QOS correctness in frame engine!
++ */
++
++#if defined(CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883)
++      sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_RT2883_PSE_FQ_CFG));
++#elif defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) ||  \
++      defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++      defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++      defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623)
++        /*use default value*/
++#else
++      sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_PSE_FQFC_CFG));
++#endif
++
++      /*
++       *FE_RST_GLO register definition -
++       *Bit 0: PSE Rest
++       *Reset PSE after re-programming PSE_FQ_CFG.
++       */
++      regVal = 0x1;
++      sysRegWrite(FE_RST_GL, regVal);
++      sysRegWrite(FE_RST_GL, 0);      // update for RSTCTL issue
++
++      regCsg = sysRegRead(CDMA_CSG_CFG);
++      printk("CDMA_CSG_CFG = %0X\n",regCsg);
++      regVal = sysRegRead(GDMA1_FWD_CFG);
++      printk("GDMA1_FWD_CFG = %0X\n",regVal);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      regVal = sysRegRead(GDMA2_FWD_CFG);
++      printk("GDMA2_FWD_CFG = %0X\n",regVal);
++#endif
++#endif
++      return 1;
++}
++
++#ifdef CONFIG_RAETH_LRO
++static int
++rt_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph,
++                       u64 *hdr_flags, void *priv)
++{
++        struct iphdr *iph = NULL;
++      int    vhdr_len = 0;
++
++        /*
++         * Make sure that this packet is Ethernet II, is not VLAN
++         * tagged, is IPv4, has a valid IP header, and is TCP.
++         */
++      if (skb->protocol == 0x0081) {
++              vhdr_len = VLAN_HLEN;
++      }
++
++      iph = (struct iphdr *)(skb->data + vhdr_len);
++      if (iph->daddr != lro_para.lan_ip1) {
++              return -1;
++      }
++
++      if(iph->protocol != IPPROTO_TCP) {
++              return -1;
++      } else {
++              *iphdr = iph;
++              *tcph = skb->data + (iph->ihl << 2) + vhdr_len;
++              *hdr_flags = LRO_IPV4 | LRO_TCP;
++
++              lro_flush_needed = 1;
++              return 0;
++      }
++}
++#endif // CONFIG_RAETH_LRO //
++
++#ifdef CONFIG_RAETH_NAPI
++static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do)
++#else
++static int rt2880_eth_recv(struct net_device* dev)
++#endif
++{
++      struct sk_buff  *skb, *rx_skb;
++      unsigned int    length = 0;
++      unsigned long   RxProcessed;
++
++      int bReschedule = 0;
++      END_DEVICE*     ei_local = netdev_priv(dev);
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING) || defined (CONFIG_RAETH_HW_LRO)
++      int rx_ring_no=0;
++#endif
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++      struct vlan_ethhdr *veth=NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      PSEUDO_ADAPTER *pAd;
++#endif
++
++      RxProcessed = 0;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_dma_owner_idx0 = (rx_calc_idx0 + 1) % NUM_RX_DESC;
++#else
++      rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++#endif
++
++#if defined (CONFIG_32B_DESC)
++      dma_cache_sync(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
++#endif
++#if defined (CONFIG_RAETH_HW_LRO)
++      rx_dma_owner_lro1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_LRO_RX_DESC;
++      rx_dma_owner_lro2 = (sysRegRead(RX_CALC_IDX2) + 1) % NUM_LRO_RX_DESC;
++      rx_dma_owner_lro3 = (sysRegRead(RX_CALC_IDX3) + 1) % NUM_LRO_RX_DESC;
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_dma_owner_idx1 = (rx_calc_idx1 + 1) % NUM_RX_DESC;
++#else
++      rx_dma_owner_idx1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_RX_DESC;
++#endif  /* CONFIG_RAETH_RW_PDMAPTR_FROM_VAR */
++#if defined(CONFIG_ARCH_MT7623)
++    rx_dma_owner_idx2 = (sysRegRead(RX_CALC_IDX2) + 1) % NUM_RX_DESC;
++    rx_dma_owner_idx3 = (sysRegRead(RX_CALC_IDX3) + 1) % NUM_RX_DESC;
++#endif
++#if defined (CONFIG_32B_DESC)
++      dma_cache_sync(NULL, &ei_local->rx_ring1[rx_dma_owner_idx1], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
++#endif
++#endif
++      for ( ; ; ) {
++
++
++#ifdef CONFIG_RAETH_NAPI
++                if(*work_done >= work_to_do)
++                        break;
++                (*work_done)++;
++#else
++              if (RxProcessed++ > NUM_RX_MAX_PROCESS)
++                {
++                        // need to reschedule rx handle
++                        bReschedule = 1;
++                        break;
++                }
++#endif
++
++
++#if defined (CONFIG_RAETH_HW_LRO)
++              if (ei_local->rx_ring3[rx_dma_owner_lro3].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring3;
++                  rx_dma_owner_idx = rx_dma_owner_lro3;
++              //    printk("rx_dma_owner_lro3=%x\n",rx_dma_owner_lro3);
++                  rx_ring_no=3;
++              }
++              else if (ei_local->rx_ring2[rx_dma_owner_lro2].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring2;
++                  rx_dma_owner_idx = rx_dma_owner_lro2;
++              //    printk("rx_dma_owner_lro2=%x\n",rx_dma_owner_lro2);
++                  rx_ring_no=2;
++              }
++              else if (ei_local->rx_ring1[rx_dma_owner_lro1].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring1;
++                  rx_dma_owner_idx = rx_dma_owner_lro1;
++              //    printk("rx_dma_owner_lro1=%x\n",rx_dma_owner_lro1);
++                  rx_ring_no=1;
++              } 
++              else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring0;
++                  rx_dma_owner_idx = rx_dma_owner_idx0;
++               //   printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0);
++                  rx_ring_no=0;
++              } else {
++                  break;
++              }
++    #if defined (CONFIG_RAETH_HW_LRO_DBG)
++        HwLroStatsUpdate(rx_ring_no, rx_ring[rx_dma_owner_idx].rxd_info2.LRO_AGG_CNT, \
++            (rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 << 14) | rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0);
++    #endif
++    #if defined(CONFIG_RAETH_HW_LRO_REASON_DBG)
++        HwLroFlushStatsUpdate(rx_ring_no, rx_ring[rx_dma_owner_idx].rxd_info2.REV);
++    #endif
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++              if (ei_local->rx_ring1[rx_dma_owner_idx1].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring1;
++                  rx_dma_owner_idx = rx_dma_owner_idx1;
++              //    printk("rx_dma_owner_idx1=%x\n",rx_dma_owner_idx1);
++                  rx_ring_no=1;
++              }
++#if defined(CONFIG_ARCH_MT7623)
++        else if (ei_local->rx_ring2[rx_dma_owner_idx2].rxd_info2.DDONE_bit == 1)  {
++            rx_ring = ei_local->rx_ring2;
++            rx_dma_owner_idx = rx_dma_owner_idx2;
++        //    printk("rx_dma_owner_idx2=%x\n",rx_dma_owner_idx2);
++            rx_ring_no=2;
++        }
++        else if (ei_local->rx_ring3[rx_dma_owner_idx3].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring3;
++                  rx_dma_owner_idx = rx_dma_owner_idx3;
++              //    printk("rx_dma_owner_idx3=%x\n",rx_dma_owner_idx3);
++                  rx_ring_no=3;
++              }               
++#endif  /* CONFIG_ARCH_MT7623 */
++        else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring0;
++                  rx_dma_owner_idx = rx_dma_owner_idx0;
++               //   printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0);
++                  rx_ring_no=0;
++              } else {
++                  break;
++              }
++#else
++
++              if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1)  {
++                  rx_ring = ei_local->rx_ring0;
++                  rx_dma_owner_idx = rx_dma_owner_idx0;
++              } else {
++                  break;
++              }
++#endif
++
++#if defined (CONFIG_32B_DESC)
++              prefetch(&rx_ring[(rx_dma_owner_idx + 1) % NUM_RX_DESC]);
++#endif
++              /* skb processing */
++#if defined (CONFIG_RAETH_HW_LRO)
++        length = (rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 << 14) | rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0;
++#else
++              length = rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0;
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if defined (CONFIG_ARCH_MT7623)
++              dma_unmap_single(NULL, rx_ring[rx_dma_owner_idx].rxd_info1.PDP0, length, DMA_FROM_DEVICE);
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++              if(rx_ring_no==3) {
++                  rx_skb = ei_local->netrx3_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx3_skbuf[rx_dma_owner_idx]->data;
++              }
++              else if(rx_ring_no==2) {
++                  rx_skb = ei_local->netrx2_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx2_skbuf[rx_dma_owner_idx]->data;
++              }
++              else if(rx_ring_no==1) {
++                  rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data;
++              } 
++              else {
++                  rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
++              }
++    #if defined(CONFIG_RAETH_PDMA_DVT)
++        raeth_pdma_lro_dvt( rx_ring_no, ei_local, rx_dma_owner_idx );
++    #endif  /* CONFIG_RAETH_PDMA_DVT */
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++              if(rx_ring_no==1) {
++                  rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data;
++              } 
++#if defined(CONFIG_ARCH_MT7623)
++              else if(rx_ring_no==2) {
++                  rx_skb = ei_local->netrx2_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx2_skbuf[rx_dma_owner_idx]->data;
++              }
++        else if(rx_ring_no==3) {
++                  rx_skb = ei_local->netrx3_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx3_skbuf[rx_dma_owner_idx]->data;
++              }
++#endif  /* CONFIG_ARCH_MT7623 */
++        else {
++                  rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
++                  rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
++              }
++    #if defined(CONFIG_RAETH_PDMA_DVT)
++        raeth_pdma_lro_dvt( rx_ring_no, ei_local, rx_dma_owner_idx );
++    #endif  /* CONFIG_RAETH_PDMA_DVT */
++#else
++              rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
++              rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
++    #if defined(CONFIG_RAETH_PDMA_DVT)
++        raeth_pdma_rx_desc_dvt( ei_local, rx_dma_owner_idx0 );
++    #endif  /* CONFIG_RAETH_PDMA_DVT */
++#endif
++              rx_skb->len     = length;
++/*TODO*/
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              rx_skb->data += NET_IP_ALIGN;
++#endif
++              rx_skb->tail    = rx_skb->data + length;
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++              if(rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
++                  if(ei_local->PseudoDev!=NULL) {
++                      rx_skb->dev       = ei_local->PseudoDev;
++                      rx_skb->protocol  = eth_type_trans(rx_skb,ei_local->PseudoDev);
++                  }else {
++                      printk("ERROR: PseudoDev is still not initialize but receive packet from GMAC2\n");
++                  }
++              }else{
++                  rx_skb->dev           = dev;
++                  rx_skb->protocol      = eth_type_trans(rx_skb,dev);
++              }
++#else
++              rx_skb->dev       = dev;
++              rx_skb->protocol  = eth_type_trans(rx_skb,dev);
++#endif
++
++#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
++#if defined (CONFIG_PDMA_NEW)
++              if(rx_ring[rx_dma_owner_idx].rxd_info4.L4VLD) {
++                      rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
++              }else {
++                  rx_skb->ip_summed = CHECKSUM_NONE;
++              }
++#else
++              if(rx_ring[rx_dma_owner_idx].rxd_info4.IPFVLD_bit) {
++                      rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
++              }else { 
++                  rx_skb->ip_summed = CHECKSUM_NONE;
++              }
++#endif
++#else
++                  rx_skb->ip_summed = CHECKSUM_NONE;
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++              /* Qwert+
++               */
++              if(ra_classifier_hook_rx!= NULL)
++              {
++#if defined(CONFIG_RALINK_EXTERNAL_TIMER)
++                      ra_classifier_hook_rx(rx_skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF));
++#else                 
++                      ra_classifier_hook_rx(rx_skb, read_c0_count());
++#endif                        
++              }
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RA_HW_NAT)  || defined (CONFIG_RA_HW_NAT_MODULE)
++              if(ra_sw_nat_hook_rx != NULL) {
++                  FOE_MAGIC_TAG(rx_skb)= FOE_MAGIC_GE;
++                  *(uint32_t *)(FOE_INFO_START_ADDR(rx_skb)+2) = *(uint32_t *)&rx_ring[rx_dma_owner_idx].rxd_info4;
++                  FOE_ALG(rx_skb) = 0;
++              }
++#endif
++
++              /* We have to check the free memory size is big enough
++               * before pass the packet to cpu*/
++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
++#if defined (CONFIG_RAETH_HW_LRO)
++            if( rx_ring != ei_local->rx_ring0 )
++                skb = __dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
++            else
++#endif  /* CONFIG_RAETH_HW_LRO */
++                skb = skbmgr_dev_alloc_skb2k();
++#else
++#if defined (CONFIG_RAETH_HW_LRO)
++        if( rx_ring != ei_local->rx_ring0 )
++            skb = __dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
++        else
++#endif  /* CONFIG_RAETH_HW_LRO */
++              skb = __dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
++#endif
++
++              if (unlikely(skb == NULL))
++              {
++                      printk(KERN_ERR "skb not available...\n");
++#ifdef CONFIG_PSEUDO_SUPPORT
++                      if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
++                              if (ei_local->PseudoDev != NULL) {
++                                      pAd = netdev_priv(ei_local->PseudoDev);
++                                      pAd->stat.rx_dropped++;
++                              }
++                      } else
++#endif
++                              ei_local->stat.rx_dropped++;
++                        bReschedule = 1;
++                      break;
++              }
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              skb_reserve(skb, NET_IP_ALIGN);
++#endif
++
++#if defined (CONFIG_RAETH_SPECIAL_TAG)
++              // port0: 0x8100 => 0x8100 0001
++              // port1: 0x8101 => 0x8100 0002
++              // port2: 0x8102 => 0x8100 0003
++              // port3: 0x8103 => 0x8100 0004
++              // port4: 0x8104 => 0x8100 0005
++              // port5: 0x8105 => 0x8100 0006
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
++              veth = (struct vlan_ethhdr *)(rx_skb->mac_header);
++#else
++              veth = (struct vlan_ethhdr *)(rx_skb->mac.raw);
++#endif
++              /*donot check 0x81 due to MT7530 SPEC*/
++              //if((veth->h_vlan_proto & 0xFF) == 0x81) 
++              {
++                  veth->h_vlan_TCI = htons( (((veth->h_vlan_proto >> 8) & 0xF) + 1) );
++                  rx_skb->protocol = veth->h_vlan_proto = htons(ETH_P_8021Q);
++              }
++#endif
++
++/* ra_sw_nat_hook_rx return 1 --> continue
++ * ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx
++ */
++#if !defined(CONFIG_RA_NAT_NONE)
++         if((ra_sw_nat_hook_rx == NULL) || 
++          (ra_sw_nat_hook_rx!= NULL && ra_sw_nat_hook_rx(rx_skb)))
++#endif
++         {
++#if defined (CONFIG_RALINK_RT3052_MP2)
++             if(mcast_rx(rx_skb)==0) {
++                 kfree_skb(rx_skb);
++             }else
++#endif
++#if defined (CONFIG_RAETH_LRO)
++             if (rx_skb->ip_summed == CHECKSUM_UNNECESSARY) {
++                     lro_receive_skb(&ei_local->lro_mgr, rx_skb, NULL);
++                     //LroStatsUpdate(&ei_local->lro_mgr,0);
++             } else
++#endif
++#ifdef CONFIG_RAETH_NAPI
++                netif_receive_skb(rx_skb);
++#else
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++              if(ei_local->vlgrp && rx_ring[rx_dma_owner_idx].rxd_info2.TAG) {
++                      vlan_hwaccel_rx(rx_skb, ei_local->vlgrp, rx_ring[rx_dma_owner_idx].rxd_info3.VID);
++              } else {
++                      netif_rx(rx_skb);
++              }
++#else
++#ifdef CONFIG_RAETH_CPU_LOOPBACK
++                skb_push(rx_skb,ETH_HLEN);
++                ei_start_xmit(rx_skb, dev, 1);
++#else         
++                netif_rx(rx_skb);
++#endif
++#endif
++#endif
++         }
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++              if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
++                      if (ei_local->PseudoDev != NULL) {
++                              pAd = netdev_priv(ei_local->PseudoDev);
++                              pAd->stat.rx_packets++;
++                              pAd->stat.rx_bytes += length;
++                      }
++              } else
++#endif
++              {
++                      ei_local->stat.rx_packets++;
++                      ei_local->stat.rx_bytes += length;
++              }
++
++
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++#if defined (CONFIG_RAETH_HW_LRO)
++        if( rx_ring != ei_local->rx_ring0 ){
++            rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++            rx_ring[rx_dma_owner_idx].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++        }
++        else
++#endif  /* CONFIG_RAETH_HW_LRO */
++              rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++              rx_ring[rx_dma_owner_idx].rxd_info2.LS0 = 0;
++#endif
++              rx_ring[rx_dma_owner_idx].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_HW_LRO)
++        if( rx_ring != ei_local->rx_ring0 )
++            rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++        else
++#endif  /* CONFIG_RAETH_HW_LRO */
++              rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++#ifdef CONFIG_32B_DESC
++              dma_cache_sync(NULL, &rx_ring[rx_dma_owner_idx], sizeof(struct PDMA_rxdesc), DMA_TO_DEVICE);
++#endif
++              /*  Move point to next RXD which wants to alloc*/
++#if defined (CONFIG_RAETH_HW_LRO)
++              if(rx_ring_no==3) {
++                  sysRegWrite(RAETH_RX_CALC_IDX3, rx_dma_owner_idx);
++                  ei_local->netrx3_skbuf[rx_dma_owner_idx] = skb;
++              }
++              else if(rx_ring_no==2) {
++                  sysRegWrite(RAETH_RX_CALC_IDX2, rx_dma_owner_idx);
++                  ei_local->netrx2_skbuf[rx_dma_owner_idx] = skb;
++              }
++              else if(rx_ring_no==1) {
++                  sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx);
++                  ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb;
++              }
++              else if(rx_ring_no==0) {
++                  sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
++                  ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
++              }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++              if(rx_ring_no==0) {
++                  sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
++                  ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                  rx_calc_idx0 = rx_dma_owner_idx;
++#endif
++              }
++#if defined(CONFIG_ARCH_MT7623)
++        else if(rx_ring_no==3) {
++                  sysRegWrite(RAETH_RX_CALC_IDX3, rx_dma_owner_idx);
++                  ei_local->netrx3_skbuf[rx_dma_owner_idx] = skb;
++              }
++              else if(rx_ring_no==2) {
++                  sysRegWrite(RAETH_RX_CALC_IDX2, rx_dma_owner_idx);
++                  ei_local->netrx2_skbuf[rx_dma_owner_idx] = skb;
++              }
++#endif  /* CONFIG_ARCH_MT7623 */
++        else {
++                  sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx);
++                  ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                  rx_calc_idx1 = rx_dma_owner_idx;
++#endif
++              }
++#else
++              sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
++              ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++              rx_calc_idx0 = rx_dma_owner_idx;
++#endif
++#endif
++
++              
++              /* Update to Next packet point that was received.
++               */
++#if defined (CONFIG_RAETH_HW_LRO)
++              if(rx_ring_no==3)
++                      rx_dma_owner_lro3 = (sysRegRead(RAETH_RX_CALC_IDX3) + 1) % NUM_LRO_RX_DESC;
++              else if(rx_ring_no==2)
++                      rx_dma_owner_lro2 = (sysRegRead(RAETH_RX_CALC_IDX2) + 1) % NUM_LRO_RX_DESC;
++              else if(rx_ring_no==1)
++                      rx_dma_owner_lro1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_LRO_RX_DESC;
++              else if(rx_ring_no==0)
++                      rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++              else {
++              }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++              if(rx_ring_no==0) {
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                      rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
++#else
++                      rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++#endif
++#if defined(CONFIG_ARCH_MT7623)
++        }else if(rx_ring_no==3) {
++            rx_dma_owner_idx3 = (sysRegRead(RAETH_RX_CALC_IDX3) + 1) % NUM_RX_DESC;
++        }else if(rx_ring_no==2) {
++            rx_dma_owner_idx2 = (sysRegRead(RAETH_RX_CALC_IDX2) + 1) % NUM_RX_DESC;
++#endif  /* CONFIG_ARCH_MT7623 */
++              }else {
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                      rx_dma_owner_idx1 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
++#else
++                      rx_dma_owner_idx1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_RX_DESC;
++#endif
++              }
++#else
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++              rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
++#else
++              rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
++#endif
++#endif
++      }       /* for */
++
++#if defined (CONFIG_RAETH_LRO)
++      if (lro_flush_needed) {
++              //LroStatsUpdate(&ei_local->lro_mgr,1);
++              lro_flush_all(&ei_local->lro_mgr);
++              lro_flush_needed = 0;
++      }
++#endif
++      return bReschedule;
++}
++
++
++///////////////////////////////////////////////////////////////////
++/////
++///// ra_get_stats - gather packet information for management plane
++/////
++///// Pass net_device_stats to the upper layer.
++/////
++/////
++///// RETURNS: pointer to net_device_stats
++///////////////////////////////////////////////////////////////////
++
++struct net_device_stats *ra_get_stats(struct net_device *dev)
++{
++      END_DEVICE *ei_local = netdev_priv(dev);
++      return &ei_local->stat;
++}
++
++#if defined (CONFIG_RT_3052_ESW)
++void kill_sig_workq(struct work_struct *work)
++{
++      struct file *fp;
++      char pid[8];
++      struct task_struct *p = NULL;
++
++      //read udhcpc pid from file, and send signal USR2,USR1 to get a new IP
++      fp = filp_open("/var/run/udhcpc.pid", O_RDONLY, 0);
++      if (IS_ERR(fp))
++          return;
++
++      if (fp->f_op && fp->f_op->read) {
++          if (fp->f_op->read(fp, pid, 8, &fp->f_pos) > 0) {
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++              p = pid_task(find_get_pid(simple_strtoul(pid, NULL, 10)),  PIDTYPE_PID);
++#else
++              p = find_task_by_pid(simple_strtoul(pid, NULL, 10));
++#endif
++
++              if (NULL != p) {
++                  send_sig(SIGUSR2, p, 0);
++                  send_sig(SIGUSR1, p, 0);
++              }
++          }
++      }
++      filp_close(fp, NULL);
++
++}
++#endif
++
++
++///////////////////////////////////////////////////////////////////
++/////
++///// ra2880Recv - process the next incoming packet
++/////
++///// Handle one incoming packet.  The packet is checked for errors and sent
++///// to the upper layer.
++/////
++///// RETURNS: OK on success or ERROR.
++///////////////////////////////////////////////////////////////////
++
++#ifndef CONFIG_RAETH_NAPI
++#if defined WORKQUEUE_BH || defined (TASKLET_WORKQUEUE_SW)
++void ei_receive_workq(struct work_struct *work)
++#else
++void ei_receive(unsigned long unused)  // device structure
++#endif // WORKQUEUE_BH //
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      unsigned long reg_int_mask=0;
++      int bReschedule=0;
++
++
++      if(tx_ring_full==0){
++              bReschedule = rt2880_eth_recv(dev);
++              if(bReschedule)
++              {
++#ifdef WORKQUEUE_BH
++                      schedule_work(&ei_local->rx_wq);
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++                      if (working_schedule == 1)
++                              schedule_work(&ei_local->rx_wq);
++                      else
++#endif
++                      tasklet_hi_schedule(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++              }else{
++                      reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
++#if defined(DELAY_INT)
++                      sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
++#else
++                      sysRegWrite(RAETH_FE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3));
++#endif
++#ifdef CONFIG_RAETH_QDMA
++                      reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#if defined(DELAY_INT)
++                      sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
++#else
++                      sysRegWrite(QFE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1));
++#endif
++
++#endif                        
++                      
++              }
++      }else{
++#ifdef WORKQUEUE_BH
++                schedule_work(&ei_local->rx_wq);
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++              if (working_schedule == 1)
++                      schedule_work(&ei_local->rx_wq);
++              else
++#endif
++                tasklet_schedule(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++      }
++}
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++void ei_hw_lro_auto_adj(unsigned int index, END_DEVICE* ei_local)
++{    
++    unsigned int entry;
++    unsigned int pkt_cnt;
++    unsigned int tick_cnt;
++    unsigned int duration_us;
++    unsigned int byte_cnt;
++
++    /* read packet count statitics of the auto-learn table */
++    entry = index  + 68;
++    sysRegWrite( PDMA_FE_ALT_CF8, entry );
++    pkt_cnt = sysRegRead(PDMA_FE_ALT_SGL_CFC) & 0xfff;
++    tick_cnt = (sysRegRead(PDMA_FE_ALT_SGL_CFC) >> 16) & 0xffff;
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++    printk("[HW LRO] ei_hw_lro_auto_adj(): pkt_cnt[%d]=%d, tick_cnt[%d]=%d\n", index, pkt_cnt, index, tick_cnt);
++    printk("[HW LRO] ei_hw_lro_auto_adj(): packet_interval[%d]=%d (ticks/pkt)\n", index, tick_cnt/pkt_cnt);
++#endif    
++
++    /* read byte count statitics of the auto-learn table */
++    entry = index  + 64;
++    sysRegWrite( PDMA_FE_ALT_CF8, entry );
++    byte_cnt = sysRegRead(PDMA_FE_ALT_SGL_CFC);
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++    printk("[HW LRO] ei_hw_lro_auto_adj(): byte_cnt[%d]=%d\n", index, byte_cnt);
++#endif
++
++    /* calculate the packet interval of the rx flow */
++    duration_us = tick_cnt * HW_LRO_TIMER_UNIT;
++    ei_local->hw_lro_pkt_interval[index - 1] = (duration_us/pkt_cnt) * ei_local->hw_lro_alpha / 100;
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++    printk("[HW LRO] ei_hw_lro_auto_adj(): packet_interval[%d]=%d (20us)\n", index, duration_us/pkt_cnt);
++#endif    
++
++    if ( !ei_local->hw_lro_fix_setting ){
++    /* adjust age_time, agg_time for the lro ring */
++      if(ei_local->hw_lro_pkt_interval[index - 1] > 0){
++              SET_PDMA_RXRING_AGE_TIME(index, (ei_local->hw_lro_pkt_interval[index - 1] * HW_LRO_MAX_AGG_CNT));
++              SET_PDMA_RXRING_AGG_TIME(index, (ei_local->hw_lro_pkt_interval[index - 1] * HW_LRO_AGG_DELTA));
++      }
++      else{
++              SET_PDMA_RXRING_AGE_TIME(index, HW_LRO_MAX_AGG_CNT);
++              SET_PDMA_RXRING_AGG_TIME(index, HW_LRO_AGG_DELTA);
++      }
++    }
++}
++
++void ei_hw_lro_workq(struct work_struct *work)
++{
++    END_DEVICE *ei_local;
++    unsigned int reg_int_val;
++    unsigned int reg_int_mask;
++
++    ei_local = container_of(work, struct end_device, hw_lro_wq);
++
++    reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++    printk("[HW LRO] ei_hw_lro_workq(): RAETH_FE_INT_STATUS=0x%x\n", reg_int_val);
++#endif
++    if((reg_int_val & ALT_RPLC_INT3)){
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++        printk("[HW LRO] ALT_RPLC_INT3 occurred!\n");
++#endif
++        sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT3);
++        ei_hw_lro_auto_adj(3, ei_local);
++    }
++    if((reg_int_val & ALT_RPLC_INT2)){
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++        printk("[HW LRO] ALT_RPLC_INT2 occurred!\n");
++#endif
++        sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT2);
++        ei_hw_lro_auto_adj(2, ei_local);
++    }
++    if((reg_int_val & ALT_RPLC_INT1)){
++#if defined (CONFIG_RAETH_HW_LRO_AUTO_ADJ_DBG)
++        printk("[HW LRO] ALT_RPLC_INT1 occurred!\n");
++#endif
++        sysRegWrite(RAETH_FE_INT_STATUS, ALT_RPLC_INT1);
++        ei_hw_lro_auto_adj(1, ei_local);
++    }
++
++    /* unmask interrupts of rx flow to hw lor rings */
++    reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);    
++    sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1);
++}
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#ifdef CONFIG_RAETH_NAPI
++static int
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++raeth_clean(struct napi_struct *napi, int budget)
++#else
++raeth_clean(struct net_device *netdev, int *budget)
++#endif
++{
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      struct net_device *netdev=dev_raether;
++        int work_to_do = budget;
++#else
++        int work_to_do = min(*budget, netdev->quota);
++#endif
++      END_DEVICE *ei_local =netdev_priv(netdev);
++        int work_done = 0;
++      unsigned long reg_int_mask=0;
++
++      ei_xmit_housekeeping(0);
++
++      rt2880_eth_recv(netdev, &work_done, work_to_do);
++
++        /* this could control when to re-enable interrupt, 0-> mean never enable interrupt*/
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
++        *budget -= work_done;
++        netdev->quota -= work_done;
++#endif
++        /* if no Tx and not enough Rx work done, exit the polling mode */
++        if(( (work_done < work_to_do)) || !netif_running(netdev)) {
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++              napi_complete(&ei_local->napi);
++#else
++                netif_rx_complete(netdev);
++#endif
++              atomic_dec_and_test(&ei_local->irq_sem);
++
++              sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL);             // ack all fe interrupts
++              reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
++
++#ifdef DELAY_INT
++              sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask |RAETH_FE_INT_DLY_INIT);  // init delay interrupt only
++#else
++              sysRegWrite(RAETH_FE_INT_ENABLE,reg_int_mask | RAETH_FE_INT_SETTING);
++#endif
++
++#ifdef CONFIG_RAETH_QDMA
++              sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
++              reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#ifdef DELAY_INT
++                sysRegWrite(QFE_INT_ENABLE, reg_int_mask |QFE_INT_DLY_INIT);  // init delay interrupt only
++#else
++                sysRegWrite(QFE_INT_ENABLE,reg_int_mask | (RX_DONE_INT0 | RX_DONE_INT1 | RLS_DONE_INT));
++#endif
++#endif // CONFIG_RAETH_QDMA //
++
++                return 0;
++        }
++
++        return 1;
++}
++
++#endif
++
++
++void gsw_delay_setting(void) 
++{
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN) 
++      END_DEVICE *ei_local = netdev_priv(dev_raether);
++      int reg_int_val = 0;
++      int link_speed = 0;
++
++      reg_int_val = sysRegRead(FE_INT_STATUS2);
++#if defined (CONFIG_RALINK_MT7621)
++      if( reg_int_val & BIT(25))
++      {
++              if(sysRegRead(RALINK_ETH_SW_BASE+0x0208) & 0x1) // link up
++              {
++                      link_speed = (sysRegRead(RALINK_ETH_SW_BASE+0x0208)>>2 & 0x3);
++                      if(link_speed == 1)
++                      {
++                              // delay setting for 100M
++                              if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)     
++                                      mii_mgr_write(31, 0x7b00, 8);
++                              printk("MT7621 GE2 link rate to 100M\n");
++                      } else 
++                      {
++                              //delay setting for 10/1000M
++                              if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)
++                                      mii_mgr_write(31, 0x7b00, 0x102);
++                              printk("MT7621 GE2 link rate to 10M/1G\n");
++                      }
++                      schedule_work(&ei_local->kill_sig_wq);
++              }
++      }
++#endif
++      sysRegWrite(FE_INT_STATUS2, reg_int_val);
++#endif
++}
++
++/**
++ * ei_interrupt - handle controler interrupt
++ *
++ * This routine is called at interrupt level in response to an interrupt from
++ * the controller.
++ *
++ * RETURNS: N/A.
++ */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++static irqreturn_t ei_interrupt(int irq, void *dev_id)
++#else
++static irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
++#endif
++{
++#if !defined(CONFIG_RAETH_NAPI)
++      unsigned long reg_int_val;
++      unsigned long reg_int_mask=0;
++      unsigned int recv = 0;
++      unsigned int transmit __maybe_unused = 0;
++      unsigned long flags;
++#endif
++
++      struct net_device *dev = (struct net_device *) dev_id;
++      END_DEVICE *ei_local = netdev_priv(dev);
++
++      //Qwert
++      /*
++      unsigned long old,cur,dcycle;
++      static int cnt = 0;
++      static unsigned long max_dcycle = 0,tcycle = 0;
++      old = read_c0_count();
++      */
++      if (dev == NULL)
++      {
++              printk (KERN_ERR "net_interrupt(): irq %x for unknown device.\n", IRQ_ENET0);
++              return IRQ_NONE;
++      }
++
++#ifdef CONFIG_RAETH_NAPI
++      gsw_delay_setting();
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        if(napi_schedule_prep(&ei_local->napi)) {
++#else
++        if(netif_rx_schedule_prep(dev)) {
++#endif
++                atomic_inc(&ei_local->irq_sem);
++              sysRegWrite(RAETH_FE_INT_ENABLE, 0);
++#ifdef CONFIG_RAETH_QDMA              
++              sysRegWrite(QFE_INT_ENABLE, 0);
++#endif
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++              __napi_schedule(&ei_local->napi);
++#else
++                __netif_rx_schedule(dev);
++#endif
++        }
++#else
++
++      spin_lock_irqsave(&(ei_local->page_lock), flags);
++      reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
++#ifdef CONFIG_RAETH_QDMA      
++      reg_int_val |= sysRegRead(QFE_INT_STATUS);
++#endif
++#if defined (DELAY_INT)
++      if((reg_int_val & RX_DLY_INT))
++              recv = 1;
++      
++      if (reg_int_val & RAETH_TX_DLY_INT)
++              transmit = 1;
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++    raeth_pdma_lro_dly_int_dvt();
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++#else
++      if((reg_int_val & (RX_DONE_INT0 | RX_DONE_INT3 | RX_DONE_INT2 | RX_DONE_INT1)))
++              recv = 1;
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#if defined(CONFIG_ARCH_MT7623)    
++    if((reg_int_val & RX_DONE_INT3))
++        recv = 3;
++    if((reg_int_val & RX_DONE_INT2))
++        recv = 2;
++#endif  /* CONFIG_ARCH_MT7623 */
++      if((reg_int_val & RX_DONE_INT1))
++              recv = 1;
++#endif
++
++      if (reg_int_val & RAETH_TX_DONE_INT0)
++              transmit |= RAETH_TX_DONE_INT0;
++#if defined (CONFIG_RAETH_QOS)
++      if (reg_int_val & TX_DONE_INT1)
++              transmit |= TX_DONE_INT1;
++      if (reg_int_val & TX_DONE_INT2)
++              transmit |= TX_DONE_INT2;
++      if (reg_int_val & TX_DONE_INT3)
++              transmit |= TX_DONE_INT3;
++#endif //CONFIG_RAETH_QOS
++
++#endif //DELAY_INT
++
++#if defined (DELAY_INT)
++      sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_DLY_INIT);
++#else
++      sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL);
++#endif
++#ifdef CONFIG_RAETH_QDMA
++#if defined (DELAY_INT)
++      sysRegWrite(QFE_INT_STATUS, QFE_INT_DLY_INIT);
++#else
++      sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
++#endif
++#endif        
++
++#if defined (CONFIG_RAETH_HW_LRO)
++    if( reg_int_val & (ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1) ){
++        /* mask interrupts of rx flow to hw lor rings */
++        reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);
++        sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1));
++        schedule_work(&ei_local->hw_lro_wq);
++    }
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++      if(transmit)
++              ei_xmit_housekeeping(0);
++#else
++              ei_xmit_housekeeping(0);
++#endif
++
++      if (((recv == 1) || (pending_recv ==1)) && (tx_ring_full==0))
++      {
++              reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);
++#if defined (DELAY_INT)
++              sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
++#else
++              sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3));
++#endif //DELAY_INT
++#ifdef CONFIG_RAETH_QDMA              
++              reg_int_mask = sysRegRead(QFE_INT_ENABLE);
++#if defined (DELAY_INT)
++              sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
++#else
++              sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1 | RX_DONE_INT2 | RX_DONE_INT3));
++#endif //DELAY_INT
++#endif
++
++              pending_recv=0;
++#ifdef WORKQUEUE_BH
++              schedule_work(&ei_local->rx_wq);
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++              if (working_schedule == 1)
++                      schedule_work(&ei_local->rx_wq);
++              else
++#endif
++              tasklet_hi_schedule(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++      } 
++      else if (recv == 1 && tx_ring_full==1) 
++      {
++              pending_recv=1;
++      }
++      else if((recv == 0) && (transmit == 0))
++      {
++              gsw_delay_setting();
++      }
++      spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++#endif
++
++      return IRQ_HANDLED;
++}
++
++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620)|| defined (CONFIG_RALINK_MT7621)
++static void esw_link_status_changed(int port_no, void *dev_id)
++{
++    unsigned int reg_val;
++    struct net_device *dev = (struct net_device *) dev_id;
++    END_DEVICE *ei_local = netdev_priv(dev);
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620)
++    reg_val = *((volatile u32 *)(RALINK_ETH_SW_BASE+ 0x3008 + (port_no*0x100)));
++#elif defined (CONFIG_RALINK_MT7621)
++    mii_mgr_read(31, (0x3008 + (port_no*0x100)), &reg_val);
++#endif    
++    if(reg_val & 0x1) {
++      printk("ESW: Link Status Changed - Port%d Link UP\n", port_no);
++#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
++      mii_mgr_write(port_no, 31, 0x52b5);
++      mii_mgr_write(port_no, 16, 0xb780);
++      mii_mgr_write(port_no, 17, 0x00e0);
++      mii_mgr_write(port_no, 16, 0x9780);
++#endif
++
++#if defined (CONFIG_WAN_AT_P0)
++      if(port_no==0) {
++          schedule_work(&ei_local->kill_sig_wq);
++      }
++#elif defined (CONFIG_WAN_AT_P4)
++      if(port_no==4) {
++          schedule_work(&ei_local->kill_sig_wq);
++      }
++#endif
++    } else {      
++      printk("ESW: Link Status Changed - Port%d Link Down\n", port_no);
++#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
++        mii_mgr_write(port_no, 31, 0x52b5);
++        mii_mgr_write(port_no, 16, 0xb780);
++        mii_mgr_write(port_no, 17, 0x0000);
++        mii_mgr_write(port_no, 16, 0x9780);
++#endif
++
++    }
++}
++#endif
++
++#if defined (CONFIG_RT_3052_ESW) && ! defined(CONFIG_RALINK_MT7621) && ! defined(CONFIG_ARCH_MT7623)
++static irqreturn_t esw_interrupt(int irq, void *dev_id)
++{
++      unsigned long flags;
++      unsigned long reg_int_val;
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined(CONFIG_RALINK_MT7620)
++      unsigned long acl_int_val;
++      unsigned long mib_int_val;
++#else
++      static unsigned long stat;
++      unsigned long stat_curr;
++#endif
++      
++      struct net_device *dev = (struct net_device *) dev_id;
++      END_DEVICE *ei_local = netdev_priv(dev);
++
++
++      spin_lock_irqsave(&(ei_local->page_lock), flags);
++      reg_int_val = (*((volatile u32 *)(ESW_ISR))); //Interrupt Status Register
++
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined(CONFIG_RALINK_MT7620)
++      if (reg_int_val & P5_LINK_CH) {
++          esw_link_status_changed(5, dev_id);
++      }
++      if (reg_int_val & P4_LINK_CH) {
++          esw_link_status_changed(4, dev_id);
++      }
++      if (reg_int_val & P3_LINK_CH) {
++          esw_link_status_changed(3, dev_id);
++      }
++      if (reg_int_val & P2_LINK_CH) {
++          esw_link_status_changed(2, dev_id);
++      }
++      if (reg_int_val & P1_LINK_CH) {
++          esw_link_status_changed(1, dev_id);
++      }
++      if (reg_int_val & P0_LINK_CH) {
++          esw_link_status_changed(0, dev_id);
++      }
++      if (reg_int_val & ACL_INT) {
++          acl_int_val = sysRegRead(ESW_AISR);
++          sysRegWrite(ESW_AISR, acl_int_val);
++      }
++      if (reg_int_val & MIB_INT) {
++
++          mib_int_val = sysRegRead(ESW_P0_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P0_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p0_rx_good_cnt ++;      
++              if(mib_int_val & TX_GOOD_CNT)
++                      p0_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p0_rx_byte_cnt ++;
++              if(mib_int_val & TX_GOCT_CNT)
++                      p0_tx_byte_cnt ++;
++          }
++
++          mib_int_val = sysRegRead(ESW_P1_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P1_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p1_rx_good_cnt ++;              
++              if(mib_int_val & TX_GOOD_CNT)
++                      p1_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p1_rx_byte_cnt ++;      
++              if(mib_int_val & TX_GOCT_CNT)
++                      p1_tx_byte_cnt ++;      
++          }
++
++          mib_int_val = sysRegRead(ESW_P2_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P2_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p2_rx_good_cnt ++;              
++              if(mib_int_val & TX_GOOD_CNT)
++                      p2_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p2_rx_byte_cnt ++;      
++              if(mib_int_val & TX_GOCT_CNT)
++                      p2_tx_byte_cnt ++;      
++          }
++
++
++          mib_int_val = sysRegRead(ESW_P3_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P3_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p3_rx_good_cnt ++;              
++              if(mib_int_val & TX_GOOD_CNT)
++                      p3_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p3_rx_byte_cnt ++;      
++              if(mib_int_val & TX_GOCT_CNT)
++                      p3_tx_byte_cnt ++;      
++          }
++
++          mib_int_val = sysRegRead(ESW_P4_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P4_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p4_rx_good_cnt ++;      
++              if(mib_int_val & TX_GOOD_CNT)
++                      p4_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p4_rx_byte_cnt ++;      
++              if(mib_int_val & TX_GOCT_CNT)
++                      p4_tx_byte_cnt ++;      
++          }   
++
++          mib_int_val = sysRegRead(ESW_P5_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P5_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p5_rx_good_cnt ++;              
++              if(mib_int_val & TX_GOOD_CNT)
++                      p5_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p5_rx_byte_cnt ++;      
++              if(mib_int_val & TX_GOCT_CNT)
++                      p5_tx_byte_cnt ++;      
++          }
++
++          mib_int_val = sysRegRead(ESW_P6_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P6_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p6_rx_good_cnt ++;              
++              if(mib_int_val & TX_GOOD_CNT)
++                      p6_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p6_rx_byte_cnt ++;      
++              if(mib_int_val & TX_GOCT_CNT)
++                      p6_tx_byte_cnt ++;      
++          }
++#if defined (CONFIG_RALINK_MT7620)
++          mib_int_val = sysRegRead(ESW_P7_IntSn);
++          if(mib_int_val){
++              sysRegWrite(ESW_P7_IntSn, mib_int_val);
++              if(mib_int_val & RX_GOOD_CNT)
++                      p7_rx_good_cnt ++;              
++              if(mib_int_val & TX_GOOD_CNT)
++                      p7_tx_good_cnt ++;      
++              if(mib_int_val & RX_GOCT_CNT)
++                      p7_rx_byte_cnt ++;      
++              if(mib_int_val & TX_GOCT_CNT)
++                      p7_tx_byte_cnt ++;      
++  
++          }
++#endif            
++      }
++
++#else // not RT6855
++      if (reg_int_val & PORT_ST_CHG) {
++              printk("RT305x_ESW: Link Status Changed\n");
++
++              stat_curr = *((volatile u32 *)(RALINK_ETH_SW_BASE+0x80));
++#ifdef CONFIG_WAN_AT_P0
++              //link down --> link up : send signal to user application
++              //link up --> link down : ignore
++              if ((stat & (1<<25)) || !(stat_curr & (1<<25)))
++#else
++              if ((stat & (1<<29)) || !(stat_curr & (1<<29)))
++#endif
++                      goto out;
++
++              schedule_work(&ei_local->kill_sig_wq);
++out:
++              stat = stat_curr;
++      }
++
++#endif // defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)//
++
++      sysRegWrite(ESW_ISR, reg_int_val);
++
++      spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++      return IRQ_HANDLED;
++}
++
++
++
++#elif defined (CONFIG_RT_3052_ESW) && defined(CONFIG_RALINK_MT7621)
++
++static irqreturn_t esw_interrupt(int irq, void *dev_id)
++{
++      unsigned long flags;
++      unsigned int reg_int_val;
++      struct net_device *dev = (struct net_device *) dev_id;
++      END_DEVICE *ei_local = netdev_priv(dev);
++
++      spin_lock_irqsave(&(ei_local->page_lock), flags);
++        mii_mgr_read(31, 0x700c, &reg_int_val);
++
++      if (reg_int_val & P4_LINK_CH) {
++          esw_link_status_changed(4, dev_id);
++      }
++
++      if (reg_int_val & P3_LINK_CH) {
++          esw_link_status_changed(3, dev_id);
++      }
++      if (reg_int_val & P2_LINK_CH) {
++          esw_link_status_changed(2, dev_id);
++      }
++      if (reg_int_val & P1_LINK_CH) {
++          esw_link_status_changed(1, dev_id);
++      }
++      if (reg_int_val & P0_LINK_CH) {
++          esw_link_status_changed(0, dev_id);
++      }
++
++        mii_mgr_write(31, 0x700c, 0x1f); //ack switch link change
++      
++      spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++      return IRQ_HANDLED;
++}
++
++#endif
++
++
++static int ei_start_xmit_fake(struct sk_buff* skb, struct net_device *dev)
++{
++      return ei_start_xmit(skb, dev, 1);
++}
++
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) 
++void dump_phy_reg(int port_no, int from, int to, int is_local)
++{
++        u32 i=0;
++        u32 temp=0;
++
++        if(is_local==0) {
++            printk("Global Register\n");
++            printk("===============");
++            mii_mgr_write(0, 31, 0); //select global register
++            for(i=from;i<=to;i++) {
++                if(i%8==0) {
++                    printk("\n");
++                }
++                mii_mgr_read(port_no,i, &temp);
++                printk("%02d: %04X ",i, temp);
++            }
++        } else {
++            mii_mgr_write(0, 31, 0x8000); //select local register
++                printk("\n\nLocal Register Port %d\n",port_no);
++                printk("===============");
++                for(i=from;i<=to;i++) {
++                    if(i%8==0) {
++                        printk("\n");
++                    }
++                    mii_mgr_read(port_no,i, &temp);
++                    printk("%02d: %04X ",i, temp);
++                }
++        }
++        printk("\n");
++}
++#else
++void dump_phy_reg(int port_no, int from, int to, int is_local, int page_no)
++{
++
++        u32 i=0;
++        u32 temp=0;
++        u32 r31=0;
++
++
++        if(is_local==0) {
++
++            printk("\n\nGlobal Register Page %d\n",page_no);
++            printk("===============");
++            r31 |= 0 << 15; //global
++            r31 |= ((page_no&0x7) << 12); //page no
++            mii_mgr_write(port_no, 31, r31); //select global page x
++            for(i=16;i<32;i++) {
++                if(i%8==0) {
++                    printk("\n");
++                }
++                mii_mgr_read(port_no,i, &temp);
++                printk("%02d: %04X ",i, temp);
++            }
++        }else {
++            printk("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
++            printk("===============");
++            r31 |= 1 << 15; //local
++            r31 |= ((page_no&0x7) << 12); //page no
++            mii_mgr_write(port_no, 31, r31); //select local page x
++            for(i=16;i<32;i++) {
++                if(i%8==0) {
++                    printk("\n");
++                }
++                mii_mgr_read(port_no,i, &temp);
++                printk("%02d: %04X ",i, temp);
++            }
++        }
++        printk("\n");
++}
++
++#endif
++
++int ei_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++#if defined(CONFIG_RT_3052_ESW) || defined(CONFIG_RAETH_QDMA)
++              esw_reg reg;
++#endif
++#if defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \
++    defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++    defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
++    defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623)
++        esw_rate ratelimit;
++#endif
++#if defined(CONFIG_RT_3052_ESW)
++      unsigned int offset = 0;
++      unsigned int value = 0;
++#endif
++
++      int ret = 0;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      ra_mii_ioctl_data mii;
++      spin_lock_irq(&ei_local->page_lock);
++
++      switch (cmd) {
++#if defined(CONFIG_RAETH_QDMA)
++#define _HQOS_REG(x)  (*((volatile u32 *)(RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + x)))
++              case RAETH_QDMA_REG_READ:
++                      copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++                      if (reg.off > REG_HQOS_MAX) {
++                              ret = -EINVAL;
++                              break;
++                      }
++                      reg.val = _HQOS_REG(reg.off);
++                      //printk("read reg off:%x val:%x\n", reg.off, reg.val);
++                      copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
++                      break;
++              case RAETH_QDMA_REG_WRITE:
++                      copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++                      if (reg.off > REG_HQOS_MAX) {
++                              ret = -EINVAL;
++                              break;
++                      }
++                      _HQOS_REG(reg.off) = reg.val;
++                      //printk("write reg off:%x val:%x\n", reg.off, reg.val);
++                      break;
++#if 0
++                case RAETH_QDMA_READ_CPU_CLK:
++                        copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++                        reg.val = get_surfboard_sysclk();
++                        //printk("read reg off:%x val:%x\n", reg.off, reg.val);
++                      copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
++                      break;
++#endif                        
++              case RAETH_QDMA_QUEUE_MAPPING:
++                      copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++                              if((reg.off&0x100) == 0x100){
++                                      lan_wan_separate = 1;
++                                      reg.off &= 0xff;
++                              }else{
++                                      lan_wan_separate = 0;
++                              }
++                      M2Q_table[reg.off] = reg.val;
++              break;
++#if defined(CONFIG_HW_SFQ)
++      case RAETH_QDMA_SFQ_WEB_ENABLE:
++                      copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++                      if((reg.val) == 0x1){
++                              web_sfq_enable = 1;
++      
++                      }else{
++                              web_sfq_enable = 0;
++                      }
++              break;
++#endif                
++              
++      
++#endif                
++              case RAETH_MII_READ:
++                      copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++                      mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
++                      //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
++                      copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
++                      break;
++
++              case RAETH_MII_WRITE:
++                      copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++                      //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
++                      mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
++                      break;
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT7623)                  
++              case RAETH_MII_READ_CL45:
++                      copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++                      //mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
++                      mii_mgr_read_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, &mii.val_out);
++                      copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
++                      break;
++              case RAETH_MII_WRITE_CL45:
++                      copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++                      //mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
++                      mii_mgr_write_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, mii.val_in);
++                      break;
++#endif
++                      
++#if defined(CONFIG_RT_3052_ESW)
++#define _ESW_REG(x)   (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
++              case RAETH_ESW_REG_READ:
++                      copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++                      if (reg.off > REG_ESW_MAX) {
++                              ret = -EINVAL;
++                              break;
++                      }
++                      reg.val = _ESW_REG(reg.off);
++                      //printk("read reg off:%x val:%x\n", reg.off, reg.val);
++                      copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
++                      break;
++              case RAETH_ESW_REG_WRITE:
++                      copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++                      if (reg.off > REG_ESW_MAX) {
++                              ret = -EINVAL;
++                              break;
++                      }
++                      _ESW_REG(reg.off) = reg.val;
++                      //printk("write reg off:%x val:%x\n", reg.off, reg.val);
++                      break;
++              case RAETH_ESW_PHY_DUMP:
++                      copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350)
++                      if (reg.val ==32 ) {//dump all phy register
++                          /* Global Register 0~31
++                           * Local Register 0~31
++                           */
++                          dump_phy_reg(0, 0, 31, 0); //dump global register
++                          for(offset=0;offset<5;offset++) {
++                              dump_phy_reg(offset, 0, 31, 1); //dump local register
++                          }
++                      } else {
++                          dump_phy_reg(reg.val, 0, 31, 0); //dump global register
++                          dump_phy_reg(reg.val, 0, 31, 1); //dump local register
++                      }
++#else
++                      /* SPEC defined Register 0~15
++                       * Global Register 16~31 for each page
++                       * Local Register 16~31 for each page
++                       */
++                      printk("SPEC defined Register");
++                      if (reg.val ==32 ) {//dump all phy register
++                          int i = 0;
++                          for(i=0; i<5; i++){ 
++                              printk("\n[Port %d]===============",i);
++                              for(offset=0;offset<16;offset++) {
++                                  if(offset%8==0) {
++                                      printk("\n");
++                              }
++                              mii_mgr_read(i,offset, &value);
++                              printk("%02d: %04X ",offset, value);
++                              }
++                          }   
++                      }
++                      else{
++                              printk("\n[Port %d]===============",reg.val);
++                              for(offset=0;offset<16;offset++) {
++                                  if(offset%8==0) {
++                                      printk("\n");
++                              }
++                              mii_mgr_read(reg.val,offset, &value);
++                              printk("%02d: %04X ",offset, value);
++                              }
++                      }
++
++#if defined (CONFIG_RALINK_MT7628)
++                      for(offset=0;offset<7;offset++) { //global register  page 0~6
++#else
++                      for(offset=0;offset<5;offset++) { //global register  page 0~4
++#endif
++                          if(reg.val == 32) //dump all phy register
++                              dump_phy_reg(0, 16, 31, 0, offset);
++                          else
++                              dump_phy_reg(reg.val, 16, 31, 0, offset);
++                      }
++
++                      if (reg.val == 32) {//dump all phy register
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++                              for(offset=0;offset<5;offset++) { //local register port 0-port4
++#else
++                              for(offset=0;offset<4;offset++) { //local register port 0-port3
++#endif            
++                                      dump_phy_reg(offset, 16, 31, 1, 0); //dump local page 0
++                                      dump_phy_reg(offset, 16, 31, 1, 1); //dump local page 1
++                                      dump_phy_reg(offset, 16, 31, 1, 2); //dump local page 2
++                                      dump_phy_reg(offset, 16, 31, 1, 3); //dump local page 3
++                              }
++                      }else {
++                              dump_phy_reg(reg.val, 16, 31, 1, 0); //dump local page 0
++                              dump_phy_reg(reg.val, 16, 31, 1, 1); //dump local page 1
++                              dump_phy_reg(reg.val, 16, 31, 1, 2); //dump local page 2
++                              dump_phy_reg(reg.val, 16, 31, 1, 3); //dump local page 3
++                      }
++#endif
++                      break;
++
++#if defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++#define _ESW_REG(x)   (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
++              case RAETH_ESW_INGRESS_RATE:
++                      copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++                      offset = 0x11c + (4 * (ratelimit.port / 2));
++                        value = _ESW_REG(offset);
++
++                      if((ratelimit.port % 2) == 0)
++                      {
++                              value &= 0xffff0000;
++                              if(ratelimit.on_off == 1)
++                              {
++                                      value |= (ratelimit.on_off << 14);
++                                      value |= (0x07 << 10);
++                                      value |= ratelimit.bw;
++                              }
++                      }
++                      else if((ratelimit.port % 2) == 1)
++                      {
++                              value &= 0x0000ffff;
++                              if(ratelimit.on_off == 1)
++                              {
++                                      value |= (ratelimit.on_off << 30);
++                                      value |= (0x07 << 26);
++                                      value |= (ratelimit.bw << 16);
++                              }
++                      }
++                      printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++
++                      _ESW_REG(offset) = value;
++                      break;
++
++              case RAETH_ESW_EGRESS_RATE:
++                      copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++                      offset = 0x140 + (4 * (ratelimit.port / 2));
++                        value = _ESW_REG(offset);
++
++                      if((ratelimit.port % 2) == 0)
++                      {
++                              value &= 0xffff0000;
++                              if(ratelimit.on_off == 1)
++                              {
++                                      value |= (ratelimit.on_off << 12);
++                                      value |= (0x03 << 10);
++                                      value |= ratelimit.bw;
++                              }
++                      }
++                      else if((ratelimit.port % 2) == 1)
++                      {
++                              value &= 0x0000ffff;
++                              if(ratelimit.on_off == 1)
++                              {
++                                      value |= (ratelimit.on_off << 28);
++                                      value |= (0x03 << 26);
++                                      value |= (ratelimit.bw << 16);
++                              }
++                      }
++                      printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++                      _ESW_REG(offset) = value;
++                      break;
++#elif  defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
++       defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++#define _ESW_REG(x)   (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
++              case RAETH_ESW_INGRESS_RATE:
++                      copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++#if defined(CONFIG_RALINK_RT6855A) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++                      offset = 0x1800 + (0x100 * ratelimit.port);
++#else
++                      offset = 0x1080 + (0x100 * ratelimit.port);
++#endif
++                        value = _ESW_REG(offset);
++
++                      value &= 0xffff0000;
++                      if(ratelimit.on_off == 1)
++                      {
++                              value |= (ratelimit.on_off << 15);
++                              if (ratelimit.bw < 100)
++                              {
++                                      value |= (0x0 << 8);
++                                      value |= ratelimit.bw;
++                              }else if(ratelimit.bw < 1000)
++                              {
++                                      value |= (0x1 << 8);
++                                      value |= ratelimit.bw/10;
++                              }else if(ratelimit.bw < 10000)
++                              {
++                                      value |= (0x2 << 8);
++                                      value |= ratelimit.bw/100;
++                              }else if(ratelimit.bw < 100000)
++                              {
++                                      value |= (0x3 << 8);
++                                      value |= ratelimit.bw/1000;
++                              }else 
++                              {
++                                      value |= (0x4 << 8);
++                                      value |= ratelimit.bw/10000;
++                              }
++                      }
++                      printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)    
++                      mii_mgr_write(0x1f, offset, value);
++#else                 
++                      _ESW_REG(offset) = value;
++#endif                        
++                      break;
++
++              case RAETH_ESW_EGRESS_RATE:
++                      copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
++                      offset = 0x1040 + (0x100 * ratelimit.port);
++                        value = _ESW_REG(offset);
++
++                      value &= 0xffff0000;
++                      if(ratelimit.on_off == 1)
++                      {
++                              value |= (ratelimit.on_off << 15);
++                              if (ratelimit.bw < 100)
++                              {
++                                      value |= (0x0 << 8);
++                                      value |= ratelimit.bw;
++                              }else if(ratelimit.bw < 1000)
++                              {
++                                      value |= (0x1 << 8);
++                                      value |= ratelimit.bw/10;
++                              }else if(ratelimit.bw < 10000)
++                              {
++                                      value |= (0x2 << 8);
++                                      value |= ratelimit.bw/100;
++                              }else if(ratelimit.bw < 100000)
++                              {
++                                      value |= (0x3 << 8);
++                                      value |= ratelimit.bw/1000;
++                              }else 
++                              {
++                                      value |= (0x4 << 8);
++                                      value |= ratelimit.bw/10000;
++                              }
++                      }
++                      printk("offset = 0x%4x value=0x%x\n\r", offset, value);
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)    
++                      mii_mgr_write(0x1f, offset, value);
++#else
++                      _ESW_REG(offset) = value;
++#endif
++                      break;
++#endif
++#endif // CONFIG_RT_3052_ESW
++              default:
++                      ret = -EOPNOTSUPP;
++                      break;
++
++      }
++
++      spin_unlock_irq(&ei_local->page_lock);
++      return ret;
++}
++
++/*
++ * Set new MTU size
++ * Change the mtu of Raeth Ethernet Device
++ */
++static int ei_change_mtu(struct net_device *dev, int new_mtu)
++{
++      END_DEVICE *ei_local = netdev_priv(dev);  // get priv ei_local pointer from net_dev structure
++
++      if ( ei_local == NULL ) {
++              printk(KERN_EMERG "%s: ei_change_mtu passed a non-existent private pointer from net_dev!\n", dev->name);
++              return -ENXIO;
++      }
++
++
++      if ( (new_mtu > 4096) || (new_mtu < 64)) {
++              return -EINVAL;
++      }
++
++#ifndef CONFIG_RAETH_JUMBOFRAME
++      if ( new_mtu > 1500 ) {
++              return -EINVAL;
++      }
++#endif
++
++      dev->mtu = new_mtu;
++
++      return 0;
++}
++
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++static void ei_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
++{
++      END_DEVICE *ei_local = netdev_priv(dev);
++      
++      ei_local->vlgrp = grp;
++
++      /* enable HW VLAN RX */
++      sysRegWrite(CDMP_EG_CTRL, 1);
++
++}
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++static const struct net_device_ops ei_netdev_ops = {
++        .ndo_init               = rather_probe,
++        .ndo_open               = ei_open,
++        .ndo_stop               = ei_close,
++        .ndo_start_xmit         = ei_start_xmit_fake,
++        .ndo_get_stats          = ra_get_stats,
++        .ndo_set_mac_address    = eth_mac_addr,
++        .ndo_change_mtu         = ei_change_mtu,
++        .ndo_do_ioctl           = ei_ioctl,
++        .ndo_validate_addr      = eth_validate_addr,
++#ifdef CONFIG_RAETH_HW_VLAN_RX
++      .ndo_vlan_rx_register   = ei_vlan_rx_register,
++#endif
++#ifdef CONFIG_NET_POLL_CONTROLLER
++        .ndo_poll_controller    = raeth_clean,
++#endif
++//    .ndo_tx_timeout         = ei_tx_timeout,
++};
++#endif
++
++void ra2880_setup_dev_fptable(struct net_device *dev)
++{
++      RAETH_PRINT(__FUNCTION__ "is called!\n");
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      dev->netdev_ops         = &ei_netdev_ops;
++#else
++      dev->open               = ei_open;
++      dev->stop               = ei_close;
++      dev->hard_start_xmit    = ei_start_xmit_fake;
++      dev->get_stats          = ra_get_stats;
++      dev->set_mac_address    = ei_set_mac_addr;
++      dev->change_mtu         = ei_change_mtu;
++      dev->mtu                = 1500;
++      dev->do_ioctl           = ei_ioctl;
++//    dev->tx_timeout         = ei_tx_timeout;
++
++#ifdef CONFIG_RAETH_NAPI
++        dev->poll = &raeth_clean;
++#if defined (CONFIG_RAETH_ROUTER)
++      dev->weight = 32;
++#elif defined (CONFIG_RT_3052_ESW)
++      dev->weight = 32;
++#else
++      dev->weight = 128;
++#endif
++#endif
++#endif
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++      dev->ethtool_ops        = &ra_ethtool_ops;
++#endif
++#define TX_TIMEOUT (5*HZ)
++      dev->watchdog_timeo = TX_TIMEOUT;
++
++}
++
++/* reset frame engine */
++void fe_reset(void)
++{
++#if defined (CONFIG_RALINK_RT6855A)
++      /* FIXME */
++#else
++      u32 val;
++
++      //val = *(volatile u32 *)(0x1b000000);
++      //printk("0x1b000000 is 0x%x\n", val);
++      //val = sysRegRead(0xFB110100);
++      //val = 0x8000;
++      //sysRegWrite(0xFB110100, val);
++
++
++
++      val = sysRegRead(RSTCTRL);
++
++// RT5350 need to reset ESW and FE at the same to avoid PDMA panic // 
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++      val = val | RALINK_FE_RST | RALINK_ESW_RST ;
++#else
++      val = val | RALINK_FE_RST;
++#endif
++      sysRegWrite(RSTCTRL, val);
++#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628)
++      val = val & ~(RALINK_FE_RST | RALINK_ESW_RST);
++#else
++      val = val & ~(RALINK_FE_RST);
++#endif
++
++      sysRegWrite(RSTCTRL, val);
++#endif
++}
++
++/* set TRGMII */
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++void trgmii_set_7621(void)
++{
++      u32 val = 0;
++      u32 val_0 = 0;
++
++      val = sysRegRead(RSTCTRL);
++// MT7621 need to reset GMAC and FE first //  
++      val = val | RALINK_FE_RST | RALINK_ETH_RST ;
++      sysRegWrite(RSTCTRL, val);
++
++//set TRGMII clock//
++      val_0 = sysRegRead(CLK_CFG_0);
++      val_0 &= 0xffffff9f;
++      val_0 |= (0x1 << 5);
++      sysRegWrite(CLK_CFG_0, val_0);
++      mdelay(1);
++      val_0 = sysRegRead(CLK_CFG_0);
++      printk("set CLK_CFG_0 = 0x%x!!!!!!!!!!!!!!!!!!1\n",val_0);
++      val = val & ~(RALINK_FE_RST | RALINK_ETH_RST);
++      sysRegWrite(RSTCTRL, val);
++}
++
++void trgmii_set_7530(void)
++{
++// set MT7530 //
++#if 0 
++      
++      mii_mgr_write(31, 103, 0x0020);
++
++
++      //disable EEE
++      mii_mgr_write(0, 0x16, 0);
++      mii_mgr_write(1, 0x16, 0);
++      mii_mgr_write(2, 0x16, 0);
++      mii_mgr_write(3, 0x16, 0);
++      mii_mgr_write(4, 0x16, 0);
++
++
++      //PLL reset for E2
++      mii_mgr_write(31, 104, 0x0608);
++      mii_mgr_write(31, 104, 0x2608);
++      
++      mii_mgr_write(31, 0x7808, 0x0);
++      mdelay(1);
++      mii_mgr_write(31, 0x7804, 0x01017e8f);
++      mdelay(1);
++      mii_mgr_write(31, 0x7808, 0x1);
++      mdelay(1);
++
++#endif
++#if 1
++      //CL45 command
++      //PLL to 150Mhz 
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x404);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_read(31, 0x7800, &regValue);
++      regValue = (regValue >> 9) & 0x3;
++      if(regValue == 0x3) { //25Mhz Xtal
++              mii_mgr_write(0, 14, 0x0A00);//25Mhz XTAL for 150Mhz CLK
++      } else if(regValue == 0x2) { //40Mhz
++              mii_mgr_write(0, 14, 0x0780);//40Mhz XTAL for 150Mhz CLK
++      }                
++      //mii_mgr_write(0, 14, 0x0C00);//ori
++      mdelay(1);
++
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x409);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x57);
++      mdelay(1);
++
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x40a);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x57);
++
++//PLL BIAS en
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x403);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x1800);
++      mdelay(1);
++
++//BIAS LPF en
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x403);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x1c00);
++
++//sys PLL en
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x401);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0xc020);
++
++//LCDDDS PWDS
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x406);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0xa030);
++      mdelay(1);
++
++//GSW_2X_CLK
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x410);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x0003);
++
++//enable P6
++      mii_mgr_write(31, 0x3600, 0x5e33b);
++
++//enable TRGMII
++      mii_mgr_write(31, 0x7830, 0x1);
++#endif        
++
++}
++#endif
++
++void ei_reset_task(struct work_struct *work)
++{
++      struct net_device *dev = dev_raether;
++
++      ei_close(dev);
++      ei_open(dev);
++
++      return;
++}
++
++void ei_tx_timeout(struct net_device *dev)
++{
++        END_DEVICE *ei_local = netdev_priv(dev);
++
++        schedule_work(&ei_local->reset_task);
++}
++
++void setup_statistics(END_DEVICE* ei_local)
++{
++      ei_local->stat.tx_packets       = 0;
++      ei_local->stat.tx_bytes         = 0;
++      ei_local->stat.tx_dropped       = 0;
++      ei_local->stat.tx_errors        = 0;
++      ei_local->stat.tx_aborted_errors= 0;
++      ei_local->stat.tx_carrier_errors= 0;
++      ei_local->stat.tx_fifo_errors   = 0;
++      ei_local->stat.tx_heartbeat_errors = 0;
++      ei_local->stat.tx_window_errors = 0;
++
++      ei_local->stat.rx_packets       = 0;
++      ei_local->stat.rx_bytes         = 0;
++      ei_local->stat.rx_dropped       = 0;
++      ei_local->stat.rx_errors        = 0;
++      ei_local->stat.rx_length_errors = 0;
++      ei_local->stat.rx_over_errors   = 0;
++      ei_local->stat.rx_crc_errors    = 0;
++      ei_local->stat.rx_frame_errors  = 0;
++      ei_local->stat.rx_fifo_errors   = 0;
++      ei_local->stat.rx_missed_errors = 0;
++
++      ei_local->stat.collisions       = 0;
++#if defined (CONFIG_RAETH_QOS)
++      ei_local->tx3_full = 0;
++      ei_local->tx2_full = 0;
++      ei_local->tx1_full = 0;
++      ei_local->tx0_full = 0;
++#else
++      ei_local->tx_full = 0;
++#endif
++#ifdef CONFIG_RAETH_NAPI
++      atomic_set(&ei_local->irq_sem, 1);
++#endif
++
++}
++
++/**
++ * rather_probe - pick up ethernet port at boot time
++ * @dev: network device to probe
++ *
++ * This routine probe the ethernet port at boot time.
++ *
++ *
++ */
++
++int __init rather_probe(struct net_device *dev)
++{
++      int i;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      struct sockaddr addr;
++      unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
++      unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
++
++      fe_reset();
++
++      //Get mac0 address from flash
++#ifdef RA_MTD_RW_BY_NUM
++      i = ra_mtd_read(2, GMAC0_OFFSET, 6, addr.sa_data);
++#else
++      i = ra_mtd_read_nm("Factory", GMAC0_OFFSET, 6, addr.sa_data);
++#endif
++      //If reading mtd failed or mac0 is empty, generate a mac address
++      if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) || 
++          (memcmp(addr.sa_data, zero2, 6) == 0)) {
++              unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
++      //      net_srandom(jiffies);
++              memcpy(addr.sa_data, mac_addr01234, 5);
++      //      addr.sa_data[5] = net_random()&0xFF;
++      }
++
++#ifdef CONFIG_RAETH_NAPI
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      netif_napi_add(dev, &ei_local->napi, raeth_clean, 128);
++#endif
++#endif
++      ei_set_mac_addr(dev, &addr);
++      spin_lock_init(&ei_local->page_lock);
++      ether_setup(dev);
++
++#ifdef CONFIG_RAETH_LRO
++      ei_local->lro_mgr.dev = dev;
++        memset(&ei_local->lro_mgr.stats, 0, sizeof(ei_local->lro_mgr.stats));
++        ei_local->lro_mgr.features = LRO_F_NAPI;
++        ei_local->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
++        ei_local->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
++        ei_local->lro_mgr.max_desc = ARRAY_SIZE(ei_local->lro_arr);
++        ei_local->lro_mgr.max_aggr = 64;
++        ei_local->lro_mgr.frag_align_pad = 0;
++        ei_local->lro_mgr.lro_arr = ei_local->lro_arr;
++        ei_local->lro_mgr.get_skb_header = rt_get_skb_header;
++#endif
++
++      setup_statistics(ei_local);
++
++      return 0;
++}
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++int VirtualIF_ioctl(struct net_device * net_dev,
++                  struct ifreq * ifr, int cmd)
++{
++      ra_mii_ioctl_data mii;
++
++      switch (cmd) {
++              case RAETH_MII_READ:
++                      copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++                      mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
++                      //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
++                      copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
++                      break;
++
++              case RAETH_MII_WRITE:
++                      copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
++                      //printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
++                      mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
++                      break;
++              default:
++                      return -EOPNOTSUPP;
++      }
++
++      return 0;
++}
++
++struct net_device_stats *VirtualIF_get_stats(struct net_device *dev)
++{
++      PSEUDO_ADAPTER *pAd = netdev_priv(dev);
++      return &pAd->stat;
++}
++
++int VirtualIF_open(struct net_device * dev)
++{
++    PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
++
++    printk("%s: ===> VirtualIF_open\n", dev->name);
++ 
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++    *((volatile u32 *)(FE_INT_ENABLE2)) |= (1<<25); //enable GE2 link change intr for MT7530 delay setting
++#endif
++
++    netif_start_queue(pPesueoAd->PseudoDev);
++
++    return 0;
++}
++
++int VirtualIF_close(struct net_device * dev)
++{
++    PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
++
++    printk("%s: ===> VirtualIF_close\n", dev->name);
++
++    netif_stop_queue(pPesueoAd->PseudoDev);
++
++    return 0;
++}
++
++int VirtualIFSendPackets(struct sk_buff * pSkb,
++                       struct net_device * dev)
++{
++    PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
++    END_DEVICE *ei_local __maybe_unused;
++
++
++    //printk("VirtualIFSendPackets --->\n");
++
++    ei_local = netdev_priv(dev);
++    if (!(pPesueoAd->RaethDev->flags & IFF_UP)) {
++      dev_kfree_skb_any(pSkb);
++      return 0;
++    }
++    //pSkb->cb[40]=0x5a;
++    pSkb->dev = pPesueoAd->RaethDev;
++    ei_start_xmit(pSkb, pPesueoAd->RaethDev, 2);
++    return 0;
++}
++
++void virtif_setup_statistics(PSEUDO_ADAPTER* pAd)
++{
++      pAd->stat.tx_packets    = 0;
++      pAd->stat.tx_bytes      = 0;
++      pAd->stat.tx_dropped    = 0;
++      pAd->stat.tx_errors     = 0;
++      pAd->stat.tx_aborted_errors= 0;
++      pAd->stat.tx_carrier_errors= 0;
++      pAd->stat.tx_fifo_errors        = 0;
++      pAd->stat.tx_heartbeat_errors = 0;
++      pAd->stat.tx_window_errors      = 0;
++
++      pAd->stat.rx_packets    = 0;
++      pAd->stat.rx_bytes      = 0;
++      pAd->stat.rx_dropped    = 0;
++      pAd->stat.rx_errors     = 0;
++      pAd->stat.rx_length_errors = 0;
++      pAd->stat.rx_over_errors        = 0;
++      pAd->stat.rx_crc_errors = 0;
++      pAd->stat.rx_frame_errors       = 0;
++      pAd->stat.rx_fifo_errors        = 0;
++      pAd->stat.rx_missed_errors      = 0;
++
++      pAd->stat.collisions    = 0;
++}
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++static const struct net_device_ops VirtualIF_netdev_ops = {
++        .ndo_open               = VirtualIF_open,
++        .ndo_stop               = VirtualIF_close,
++        .ndo_start_xmit         = VirtualIFSendPackets,
++        .ndo_get_stats          = VirtualIF_get_stats,
++        .ndo_set_mac_address    = ei_set_mac2_addr,
++        .ndo_change_mtu         = ei_change_mtu,
++        .ndo_do_ioctl           = VirtualIF_ioctl,
++        .ndo_validate_addr      = eth_validate_addr,
++};
++#endif
++// Register pseudo interface
++void RAETH_Init_PSEUDO(pEND_DEVICE pAd, struct net_device *net_dev)
++{
++    int index;
++    struct net_device *dev;
++    PSEUDO_ADAPTER *pPseudoAd;
++    int i = 0;
++    struct sockaddr addr;
++    unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
++    unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
++
++    for (index = 0; index < MAX_PSEUDO_ENTRY; index++) {
++
++      dev = alloc_etherdev(sizeof(PSEUDO_ADAPTER));
++      if (NULL == dev)
++      {
++              printk(" alloc_etherdev for PSEUDO_ADAPTER failed.\n");
++              return;
++      }
++      strcpy(dev->name, DEV2_NAME);
++
++      //Get mac2 address from flash
++#ifdef RA_MTD_RW_BY_NUM
++      i = ra_mtd_read(2, GMAC2_OFFSET, 6, addr.sa_data);
++#else
++      i = ra_mtd_read_nm("Factory", GMAC2_OFFSET, 6, addr.sa_data);
++#endif
++
++      //If reading mtd failed or mac0 is empty, generate a mac address
++      if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) || 
++          (memcmp(addr.sa_data, zero2, 6) == 0)) {
++              unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
++      //      net_srandom(jiffies);
++              memcpy(addr.sa_data, mac_addr01234, 5);
++      //      addr.sa_data[5] = net_random()&0xFF;
++      }
++
++      ei_set_mac2_addr(dev, &addr);
++      ether_setup(dev);
++      pPseudoAd = netdev_priv(dev);
++
++      pPseudoAd->PseudoDev = dev;
++      pPseudoAd->RaethDev = net_dev;
++      virtif_setup_statistics(pPseudoAd);
++      pAd->PseudoDev = dev;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      dev->netdev_ops         = &VirtualIF_netdev_ops;
++#else
++      dev->hard_start_xmit = VirtualIFSendPackets;
++      dev->stop = VirtualIF_close;
++      dev->open = VirtualIF_open;
++      dev->do_ioctl = VirtualIF_ioctl;
++      dev->set_mac_address = ei_set_mac2_addr;
++      dev->get_stats = VirtualIF_get_stats;
++      dev->change_mtu = ei_change_mtu;
++      dev->mtu = 1500;
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO) 
++    dev->features |= NETIF_F_HW_CSUM;
++#else
++      dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++#if defined(CONFIG_RALINK_MT7620)
++#if defined (CONFIG_RAETH_TSO)
++      if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++              dev->features |= NETIF_F_SG;
++              dev->features |= NETIF_F_TSO;
++      }
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++      if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++              dev->features |= NETIF_F_TSO6;
++              dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++      }
++#endif 
++#else
++#if defined (CONFIG_RAETH_TSO)
++        dev->features |= NETIF_F_SG;
++        dev->features |= NETIF_F_TSO;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++        dev->features |= NETIF_F_TSO6;
++        dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
++#endif 
++#endif // CONFIG_RALINK_MT7620 //
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
++      dev->vlan_features = dev->features;
++#endif
++
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++      dev->ethtool_ops = &ra_virt_ethtool_ops;
++    // init mii structure
++      pPseudoAd->mii_info.dev = dev;
++      pPseudoAd->mii_info.mdio_read = mdio_virt_read;
++      pPseudoAd->mii_info.mdio_write = mdio_virt_write;
++      pPseudoAd->mii_info.phy_id_mask = 0x1f;
++      pPseudoAd->mii_info.reg_num_mask = 0x1f;
++      pPseudoAd->mii_info.phy_id = 0x1e;
++      pPseudoAd->mii_info.supports_gmii = mii_check_gmii_support(&pPseudoAd->mii_info);
++#endif
++
++      // Register this device
++      register_netdevice(dev);
++    }
++}
++#endif
++
++/**
++ * ei_open - Open/Initialize the ethernet port.
++ * @dev: network device to initialize
++ *
++ * This routine goes all-out, setting everything
++ * up a new at each open, even though many of these registers should only need to be set once at boot.
++ */
++int ei_open(struct net_device *dev)
++{
++      int i, err;
++#if !defined (CONFIG_MT7623_FPGA)
++      unsigned long flags;
++#endif
++      END_DEVICE *ei_local;
++
++#ifdef CONFIG_RAETH_LRO
++      const char *lan_ip_tmp; 
++#ifdef CONFIG_DUAL_IMAGE
++#define RT2860_NVRAM  1
++#else
++#define RT2860_NVRAM  0
++#endif
++#endif // CONFIG_RAETH_LRO //
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++      if (!try_module_get(THIS_MODULE))
++      {
++              printk("%s: Cannot reserve module\n", __FUNCTION__);
++              return -1;
++      }
++#else
++      MOD_INC_USE_COUNT;
++#endif
++
++      printk("Raeth %s (",RAETH_VERSION);
++#if defined (CONFIG_RAETH_NAPI)
++      printk("NAPI\n");
++#elif defined (CONFIG_RA_NETWORK_TASKLET_BH)
++      printk("Tasklet");
++#elif defined (CONFIG_RA_NETWORK_WORKQUEUE_BH)
++      printk("Workqueue");
++#endif
++
++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
++      printk(",SkbRecycle");
++#endif
++      printk(")\n");
++
++
++      ei_local = netdev_priv(dev); // get device pointer from System
++      // unsigned int flags;
++
++      if (ei_local == NULL)
++      {
++              printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
++              return -ENXIO;
++      }
++
++        /* receiving packet buffer allocation - NUM_RX_DESC x MAX_RX_LENGTH */
++        for ( i = 0; i < NUM_RX_DESC; i++)
++        {
++#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
++                ei_local->netrx0_skbuf[i] = skbmgr_dev_alloc_skb2k();
++#else
++                ei_local->netrx0_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++#endif
++                if (ei_local->netrx0_skbuf[i] == NULL ) {
++                        printk("rx skbuff buffer allocation failed!");
++              } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++                  skb_reserve(ei_local->netrx0_skbuf[i], NET_IP_ALIGN);
++#endif
++              }
++              
++
++#if defined (CONFIG_RAETH_HW_LRO) 
++              ei_local->netrx3_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN);
++        if (ei_local->netrx3_skbuf[i] == NULL ) {
++            printk("rx3 skbuff buffer allocation failed!");
++              } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++                  skb_reserve(ei_local->netrx3_skbuf[i], NET_IP_ALIGN);
++#endif
++              }
++              ei_local->netrx2_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN);
++        if (ei_local->netrx2_skbuf[i] == NULL ) {
++            printk("rx2 skbuff buffer allocation failed!");
++              } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++                  skb_reserve(ei_local->netrx2_skbuf[i], NET_IP_ALIGN);
++#endif
++              }
++              ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_LRO_RX_LENGTH + NET_IP_ALIGN);
++        if (ei_local->netrx1_skbuf[i] == NULL ) {
++            printk("rx1 skbuff buffer allocation failed!");
++              } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++                  skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN);
++#endif
++              }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING) 
++#if defined(CONFIG_ARCH_MT7623)
++              ei_local->netrx3_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++        if (ei_local->netrx3_skbuf[i] == NULL ) {
++            printk("rx3 skbuff buffer allocation failed!");
++              } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++                  skb_reserve(ei_local->netrx3_skbuf[i], NET_IP_ALIGN);
++#endif
++              }
++              ei_local->netrx2_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++        if (ei_local->netrx2_skbuf[i] == NULL ) {
++            printk("rx2 skbuff buffer allocation failed!");
++              } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++                  skb_reserve(ei_local->netrx2_skbuf[i], NET_IP_ALIGN);
++#endif
++              }
++#endif  /* CONFIG_ARCH_MT7623 */
++              ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
++                if (ei_local->netrx1_skbuf[i] == NULL ) {
++                        printk("rx1 skbuff buffer allocation failed!");
++              } else {
++#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++                  skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN);
++#endif
++              }
++#endif
++        }
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++      trgmii_set_7621(); //reset FE/GMAC in this function
++#endif
++      
++        fe_dma_init(dev);
++      
++#if defined (CONFIG_RAETH_HW_LRO)
++    fe_hw_lro_init(dev);
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++      fe_sw_init(); //initialize fe and switch register
++#if defined (CONFIG_MIPS)
++      err = request_irq( dev->irq, ei_interrupt, IRQF_DISABLED, dev->name, dev);      // try to fix irq in open
++#else
++      err = request_irq(dev->irq, ei_interrupt, /*IRQF_TRIGGER_LOW*/ 0, dev->name, dev);      // try to fix irq in open
++#endif        
++      if (err)
++          return err;
++
++      if ( dev->dev_addr != NULL) {
++          ra2880MacAddressSet((void *)(dev->dev_addr));
++      } else {
++          printk("dev->dev_addr is empty !\n");
++      } 
++/*TODO: MT7623 MCM INT */
++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_ARCH_MT7623)
++      err = request_irq(SURFBOARDINT_ESW, esw_interrupt, IRQF_DISABLED, "Ralink_ESW", dev);
++      if (err)
++              return err;
++      INIT_WORK(&ei_local->kill_sig_wq, kill_sig_workq);
++#if defined (CONFIG_RALINK_MT7621)
++        mii_mgr_write(31, 0x7008, 0x1f); //enable switch link change intr
++      
++#else
++      *((volatile u32 *)(RALINK_INTCL_BASE + 0x34)) = (1<<17);
++      *((volatile u32 *)(ESW_IMR)) &= ~(ESW_INT_ALL);
++
++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \
++    defined (CONFIG_RALINK_MT7620)
++      *((volatile u32 *)(ESW_P0_IntMn)) &= ~(MSK_CNT_INT_ALL);
++      *((volatile u32 *)(ESW_P1_IntMn)) &= ~(MSK_CNT_INT_ALL);
++      *((volatile u32 *)(ESW_P2_IntMn)) &= ~(MSK_CNT_INT_ALL);
++      *((volatile u32 *)(ESW_P3_IntMn)) &= ~(MSK_CNT_INT_ALL);
++      *((volatile u32 *)(ESW_P4_IntMn)) &= ~(MSK_CNT_INT_ALL);
++      *((volatile u32 *)(ESW_P5_IntMn)) &= ~(MSK_CNT_INT_ALL);
++      *((volatile u32 *)(ESW_P6_IntMn)) &= ~(MSK_CNT_INT_ALL);
++#endif
++#if defined(CONFIG_RALINK_MT7620)
++      *((volatile u32 *)(ESW_P7_IntMn)) &= ~(MSK_CNT_INT_ALL);
++#endif
++
++#endif        
++#endif // CONFIG_RT_3052_ESW //
++
++/*TODO*/
++#if !defined (CONFIG_MT7623_FPGA)
++        spin_lock_irqsave(&(ei_local->page_lock), flags);
++#endif
++
++
++#ifdef DELAY_INT
++        sysRegWrite(RAETH_DLY_INT_CFG, DELAY_INT_INIT);
++      sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT);
++    #if defined (CONFIG_RAETH_HW_LRO)
++        sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1);
++    #endif  /* CONFIG_RAETH_HW_LRO */
++#else
++      sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL);
++    #if defined (CONFIG_RAETH_HW_LRO)
++        sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL | ALT_RPLC_INT3 | ALT_RPLC_INT2 | ALT_RPLC_INT1);
++    #endif  /* CONFIG_RAETH_HW_LRO */
++#endif
++
++#ifdef CONFIG_RAETH_QDMA
++#ifdef DELAY_INT
++        sysRegWrite(QDMA_DELAY_INT, DELAY_INT_INIT);
++      sysRegWrite(QFE_INT_ENABLE, QFE_INT_DLY_INIT);
++#else
++      sysRegWrite(QFE_INT_ENABLE, QFE_INT_ALL);
++
++#endif
++#endif
++
++      INIT_WORK(&ei_local->reset_task, ei_reset_task);
++      
++#ifdef WORKQUEUE_BH
++#ifndef CONFIG_RAETH_NAPI
++      INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
++#endif // CONFIG_RAETH_NAPI //
++#else
++#ifndef CONFIG_RAETH_NAPI
++#if defined (TASKLET_WORKQUEUE_SW)
++      working_schedule = init_schedule;
++      INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
++      tasklet_init(&ei_local->rx_tasklet, ei_receive_workq, 0);
++#else
++      tasklet_init(&ei_local->rx_tasklet, ei_receive, 0);
++#endif
++#endif // CONFIG_RAETH_NAPI //
++#endif // WORKQUEUE_BH //
++
++      netif_start_queue(dev);
++
++#ifdef CONFIG_RAETH_NAPI
++      atomic_dec(&ei_local->irq_sem);
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        napi_enable(&ei_local->napi);
++#else
++        netif_poll_enable(dev);
++#endif
++#endif
++//*TODO*/     
++#if !defined (CONFIG_MT7623_FPGA)
++      spin_unlock_irqrestore(&(ei_local->page_lock), flags);
++#endif        
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      if(ei_local->PseudoDev == NULL) {
++          RAETH_Init_PSEUDO(ei_local, dev);
++      }
++ 
++      if(ei_local->PseudoDev == NULL) 
++              printk("Open PseudoDev failed.\n");
++      else
++              VirtualIF_open(ei_local->PseudoDev);
++
++#endif
++
++#ifdef CONFIG_RAETH_LRO
++      lan_ip_tmp = nvram_get(RT2860_NVRAM, "lan_ipaddr");
++      str_to_ip(&lan_ip, lan_ip_tmp);
++      lro_para.lan_ip1 = lan_ip = htonl(lan_ip);
++#endif // CONFIG_RAETH_LRO //
++
++#if defined (CONFIG_RAETH_HW_LRO)
++    INIT_WORK(&ei_local->hw_lro_wq, ei_hw_lro_workq);
++#endif  /* CONFIG_RAETH_HW_LRO */
++
++      forward_config(dev);
++      return 0;
++}
++
++/**
++ * ei_close - shut down network device
++ * @dev: network device to clear
++ *
++ * This routine shut down network device.
++ *
++ *
++ */
++int ei_close(struct net_device *dev)
++{
++      int i;
++      END_DEVICE *ei_local = netdev_priv(dev);        // device pointer
++
++      netif_stop_queue(dev);
++        ra2880stop(ei_local);
++
++      free_irq(dev->irq, dev);
++
++/*TODO: MT7623 MCM INT */
++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_ARCH_MT7623)
++      free_irq(SURFBOARDINT_ESW, dev);
++#endif        
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      cancel_work_sync(&ei_local->reset_task);
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      VirtualIF_close(ei_local->PseudoDev);
++#endif
++
++
++#ifdef WORKQUEUE_BH
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      cancel_work_sync(&ei_local->rx_wq);
++#endif
++#else
++#if defined (TASKLET_WORKQUEUE_SW)
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      cancel_work_sync(&ei_local->rx_wq);
++#endif
++#endif
++      tasklet_kill(&ei_local->tx_tasklet);
++      tasklet_kill(&ei_local->rx_tasklet);
++#endif // WORKQUEUE_BH //
++
++#ifdef CONFIG_RAETH_NAPI
++      atomic_inc(&ei_local->irq_sem);
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++        napi_disable(&ei_local->napi);
++#else
++        netif_poll_disable(dev);
++#endif
++#endif
++
++
++#if defined (CONFIG_RAETH_HW_LRO)
++    cancel_work_sync(&ei_local->hw_lro_wq);
++#endif  /* CONFIG_RAETH_HW_LRO */   
++
++        for ( i = 0; i < NUM_RX_DESC; i++)
++        {
++                if (ei_local->netrx0_skbuf[i] != NULL) {
++                        dev_kfree_skb(ei_local->netrx0_skbuf[i]);
++                      ei_local->netrx0_skbuf[i] = NULL;
++              }
++#if defined (CONFIG_RAETH_HW_LRO)
++                if (ei_local->netrx3_skbuf[i] != NULL) {
++                        dev_kfree_skb(ei_local->netrx3_skbuf[i]);
++                      ei_local->netrx3_skbuf[i] = NULL;
++              }
++                if (ei_local->netrx2_skbuf[i] != NULL) {
++                        dev_kfree_skb(ei_local->netrx2_skbuf[i]);
++                      ei_local->netrx2_skbuf[i] = NULL;
++              }
++                if (ei_local->netrx1_skbuf[i] != NULL) {
++                        dev_kfree_skb(ei_local->netrx1_skbuf[i]);
++                      ei_local->netrx1_skbuf[i] = NULL;
++              }
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#if defined(CONFIG_ARCH_MT7623)
++                if (ei_local->netrx3_skbuf[i] != NULL) {
++                        dev_kfree_skb(ei_local->netrx3_skbuf[i]);
++                      ei_local->netrx3_skbuf[i] = NULL;
++              }
++                if (ei_local->netrx2_skbuf[i] != NULL) {
++                        dev_kfree_skb(ei_local->netrx2_skbuf[i]);
++                      ei_local->netrx2_skbuf[i] = NULL;
++              }
++#endif  /* CONFIG_ARCH_MT7623 */
++                if (ei_local->netrx1_skbuf[i] != NULL) {
++                        dev_kfree_skb(ei_local->netrx1_skbuf[i]);
++                      ei_local->netrx1_skbuf[i] = NULL;
++              }
++#endif
++        }
++
++      for ( i = 0; i < NUM_TX_DESC; i++)
++      {
++              if((ei_local->skb_free[i]!=(struct  sk_buff *)0xFFFFFFFF) && (ei_local->skb_free[i]!= 0))
++              {
++                      dev_kfree_skb_any(ei_local->skb_free[i]);
++              }
++      }
++
++      /* TX Ring */
++#ifdef CONFIG_RAETH_QDMA
++       if (ei_local->txd_pool != NULL) {
++         pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct QDMA_txdesc), ei_local->txd_pool, ei_local->phy_txd_pool);
++       }
++       if (ei_local->free_head != NULL){
++             pci_free_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), ei_local->free_head, ei_local->phy_free_head);
++       }
++       if (ei_local->free_page_head != NULL){
++             pci_free_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, ei_local->free_page_head, ei_local->phy_free_page_head);
++       }
++#else 
++       if (ei_local->tx_ring0 != NULL) {
++         pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring0, ei_local->phy_tx_ring0);
++       }
++#endif       
++
++#if defined (CONFIG_RAETH_QOS)
++       if (ei_local->tx_ring1 != NULL) {
++         pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring1, ei_local->phy_tx_ring1);
++       }
++
++#if !defined (CONFIG_RALINK_RT2880)
++       if (ei_local->tx_ring2 != NULL) {
++         pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring2, ei_local->phy_tx_ring2);
++       }
++
++       if (ei_local->tx_ring3 != NULL) {
++         pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring3, ei_local->phy_tx_ring3);
++       }
++#endif
++#endif
++      /* RX Ring */
++#ifdef CONFIG_32B_DESC
++       kfree(ei_local->rx_ring0);
++#else
++        pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring0, ei_local->phy_rx_ring0);
++#endif
++#if defined CONFIG_RAETH_QDMA && !defined(CONFIG_RAETH_QDMATX_QDMARX) 
++#ifdef CONFIG_32B_DESC
++      kfree(ei_local->qrx_ring);
++#else
++      pci_free_consistent(NULL, NUM_QRX_DESC*sizeof(struct PDMA_rxdesc), ei_local->qrx_ring, ei_local->phy_qrx_ring);
++#endif
++#endif        
++#if defined (CONFIG_RAETH_HW_LRO)
++        pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring3, ei_local->phy_rx_ring3);
++        pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring2, ei_local->phy_rx_ring2);
++        pci_free_consistent(NULL, NUM_LRO_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1);
++#elif defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#ifdef CONFIG_32B_DESC
++      kfree(ei_local->rx_ring1);
++#else
++#if defined(CONFIG_ARCH_MT7623)
++        pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring3, ei_local->phy_rx_ring3);
++        pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring2, ei_local->phy_rx_ring2);
++#endif  /* CONFIG_ARCH_MT7623 */
++        pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1);
++#endif
++#endif
++
++      printk("Free TX/RX Ring Memory!\n");
++
++      fe_reset();
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++      module_put(THIS_MODULE);
++#else
++      MOD_DEC_USE_COUNT;
++#endif
++      return 0;
++}
++
++#if defined (CONFIG_RT6855A_FPGA)
++void rt6855A_eth_gpio_reset(void)
++{
++      u8 ether_gpio = 12;
++
++      /* Load the ethernet gpio value to reset Ethernet PHY */
++      *(unsigned long *)(RALINK_PIO_BASE + 0x00) |= 1<<(ether_gpio<<1);
++      *(unsigned long *)(RALINK_PIO_BASE + 0x14) |= 1<<(ether_gpio);
++      *(unsigned long *)(RALINK_PIO_BASE + 0x04) &= ~(1<<ether_gpio);
++
++      udelay(100000);
++
++      *(unsigned long *)(RALINK_PIO_BASE + 0x04) |= (1<<ether_gpio);
++
++      /* must wait for 0.6 seconds after reset*/
++      udelay(600000);
++}
++#endif
++
++#if defined(CONFIG_RALINK_RT6855A)
++void rt6855A_gsw_init(void)
++{
++      u32 phy_val=0;
++      u32 rev=0;
++
++#if defined (CONFIG_RT6855A_FPGA)
++    /*keep dump switch mode */
++    rt6855A_eth_gpio_reset();
++
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e353;//(P0,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e353;//(P1,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
++    //*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
++    //*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x8000;//link down
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x8000;//link down
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x8000;//link down
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
++
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
++
++    /* In order to use 10M/Full on FPGA board. We configure phy capable to
++     * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
++    for(i=6;i<8;i++){
++      mii_mgr_write(i, 4, 0x07e1);   //Capable of 10M&100M Full/Half Duplex, flow control on/off
++      //mii_mgr_write(i, 4, 0x0461);   //Capable of 10M Full/Half Duplex, flow control on/off
++      mii_mgr_write(i, 0, 0xB100);   //reset all digital logic, except phy_reg
++      mii_mgr_read(i, 9, &phy_val);
++      phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement  (9.9=1000Full, 9.8=1000Half)
++      mii_mgr_write(i, 9, phy_val);
++    }
++#elif defined (CONFIG_RT6855A_ASIC)
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
++
++    *(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1ec) = 0x0fffffff;//Set PSE should pause 4 tx ring as default
++    *(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1f0) = 0x0fffffff;//switch IOT more stable
++    
++    *(unsigned long *)(CKGCR) &= ~(0x3 << 4); //keep rx/tx port clock ticking, disable internal clock-gating to avoid switch stuck 
++  
++    /*
++     *Reg 31: Page Control
++     * Bit 15     => PortPageSel, 1=local, 0=global
++     * Bit 14:12  => PageSel, local:0~3, global:0~4
++     *
++     *Reg16~30:Local/Global registers
++     *
++    */
++    /*correct  PHY  setting J8.0*/
++    mii_mgr_read(0, 31, &rev);
++    rev &= (0x0f);
++
++    mii_mgr_write(1, 31, 0x4000); //global, page 4
++  
++    mii_mgr_write(1, 16, 0xd4cc);
++    mii_mgr_write(1, 17, 0x7444);
++    mii_mgr_write(1, 19, 0x0112);
++    mii_mgr_write(1, 21, 0x7160);
++    mii_mgr_write(1, 22, 0x10cf);
++    mii_mgr_write(1, 26, 0x0777);
++    
++    if(rev == 0){
++          mii_mgr_write(1, 25, 0x0102);
++          mii_mgr_write(1, 29, 0x8641);
++    }
++    else{
++            mii_mgr_write(1, 25, 0x0212);
++          mii_mgr_write(1, 29, 0x4640);
++    }
++
++    mii_mgr_write(1, 31, 0x2000); //global, page 2
++    mii_mgr_write(1, 21, 0x0655);
++    mii_mgr_write(1, 22, 0x0fd3);
++    mii_mgr_write(1, 23, 0x003d);
++    mii_mgr_write(1, 24, 0x096e);
++    mii_mgr_write(1, 25, 0x0fed);
++    mii_mgr_write(1, 26, 0x0fc4);
++    
++    mii_mgr_write(1, 31, 0x1000); //global, page 1
++    mii_mgr_write(1, 17, 0xe7f8);
++    
++    
++    mii_mgr_write(1, 31, 0xa000); //local, page 2
++
++    mii_mgr_write(0, 16, 0x0e0e);
++    mii_mgr_write(1, 16, 0x0c0c);
++    mii_mgr_write(2, 16, 0x0f0f);
++    mii_mgr_write(3, 16, 0x1010);
++    mii_mgr_write(4, 16, 0x0909);
++
++    mii_mgr_write(0, 17, 0x0000);
++    mii_mgr_write(1, 17, 0x0000);
++    mii_mgr_write(2, 17, 0x0000);
++    mii_mgr_write(3, 17, 0x0000);
++    mii_mgr_write(4, 17, 0x0000);
++#endif
++
++#if defined (CONFIG_RT6855A_ASIC)
++
++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c;//disable port0-port4 internal phy, set phy base address to 12 
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
++
++#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      //rt6855/6 need to modify TX/RX phase
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0xc;//TX/RX CLOCK Phase select
++      
++      enable_auto_negotiate(1);
++
++      if (isICPlusGigaPHY(1)) {
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
++              phy_val |= 1<<10; //enable pause ability
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++              phy_val |= 1<<9; //restart AN
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++      }
++
++      if (isMarvellGigaPHY(1)) {
++              printk("Reset MARVELL phy1\n");
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
++              phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++              phy_val |= 1<<15; //PHY Software Reset
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++        }
++      if (isVtssGigaPHY(1)) {
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
++              printk("Vitesse phy skew: %x --> ", phy_val);
++              phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++              phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++              printk("%x\n", phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
++        }
++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#else // Port 5 Disabled //
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
++#endif
++#endif
++}
++#endif
++
++
++
++
++#if defined (CONFIG_MT7623_FPGA)
++void setup_fpga_gsw(void)
++{
++      u32     i;
++      u32     regValue;
++
++      /* reduce RGMII2 PAD driving strength */
++      *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
++
++      //RGMII1=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
++
++      //GMAC1= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
++
++      //enable MDIO to control MT7530
++      regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++      regValue &= ~(0x3 << 12);
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++      for(i=0;i<=4;i++)
++        {
++              //turn off PHY
++               mii_mgr_read(i, 0x0 ,&regValue);
++             regValue |= (0x1<<11);
++             mii_mgr_write(i, 0x0, regValue); 
++      }
++        mii_mgr_write(31, 0x7000, 0x3); //reset switch
++        udelay(10);
++      sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e337);//(GE1, Force 100M/FD, FC ON)
++      mii_mgr_write(31, 0x3600, 0x5e337);
++
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
++      mii_mgr_write(31, 0x3500, 0x8000);
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++      //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
++      mii_mgr_read(31, 0x7804 ,&regValue);
++      regValue &= ~(1<<8); //Enable Port 6
++      regValue |= (1<<6); //Disable Port 5
++      regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++
++#if defined (CONFIG_RAETH_GMAC2)
++      //RGMII2=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++
++      //GMAC2= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++
++      mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling)
++
++      enable_auto_negotiate(0);//set polling address
++      /* set MT7530 Port 5 to PHY 0/4 mode */
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
++      regValue &= ~((1<<13)|(1<<6));
++      regValue |= ((1<<7)|(1<<16)|(1<<20));
++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++      regValue &= ~((1<<13)|(1<<6)|((1<<20)));
++      regValue |= ((1<<7)|(1<<16));
++#endif
++
++      //sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
++#endif
++      regValue |= (1<<16);//change HW-TRAP
++      printk("change HW-TRAP to 0x%x\n",regValue);
++      mii_mgr_write(31, 0x7804 ,regValue);
++#endif
++      mii_mgr_write(0, 14, 0x1);  /*RGMII*/
++/* set MT7530 central align */
++        mii_mgr_read(31, 0x7830, &regValue);
++        regValue &= ~1;
++        regValue |= 1<<1;
++        mii_mgr_write(31, 0x7830, regValue);
++
++        mii_mgr_read(31, 0x7a40, &regValue);
++        regValue &= ~(1<<30);
++        mii_mgr_write(31, 0x7a40, regValue);
++
++        regValue = 0x855;
++        mii_mgr_write(31, 0x7a78, regValue);
++
++/*to check!!*/
++      mii_mgr_write(31, 0x7b00, 0x102);  //delay setting for 10/1000M
++      mii_mgr_write(31, 0x7b04, 0x14);  //delay setting for 10/1000M
++
++      for(i=0;i<=4;i++) {     
++              mii_mgr_read(i, 4, &regValue);
++                regValue |= (3<<7); //turn on 100Base-T Advertisement
++                //regValue &= ~(3<<7); //turn off 100Base-T Advertisement
++              mii_mgr_write(i, 4, regValue);
++      
++              mii_mgr_read(i, 9, &regValue);
++                //regValue |= (3<<8); //turn on 1000Base-T Advertisement
++              regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
++                mii_mgr_write(i, 9, regValue);
++
++              //restart AN
++              mii_mgr_read(i, 0, &regValue);
++              regValue |= (1 << 9);
++              mii_mgr_write(i, 0, regValue);
++      }
++
++      /*Tx Driving*/
++      mii_mgr_write(31, 0x7a54, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a5c, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a64, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a6c, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a74, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a7c, 0x44);  //lower driving
++
++      for(i=0;i<=4;i++)
++        {
++      //turn on PHY
++                mii_mgr_read(i, 0x0 ,&regValue);
++              regValue &= ~(0x1<<11);
++              mii_mgr_write(i, 0x0, regValue);        
++      }
++}
++#endif
++
++
++#if defined (CONFIG_RALINK_MT7621)
++
++
++void setup_external_gsw(void)
++{
++      u32     regValue;
++
++      /* reduce RGMII2 PAD driving strength */
++      *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
++      //enable MDIO 
++      regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++      regValue &= ~(0x3 << 12);
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++      //RGMII1=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
++      //GMAC1= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
++      
++      sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x00008000);//(GE1, Link down)
++
++      //RGMII2=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++      //GMAC2= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2105e33b);//(GE2, Force 1000M/FD, FC ON)
++
++}
++
++
++
++
++
++
++
++
++
++
++void IsSwitchVlanTableBusy(void)
++{
++      int j = 0;
++      unsigned int value = 0;
++
++      for (j = 0; j < 20; j++) {
++          mii_mgr_read(31, 0x90, &value);
++          if ((value & 0x80000000) == 0 ){ //table busy
++              break;
++          }
++          udelay(70000);
++      }
++      if (j == 20)
++          printk("set vlan timeout value=0x%x.\n", value);
++}
++
++void LANWANPartition(void)
++{
++/*Set  MT7530 */
++#ifdef CONFIG_WAN_AT_P0
++      printk("set LAN/WAN WLLLL\n");
++      //WLLLL, wan at P0
++      //LAN/WAN ports as security mode
++      mii_mgr_write(31, 0x2004, 0xff0003);//port0
++      mii_mgr_write(31, 0x2104, 0xff0003);//port1
++      mii_mgr_write(31, 0x2204, 0xff0003);//port2
++      mii_mgr_write(31, 0x2304, 0xff0003);//port3
++      mii_mgr_write(31, 0x2404, 0xff0003);//port4
++
++      //set PVID
++      mii_mgr_write(31, 0x2014, 0x10002);//port0
++      mii_mgr_write(31, 0x2114, 0x10001);//port1
++      mii_mgr_write(31, 0x2214, 0x10001);//port2
++      mii_mgr_write(31, 0x2314, 0x10001);//port3
++      mii_mgr_write(31, 0x2414, 0x10001);//port4
++      /*port6 */
++      //VLAN member
++      IsSwitchVlanTableBusy();
++      mii_mgr_write(31, 0x94, 0x407e0001);//VAWD1
++      mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
++      IsSwitchVlanTableBusy();
++
++      mii_mgr_write(31, 0x94, 0x40610001);//VAWD1
++      mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
++      IsSwitchVlanTableBusy();
++#endif
++#ifdef CONFIG_WAN_AT_P4
++      printk("set LAN/WAN LLLLW\n");
++      //LLLLW, wan at P4
++      //LAN/WAN ports as security mode
++      mii_mgr_write(31, 0x2004, 0xff0003);//port0
++      mii_mgr_write(31, 0x2104, 0xff0003);//port1
++      mii_mgr_write(31, 0x2204, 0xff0003);//port2
++      mii_mgr_write(31, 0x2304, 0xff0003);//port3
++      mii_mgr_write(31, 0x2404, 0xff0003);//port4
++
++      //set PVID
++      mii_mgr_write(31, 0x2014, 0x10001);//port0
++      mii_mgr_write(31, 0x2114, 0x10001);//port1
++      mii_mgr_write(31, 0x2214, 0x10001);//port2
++      mii_mgr_write(31, 0x2314, 0x10001);//port3
++      mii_mgr_write(31, 0x2414, 0x10002);//port4
++
++      //VLAN member
++      IsSwitchVlanTableBusy();
++      mii_mgr_write(31, 0x94, 0x404f0001);//VAWD1
++      mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
++      IsSwitchVlanTableBusy();
++      mii_mgr_write(31, 0x94, 0x40500001);//VAWD1
++      mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
++      IsSwitchVlanTableBusy();
++#endif
++}
++
++#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
++void mt7621_eee_patch(void)
++{
++      u32 i;
++
++      for(i=0;i<5;i++)
++      {
++              /* Enable EEE */
++              mii_mgr_write(i, 13, 0x07);
++              mii_mgr_write(i, 14, 0x3c);
++              mii_mgr_write(i, 13, 0x4007);
++              mii_mgr_write(i, 14, 0x6);
++
++              /* Forced Slave mode */
++              mii_mgr_write(i, 31, 0x0);
++              mii_mgr_write(i, 9, 0x1600);
++              /* Increase SlvDPSready time */
++              mii_mgr_write(i, 31, 0x52b5);
++              mii_mgr_write(i, 16, 0xafae);
++              mii_mgr_write(i, 18, 0x2f);
++              mii_mgr_write(i, 16, 0x8fae);
++              /* Incease post_update_timer */
++              mii_mgr_write(i, 31, 0x3);
++              mii_mgr_write(i, 17, 0x4b);
++              /* Adjust 100_mse_threshold */
++              mii_mgr_write(i, 13, 0x1e);
++              mii_mgr_write(i, 14, 0x123);
++              mii_mgr_write(i, 13, 0x401e);
++              mii_mgr_write(i, 14, 0xffff);
++              /* Disable mcc
++                 mii_mgr_write(i, 13, 0x1e);
++                 mii_mgr_write(i, 14, 0xa6);
++                 mii_mgr_write(i, 13, 0x401e);
++                 mii_mgr_write(i, 14, 0x300);
++              */
++      }
++
++}
++#endif
++
++
++#if defined (CONFIG_RALINK_MT7621) 
++void setup_internal_gsw(void)
++{
++      u32     i;
++      u32     regValue;
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++      /*Hardware reset Switch*/
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2);
++        udelay(1000);
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2);
++        udelay(10000);
++
++      /* reduce RGMII2 PAD driving strength */
++      *(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
++
++      //RGMII1=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
++
++      //GMAC1= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
++
++      //enable MDIO to control MT7530
++      regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++      regValue &= ~(0x3 << 12);
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++      for(i=0;i<=4;i++)
++        {
++              //turn off PHY
++               mii_mgr_read(i, 0x0 ,&regValue);
++             regValue |= (0x1<<11);
++             mii_mgr_write(i, 0x0, regValue); 
++      }
++        mii_mgr_write(31, 0x7000, 0x3); //reset switch
++        udelay(100);
++                                             
++
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++      trgmii_set_7530();   //reset FE, config MDIO again
++
++      //enable MDIO to control MT7530
++      regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
++      regValue &= ~(0x3 << 12);
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
++
++      // switch to APLL if TRGMII and DDR2
++      if ((sysRegRead(0xBE000010)>>4)&0x1)
++      {
++              apll_xtal_enable();
++      }
++#endif
++
++#if defined (CONFIG_MT7621_ASIC)
++      if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) {
++              sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e30b);//(GE1, Force 1000M/FD, FC ON)
++              mii_mgr_write(31, 0x3600, 0x5e30b);
++      } else {
++              sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e33b);//(GE1, Force 1000M/FD, FC ON)
++              mii_mgr_write(31, 0x3600, 0x5e33b);
++      }
++#elif defined (CONFIG_MT7621_FPGA)
++      sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e337);//(GE1, Force 100M/FD, FC ON)
++      mii_mgr_write(31, 0x3600, 0x5e337);
++#endif
++
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
++#endif
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++      //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
++      mii_mgr_read(31, 0x7804 ,&regValue);
++      regValue &= ~(1<<8); //Enable Port 6
++      regValue |= (1<<6); //Disable Port 5
++      regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++
++#if defined (CONFIG_RAETH_GMAC2)
++      //RGMII2=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++
++      //GMAC2= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++#if !defined (CONFIG_RAETH_8023AZ_EEE)        
++      mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling)
++
++      enable_auto_negotiate(0);//set polling address
++#endif
++#if defined (CONFIG_RAETH_8023AZ_EEE) 
++      mii_mgr_write(31, 0x3500, 0x5e33b); //MT7530 P5 Force 1000, we can ignore this setting??????
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2105e33b);//(GE2, Force 1000)
++#endif
++
++
++
++      /* set MT7530 Port 5 to PHY 0/4 mode */
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
++      regValue &= ~((1<<13)|(1<<6));
++      regValue |= ((1<<7)|(1<<16)|(1<<20));
++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++      regValue &= ~((1<<13)|(1<<6)|(1<<20));
++      regValue |= ((1<<7)|(1<<16));
++#endif
++      
++#if defined (CONFIG_RAETH_8023AZ_EEE) 
++      regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++#endif
++      //sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
++#endif
++      regValue |= (1<<16);//change HW-TRAP
++      //printk("change HW-TRAP to 0x%x\n",regValue);
++      mii_mgr_write(31, 0x7804 ,regValue);
++#endif
++      mii_mgr_read(31, 0x7800, &regValue);
++      regValue = (regValue >> 9) & 0x3;
++      if(regValue == 0x3) { //25Mhz Xtal
++              /* do nothing */
++      } else if(regValue == 0x2) { //40Mhz
++
++          mii_mgr_write(0, 13, 0x1f);  // disable MT7530 core clock
++          mii_mgr_write(0, 14, 0x410);
++          mii_mgr_write(0, 13, 0x401f);
++          mii_mgr_write(0, 14, 0x0);
++
++          mii_mgr_write(0, 13, 0x1f);  // disable MT7530 PLL
++          mii_mgr_write(0, 14, 0x40d);
++          mii_mgr_write(0, 13, 0x401f);
++          mii_mgr_write(0, 14, 0x2020);
++
++          mii_mgr_write(0, 13, 0x1f);  // for MT7530 core clock = 500Mhz
++          mii_mgr_write(0, 14, 0x40e);  
++          mii_mgr_write(0, 13, 0x401f);  
++          mii_mgr_write(0, 14, 0x119);   
++
++          mii_mgr_write(0, 13, 0x1f);  // enable MT7530 PLL
++          mii_mgr_write(0, 14, 0x40d);
++          mii_mgr_write(0, 13, 0x401f);
++          mii_mgr_write(0, 14, 0x2820);
++
++          udelay(20); //suggest by CD
++
++          mii_mgr_write(0, 13, 0x1f);  // enable MT7530 core clock
++          mii_mgr_write(0, 14, 0x410);
++          mii_mgr_write(0, 13, 0x401f);
++      }else { //20Mhz Xtal
++
++              /* TODO */
++
++      }
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++      mii_mgr_write(0, 14, 0x3); /*TRGMII*/
++#else
++      mii_mgr_write(0, 14, 0x1);  /*RGMII*/
++/* set MT7530 central align */
++        mii_mgr_read(31, 0x7830, &regValue);
++        regValue &= ~1;
++        regValue |= 1<<1;
++        mii_mgr_write(31, 0x7830, regValue);
++
++        mii_mgr_read(31, 0x7a40, &regValue);
++        regValue &= ~(1<<30);
++        mii_mgr_write(31, 0x7a40, regValue);
++
++        regValue = 0x855;
++        mii_mgr_write(31, 0x7a78, regValue);
++
++#endif
++#if !defined (CONFIG_RAETH_8023AZ_EEE)        
++      mii_mgr_write(31, 0x7b00, 0x102);  //delay setting for 10/1000M
++      mii_mgr_write(31, 0x7b04, 0x14);  //delay setting for 10/1000M
++#endif
++#if 0 
++      for(i=0;i<=4;i++) {     
++              mii_mgr_read(i, 4, &regValue);
++                regValue |= (3<<7); //turn on 100Base-T Advertisement
++                //regValue &= ~(3<<7); //turn off 100Base-T Advertisement
++              mii_mgr_write(i, 4, regValue);
++      
++              mii_mgr_read(i, 9, &regValue);
++                regValue |= (3<<8); //turn on 1000Base-T Advertisement
++              //regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
++                mii_mgr_write(i, 9, regValue);
++
++              //restart AN
++              mii_mgr_read(i, 0, &regValue);
++              regValue |= (1 << 9);
++              mii_mgr_write(i, 0, regValue);
++      }
++#endif
++
++      /*Tx Driving*/
++      mii_mgr_write(31, 0x7a54, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a5c, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a64, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a6c, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a74, 0x44);  //lower driving
++      mii_mgr_write(31, 0x7a7c, 0x44);  //lower driving
++
++
++      LANWANPartition();
++
++#if !defined (CONFIG_RAETH_8023AZ_EEE)        
++      //disable EEE
++      for(i=0;i<=4;i++)
++      {
++          mii_mgr_write(i, 13, 0x7);
++          mii_mgr_write(i, 14, 0x3C);
++          mii_mgr_write(i, 13, 0x4007);
++          mii_mgr_write(i, 14, 0x0);
++      }
++
++      //Disable EEE 10Base-Te:
++      for(i=0;i<=4;i++)
++      {
++          mii_mgr_write(i, 13, 0x1f);
++          mii_mgr_write(i, 14, 0x027b);
++          mii_mgr_write(i, 13, 0x401f);
++          mii_mgr_write(i, 14, 0x1177);
++      }
++#endif
++
++      for(i=0;i<=4;i++)
++        {
++      //turn on PHY
++                mii_mgr_read(i, 0x0 ,&regValue);
++              regValue &= ~(0x1<<11);
++              mii_mgr_write(i, 0x0, regValue);        
++      }
++      
++      mii_mgr_read(31, 0x7808 ,&regValue);
++        regValue |= (3<<16); //Enable INTR
++      mii_mgr_write(31, 0x7808 ,regValue);
++#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
++                      mt7621_eee_patch();
++#endif
++}
++#endif
++
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
++void apll_xtal_enable(void)
++{
++        unsigned long data = 0;
++        unsigned long regValue = 0;
++
++        /* Firstly, reset all required register to default value */
++        sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008000);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, 0x01401d61);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, 0x80120004);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
++
++        /* toggle RG_XPTL_CHG */
++        sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008800);
++        sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008c00);
++
++        data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0014);
++        data &= ~(0x0000ffc0);
++
++      regValue = *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x10);
++      regValue = (regValue >> 6) & 0x7;
++      if(regValue < 6) { //20/40Mhz Xtal
++              data |= REGBIT(0x1d, 8);
++      }else {
++              data |= REGBIT(0x17, 8);
++      }
++      
++      if(regValue < 6) { //20/40Mhz Xtal
++              data |= REGBIT(0x1, 6);
++      }
++        
++      sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, data);
++
++        data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0018);
++        data &= ~(0xf0773f00);
++        data |= REGBIT(0x3, 28);
++        data |= REGBIT(0x2, 20);
++      if(regValue < 6) { //20/40Mhz Xtal
++              data |= REGBIT(0x3, 16);
++      }else {
++              data |= REGBIT(0x2, 16);
++      }
++        data |= REGBIT(0x3, 12);
++
++      if(regValue < 6) { //20/40Mhz Xtal
++              data |= REGBIT(0xd, 8);
++      }else {
++              data |= REGBIT(0x7, 8);
++      }
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, data);
++
++      if(regValue < 6) { //20/40Mhz Xtal
++              sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
++      }else {
++              sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1697cc39);
++      }
++      //*Common setting - Set PLLGP_CTRL_4 *//
++      ///* 1. Bit 31 */
++        data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++        data &= ~(REGBIT(0x1, 31));
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++      /* 2. Bit 0 */
++      data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++        data |= REGBIT(0x1, 0);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++      /* 3. Bit 3 */
++      data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++        data |= REGBIT(0x1, 3);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++      /* 4. Bit 8 */
++      data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++        data |= REGBIT(0x1, 8);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++      /* 5. Bit 6 */
++        data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++        data |= REGBIT(0x1, 6);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++      /* 6. Bit 7 */
++        data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++        data |= REGBIT(0x1, 5);
++        data |= REGBIT(0x1, 7);
++        sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++
++      /* 7. Bit 17 */
++        data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
++        data &= ~REGBIT(0x1, 17);
++      sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
++        
++      /* 8. TRGMII TX CLK SEL APLL */
++      data = sysRegRead(0xbe00002c);
++      data &= 0xffffff9f;
++      data |= 0x40;
++      sysRegWrite(0xbe00002c, data);
++
++}
++#endif
++
++#endif
++#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
++void rt_gsw_init(void)
++{
++#if defined (CONFIG_P4_MAC_TO_PHY_MODE) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      u32 phy_val=0;
++#endif
++#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
++      u32 i=0;
++#elif defined (CONFIG_MT7620_ASIC)
++      u32 is_BGA=0;
++#endif
++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++        unsigned int regValue = 0;
++#endif
++#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
++    /*keep dump switch mode */
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x5e333;//(P2, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x5e333;//(P3, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++#if defined (CONFIG_RAETH_HAS_PORT4)
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#else
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e333;//(P4, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
++#endif
++    *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++
++    /* In order to use 10M/Full on FPGA board. We configure phy capable to
++     * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
++#if defined (CONFIG_RAETH_HAS_PORT4)
++    for(i=0;i<4;i++){
++#else
++    for(i=0;i<5;i++){
++#endif
++      mii_mgr_write(i, 4, 0x0461);   //Capable of 10M Full/Half Duplex, flow control on/off
++      mii_mgr_write(i, 0, 0xB100);   //reset all digital logic, except phy_reg
++    }
++
++#endif
++
++#if defined (CONFIG_PDMA_NEW)
++    *(unsigned long *)(SYSCFG1) |= (0x1 << 8); //PCIE_RC_MODE=1
++#endif
++
++
++#if defined (CONFIG_MT7620_ASIC) && !defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++    is_BGA = (sysRegRead(RALINK_SYSCTL_BASE + 0xc) >> 16) & 0x1;
++    /*
++    * Reg 31: Page Control
++    * Bit 15     => PortPageSel, 1=local, 0=global
++    * Bit 14:12  => PageSel, local:0~3, global:0~4
++    *
++    * Reg16~30:Local/Global registers
++    *
++    */
++    /*correct  PHY  setting L3.0 BGA*/
++    mii_mgr_write(1, 31, 0x4000); //global, page 4
++  
++    mii_mgr_write(1, 17, 0x7444);
++    if(is_BGA){
++      mii_mgr_write(1, 19, 0x0114);
++    }else{
++      mii_mgr_write(1, 19, 0x0117);
++    }
++
++    mii_mgr_write(1, 22, 0x10cf);
++    mii_mgr_write(1, 25, 0x6212);
++    mii_mgr_write(1, 26, 0x0777);
++    mii_mgr_write(1, 29, 0x4000);
++    mii_mgr_write(1, 28, 0xc077);
++    mii_mgr_write(1, 24, 0x0000);
++    
++    mii_mgr_write(1, 31, 0x3000); //global, page 3
++    mii_mgr_write(1, 17, 0x4838);
++
++    mii_mgr_write(1, 31, 0x2000); //global, page 2
++    if(is_BGA){
++      mii_mgr_write(1, 21, 0x0515);
++      mii_mgr_write(1, 22, 0x0053);
++      mii_mgr_write(1, 23, 0x00bf);
++      mii_mgr_write(1, 24, 0x0aaf);
++      mii_mgr_write(1, 25, 0x0fad);
++      mii_mgr_write(1, 26, 0x0fc1);
++    }else{
++      mii_mgr_write(1, 21, 0x0517);
++      mii_mgr_write(1, 22, 0x0fd2);
++      mii_mgr_write(1, 23, 0x00bf);
++      mii_mgr_write(1, 24, 0x0aab);
++      mii_mgr_write(1, 25, 0x00ae);
++      mii_mgr_write(1, 26, 0x0fff);
++    }
++    mii_mgr_write(1, 31, 0x1000); //global, page 1
++    mii_mgr_write(1, 17, 0xe7f8);
++    
++    mii_mgr_write(1, 31, 0x8000); //local, page 0
++    mii_mgr_write(0, 30, 0xa000);
++    mii_mgr_write(1, 30, 0xa000);
++    mii_mgr_write(2, 30, 0xa000);
++    mii_mgr_write(3, 30, 0xa000);
++#if !defined (CONFIG_RAETH_HAS_PORT4)   
++    mii_mgr_write(4, 30, 0xa000);
++#endif
++
++    mii_mgr_write(0, 4, 0x05e1);
++    mii_mgr_write(1, 4, 0x05e1);
++    mii_mgr_write(2, 4, 0x05e1);
++    mii_mgr_write(3, 4, 0x05e1);
++#if !defined (CONFIG_RAETH_HAS_PORT4)   
++    mii_mgr_write(4, 4, 0x05e1);
++#endif
++
++    mii_mgr_write(1, 31, 0xa000); //local, page 2
++    mii_mgr_write(0, 16, 0x1111);
++    mii_mgr_write(1, 16, 0x1010);
++    mii_mgr_write(2, 16, 0x1515);
++    mii_mgr_write(3, 16, 0x0f0f);
++#if !defined (CONFIG_RAETH_HAS_PORT4)   
++    mii_mgr_write(4, 16, 0x1313);
++#endif
++
++#if !defined (CONFIG_RAETH_8023AZ_EEE)        
++    mii_mgr_write(1, 31, 0xb000); //local, page 3
++    mii_mgr_write(0, 17, 0x0);
++    mii_mgr_write(1, 17, 0x0);
++    mii_mgr_write(2, 17, 0x0);
++    mii_mgr_write(3, 17, 0x0);
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++    mii_mgr_write(4, 17, 0x0);
++#endif
++#endif
++
++
++
++#if 0
++    // for ethernet extended mode
++    mii_mgr_write(1, 31, 0x3000);
++    mii_mgr_write(1, 19, 0x122);
++    mii_mgr_write(1, 20, 0x0044);
++    mii_mgr_write(1, 23, 0xa80c);
++    mii_mgr_write(1, 24, 0x129d);
++    mii_mgr_write(1, 31, 9000);
++    mii_mgr_write(0, 18, 0x140c);
++    mii_mgr_write(1, 18, 0x140c);
++    mii_mgr_write(2, 18, 0x140c);
++    mii_mgr_write(3, 18, 0x140c);
++    mii_mgr_write(0, 0, 0x3300);
++    mii_mgr_write(1, 0, 0x3300);
++    mii_mgr_write(2, 0, 0x3300);
++    mii_mgr_write(3, 0, 0x3300);
++#if !defined (CONFIG_RAETH_HAS_PORT4)
++    mii_mgr_write(4, 18, 0x140c);
++    mii_mgr_write(4, 0, 0x3300);
++#endif
++#endif
++
++#endif
++
++#if defined(CONFIG_RALINK_MT7620)
++      if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
++              *(unsigned long *)(RALINK_ETH_SW_BASE+0x701c) = 0x800000c; //enlarge FE2SW_IPG
++      }
++#endif // CONFIG_RAETH_7620 //
++
++
++
++#if defined (CONFIG_MT7620_FPGA)|| defined (CONFIG_MT7620_ASIC)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0x7f7f7fe0;//Set Port6 CPU Port
++
++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c; //disable port 0 ~ 4 internal phy, set phy base address to 12
++      /*MT7620 need mac learning for PPE*/
++      //*(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
++      //*(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++      //rxclk_skew, txclk_skew = 0
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
++#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
++
++      *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
++
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330;//(P4, AN)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++      //rxclk_skew, txclk_skew = 0
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
++
++
++      /* set MT7530 Port 0 to PHY mode */
++      mii_mgr_read(31, 0x7804 ,&regValue);
++#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
++      regValue &= ~((1<<13)|(1<<6)|(1<<5)|(1<<15));
++      regValue |= ((1<<7)|(1<<16)|(1<<20)|(1<<24));
++      //mii_mgr_write(31, 0x7804 ,0x115c8f);
++#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
++      regValue &= ~((1<<13)|(1<<6)|(1<<20)|(1<<5)|(1<<15));
++      regValue |= ((1<<7)|(1<<16)|(1<<24));
++#endif
++      regValue &= ~(1<<8); //Enable Port 6
++      mii_mgr_write(31, 0x7804 ,regValue); //bit 24 standalone switch
++
++/* set MT7530 central align */
++        mii_mgr_read(31, 0x7830, &regValue);
++        regValue &= ~1;
++        regValue |= 1<<1;
++        mii_mgr_write(31, 0x7830, regValue);
++
++        mii_mgr_read(31, 0x7a40, &regValue);
++        regValue &= ~(1<<30);
++        mii_mgr_write(31, 0x7a40, regValue);
++
++        regValue = 0x855;
++        mii_mgr_write(31, 0x7a78, regValue);
++
++      /*AN should be set after MT7530 HWSTRAP*/
++#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000100;//(P0, AN polling)
++#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000504;//(P4, AN polling)
++#endif
++#endif
++
++#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
++      *(unsigned long *)(SYSCFG1) |= (0x1 << 12);
++
++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++      *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
++      
++      enable_auto_negotiate(1);
++
++      if (isICPlusGigaPHY(1)) {
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
++              phy_val |= 1<<10; //enable pause ability
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++              phy_val |= 1<<9; //restart AN
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++      }else if (isMarvellGigaPHY(1)) {
++#if defined (CONFIG_MT7620_FPGA)
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
++              phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement  (9.9=1000Full, 9.8=1000Half)
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
++#endif
++              printk("Reset MARVELL phy1\n");
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
++              phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++              phy_val |= 1<<15; //PHY Software Reset
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++        }else if (isVtssGigaPHY(1)) {
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
++              printk("Vitesse phy skew: %x --> ", phy_val);
++              phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++              phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++              printk("%x\n", phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
++        }
++
++
++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
++      *(unsigned long *)(SYSCFG1) |= (0x2 << 12);
++
++#else // Port 5 Disabled //
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
++      *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode
++#endif
++#endif
++
++#if defined (CONFIG_P4_RGMII_TO_MAC_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e33b;//(P4, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++      //rxclk_skew, txclk_skew = 0
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
++
++#elif defined (CONFIG_P4_MII_TO_MAC_MODE)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
++      *(unsigned long *)(SYSCFG1) |= (0x1 << 14);
++
++#elif defined (CONFIG_P4_MAC_TO_PHY_MODE)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++      *(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
++
++      enable_auto_negotiate(1);
++ 
++      if (isICPlusGigaPHY(2)) {
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, &phy_val);
++              phy_val |= 1<<10; //enable pause ability
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, phy_val);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
++              phy_val |= 1<<9; //restart AN
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
++      }else if (isMarvellGigaPHY(2)) {
++#if defined (CONFIG_MT7620_FPGA)
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &phy_val);
++              phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement  (9.9=1000Full, 9.8=1000Half)
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, phy_val);
++#endif
++              printk("Reset MARVELL phy2\n");
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &phy_val);
++              phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, phy_val);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
++              phy_val |= 1<<15; //PHY Software Reset
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
++        }else if (isVtssGigaPHY(2)) {
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0001); //extended page
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &phy_val);
++              printk("Vitesse phy skew: %x --> ", phy_val);
++              phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++              phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++              printk("%x\n", phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0000); //main registers
++        }
++
++#elif defined (CONFIG_P4_RMII_TO_MAC_MODE)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE1_MODE=RvMii Mode
++      *(unsigned long *)(SYSCFG1) |= (0x2 << 14);
++#elif defined (CONFIG_GE_RGMII_MT7530_P0_AN) || defined (CONFIG_GE_RGMII_MT7530_P4_AN)
++#else // Port 4 Disabled //
++        *(unsigned long *)(SYSCFG1) |= (0x3 << 14); //GE2_MODE=RJ45 Mode
++      *(unsigned long *)(0xb0000060) |= (1 << 10); //set RGMII2 to GPIO mode
++#endif
++
++}
++#endif
++
++#if defined (CONFIG_RALINK_MT7628)
++
++void mt7628_ephy_init(void)
++{
++      int i;
++      u32 phy_val;
++      mii_mgr_write(0, 31, 0x2000); //change G2 page
++      mii_mgr_write(0, 26, 0x0000);
++
++      for(i=0; i<5; i++){
++              mii_mgr_write(i, 31, 0x8000); //change L0 page
++              mii_mgr_write(i,  0, 0x3100);
++
++#if defined (CONFIG_RAETH_8023AZ_EEE) 
++              mii_mgr_read(i, 26, &phy_val);// EEE setting
++              phy_val |= (1 << 5);
++              mii_mgr_write(i, 26, phy_val);
++#else
++              //disable EEE
++              mii_mgr_write(i, 13, 0x7);
++              mii_mgr_write(i, 14, 0x3C);
++              mii_mgr_write(i, 13, 0x4007);
++              mii_mgr_write(i, 14, 0x0);
++#endif
++              mii_mgr_write(i, 30, 0xa000);
++              mii_mgr_write(i, 31, 0xa000); // change L2 page
++              mii_mgr_write(i, 16, 0x0606);
++              mii_mgr_write(i, 23, 0x0f0e);
++              mii_mgr_write(i, 24, 0x1610);
++              mii_mgr_write(i, 30, 0x1f15);
++              mii_mgr_write(i, 28, 0x6111);
++
++              mii_mgr_read(i, 4, &phy_val);
++              phy_val |= (1 << 10);
++              mii_mgr_write(i, 4, phy_val);
++      }
++
++        //100Base AOI setting
++      mii_mgr_write(0, 31, 0x5000);  //change G5 page
++      mii_mgr_write(0, 19, 0x004a);
++      mii_mgr_write(0, 20, 0x015a);
++      mii_mgr_write(0, 21, 0x00ee);
++      mii_mgr_write(0, 22, 0x0033);
++      mii_mgr_write(0, 23, 0x020a);
++      mii_mgr_write(0, 24, 0x0000);
++      mii_mgr_write(0, 25, 0x024a);
++      mii_mgr_write(0, 26, 0x035a);
++      mii_mgr_write(0, 27, 0x02ee);
++      mii_mgr_write(0, 28, 0x0233);
++      mii_mgr_write(0, 29, 0x000a);
++      mii_mgr_write(0, 30, 0x0000);
++      /* Fix EPHY idle state abnormal behavior */
++      mii_mgr_write(0, 31, 0x4000); //change G4 page
++      mii_mgr_write(0, 29, 0x000d);
++      mii_mgr_write(0, 30, 0x0500);
++
++}
++
++#endif
++
++
++#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++void rt305x_esw_init(void)
++{
++      int i=0;
++      u32 phy_val=0, val=0;
++#if defined (CONFIG_RT3052_ASIC)
++      u32 phy_val2;
++#endif
++
++#if defined (CONFIG_RT5350_ASIC)
++      *(unsigned long *)(RALINK_ETH_SW_BASE+0x0168) = 0x17;
++#endif
++
++      /*
++       * FC_RLS_TH=200, FC_SET_TH=160
++       * DROP_RLS=120, DROP_SET_TH=80
++       */
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0008) = 0xC8A07850;
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00E4) = 0x00000000;
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0014) = 0x00405555;
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0050) = 0x00002001;
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0090) = 0x00007f7f;
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0098) = 0x00007f3f; //disable VLAN
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00CC) = 0x0002500c;
++#ifndef CONFIG_UNH_TEST
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x0008a301; //hashing algorithm=XOR48, aging interval=300sec
++#else
++      /*
++       * bit[30]:1    Backoff Algorithm Option: The latest one to pass UNH test
++       * bit[29]:1    Length of Received Frame Check Enable
++       * bit[8]:0     Enable collision 16 packet abort and late collision abort
++       * bit[7:6]:01  Maximum Packet Length: 1518
++       */
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x6008a241;
++#endif
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x008C) = 0x02404040;
++#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC) || defined (CONFIG_RT5350_ASIC) || defined (CONFIG_MT7628_ASIC)
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x3f502b28; //Change polling Ext PHY Addr=0x1F
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0x00000000;
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x7d000000; //1us cycle number=125 (FE's clock=125Mhz)
++#elif defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA) || defined (CONFIG_RT5350_FPGA) || defined (CONFIG_MT7628_FPGA)
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x00f03ff9; //polling Ext PHY Addr=0x0, force port5 as 100F/D (disable auto-polling)
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0xffdf1f00;
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x0d000000; //1us cycle number=13 (FE's clock=12.5Mhz)
++
++      /* In order to use 10M/Full on FPGA board. We configure phy capable to
++       * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
++        for(i=0;i<5;i++){
++          mii_mgr_write(i, 4, 0x0461);   //Capable of 10M Full/Half Duplex, flow control on/off
++          mii_mgr_write(i, 0, 0xB100);   //reset all digital logic, except phy_reg
++      }
++#endif
++      
++      /*
++       * set port 5 force to 1000M/Full when connecting to switch or iNIC
++       */
++#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3fff; //force 1000M full duplex
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0xf<<20); //rxclk_skew, txclk_skew = 0
++#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff); 
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
++
++#if defined (CONFIG_RALINK_RT3352)
++        *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
++        *(unsigned long *)(SYSCFG1) |= (0x1 << 12);
++#endif
++
++#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++      *(unsigned long *)(0xb0000060) &= ~(1 << 7); //set MDIO to Normal mode
++#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC)
++      enable_auto_negotiate(1);
++#endif
++        if (isMarvellGigaPHY(1)) {
++#if defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA)
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
++              phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement  (9.9=1000Full, 9.8=1000Half)
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
++#endif
++              printk("\n Reset MARVELL phy\n");
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
++              phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
++              phy_val |= 1<<15; //PHY Software Reset
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
++        }
++      if (isVtssGigaPHY(1)) {
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
++              printk("Vitesse phy skew: %x --> ", phy_val);
++              phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
++              phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
++              printk("%x\n", phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
++        }
++       
++#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
++      *(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff); 
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
++        
++#if defined (CONFIG_RALINK_RT3352)
++      *(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
++        *(unsigned long *)(SYSCFG1) |= (0x2 << 12);
++#endif
++#else // Port 5 Disabled //
++
++#if defined (CONFIG_RALINK_RT3052)
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
++        *(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
++        *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO41-GPIO50)
++        *(unsigned long *)(0xb0000674) = 0xFFF; //GPIO41-GPIO50 output mode
++        *(unsigned long *)(0xb000067C) = 0x0; //GPIO41-GPIO50 output low
++#elif defined (CONFIG_RALINK_RT3352)
++        *(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
++      *(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
++        *(unsigned long *)(0xb0000624) = 0xC0000000; //GPIO22-GPIO23 output mode
++        *(unsigned long *)(0xb000062C) = 0xC0000000; //GPIO22-GPIO23 output high
++        
++        *(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO24-GPIO35)
++      *(unsigned long *)(0xb000064C) = 0xFFF; //GPIO24-GPIO35 output mode
++        *(unsigned long *)(0xb0000654) = 0xFFF; //GPIO24-GPIO35 output high
++#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
++      /* do nothing */
++#endif
++#endif // CONFIG_P5_RGMII_TO_MAC_MODE //
++
++
++#if defined (CONFIG_RT3052_ASIC)
++      rw_rf_reg(0, 0, &phy_val);
++        phy_val = phy_val >> 4;
++
++        if(phy_val > 0x5) {
++
++            rw_rf_reg(0, 26, &phy_val);
++            phy_val2 = (phy_val | (0x3 << 5));
++            rw_rf_reg(1, 26, &phy_val2);
++
++                      // reset EPHY
++                      val = sysRegRead(RSTCTRL);
++                      val = val | RALINK_EPHY_RST;
++                      sysRegWrite(RSTCTRL, val);
++                      val = val & ~(RALINK_EPHY_RST);
++                      sysRegWrite(RSTCTRL, val);
++
++            rw_rf_reg(1, 26, &phy_val);
++
++            //select local register
++            mii_mgr_write(0, 31, 0x8000);
++            for(i=0;i<5;i++){
++                mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
++                mii_mgr_write(i, 29, 0x7058);   //TX100/TX10 AD/DA current bias
++                mii_mgr_write(i, 30, 0x0018);   //TX100 slew rate control
++            }
++
++            //select global register
++            mii_mgr_write(0, 31, 0x0);
++            mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++            mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++            mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
++//#define ENABLE_LDPS
++#if defined (ENABLE_LDPS)
++            mii_mgr_write(0, 12, 0x7eaa);
++            mii_mgr_write(0, 22, 0x252f); //tune TP_IDL tail and head waveform, enable power down slew rate control
++#else
++            mii_mgr_write(0, 12, 0x0);
++            mii_mgr_write(0, 22, 0x052f);
++#endif
++            mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
++            mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++            mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++            mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++            mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
++            mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++            mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++          mii_mgr_write(0, 31, 0x8000); //select local register
++
++            for(i=0;i<5;i++){
++                //LSB=1 enable PHY
++                mii_mgr_read(i, 26, &phy_val);
++                phy_val |= 0x0001;
++                mii_mgr_write(i, 26, phy_val);
++            }
++      } else {
++          //select local register
++            mii_mgr_write(0, 31, 0x8000);
++            for(i=0;i<5;i++){
++                mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
++                mii_mgr_write(i, 29, 0x7058);   //TX100/TX10 AD/DA current bias
++                mii_mgr_write(i, 30, 0x0018);   //TX100 slew rate control
++            }
++
++            //select global register
++            mii_mgr_write(0, 31, 0x0);
++            mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++            mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++            mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
++            mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
++            mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++            mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++            mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++            mii_mgr_write(0, 22, 0x052f); //tune TP_IDL tail and head waveform
++            mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
++            mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++          mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++          mii_mgr_write(0, 31, 0x8000); //select local register
++
++            for(i=0;i<5;i++){
++                //LSB=1 enable PHY
++                mii_mgr_read(i, 26, &phy_val);
++                phy_val |= 0x0001;
++                mii_mgr_write(i, 26, phy_val);
++            }
++      }
++#elif defined (CONFIG_RT3352_ASIC)
++      //PHY IOT
++      // reset EPHY
++      val = sysRegRead(RSTCTRL);
++      val = val | RALINK_EPHY_RST;
++      sysRegWrite(RSTCTRL, val);
++      val = val & ~(RALINK_EPHY_RST);
++      sysRegWrite(RSTCTRL, val);
++
++      //select local register
++        mii_mgr_write(0, 31, 0x8000);
++        for(i=0;i<5;i++){
++            mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
++            mii_mgr_write(i, 29, 0x7016);   //TX100/TX10 AD/DA current bias
++            mii_mgr_write(i, 30, 0x0038);   //TX100 slew rate control
++        }
++
++        //select global register
++        mii_mgr_write(0, 31, 0x0);
++        mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++        mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++        mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
++        mii_mgr_write(0, 12, 0x7eaa);
++        mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
++        mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++        mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++        mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++        mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
++        mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
++        mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++        mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++        mii_mgr_write(0, 31, 0x8000); //select local register
++
++        for(i=0;i<5;i++){
++            //LSB=1 enable PHY
++            mii_mgr_read(i, 26, &phy_val);
++            phy_val |= 0x0001;
++            mii_mgr_write(i, 26, phy_val);
++        }
++
++#elif defined (CONFIG_RT5350_ASIC)
++      //PHY IOT
++      // reset EPHY
++      val = sysRegRead(RSTCTRL);
++      val = val | RALINK_EPHY_RST;
++      sysRegWrite(RSTCTRL, val);
++      val = val & ~(RALINK_EPHY_RST);
++      sysRegWrite(RSTCTRL, val);
++
++      //select local register
++        mii_mgr_write(0, 31, 0x8000);
++        for(i=0;i<5;i++){
++            mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
++            mii_mgr_write(i, 29, 0x7015);   //TX100/TX10 AD/DA current bias
++            mii_mgr_write(i, 30, 0x0038);   //TX100 slew rate control
++        }
++
++        //select global register
++        mii_mgr_write(0, 31, 0x0);
++        mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
++        mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
++        mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
++        mii_mgr_write(0, 12, 0x7eaa);
++        mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
++        mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
++        mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
++        mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
++        mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
++        mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
++        mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
++        mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
++        mii_mgr_write(0, 31, 0x8000); //select local register
++
++        for(i=0;i<5;i++){
++            //LSB=1 enable PHY
++            mii_mgr_read(i, 26, &phy_val);
++            phy_val |= 0x0001;
++            mii_mgr_write(i, 26, phy_val);
++        }
++#elif defined (CONFIG_MT7628_ASIC)
++/*INIT MT7628 PHY HERE*/
++      val = sysRegRead(RT2880_AGPIOCFG_REG);
++#if defined (CONFIG_ETH_ONE_PORT_ONLY)
++      val |= (MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
++      val = val & ~(MT7628_P0_EPHY_AIO_EN);
++#else
++      val = val & ~(MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
++#endif
++      if ((*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x8))) & 0x10000)
++              val &= ~0x1f0000;
++      sysRegWrite(RT2880_AGPIOCFG_REG, val);
++
++      val = sysRegRead(RSTCTRL);
++      val = val | RALINK_EPHY_RST;
++      sysRegWrite(RSTCTRL, val);
++      val = val & ~(RALINK_EPHY_RST);
++      sysRegWrite(RSTCTRL, val);
++
++
++      val = sysRegRead(RALINK_SYSCTL_BASE + 0x64);
++#if defined (CONFIG_ETH_ONE_PORT_ONLY)
++      val &= 0xf003f003;
++      val |= 0x05540554;
++      sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0 EPHY LED mode
++#else
++      val &= 0xf003f003;
++      sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0~P4 EPHY LED mode
++#endif
++
++      udelay(5000);
++      mt7628_ephy_init();
++
++#endif
++}
++#endif
++
++#if defined (CONFIG_ARCH_MT7623)      /* TODO: just for bring up, should be removed!!! */
++void mt7623_pinmux_set(void)
++{
++      unsigned long regValue;
++      
++      //printk("[mt7623_pinmux_set]start\n");
++      /* Pin277: ESW_RST (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0));
++      regValue &= ~(BITS(6,8));
++      regValue |= BIT(6);
++      *(volatile u_long *)(0xf0005ad0) = regValue;
++
++      /* Pin262: G2_TXEN (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0));
++      regValue &= ~(BITS(6,8));
++      regValue |= BIT(6);
++      *(volatile u_long *)(0xf0005aa0) = regValue;
++      /* Pin263: G2_TXD3 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0));
++      regValue &= ~(BITS(9,11));
++      regValue |= BIT(9);
++      *(volatile u_long *)(0xf0005aa0) = regValue;
++      /* Pin264: G2_TXD2 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005aa0));
++      regValue &= ~(BITS(12,14));
++      regValue |= BIT(12);
++      *(volatile u_long *)(0xf0005aa0) = regValue;
++      /* Pin265: G2_TXD1 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++      regValue &= ~(BITS(0,2));
++      regValue |= BIT(0);
++      *(volatile u_long *)(0xf0005ab0) = regValue;
++      /* Pin266: G2_TXD0 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++      regValue &= ~(BITS(3,5));
++      regValue |= BIT(3);
++      *(volatile u_long *)(0xf0005ab0) = regValue;
++      /* Pin267: G2_TXC (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++      regValue &= ~(BITS(6,8));
++      regValue |= BIT(6);
++      *(volatile u_long *)(0xf0005ab0) = regValue;
++      /* Pin268: G2_RXC (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++      regValue &= ~(BITS(9,11));
++      regValue |= BIT(9);
++      *(volatile u_long *)(0xf0005ab0) = regValue;
++      /* Pin269: G2_RXD0 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ab0));
++      regValue &= ~(BITS(12,14));
++      regValue |= BIT(12);
++      *(volatile u_long *)(0xf0005ab0) = regValue;
++      /* Pin270: G2_RXD1 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++      regValue &= ~(BITS(0,2));
++      regValue |= BIT(0);
++      *(volatile u_long *)(0xf0005ac0) = regValue;
++      /* Pin271: G2_RXD2 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++      regValue &= ~(BITS(3,5));
++      regValue |= BIT(3);
++      *(volatile u_long *)(0xf0005ac0) = regValue;
++      /* Pin272: G2_RXD3 (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++      regValue &= ~(BITS(6,8));
++      regValue |= BIT(6);
++      *(volatile u_long *)(0xf0005ac0) = regValue;
++      /* Pin274: G2_RXDV (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ac0));
++      regValue &= ~(BITS(12,14));
++      regValue |= BIT(12);
++      *(volatile u_long *)(0xf0005ac0) = regValue;
++
++      /* Pin275: MDC (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0));
++      regValue &= ~(BITS(0,2));
++      regValue |= BIT(0);
++      *(volatile u_long *)(0xf0005ad0) = regValue;
++      /* Pin276: MDIO (1) */
++      regValue = le32_to_cpu(*(volatile u_long *)(0xf0005ad0));
++      regValue &= ~(BITS(3,5));
++      regValue |= BIT(3);
++      *(volatile u_long *)(0xf0005ad0) = regValue;
++      //printk("[mt7623_pinmux_set]end\n");
++}
++
++void wait_loop(void) {
++      int i,j;
++      int read_data;
++      j =0;
++      while (j< 10) {
++              for(i = 0; i<32; i = i+1){
++                      read_data = *(volatile u_long *)(0xFB110610);
++              }
++              j++;
++      }
++}
++
++void trgmii_calibration_7623(void) {
++
++      unsigned int  tap_a[5]; // minumum delay for all correct
++      unsigned int  tap_b[5]; // maximum delay for all correct
++      unsigned int  final_tap[5];
++      unsigned int  bslip_en;
++      unsigned int  rxc_step_size;
++      unsigned int  rxd_step_size;
++      unsigned int  read_data;
++      unsigned int  tmp;
++      unsigned int  rd_wd;
++      int  i;
++      unsigned int err_cnt[5];
++      unsigned int init_toggle_data;
++      unsigned int err_flag[5];
++      unsigned int err_total_flag;
++      unsigned int training_word;
++      unsigned int rd_tap;
++
++      u32  TRGMII_7623_base;
++      u32  TRGMII_7623_RD_0;
++      u32  TRGMII_RD_1;
++      u32  TRGMII_RD_2;
++      u32  TRGMII_RD_3;
++      u32  TRGMII_RXCTL;
++      u32  TRGMII_RCK_CTRL;
++      u32 TRGMII_7530_base;
++      TRGMII_7623_base = 0xFB110300;
++      TRGMII_7623_RD_0 = TRGMII_7623_base + 0x10;
++      TRGMII_RCK_CTRL = TRGMII_7623_base;
++      rxd_step_size =0x1;
++      rxc_step_size =0x4;
++      init_toggle_data = 0x00000055;
++      training_word    = 0x000000AC;
++
++      //printk("Calibration begin ........");
++      *(volatile u_long *)(TRGMII_7623_base +0x04) &= 0x3fffffff;   // RX clock gating in MT7623
++      *(volatile u_long *)(TRGMII_7623_base +0x00) |= 0x80000000;   // Assert RX  reset in MT7623
++      *(volatile u_long *)(TRGMII_7623_base +0x78) |= 0x00002000;   // Set TX OE edge in  MT7623
++      *(volatile u_long *)(TRGMII_7623_base +0x04) |= 0xC0000000;   // Disable RX clock gating in MT7623
++      *(volatile u_long *)(TRGMII_7623_base )      &= 0x7fffffff;   // Release RX reset in MT7623
++      //printk("Check Point 1 .....\n");
++      for (i = 0 ; i<5 ; i++) {
++              *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) |= 0x80000000;   // Set bslip_en = 1
++      }
++
++      //printk("Enable Training Mode in MT7530\n");
++      mii_mgr_read(0x1F,0x7A40,&read_data);
++      read_data |= 0xc0000000;
++      mii_mgr_write(0x1F,0x7A40,read_data);  //Enable Training Mode in MT7530
++      err_total_flag = 0;
++      //printk("Adjust RXC delay in MT7623\n");
++      read_data =0x0;
++      while (err_total_flag == 0 && read_data != 0x68) {
++              //printk("2nd Enable EDGE CHK in MT7623\n");
++              /* Enable EDGE CHK in MT7623*/
++              for (i = 0 ; i<5 ; i++) {
++                      tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++                      tmp |= 0x40000000;
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++              }
++              wait_loop();
++              err_total_flag = 1;
++              for  (i = 0 ; i<5 ; i++) {
++                      err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8)  & 0x0000000f;
++                      rd_wd = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 16)  & 0x000000ff;
++                      //printk("ERR_CNT = %d, RD_WD =%x\n",err_cnt[i],rd_wd);
++                      if ( err_cnt[i] !=0 ) {
++                              err_flag[i] = 1;
++                      }
++                      else if (rd_wd != 0x55) {
++                              err_flag[i] = 1;
++                      }       
++                      else {
++                              err_flag[i] = 0;
++                      }
++                      err_total_flag = err_flag[i] &  err_total_flag;
++              }
++
++              //printk("2nd Disable EDGE CHK in MT7623\n");
++              /* Disable EDGE CHK in MT7623*/
++              for (i = 0 ; i<5 ; i++) {
++                      tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++                      tmp |= 0x40000000;
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++              }
++              wait_loop();
++              //printk("2nd Disable EDGE CHK in MT7623\n");
++              /* Adjust RXC delay */
++              *(volatile u_long *)(TRGMII_7623_base +0x00) |= 0x80000000;   // Assert RX  reset in MT7623
++              *(volatile u_long *)(TRGMII_7623_base +0x04) &= 0x3fffffff;   // RX clock gating in MT7623
++              read_data = *(volatile u_long *)(TRGMII_7623_base);
++              if (err_total_flag == 0) {
++                tmp = (read_data & 0x0000007f) + rxc_step_size;
++                //printk(" RXC delay = %d\n", tmp);
++                read_data >>= 8;
++                read_data &= 0xffffff80;
++                read_data |= tmp;
++                read_data <<=8;
++                read_data &= 0xffffff80;
++                read_data |=tmp;
++                *(volatile u_long *)(TRGMII_7623_base)  =   read_data;
++              }
++                read_data &=0x000000ff;
++                *(volatile u_long *)(TRGMII_7623_base )      &= 0x7fffffff;   // Release RX reset in MT7623
++                *(volatile u_long *)(TRGMII_7623_base +0x04) |= 0xC0000000;   // Disable RX clock gating in MT7623
++                for (i = 0 ; i<5 ; i++) {
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) =  (*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) | 0x80000000;  // Set bslip_en = ~bit_slip_en
++                }
++      }
++      //printk("Finish RXC Adjustment while loop\n");
++      //printk("Read RD_WD MT7623\n");
++      /* Read RD_WD MT7623*/
++      for  (i = 0 ; i<5 ; i++) {
++              rd_tap=0;
++              while (err_flag[i] != 0) {
++                      /* Enable EDGE CHK in MT7623*/
++                      tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++                      tmp |= 0x40000000;
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++                      wait_loop();
++                      read_data = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++                      err_cnt[i] = (read_data >> 8)  & 0x0000000f;     // Read MT7623 Errcnt
++                      rd_wd = (read_data >> 16)  & 0x000000ff;
++                      if (err_cnt[i] != 0 || rd_wd !=0x55){
++                         err_flag [i] =  1;
++                      }   
++                      else {
++                         err_flag[i] =0;
++                      }       
++                      /* Disable EDGE CHK in MT7623*/
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) &= 0x4fffffff;
++                      tmp |= 0x40000000;
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++                      wait_loop();
++                      //err_cnt[i] = ((read_data) >> 8)  & 0x0000000f;     // Read MT7623 Errcnt
++                      if (err_flag[i] !=0) {
++                          rd_tap    = (read_data & 0x0000007f) + rxd_step_size;                     // Add RXD delay in MT7623
++                          read_data = (read_data & 0xffffff80) | rd_tap;
++                          *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++                          tap_a[i] = rd_tap;
++                      } else {
++                            rd_tap    = (read_data & 0x0000007f) + 4;
++                          read_data = (read_data & 0xffffff80) | rd_tap;
++                          *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++                      }       
++                      //err_cnt[i] = (*(volatile u_long *)(TRGMII_7623_RD_0 + i*8) >> 8)  & 0x0000000f;     // Read MT7623 Errcnt
++
++              }
++              //printk("%dth bit  Tap_a = %d\n", i, tap_a[i]);
++      }
++      //printk("Last While Loop\n");
++      for  (i = 0 ; i<5 ; i++) {
++              //printk(" Bit%d\n", i);
++              rd_tap =0;
++              while ((err_cnt[i] == 0) && (rd_tap !=128)) {
++                      read_data = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++                      rd_tap    = (read_data & 0x0000007f) + rxd_step_size;                     // Add RXD delay in MT7623
++                      read_data = (read_data & 0xffffff80) | rd_tap;
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++                      /* Enable EDGE CHK in MT7623*/
++                      tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++                      tmp |= 0x40000000;
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++                      wait_loop();
++                      err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8)  & 0x0000000f;     // Read MT7623 Errcnt
++                      /* Disable EDGE CHK in MT7623*/
++                      tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++                      tmp |= 0x40000000;
++                      *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++                      wait_loop();
++                      //err_cnt[i] = ((*(volatile u_long *)(TRGMII_7623_RD_0 + i*8)) >> 8)  & 0x0000000f;     // Read MT7623 Errcnt
++
++              }
++              tap_b[i] =   rd_tap;// -rxd_step_size;                                        // Record the max delay TAP_B
++              //printk("tap_b[%d] is %d \n", i,tap_b[i]);
++              final_tap[i] = (tap_a[i]+tap_b[i])/2;                                              //  Calculate RXD delay = (TAP_A + TAP_B)/2
++              //printk("%dth bit Final Tap = %d\n", i, final_tap[i]);
++              read_data = (read_data & 0xffffff80) | final_tap[i];
++              *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = read_data;
++      }
++//    /*word alignment*/
++//    mii_mgr_read(0x1F,0x7A50,&read_data);
++//    read_data &= ~(0xff);
++//    read_data |= 0xac;
++//    mii_mgr_write(0x1F,0x7A50,read_data);
++//    while (i <10) {
++//            i++;
++//            wait_loop();
++//    }
++//    /* Enable EDGE CHK in MT7623*/
++//    for (i=0; i<5; i++) {
++//            tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++//            tmp |= 0x40000000;
++//            *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++//            wait_loop();
++//            /* Disable EDGE CHK in MT7623*/
++//            tmp = *(volatile u_long *)(TRGMII_7623_RD_0 + i*8);
++//            tmp |= 0x40000000;
++//            *(volatile u_long *)(TRGMII_7623_RD_0 + i*8) = tmp & 0x4fffffff;
++//            wait_loop();
++//            read_data = *(volatile u_long *)(TRGMII_7623_RD_0+i*8);
++//            printk(" MT7623 training word = %x\n", read_data);
++//    }
++
++
++      mii_mgr_read(0x1F,0x7A40,&read_data);
++      //printk(" MT7530 0x7A40 = %x\n", read_data);
++      read_data &=0x3fffffff;
++      mii_mgr_write(0x1F,0x7A40,read_data);
++}
++
++
++void trgmii_calibration_7530(void){ 
++
++      unsigned int  tap_a[5];
++      unsigned int  tap_b[5];
++      unsigned int  final_tap[5];
++      unsigned int  bslip_en;
++      unsigned int  rxc_step_size;
++      unsigned int  rxd_step_size;
++      unsigned int  read_data;
++      unsigned int  tmp;
++      int  i,j;
++      unsigned int err_cnt[5];
++      unsigned int rd_wd;
++      unsigned int init_toggle_data;
++      unsigned int err_flag[5];
++      unsigned int err_total_flag;
++      unsigned int training_word;
++      unsigned int rd_tap;
++
++      u32  TRGMII_7623_base;
++      u32  TRGMII_7530_RD_0;
++      u32  TRGMII_RD_1;
++      u32  TRGMII_RD_2;
++      u32  TRGMII_RD_3;
++      u32  TRGMII_RXCTL;
++      u32  TRGMII_RCK_CTRL;
++      u32 TRGMII_7530_base;
++      u32 TRGMII_7530_TX_base;
++      TRGMII_7623_base = 0xFB110300;
++      TRGMII_7530_base = 0x7A00;
++      TRGMII_7530_RD_0 = TRGMII_7530_base + 0x10;
++      TRGMII_RCK_CTRL = TRGMII_7623_base;
++      rxd_step_size = 0x1;
++      rxc_step_size = 0x8;
++      init_toggle_data = 0x00000055;
++      training_word = 0x000000AC;
++
++      TRGMII_7530_TX_base = TRGMII_7530_base + 0x50;
++
++      //printk("Calibration begin ........\n");
++      *(volatile u_long *)(TRGMII_7623_base + 0x40) |= 0x80000000;
++      mii_mgr_read(0x1F, 0x7a10, &read_data);
++      //printk("TRGMII_7530_RD_0 is %x\n", read_data);
++
++      mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++      read_data &= 0x3fffffff;
++      mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data);     // RX clock gating in MT7530
++
++      mii_mgr_read(0x1F,TRGMII_7530_base+0x78,&read_data);
++      read_data |= 0x00002000;
++      mii_mgr_write(0x1F,TRGMII_7530_base+0x78,read_data);     // Set TX OE edge in  MT7530
++
++      mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++      read_data |= 0x80000000;
++      mii_mgr_write(0x1F,TRGMII_7530_base,read_data);          // Assert RX  reset in MT7530
++
++
++      mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++      read_data &= 0x7fffffff;
++      mii_mgr_write(0x1F,TRGMII_7530_base,read_data);          // Release RX reset in MT7530
++
++      mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++      read_data |= 0xC0000000;
++      mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data);     // Disable RX clock gating in MT7530
++
++      //printk("Enable Training Mode in MT7623\n");
++      /*Enable Training Mode in MT7623*/
++      *(volatile u_long *)(TRGMII_7623_base + 0x40) &= 0xbfffffff;
++      *(volatile u_long *)(TRGMII_7623_base + 0x40) |= 0x80000000;
++      *(volatile u_long *)(TRGMII_7623_base + 0x78) &= 0xfffff0ff;
++      *(volatile u_long *)(TRGMII_7623_base + 0x78) |= 0x00000400;
++
++      err_total_flag =0;
++      //printk("Adjust RXC delay in MT7530\n");
++      read_data =0x0;
++      while (err_total_flag == 0 && (read_data != 0x68)) {
++              //printk("2nd Enable EDGE CHK in MT7530\n");
++              /* Enable EDGE CHK in MT7530*/
++              for (i = 0 ; i<5 ; i++) {
++                      mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++                      read_data |= 0x40000000;
++                      read_data &= 0x4fffffff;
++                      mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                      wait_loop();
++                      //printk("2nd Disable EDGE CHK in MT7530\n");
++                      mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&err_cnt[i]);
++                      //printk("***** MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]);
++                      //printk("MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]);
++                      err_cnt[i] >>= 8;
++                      err_cnt[i] &= 0x0000ff0f;
++                      rd_wd  = err_cnt[i] >> 8;
++                      rd_wd &= 0x000000ff;    
++                      err_cnt[i] &= 0x0000000f;
++                      //mii_mgr_read(0x1F,0x7a10,&read_data);
++                      if ( err_cnt[i] !=0 ) {
++                              err_flag[i] = 1;
++                      }
++                      else if (rd_wd != 0x55) {
++                                err_flag[i] = 1;
++                      } else {        
++                              err_flag[i] = 0;
++                      }
++                      if (i==0) {
++                         err_total_flag = err_flag[i];
++                      } else {
++                         err_total_flag = err_flag[i] & err_total_flag;
++                      }       
++              /* Disable EDGE CHK in MT7530*/
++                      mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++                      read_data |= 0x40000000;
++                      read_data &= 0x4fffffff;
++                      mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                        wait_loop();
++              }
++              /*Adjust RXC delay*/
++              if (err_total_flag ==0) {
++                 mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++                 read_data |= 0x80000000;
++                 mii_mgr_write(0x1F,TRGMII_7530_base,read_data);          // Assert RX  reset in MT7530
++
++                 mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++                 read_data &= 0x3fffffff;
++                 mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data);       // RX clock gating in MT7530
++
++                 mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++                 tmp = read_data;
++                 tmp &= 0x0000007f;
++                 tmp += rxc_step_size;
++                 //printk("Current rxc delay = %d\n", tmp);
++                 read_data &= 0xffffff80;
++                 read_data |= tmp;
++                 mii_mgr_write (0x1F,TRGMII_7530_base,read_data);
++                 mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++                 //printk("Current RXC delay = %x\n", read_data); 
++
++                 mii_mgr_read(0x1F,TRGMII_7530_base,&read_data);
++                 read_data &= 0x7fffffff;
++                 mii_mgr_write(0x1F,TRGMII_7530_base,read_data);          // Release RX reset in MT7530
++
++                 mii_mgr_read(0x1F,TRGMII_7530_base+0x04,&read_data);
++                 read_data |= 0xc0000000;
++                 mii_mgr_write(0x1F,TRGMII_7530_base+0x04,read_data);       // Disable RX clock gating in MT7530
++                }
++              read_data = tmp;
++      }
++      //printk("RXC delay is %d\n", tmp);
++      //printk("Finish RXC Adjustment while loop\n");
++
++      //printk("Read RD_WD MT7530\n");
++      /* Read RD_WD MT7530*/
++      for  (i = 0 ; i<5 ; i++) {
++              rd_tap = 0;
++              while (err_flag[i] != 0) {
++                      /* Enable EDGE CHK in MT7530*/
++                      mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++                      read_data |= 0x40000000;
++                      read_data &= 0x4fffffff;
++                      mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                      wait_loop();
++                      err_cnt[i] = (read_data >> 8) & 0x0000000f; 
++                      rd_wd = (read_data >> 16) & 0x000000ff;
++                      //printk("##### %dth bit  ERR_CNT = %x RD_WD =%x ######\n", i, err_cnt[i],rd_wd);
++                      if (err_cnt[i] != 0 || rd_wd !=0x55){
++                         err_flag [i] =  1;
++                      }   
++                      else {
++                         err_flag[i] =0;
++                      }       
++                      if (err_flag[i] !=0 ) { 
++                         rd_tap = (read_data & 0x0000007f) + rxd_step_size;                        // Add RXD delay in MT7530
++                         read_data = (read_data & 0xffffff80) | rd_tap;
++                         mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                         tap_a[i] = rd_tap;
++                      } else {
++                         tap_a[i] = (read_data & 0x0000007f);                                     // Record the min delay TAP_A
++                         rd_tap   =  tap_a[i] + 0x4;                     
++                         read_data = (read_data & 0xffffff80) | rd_tap  ;
++                         mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                      }       
++
++                      /* Disable EDGE CHK in MT7530*/
++                      mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++                      read_data |= 0x40000000;
++                      read_data &= 0x4fffffff;
++                      mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                      wait_loop();
++
++              }
++              //printk("%dth bit  Tap_a = %d\n", i, tap_a[i]);
++      }
++      //printk("Last While Loop\n");
++      for  (i = 0 ; i<5 ; i++) {
++      rd_tap =0;
++              while (err_cnt[i] == 0 && (rd_tap!=128)) {
++                      /* Enable EDGE CHK in MT7530*/
++                      mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++                      read_data |= 0x40000000;
++                      read_data &= 0x4fffffff;
++                      mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                      wait_loop();
++                      err_cnt[i] = (read_data >> 8) & 0x0000000f;
++                      //rd_tap = (read_data & 0x0000007f) + 0x4;                                    // Add RXD delay in MT7530
++                      if (err_cnt[i] == 0 && (rd_tap!=128)) {
++                          rd_tap = (read_data & 0x0000007f) + rxd_step_size;                        // Add RXD delay in MT7530
++                          read_data = (read_data & 0xffffff80) | rd_tap;
++                          mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                      }    
++                      /* Disable EDGE CHK in MT7530*/
++                      mii_mgr_read(0x1F,TRGMII_7530_RD_0+i*8,&read_data);
++                      read_data |= 0x40000000;
++                      read_data &= 0x4fffffff;
++                      mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++                      wait_loop();
++              }
++              tap_b[i] = rd_tap;// - rxd_step_size;                                     // Record the max delay TAP_B
++              //printk("%dth bit  Tap_b = %d, ERR_CNT=%d\n", i, tap_b[i],err_cnt[i]);
++              final_tap[i] = (tap_a[i]+tap_b[i])/2;                                     //  Calculate RXD delay = (TAP_A + TAP_B)/2
++              //printk("%dth bit Final Tap = %d\n", i, final_tap[i]);
++
++              read_data = ( read_data & 0xffffff80) | final_tap[i];
++              mii_mgr_write(0x1F,TRGMII_7530_RD_0+i*8,read_data);
++      }
++              *(volatile u_long *)(TRGMII_7623_base + 0x40) &=0x3fffffff;
++      
++}
++
++void set_trgmii_325_delay_setting(void)
++{
++      /*mt7530 side*/                               
++      *(volatile u_long *)(0xfb110300) = 0x80020050;
++      *(volatile u_long *)(0xfb110304) = 0x00980000;
++      *(volatile u_long *)(0xfb110300) = 0x40020050;
++      *(volatile u_long *)(0xfb110304) = 0xc0980000;
++      *(volatile u_long *)(0xfb110310) = 0x00000028;
++      *(volatile u_long *)(0xfb110318) = 0x0000002e;
++      *(volatile u_long *)(0xfb110320) = 0x0000002d;
++      *(volatile u_long *)(0xfb110328) = 0x0000002b;
++      *(volatile u_long *)(0xfb110330) = 0x0000002a;
++      *(volatile u_long *)(0xfb110340) = 0x00020000;
++      /*mt7530 side*/                               
++      mii_mgr_write(31, 0x7a00, 0x10);              
++      mii_mgr_write(31, 0x7a10, 0x23);              
++      mii_mgr_write(31, 0x7a18, 0x27);              
++      mii_mgr_write(31, 0x7a20, 0x24);              
++      mii_mgr_write(31, 0x7a28, 0x29);              
++      mii_mgr_write(31, 0x7a30, 0x24);              
++
++}
++
++
++void setup_internal_gsw(void)
++{
++      u32     i;
++      u32     regValue;
++      u32     xtal_mode;
++
++      mt7623_pinmux_set();    /* TODO: just for bring up, should be removed!!! */
++
++#if 0
++      /* GE1: RGMII mode setting */   
++      *(volatile u_long *)(0xfb110300) = 0x80020000;
++      *(volatile u_long *)(0xfb110304) = 0x00980000;
++      *(volatile u_long *)(0xfb110300) = 0x40020000;
++      *(volatile u_long *)(0xfb110304) = 0xc0980000;
++      *(volatile u_long *)(0xfb110310) = 0x00000041;
++      *(volatile u_long *)(0xfb110318) = 0x00000044;
++      *(volatile u_long *)(0xfb110320) = 0x00000043;
++      *(volatile u_long *)(0xfb110328) = 0x00000042;
++      *(volatile u_long *)(0xfb110330) = 0x00000042;
++      *(volatile u_long *)(0xfb110340) = 0x00020000;
++      *(volatile u_long *)(0xfb110390) &= 0xfffffff8; //RGMII mode
++#else
++      /* GE1: TRGMII mode setting */  
++      *(volatile u_long *)(0xfb110390) |= 0x00000002; //TRGMII mode
++#endif
++
++      /*Todo: Hardware reset Switch*/
++      /*Hardware reset Switch*/
++#if defined(CONFIG_ARCH_MT7623)
++      regValue = *(volatile u_long *)(0xfb00000c);
++      /*MT7530 Reset. Flows for MT7623 and MT7683 are both excuted.*/
++      /* Should Modify this section if EFUSE is ready*/
++      /*For MT7683 reset MT7530*/
++      if(!(regValue & (1<<16)))
++      {
++              *(volatile u_long *)(0xf0005520) &= ~(1<<1);
++              udelay(1000);
++              *(volatile u_long *)(0xf0005520) |= (1<<1);
++              mdelay(100);
++      }
++      //printk("Assert MT7623 RXC reset\n");
++      *(volatile u_long *)(0xfb110300) |= 0x80000000;   // Assert MT7623 RXC reset
++        /*For MT7623 reset MT7530*/
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2);
++      udelay(1000);
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2);
++      mdelay(100);
++#endif
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++      for(i=0;i<=4;i++)
++        {
++              //turn off PHY
++               mii_mgr_read(i, 0x0 ,&regValue);
++             regValue |= (0x1<<11);
++             mii_mgr_write(i, 0x0, regValue); 
++      }
++        mii_mgr_write(31, 0x7000, 0x3); //reset switch
++        udelay(100);
++
++#if defined (CONFIG_MT7621_ASIC) || defined (CONFIG_ARCH_MT7623)
++#if 0
++      if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) {
++              sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e30b);//(GE1, Force 1000M/FD, FC ON)
++              mii_mgr_write(31, 0x3600, 0x5e30b);
++      } else 
++#endif
++      {
++              sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2105e33b);//(GE1, Force 1000M/FD, FC ON)
++              mii_mgr_write(31, 0x3600, 0x5e33b);
++              mii_mgr_read(31, 0x3600 ,&regValue);
++      }
++#endif
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
++#endif
++
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200) || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++      //regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
++      mii_mgr_read(31, 0x7804 ,&regValue);
++      regValue &= ~(1<<8); //Enable Port 6
++      regValue |= (1<<6); //Disable Port 5
++      regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
++
++#if defined (CONFIG_RAETH_GMAC2)
++      //RGMII2=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++
++      //GMAC2= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++      mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(GE2, auto-polling)
++      enable_auto_negotiate(0);//set polling address
++      
++      /* set MT7530 Port 5 to PHY 0/4 mode */
++#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
++      regValue &= ~((1<<13)|(1<<6));
++      regValue |= ((1<<7)|(1<<16)|(1<<20));
++#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
++      regValue &= ~((1<<13)|(1<<6)|(1<<20));
++      regValue |= ((1<<7)|(1<<16));
++#endif
++      /*Set MT7530 phy direct access mode**/
++      regValue &= ~(1<<5);
++
++      //sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
++#endif
++      regValue |= (1<<16);//change HW-TRAP
++      printk("change HW-TRAP to 0x%x\n",regValue);
++      mii_mgr_write(31, 0x7804 ,regValue);
++#endif
++      mii_mgr_read(31, 0x7800, &regValue);
++      regValue = (regValue >> 9) & 0x3;
++      if(regValue == 0x3)//25Mhz Xtal
++              xtal_mode = 1;
++      else if(regValue == 0x2) //40Mhz
++              xtal_mode = 2;
++      else
++              xtal_mode = 3;
++
++      if(xtal_mode == 1) { //25Mhz Xtal
++              /* do nothing */
++      } else if(xtal_mode = 2) { //40Mhz
++              mii_mgr_write(0, 13, 0x1f);  // disable MT7530 core clock
++              mii_mgr_write(0, 14, 0x410);
++              mii_mgr_write(0, 13, 0x401f);
++              mii_mgr_write(0, 14, 0x0);
++
++              mii_mgr_write(0, 13, 0x1f);  // disable MT7530 PLL
++              mii_mgr_write(0, 14, 0x40d);
++              mii_mgr_write(0, 13, 0x401f);
++              mii_mgr_write(0, 14, 0x2020);
++
++              mii_mgr_write(0, 13, 0x1f);  // for MT7530 core clock = 500Mhz
++              mii_mgr_write(0, 14, 0x40e);
++              mii_mgr_write(0, 13, 0x401f);
++              mii_mgr_write(0, 14, 0x119);
++
++              mii_mgr_write(0, 13, 0x1f);  // enable MT7530 PLL
++              mii_mgr_write(0, 14, 0x40d);
++              mii_mgr_write(0, 13, 0x401f);
++              mii_mgr_write(0, 14, 0x2820);
++
++              udelay(20); //suggest by CD
++
++              mii_mgr_write(0, 13, 0x1f);  // enable MT7530 core clock
++              mii_mgr_write(0, 14, 0x410);
++              mii_mgr_write(0, 13, 0x401f);
++      }else {//20MHz
++              /*TODO*/
++      }
++
++#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
++      mii_mgr_write(0, 14, 0x3); /*TRGMII*/
++#else
++      mii_mgr_write(0, 14, 0x1);  /*RGMII*/
++/* set MT7530 central align */
++        mii_mgr_read(31, 0x7830, &regValue);
++        regValue &= ~1;
++        regValue |= 1<<1;
++        mii_mgr_write(31, 0x7830, regValue);
++
++        mii_mgr_read(31, 0x7a40, &regValue);
++        regValue &= ~(1<<30);
++        mii_mgr_write(31, 0x7a40, regValue);
++
++        regValue = 0x855;
++        mii_mgr_write(31, 0x7a78, regValue);
++
++#endif
++      mii_mgr_write(31, 0x7b00, 0x104);  //delay setting for 10/1000M
++      mii_mgr_write(31, 0x7b04, 0x10);  //delay setting for 10/1000M
++
++      /*Tx Driving*/
++      mii_mgr_write(31, 0x7a54, 0x88);  //lower GE1 driving
++      mii_mgr_write(31, 0x7a5c, 0x88);  //lower GE1 driving
++      mii_mgr_write(31, 0x7a64, 0x88);  //lower GE1 driving
++      mii_mgr_write(31, 0x7a6c, 0x88);  //lower GE1 driving
++      mii_mgr_write(31, 0x7a74, 0x88);  //lower GE1 driving
++      mii_mgr_write(31, 0x7a7c, 0x88);  //lower GE1 driving
++      mii_mgr_write(31, 0x7810, 0x11);  //lower GE2 driving
++      /*Set MT7623/MT7683 TX Driving*/
++      *(volatile u_long *)(0xfb110354) = 0x88;
++      *(volatile u_long *)(0xfb11035c) = 0x88;
++      *(volatile u_long *)(0xfb110364) = 0x88;
++      *(volatile u_long *)(0xfb11036c) = 0x88;
++      *(volatile u_long *)(0xfb110374) = 0x88;
++      *(volatile u_long *)(0xfb11037c) = 0x88;
++#if defined (CONFIG_GE2_RGMII_AN)     
++      *(volatile u_long *)(0xf0005f00) = 0xe00; //Set GE2 driving and slew rate
++#else
++      *(volatile u_long *)(0xf0005f00) = 0xa00; //Set GE2 driving and slew rate
++#endif
++      *(volatile u_long *)(0xf00054c0) = 0x5;   //set GE2 TDSEL
++      *(volatile u_long *)(0xf0005ed0) = 0;     //set GE2 TUNE
++
++      /* TRGMII Clock */
++//    printk("Set TRGMII mode clock stage 1\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x404);
++      mii_mgr_write(0, 13, 0x401f);
++      if (xtal_mode == 1){ //25MHz
++#if defined (CONFIG_GE1_TRGMII_FORCE_2900)
++              mii_mgr_write(0, 14, 0x1d00); // 362.5MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600)
++              mii_mgr_write(0, 14, 0x1a00); // 325MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000)
++              mii_mgr_write(0, 14, 0x1400); //250MHz
++#elif defined (CONFIG_GE1_RGMII_FORCE_1000)
++              mii_mgr_write(0, 14, 0x00a0); //125MHz
++#endif
++      }else if(xtal_mode == 2){//40MHz
++#if defined (CONFIG_GE1_TRGMII_FORCE_2900)
++              mii_mgr_write(0, 14, 0x1220); // 362.5MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600)
++              mii_mgr_write(0, 14, 0x1040); // 325MHz
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000)
++              mii_mgr_write(0, 14, 0x0c80); //250MHz
++#elif defined (CONFIG_GE1_RGMII_FORCE_1000)
++              mii_mgr_write(0, 14, 0x0640); //125MHz
++#endif        
++      }
++//    printk("Set TRGMII mode clock stage 2\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x405);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x0);
++
++//    printk("Set TRGMII mode clock stage 3\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x409);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x0087);             
++
++//    printk("Set TRGMII mode clock stage 4\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x40a);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x0087);
++
++//    printk("Set TRGMII mode clock stage 5\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x403);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x1800);
++
++//    printk("Set TRGMII mode clock stage 6\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x403);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x1c00);
++
++//    printk("Set TRGMII mode clock stage 7\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x401);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0xc020);
++
++//    printk("Set TRGMII mode clock stage 8\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x406);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0xa030);
++
++//    printk("Set TRGMII mode clock stage 9\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x406);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0xa038);
++
++      udelay(120); // for MT7623 bring up test
++
++//    printk("Set TRGMII mode clock stage 10\n");
++      mii_mgr_write(0, 13, 0x1f);
++      mii_mgr_write(0, 14, 0x410);
++      mii_mgr_write(0, 13, 0x401f);
++      mii_mgr_write(0, 14, 0x3);
++
++//    printk("Set TRGMII mode clock stage 11\n");
++
++      mii_mgr_read(31, 0x7830 ,&regValue);
++      regValue &=0xFFFFFFFC;
++      regValue |=0x00000001;
++      mii_mgr_write(31, 0x7830, regValue);
++
++//    printk("Set TRGMII mode clock stage 12\n");
++      mii_mgr_read(31, 0x7a40 ,&regValue);
++      regValue &= ~(0x1<<30);
++      regValue &= ~(0x1<<28);
++      mii_mgr_write(31, 0x7a40, regValue);
++
++      //mii_mgr_write(31, 0x7a78, 0x855);            
++      mii_mgr_write(31, 0x7a78, 0x55);            
++//    printk(" Adjust MT7530 TXC delay\n");
++      udelay(100); // for mt7623 bring up test
++
++//    printk(" Release MT7623 RXC Reset\n");
++      *(volatile u_long *)(0xfb110300) &= 0x7fffffff;   // Release MT7623 RXC reset
++      //disable EEE
++      for(i=0;i<=4;i++)
++      {
++          mii_mgr_write(i, 13, 0x7);
++          mii_mgr_write(i, 14, 0x3C);
++          mii_mgr_write(i, 13, 0x4007);
++          mii_mgr_write(i, 14, 0x0);
++      }
++
++      //Disable EEE 10Base-Te:
++      for(i=0;i<=4;i++)
++      {
++          mii_mgr_write(i, 13, 0x1f);
++          mii_mgr_write(i, 14, 0x027b);
++          mii_mgr_write(i, 13, 0x401f);
++          mii_mgr_write(i, 14, 0x1177);
++      }
++
++      for(i=0;i<=4;i++)
++        {
++      //turn on PHY
++                mii_mgr_read(i, 0x0 ,&regValue);
++              regValue &= ~(0x1<<11);
++              mii_mgr_write(i, 0x0, regValue);        
++      }
++
++      for(i=0;i<=4;i++) {
++              mii_mgr_read(i, 4, &regValue);
++                regValue |= (3<<7); //turn on 100Base-T Advertisement
++              mii_mgr_write(i, 4, regValue);
++      
++              mii_mgr_read(i, 9, &regValue);
++                regValue |= (3<<8); //turn on 1000Base-T Advertisement
++                mii_mgr_write(i, 9, regValue);
++
++              //restart AN
++              mii_mgr_read(i, 0, &regValue);
++              regValue |= (1 << 9);
++              mii_mgr_write(i, 0, regValue);
++      }
++
++      mii_mgr_read(31, 0x7808 ,&regValue);
++        regValue |= (3<<16); //Enable INTR
++      mii_mgr_write(31, 0x7808 ,regValue);
++}
++
++void mt7623_ethifsys_init(void)
++{
++#define TRGPLL_CON0             (0xF0209280)
++#define TRGPLL_CON1             (0xF0209284)
++#define TRGPLL_CON2             (0xF0209288)
++#define TRGPLL_PWR_CON0         (0xF020928C)
++#define ETHPLL_CON0             (0xF0209290)
++#define ETHPLL_CON1             (0xF0209294)
++#define ETHPLL_CON2             (0xF0209298)
++#define ETHPLL_PWR_CON0         (0xF020929C)
++#define ETH_PWR_CON             (0xF00062A0)
++#define HIF_PWR_CON             (0xF00062A4)
++
++        u32 temp, pwr_ack_status;
++        /*=========================================================================*/
++        /* Enable ETHPLL & TRGPLL*/
++        /*=========================================================================*/
++        /* xPLL PWR ON*/
++        temp = sysRegRead(ETHPLL_PWR_CON0);
++        sysRegWrite(ETHPLL_PWR_CON0, temp | 0x1);
++
++        temp = sysRegRead(TRGPLL_PWR_CON0);
++        sysRegWrite(TRGPLL_PWR_CON0, temp | 0x1);
++
++        udelay(5); /* wait for xPLL_PWR_ON ready (min delay is 1us)*/
++
++        /* xPLL ISO Disable*/
++        temp = sysRegRead(ETHPLL_PWR_CON0);
++        sysRegWrite(ETHPLL_PWR_CON0, temp & ~0x2);
++
++        temp = sysRegRead(TRGPLL_PWR_CON0);
++        sysRegWrite(TRGPLL_PWR_CON0, temp & ~0x2);
++
++        /* xPLL Frequency Set*/
++        temp = sysRegRead(ETHPLL_CON0);
++        sysRegWrite(ETHPLL_CON0, temp | 0x1);
++#if defined (CONFIG_GE1_TRGMII_FORCE_2900)
++      temp = sysRegRead(TRGPLL_CON0);
++      sysRegWrite(TRGPLL_CON0,  temp | 0x1);
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2600)  
++        sysRegWrite(TRGPLL_CON1,  0xB2000000);
++        temp = sysRegRead(TRGPLL_CON0);
++        sysRegWrite(TRGPLL_CON0, temp | 0x1);
++#elif defined (CONFIG_GE1_TRGMII_FORCE_2000)
++        sysRegWrite(TRGPLL_CON1, 0xCCEC4EC5);
++        sysRegWrite(TRGPLL_CON0,  0x121);
++#endif
++        udelay(40); /* wait for PLL stable (min delay is 20us)*/
++
++      
++      /*=========================================================================*/
++      /* Power on ETHDMASYS and HIFSYS*/
++      /*=========================================================================*/
++      /* Power on ETHDMASYS*/
++      sysRegWrite(0xF0006000, 0x0b160001);
++      pwr_ack_status = (sysRegRead(ETH_PWR_CON) & 0x0000f000) >> 12;
++
++      if(pwr_ack_status == 0x0) {
++              printk("ETH already turn on and power on flow will be skipped...\n");
++      }else {
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp | 0x4);          /* PWR_ON*/
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp | 0x8);          /* PWR_ON_S*/
++
++              udelay(5); /* wait power settle time (min delay is 1us)*/
++
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp & ~0x10);      /* PWR_CLK_DIS*/
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp & ~0x2);        /* PWR_ISO*/
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp & ~0x100);   /* SRAM_PDN 0*/
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp & ~0x200);   /* SRAM_PDN 1*/
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp & ~0x400);   /* SRAM_PDN 2*/
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp & ~0x800);   /* SRAM_PDN 3*/
++
++              udelay(5); /* wait SRAM settle time (min delay is 1Us)*/
++
++              temp = sysRegRead(ETH_PWR_CON)  ;
++              sysRegWrite(ETH_PWR_CON, temp | 0x1);          /* PWR_RST_B*/
++      }
++
++      /* Power on HIFSYS*/
++      pwr_ack_status = (sysRegRead(HIF_PWR_CON) & 0x0000f000) >> 12;
++      if(pwr_ack_status == 0x0) {
++              printk("HIF already turn on and power on flow will be skipped...\n");
++      }
++      else {
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp | 0x4);          /* PWR_ON*/
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp | 0x8);          /* PWR_ON_S*/
++
++              udelay(5); /* wait power settle time (min delay is 1us)*/
++
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp & ~0x10);      /* PWR_CLK_DIS*/
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp & ~0x2);        /* PWR_ISO*/
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp & ~0x100);   /* SRAM_PDN 0*/
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp & ~0x200);   /* SRAM_PDN 1*/
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp & ~0x400);   /* SRAM_PDN 2*/
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp & ~0x800);   /* SRAM_PDN 3*/
++
++              udelay(5); /* wait SRAM settle time (min delay is 1Us)*/
++
++              temp = sysRegRead(HIF_PWR_CON)  ;
++              sysRegWrite(HIF_PWR_CON, temp | 0x1);          /* PWR_RST_B*/
++      }
++
++      /* Release mt7530 reset */
++      temp = le32_to_cpu(*(volatile u_long *)(0xfb000034));
++      temp &= ~(BIT(2));
++      *(volatile u_long *)(0xfb000034) = temp;
++}
++#endif
++
++/**
++ * ra2882eth_init - Module Init code
++ *
++ * Called by kernel to register net_device
++ *
++ */
++
++static int fe_probe(struct platform_device *pdev)
++{
++      int ret;
++      struct net_device *dev = alloc_etherdev(sizeof(END_DEVICE));
++
++        fe_irq = platform_get_irq(pdev, 0);
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++      int sw_id=0;
++      mii_mgr_read(29, 31, &sw_id);
++      is_switch_175c = (sw_id == 0x175c) ? 1:0;
++#endif 
++
++      if (!dev)
++              return -ENOMEM;
++
++      strcpy(dev->name, DEV_NAME);
++      printk("%s:%s[%d]%d\n", __FILE__, __func__, __LINE__, fe_irq);
++      dev->irq  = fe_irq;
++      dev->addr_len = 6;
++      dev->base_addr = RALINK_FRAME_ENGINE_BASE;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      rather_probe(dev);
++#else
++      dev->init =  rather_probe;
++#endif
++      ra2880_setup_dev_fptable(dev);
++
++      /* net_device structure Init */
++      ethtool_init(dev);
++      printk("Ralink APSoC Ethernet Driver Initilization. %s  %d rx/tx descriptors allocated, mtu = %d!\n", RAETH_VERSION, NUM_RX_DESC, dev->mtu);
++#ifdef CONFIG_RAETH_NAPI
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      printk("NAPI enable, Tx Ring = %d, Rx Ring = %d\n", NUM_TX_DESC, NUM_RX_DESC);
++#else
++      printk("NAPI enable, weight = %d, Tx Ring = %d, Rx Ring = %d\n", dev->weight, NUM_TX_DESC, NUM_RX_DESC);
++#endif
++#endif
++
++      /* Register net device for the driver */
++      if ( register_netdev(dev) != 0) {
++              printk(KERN_WARNING " " __FILE__ ": No ethernet port found.\n");
++              return -ENXIO;
++      }
++
++
++#ifdef CONFIG_RAETH_NETLINK
++      csr_netlink_init();
++#endif
++      ret = debug_proc_init();
++
++      dev_raether = dev;
++#ifdef CONFIG_ARCH_MT7623
++      mt7623_ethifsys_init();
++#endif
++      return ret;
++}
++
++
++
++
++
++
++
++void fe_sw_init(void)
++{
++#if defined (CONFIG_GIGAPHY) || defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
++        unsigned int regValue = 0;
++#endif
++
++      // Case1: RT288x/RT3883/MT7621 GE1 + GigaPhy
++#if defined (CONFIG_GE1_RGMII_AN)
++      enable_auto_negotiate(1);
++      if (isMarvellGigaPHY(1)) {
++#if defined (CONFIG_RT3883_FPGA)
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
++              regValue &= ~(3<<8); //turn off 1000Base-T Advertisement  (9.9=1000Full, 9.8=1000Half)
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
++              
++              printk("\n Reset MARVELL phy\n");
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &regValue);
++              regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, regValue);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
++              regValue |= 1<<15; //PHY Software Reset
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
++#elif defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7623_FPGA)
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
++              regValue &= ~(3<<8); //turn off 1000Base-T Advertisement  (9.9=1000Full, 9.8=1000Half)
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
++      
++              /*10Mbps, debug*/
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, 0x461);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
++              regValue |= 1<<9; //restart AN
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
++#endif
++
++      }
++      if (isVtssGigaPHY(1)) {
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 1);
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &regValue);
++              printk("Vitesse phy skew: %x --> ", regValue);
++              regValue |= (0x3<<12);
++              regValue &= ~(0x3<<14);
++              printk("%x\n", regValue);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, regValue);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0);
++        }
++#if defined (CONFIG_RALINK_MT7621)
++      sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x21056300);//(P0, Auto mode)
++#endif
++#endif // CONFIG_GE1_RGMII_AN //
++
++      // Case2: RT3883/MT7621 GE2 + GigaPhy
++#if defined (CONFIG_GE2_RGMII_AN)
++      enable_auto_negotiate(2);
++      if (isMarvellGigaPHY(2)) {
++#if defined (CONFIG_RT3883_FPGA)
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
++              regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
++              
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &regValue);
++              regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, regValue);
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
++              regValue |= 1<<15; //PHY Software Reset
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
++#elif defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7623_FPGA)
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
++              regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
++              
++              /*10Mbps, debug*/
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, 0x461);
++
++
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
++              regValue |= 1<<9; //restart AN
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
++#endif
++
++      }
++      if (isVtssGigaPHY(2)) {
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 1);
++              mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &regValue);
++              printk("Vitesse phy skew: %x --> ", regValue);
++              regValue |= (0x3<<12);
++              regValue &= ~(0x3<<14);
++              printk("%x\n", regValue);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, regValue);
++              mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0);
++      }
++#if defined (CONFIG_RALINK_MT7621)
++      //RGMII2=Normal mode
++      *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
++      //GMAC2= RGMII mode
++      *(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
++
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(P1, Auto mode)
++#endif
++#endif // CONFIG_GE2_RGMII_AN //
++
++      // Case3: RT305x/RT335x/RT6855/RT6855A/MT7620 + EmbeddedSW
++#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_RALINK_MT7621) && !defined(CONFIG_ARCH_MT7623)
++#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
++      rt_gsw_init();
++#elif defined(CONFIG_RALINK_RT6855A)
++      rt6855A_gsw_init();
++#else
++      rt305x_esw_init();
++#endif
++#endif 
++      // Case4:  RT288x/RT388x/MT7621 GE1 + Internal GigaSW
++#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200)  || defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)
++#if defined (CONFIG_RALINK_MT7621)
++      setup_internal_gsw();
++      /*MT7530 Init*/
++#elif defined (CONFIG_ARCH_MT7623)
++#if defined (CONFIG_GE1_TRGMII_FORCE_2000) || defined (CONFIG_GE1_TRGMII_FORCE_2600)        
++      *(volatile u_long *)(0xfb00002c) |=  (1<<11);
++#else
++      *(volatile u_long *)(0xfb00002c) &= ~(1<<11);
++#endif
++      setup_internal_gsw();
++      trgmii_calibration_7623();
++      trgmii_calibration_7530();
++      //*(volatile u_long *)(0xfb110300) |= (0x1f << 24);     //Just only for 312.5/325MHz
++      *(volatile u_long *)(0xfb110340) = 0x00020000;
++      *(volatile u_long *)(0xfb110304) &= 0x3fffffff;         // RX clock gating in MT7623
++      *(volatile u_long *)(0xfb110300) |= 0x80000000;         // Assert RX  reset in MT7623
++      *(volatile u_long *)(0xfb110300 )      &= 0x7fffffff;   // Release RX reset in MT7623
++      *(volatile u_long *)(0xfb110300 +0x04) |= 0xC0000000;   // Disable RX clock gating in MT7623
++/*GE1@125MHz(RGMII mode) TX delay adjustment*/
++#if defined (CONFIG_GE1_RGMII_FORCE_1000)
++        *(volatile u_long *)(0xfb110350) = 0x55;
++        *(volatile u_long *)(0xfb110358) = 0x55;
++        *(volatile u_long *)(0xfb110360) = 0x55;
++        *(volatile u_long *)(0xfb110368) = 0x55;
++        *(volatile u_long *)(0xfb110370) = 0x55;
++        *(volatile u_long *)(0xfb110378) = 0x855;
++#endif
++
++      
++#elif defined (CONFIG_MT7623_FPGA)    /* Nelson: remove for bring up, should be added!!! */
++      setup_fpga_gsw();
++#else
++      sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_1000_FD);
++#endif
++#endif 
++
++      // Case5: RT388x/MT7621 GE2 + GigaSW
++#if defined (CONFIG_GE2_RGMII_FORCE_1000)
++#if defined (CONFIG_RALINK_MT7621)
++      setup_external_gsw();
++#else
++      sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_1000_FD);
++#endif
++#endif 
++
++      // Case6: RT288x GE1 /RT388x,MT7621 GE1/GE2 + (10/100 Switch or 100PHY)
++#if defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
++
++      //set GMAC to MII or RvMII mode
++#if defined (CONFIG_RALINK_RT3883)
++      regValue = sysRegRead(SYSCFG1);
++#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE1_MII_AN)
++      regValue &= ~(0x3 << 12);
++      regValue |= 0x1 << 12; // GE1 MII Mode
++#elif defined (CONFIG_GE1_RVMII_FORCE_100)
++      regValue &= ~(0x3 << 12);
++      regValue |= 0x2 << 12; // GE1 RvMII Mode
++#endif 
++
++#if defined (CONFIG_GE2_MII_FORCE_100) || defined (CONFIG_GE2_MII_AN) 
++      regValue &= ~(0x3 << 14);
++      regValue |= 0x1 << 14; // GE2 MII Mode
++#elif defined (CONFIG_GE2_RVMII_FORCE_100)
++      regValue &= ~(0x3 << 14);
++      regValue |= 0x2 << 14; // GE2 RvMII Mode
++#endif 
++      sysRegWrite(SYSCFG1, regValue);
++#endif // CONFIG_RALINK_RT3883 //
++
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++
++#if defined (CONFIG_GE1_MII_FORCE_100)
++      sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x5e337);//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#endif
++#if defined (CONFIG_GE2_MII_FORCE_100)
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x5e337);//(P1, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
++#endif
++#if defined (CONFIG_GE1_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
++      enable_auto_negotiate(1);
++#if defined (CONFIG_RALINK_MT7621)
++      sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x21056300);//(P0, Auto mode)
++#endif
++#endif
++#if defined (CONFIG_GE2_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
++      enable_auto_negotiate(2);
++#if defined (CONFIG_RALINK_MT7621)
++      sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x21056300);//(P1, Auto mode)
++#endif
++#endif
++
++#else
++#if defined (CONFIG_GE1_MII_FORCE_100)
++#if defined (CONFIG_RALINK_MT7621)
++#else
++      sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_100_FD);
++#endif
++#endif
++#if defined (CONFIG_GE2_MII_FORCE_100)
++#if defined (CONFIG_RALINK_MT7621)
++#else
++      sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_100_FD);
++#endif
++#endif
++      //add switch configuration here for other switch chips.
++#if defined (CONFIG_GE1_MII_FORCE_100) ||  defined (CONFIG_GE2_MII_FORCE_100)
++      // IC+ 175x: force IC+ switch cpu port is 100/FD
++      mii_mgr_write(29, 22, 0x8420);
++#endif
++
++
++#endif // defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY) //
++
++}
++
++
++/**
++ * ra2882eth_cleanup_module - Module Exit code
++ *
++ * Cmd 'rmmod' will invode the routine to exit the module
++ *
++ */
++#if 0
++ void ra2882eth_cleanup_module(void)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local;
++
++      ei_local = netdev_priv(dev);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      unregister_netdev(ei_local->PseudoDev);
++      free_netdev(ei_local->PseudoDev);
++#endif
++      unregister_netdev(dev);
++      RAETH_PRINT("Free ei_local and unregister netdev...\n");
++
++      free_netdev(dev);
++      debug_proc_exit();
++#ifdef CONFIG_RAETH_NETLINK
++      csr_netlink_end();
++#endif
++}
++#endif
++EXPORT_SYMBOL(set_fe_dma_glo_cfg);
++//module_init(ra2882eth_init);
++//module_exit(ra2882eth_cleanup_module);
++
++const struct of_device_id of_fe_match[] = {
++      { .compatible = "mediatek,mt7623-net", },
++      {},
++};
++
++MODULE_DEVICE_TABLE(of, of_fe_match);
++
++static struct platform_driver fe_driver = {
++      .probe = fe_probe,
++//    .remove = ra2882eth_cleanup_module,
++      .driver = {
++              .name = "ralink_soc_eth",
++              .owner = THIS_MODULE,
++              .of_match_table = of_fe_match,
++      },
++};
++
++static int __init init_rtfe(void)
++{
++      int ret;
++      ret = platform_driver_register(&fe_driver);
++      return ret;
++}
++
++static void __exit exit_rtfe(void)
++{
++      platform_driver_unregister(&fe_driver);
++}
++
++module_init(init_rtfe);
++module_exit(exit_rtfe);
++
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ethernet/raeth/raether.h b/drivers/net/ethernet/raeth/raether.h
+new file mode 100644
+index 0000000..7a97109
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether.h
+@@ -0,0 +1,126 @@
++#ifndef RA2882ETHEND_H
++#define RA2882ETHEND_H
++
++#ifdef DSP_VIA_NONCACHEABLE
++#define ESRAM_BASE    0xa0800000      /* 0x0080-0000  ~ 0x00807FFF */
++#else
++#define ESRAM_BASE    0x80800000      /* 0x0080-0000  ~ 0x00807FFF */
++#endif
++
++#define RX_RING_BASE  ((int)(ESRAM_BASE + 0x7000))
++#define TX_RING_BASE  ((int)(ESRAM_BASE + 0x7800))
++
++#if defined(CONFIG_RALINK_RT2880)
++#define NUM_TX_RINGS  1
++#else
++#define NUM_TX_RINGS  4
++#endif
++#ifdef MEMORY_OPTIMIZATION
++#ifdef CONFIG_RAETH_ROUTER
++#define NUM_RX_DESC     32 //128
++#define NUM_TX_DESC           32 //128
++#elif CONFIG_RT_3052_ESW
++#define NUM_RX_DESC     16 //64
++#define NUM_TX_DESC     16 //64
++#else
++#define NUM_RX_DESC     32 //128
++#define NUM_TX_DESC     32 //128
++#endif
++//#define NUM_RX_MAX_PROCESS 32
++#define NUM_RX_MAX_PROCESS 32
++#else
++#if defined (CONFIG_RAETH_ROUTER)
++#define NUM_RX_DESC     256
++#define NUM_TX_DESC           256
++#elif defined (CONFIG_RT_3052_ESW)
++#if defined (CONFIG_RALINK_MT7621)
++#define NUM_RX_DESC     512
++#define NUM_QRX_DESC     16
++#define NUM_TX_DESC     512 
++#else
++#define NUM_RX_DESC     256
++#define NUM_QRX_DESC NUM_RX_DESC
++#define NUM_TX_DESC     256
++#endif
++#else
++#define NUM_RX_DESC     256
++#define NUM_QRX_DESC NUM_RX_DESC
++#define NUM_TX_DESC     256
++#endif
++#if defined(CONFIG_RALINK_RT3883) || defined(CONFIG_RALINK_MT7620) 
++#define NUM_RX_MAX_PROCESS 2
++#else
++#define NUM_RX_MAX_PROCESS 16
++#endif
++#endif
++#define NUM_LRO_RX_DESC       16
++
++#if defined (CONFIG_SUPPORT_OPENWRT)
++#define DEV_NAME        "eth0"
++#define DEV2_NAME       "eth1"
++#else
++#define DEV_NAME        "eth2"
++#define DEV2_NAME       "eth3"
++#endif
++
++#if defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7621)
++#define GMAC0_OFFSET    0xE000
++#define GMAC2_OFFSET    0xE006
++#else
++#define GMAC0_OFFSET    0x28 
++#define GMAC2_OFFSET    0x22
++#endif
++
++#if defined(CONFIG_RALINK_RT6855A)
++#define IRQ_ENET0     22
++#elif defined(CONFIG_ARCH_MT7623)
++#define IRQ_ENET0     232
++#else
++#define IRQ_ENET0     3       /* hardware interrupt #3, defined in RT2880 Soc Design Spec Rev 0.03, pp43 */
++#endif
++
++#if defined (CONFIG_RAETH_HW_LRO)
++#define       HW_LRO_TIMER_UNIT   1
++#define       HW_LRO_REFRESH_TIME 50000
++#define       HW_LRO_MAX_AGG_CNT      64
++#define       HW_LRO_AGG_DELTA        1
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#define       MAX_LRO_RX_LENGTH       10240
++#else
++#define       MAX_LRO_RX_LENGTH       (PAGE_SIZE - SKB_DATA_ALIGN(NET_SKB_PAD + sizeof(struct skb_shared_info)))
++#endif
++#define       HW_LRO_AGG_TIME         10      /* 200us */
++#define       HW_LRO_AGE_TIME         50
++#define       HW_LRO_BW_THRE          3000
++#define       HW_LRO_PKT_INT_ALPHA    100
++#endif  /* CONFIG_RAETH_HW_LRO */
++#define FE_INT_STATUS_REG (*(volatile unsigned long *)(FE_INT_STATUS))
++#define FE_INT_STATUS_CLEAN(reg) (*(volatile unsigned long *)(FE_INT_STATUS)) = reg
++
++//#define RAETH_DEBUG
++#ifdef RAETH_DEBUG
++#define RAETH_PRINT(fmt, args...) printk(KERN_INFO fmt, ## args)
++#else
++#define RAETH_PRINT(fmt, args...) { }
++#endif
++
++struct net_device_stats *ra_get_stats(struct net_device *dev);
++
++void ei_tx_timeout(struct net_device *dev);
++int rather_probe(struct net_device *dev);
++int ei_open(struct net_device *dev);
++int ei_close(struct net_device *dev);
++
++int ra2882eth_init(void);
++void ra2882eth_cleanup_module(void);
++
++void ei_xmit_housekeeping(unsigned long data);
++
++u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data);
++u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data);
++u32 mii_mgr_cl45_set_address(u32 port_num, u32 dev_addr, u32 reg_addr);
++u32 mii_mgr_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *read_data);
++u32 mii_mgr_write_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data);
++void fe_sw_init(void);
++
++#endif
+diff --git a/drivers/net/ethernet/raeth/raether_hwlro.c b/drivers/net/ethernet/raeth/raether_hwlro.c
+new file mode 100755
+index 0000000..5fc4f36
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_hwlro.c
+@@ -0,0 +1,347 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <asm/rt2880/rt_mmap.h>
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++
++#if defined(CONFIG_RAETH_HW_LRO_FORCE)
++int set_fe_lro_ring1_cfg(struct net_device *dev)
++{
++      unsigned int ip;
++
++      netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring1_cfg()\n");
++
++      /* 1. Set RX ring mode to force port */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_FORCE_PORT);
++
++      /* 2. Configure lro ring */
++      /* 2.1 set src/destination TCP ports */
++      SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING1, 1122);
++      SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING1, 3344);
++      /* 2.2 set src/destination IPs */
++      str_to_ip(&ip, "10.10.10.3");
++      sysRegWrite(LRO_RX_RING1_SIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.254");
++      sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++      /* 2.3 IPv4 force port mode */
++      SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING1, 1);
++      /* 2.4 IPv6 force port mode */
++      SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING1, 1);
++
++      /* 3. Set Age timer: 10 msec. */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++
++      /* 4. Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++
++      return 0;
++}
++
++int set_fe_lro_ring2_cfg(struct net_device *dev)
++{
++      unsigned int ip;
++
++      netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring2_cfg()\n");
++
++      /* 1. Set RX ring mode to force port */
++      SET_PDMA_RXRING2_MODE(PDMA_RX_FORCE_PORT);
++
++      /* 2. Configure lro ring */
++      /* 2.1 set src/destination TCP ports */
++      SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING2, 5566);
++      SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING2, 7788);
++      /* 2.2 set src/destination IPs */
++      str_to_ip(&ip, "10.10.10.3");
++      sysRegWrite(LRO_RX_RING2_SIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.254");
++      sysRegWrite(LRO_RX_RING2_DIP_DW0, ip);
++      /* 2.3 IPv4 force port mode */
++      SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING2, 1);
++      /* 2.4 IPv6 force port mode */
++      SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING2, 1);
++
++      /* 3. Set Age timer: 10 msec. */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++
++      /* 4. Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++
++      return 0;
++}
++
++int set_fe_lro_ring3_cfg(struct net_device *dev)
++{
++      unsigned int ip;
++
++      netdev_printk(KERN_CRIT, dev, "set_fe_lro_ring3_cfg()\n");
++
++      /* 1. Set RX ring mode to force port */
++      SET_PDMA_RXRING3_MODE(PDMA_RX_FORCE_PORT);
++
++      /* 2. Configure lro ring */
++      /* 2.1 set src/destination TCP ports */
++      SET_PDMA_RXRING_TCP_SRC_PORT(ADMA_RX_RING3, 9900);
++      SET_PDMA_RXRING_TCP_DEST_PORT(ADMA_RX_RING3, 99);
++      /* 2.2 set src/destination IPs */
++      str_to_ip(&ip, "10.10.10.3");
++      sysRegWrite(LRO_RX_RING3_SIP_DW0, ip);
++      str_to_ip(&ip, "10.10.10.254");
++      sysRegWrite(LRO_RX_RING3_DIP_DW0, ip);
++      /* 2.3 IPv4 force port mode */
++      SET_PDMA_RXRING_IPV4_FORCE_MODE(ADMA_RX_RING3, 1);
++      /* 2.4 IPv6 force port mode */
++      SET_PDMA_RXRING_IPV6_FORCE_MODE(ADMA_RX_RING3, 1);
++
++      /* 3. Set Age timer: 10 msec. */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++      /* 4. Valid LRO ring */
++      SET_PDMA_RXRING3_VALID(1);
++
++      return 0;
++}
++
++int set_fe_lro_glo_cfg(struct net_device *dev)
++{
++      unsigned int regVal = 0;
++
++      netdev_printk(KERN_CRIT, dev, "set_fe_lro_glo_cfg()\n");
++
++      /* 1 Set max AGG timer: 10 msec. */
++      SET_PDMA_LRO_MAX_AGG_TIME(HW_LRO_AGG_TIME);
++
++      /* 2. Set max LRO agg count */
++      SET_PDMA_LRO_MAX_AGG_CNT(HW_LRO_MAX_AGG_CNT);
++
++      /* PDMA prefetch enable setting */
++      SET_PDMA_LRO_RXD_PREFETCH_EN(0x3);
++
++      /* 2.1 IPv4 checksum update enable */
++      SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++      /* 3. Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH)
++              ;
++
++      /* 4. Enable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal |= PDMA_LRO_EN;
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++      return 0;
++}
++#else
++int set_fe_lro_auto_cfg(struct net_device *dev)
++{
++      unsigned int regVal = 0;
++      unsigned int ip;
++
++      netdev_printk(KERN_CRIT, dev, "set_fe_lro_auto_cfg()\n");
++
++      /* 1.1 Set my IP_1 */
++      str_to_ip(&ip, "10.10.10.254");
++      sysRegWrite(LRO_RX_RING0_DIP_DW0, ip);
++      sysRegWrite(LRO_RX_RING0_DIP_DW1, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW2, 0);
++      sysRegWrite(LRO_RX_RING0_DIP_DW3, 0);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING0, 1);
++
++      /* 1.2 Set my IP_2 */
++      str_to_ip(&ip, "10.10.20.254");
++      sysRegWrite(LRO_RX_RING1_DIP_DW0, ip);
++      sysRegWrite(LRO_RX_RING1_DIP_DW1, 0);
++      sysRegWrite(LRO_RX_RING1_DIP_DW2, 0);
++      sysRegWrite(LRO_RX_RING1_DIP_DW3, 0);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING1, 1);
++
++      /* 1.3 Set my IP_3 */
++      sysRegWrite(LRO_RX_RING2_DIP_DW3, 0x20010238);
++      sysRegWrite(LRO_RX_RING2_DIP_DW2, 0x08000000);
++      sysRegWrite(LRO_RX_RING2_DIP_DW1, 0x00000000);
++      sysRegWrite(LRO_RX_RING2_DIP_DW0, 0x00000254);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING2, 1);
++
++      /* 1.4 Set my IP_4 */
++      sysRegWrite(LRO_RX_RING3_DIP_DW3, 0x20010238);
++      sysRegWrite(LRO_RX_RING3_DIP_DW2, 0x08010000);
++      sysRegWrite(LRO_RX_RING3_DIP_DW1, 0x00000000);
++      sysRegWrite(LRO_RX_RING3_DIP_DW0, 0x00000254);
++      SET_PDMA_RXRING_MYIP_VALID(ADMA_RX_RING3, 1);
++
++      /* 2.1 Set RX ring1~3 to auto-learn modes */
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING1, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING2, PDMA_RX_AUTO_LEARN);
++      SET_PDMA_RXRING_MODE(ADMA_RX_RING3, PDMA_RX_AUTO_LEARN);
++
++      /* 2.2 Valid LRO ring */
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING0, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING1, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING2, 1);
++      SET_PDMA_RXRING_VALID(ADMA_RX_RING3, 1);
++
++      /* 2.3 Set AGE timer */
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING1, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING2, HW_LRO_AGE_TIME);
++      SET_PDMA_RXRING_AGE_TIME(ADMA_RX_RING3, HW_LRO_AGE_TIME);
++
++      /* 2.4 Set max AGG timer */
++      SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING1, HW_LRO_AGG_TIME);
++      SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING2, HW_LRO_AGG_TIME);
++      SET_PDMA_RXRING_AGG_TIME(ADMA_RX_RING3, HW_LRO_AGG_TIME);
++
++      /* 2.5 Set max LRO agg count */
++      SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING1, HW_LRO_MAX_AGG_CNT);
++      SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING2, HW_LRO_MAX_AGG_CNT);
++      SET_PDMA_RXRING_MAX_AGG_CNT(ADMA_RX_RING3, HW_LRO_MAX_AGG_CNT);
++
++      /* 3.0 IPv6 LRO enable */
++      SET_PDMA_LRO_IPV6_EN(1);
++
++      /* 3.1 IPv4 checksum update enable */
++      SET_PDMA_LRO_IPV4_CSUM_UPDATE_EN(1);
++
++      /* 3.2 TCP push option check disable */
++      //SET_PDMA_LRO_IPV4_CTRL_PUSH_EN(0);
++
++      /* PDMA prefetch enable setting */
++      SET_PDMA_LRO_RXD_PREFETCH_EN(0x3);
++
++      /* 3.2 switch priority comparison to byte count mode */
++/* SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_BYTE_CNT_MODE); */
++      SET_PDMA_LRO_ALT_SCORE_MODE(PDMA_LRO_ALT_PKT_CNT_MODE);
++
++      /* 3.3 bandwidth threshold setting */
++      SET_PDMA_LRO_BW_THRESHOLD(HW_LRO_BW_THRE);
++
++      /* 3.4 auto-learn score delta setting */
++      sysRegWrite(LRO_ALT_SCORE_DELTA, 0);
++
++      /* 3.5 Set ALT timer to 20us: (unit: 20us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER_UNIT(HW_LRO_TIMER_UNIT);
++      /* 3.6 Set ALT refresh timer to 1 sec. (unit: 20us) */
++      SET_PDMA_LRO_ALT_REFRESH_TIMER(HW_LRO_REFRESH_TIME);
++
++      /* 3.7 the least remaining room of SDL0 in RXD for lro aggregation */
++      SET_PDMA_LRO_MIN_RXD_SDL(1522);
++
++      /* 4. Polling relinguish */
++      while (sysRegRead(ADMA_LRO_CTRL_DW0) & PDMA_LRO_RELINGUISH)
++              ;
++
++      /* 5. Enable LRO */
++      regVal = sysRegRead(ADMA_LRO_CTRL_DW0);
++      regVal |= PDMA_LRO_EN;
++      sysRegWrite(ADMA_LRO_CTRL_DW0, regVal);
++
++      return 0;
++}
++#endif /* CONFIG_RAETH_HW_LRO_FORCE */
++
++int fe_hw_lro_init(struct net_device *dev)
++{
++      int i;
++      END_DEVICE *ei_local = netdev_priv(dev);
++
++      /* Initial RX Ring 3 */
++      ei_local->rx_ring3 =
++          pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc),
++                               &ei_local->phy_rx_ring3);
++      for (i = 0; i < NUM_LRO_RX_DESC; i++) {
++              memset(&ei_local->rx_ring3[i], 0, sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring3[i].rxd_info2.DDONE_bit = 0;
++              ei_local->rx_ring3[i].rxd_info2.LS0 = 0;
++              ei_local->rx_ring3[i].rxd_info2.PLEN0 =
++                  SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++              ei_local->rx_ring3[i].rxd_info2.PLEN1 =
++                  SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++              ei_local->rx_ring3[i].rxd_info1.PDP0 =
++                  dma_map_single(NULL, ei_local->netrx3_skbuf[i]->data,
++                                 MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      netdev_printk(KERN_CRIT, dev,
++                    "\nphy_rx_ring3 = 0x%08x, rx_ring3 = 0x%p\n",
++                    ei_local->phy_rx_ring3, ei_local->rx_ring3);
++      /* Initial RX Ring 2 */
++      ei_local->rx_ring2 =
++          pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc),
++                               &ei_local->phy_rx_ring2);
++      for (i = 0; i < NUM_LRO_RX_DESC; i++) {
++              memset(&ei_local->rx_ring2[i], 0, sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring2[i].rxd_info2.DDONE_bit = 0;
++              ei_local->rx_ring2[i].rxd_info2.LS0 = 0;
++              ei_local->rx_ring2[i].rxd_info2.PLEN0 =
++                  SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++              ei_local->rx_ring2[i].rxd_info2.PLEN1 =
++                  SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++              ei_local->rx_ring2[i].rxd_info1.PDP0 =
++                  dma_map_single(NULL, ei_local->netrx2_skbuf[i]->data,
++                                 MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      netdev_printk(KERN_CRIT, dev,
++                    "\nphy_rx_ring2 = 0x%08x, rx_ring2 = 0x%p\n",
++                    ei_local->phy_rx_ring2, ei_local->rx_ring2);
++      /* Initial RX Ring 1 */
++      ei_local->rx_ring1 =
++          pci_alloc_consistent(NULL, NUM_LRO_RX_DESC * sizeof(struct PDMA_rxdesc),
++                               &ei_local->phy_rx_ring1);
++      for (i = 0; i < NUM_LRO_RX_DESC; i++) {
++              memset(&ei_local->rx_ring1[i], 0, sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0;
++              ei_local->rx_ring1[i].rxd_info2.LS0 = 0;
++              ei_local->rx_ring1[i].rxd_info2.PLEN0 =
++                  SET_ADMA_RX_LEN0(MAX_LRO_RX_LENGTH);
++              ei_local->rx_ring1[i].rxd_info2.PLEN1 =
++                  SET_ADMA_RX_LEN1(MAX_LRO_RX_LENGTH >> 14);
++              ei_local->rx_ring1[i].rxd_info1.PDP0 =
++                  dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data,
++                                 MAX_LRO_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      netdev_printk(KERN_CRIT, dev,
++                    "\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",
++                    ei_local->phy_rx_ring1, ei_local->rx_ring1);
++
++      sysRegWrite(RX_BASE_PTR3, phys_to_bus((u32) ei_local->phy_rx_ring3));
++      sysRegWrite(RX_MAX_CNT3, cpu_to_le32((u32) NUM_LRO_RX_DESC));
++      sysRegWrite(RX_CALC_IDX3, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1)));
++      sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX3);
++      sysRegWrite(RX_BASE_PTR2, phys_to_bus((u32) ei_local->phy_rx_ring2));
++      sysRegWrite(RX_MAX_CNT2, cpu_to_le32((u32) NUM_LRO_RX_DESC));
++      sysRegWrite(RX_CALC_IDX2, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1)));
++      sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX2);
++      sysRegWrite(RX_BASE_PTR1, phys_to_bus((u32) ei_local->phy_rx_ring1));
++      sysRegWrite(RX_MAX_CNT1, cpu_to_le32((u32) NUM_LRO_RX_DESC));
++      sysRegWrite(RX_CALC_IDX1, cpu_to_le32((u32) (NUM_LRO_RX_DESC - 1)));
++      sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX1);
++
++#if defined(CONFIG_RAETH_HW_LRO_FORCE)
++      set_fe_lro_ring1_cfg(dev);
++      set_fe_lro_ring2_cfg(dev);
++      set_fe_lro_ring3_cfg(dev);
++      set_fe_lro_glo_cfg(dev);
++#else
++      set_fe_lro_auto_cfg(dev);
++#endif /* CONFIG_RAETH_HW_LRO_FORCE */
++
++      /* HW LRO parameter settings */
++      ei_local->hw_lro_alpha = HW_LRO_PKT_INT_ALPHA;
++      ei_local->hw_lro_fix_setting = 1;
++
++      return 1;
++}
++EXPORT_SYMBOL(fe_hw_lro_init);
++
+diff --git a/drivers/net/ethernet/raeth/raether_pdma.c b/drivers/net/ethernet/raeth/raether_pdma.c
+new file mode 100755
+index 0000000..4d47ee2
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_pdma.c
+@@ -0,0 +1,1121 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#if defined (CONFIG_RAETH_LRO)
++#include <linux/inet_lro.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++ 
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++#if defined(CONFIG_RAETH_PDMA_DVT)
++#include "dvt/raether_pdma_dvt.h"
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++#if 0
++#ifdef RA_MTD_RW_BY_NUM
++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
++#else
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
++#endif
++#endif
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#if defined     (CONFIG_ARCH_MT7623)
++#undef DELAY_INT
++#else
++#define DELAY_INT       1
++#endif
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define       MAX_RX_LENGTH   4096
++#else
++#define       MAX_RX_LENGTH   1536
++#endif
++
++extern struct net_device              *dev_raether;
++
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++extern int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++extern int rx_calc_idx0;
++static unsigned long tx_cpu_owner_idx0=0;
++#endif
++extern unsigned long tx_ring_full;
++
++#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
++#include "ra_ethtool.h"
++extern struct ethtool_ops     ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops     ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX     /* QDMA RX */
++struct QDMA_txdesc *free_head = NULL;
++#endif
++
++//#if defined (CONFIG_RAETH_LRO)
++#if 0
++unsigned int lan_ip;
++struct lro_para_struct lro_para; 
++int lro_flush_needed;
++extern char const *nvram_get(int index, char *name);
++#endif
++
++#define KSEG1                   0xa0000000
++#define PHYS_TO_VIRT(x)         ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x)         ((unsigned long)(x) & ~KSEG1)
++
++extern void set_fe_dma_glo_cfg(void);
++
++/*
++ *  @brief cal txd number for a page
++ *
++ *  @parm size
++ *
++ *  @return frag_txd_num
++ */
++
++unsigned int cal_frag_txd_num(unsigned int size)
++{
++      unsigned int frag_txd_num = 0;
++      if(size == 0)
++              return 0;
++      while(size > 0){
++              if(size > MAX_TXD_LEN){
++                      frag_txd_num++;
++                      size -= MAX_TXD_LEN;
++              }else{
++                      frag_txd_num++;
++                      size = 0;
++              }
++      }
++      return frag_txd_num;
++
++}
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX     /* QDMA RX */
++bool fq_qdma_init(struct net_device *dev)
++{
++      END_DEVICE* ei_local = netdev_priv(dev);
++      unsigned int phy_free_head;
++      unsigned int phy_free_tail;
++      unsigned int *free_page_head = NULL;
++      unsigned int phy_free_page_head;
++      int i;
++    
++      free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &phy_free_head);
++      if (unlikely(free_head == NULL)){
++              printk(KERN_ERR "QDMA FQ decriptor not available...\n");
++              return 0;
++      }
++      memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE);
++
++      free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &phy_free_page_head);
++      if (unlikely(free_page_head == NULL)){
++              printk(KERN_ERR "QDMA FQ page not available...\n");
++              return 0;
++      }       
++      for (i=0; i < NUM_QDMA_PAGE; i++) {
++              free_head[i].txd_info1.SDP = (phy_free_page_head + (i * QDMA_PAGE_SIZE));
++              if(i < (NUM_QDMA_PAGE-1)){
++                      free_head[i].txd_info2.NDP = (phy_free_head + ((i+1) * sizeof(struct QDMA_txdesc)));
++
++
++#if 0
++                      printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) );
++                      printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] );
++                      printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP );
++                      printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP );
++#endif
++              }
++              free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE;
++
++      }
++      phy_free_tail = (phy_free_head + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc)));
++
++      printk("phy_free_head is 0x%x!!!\n", phy_free_head);
++      printk("phy_free_tail_phy is 0x%x!!!\n", phy_free_tail);
++      sysRegWrite(QDMA_FQ_HEAD, (u32)phy_free_head);
++      sysRegWrite(QDMA_FQ_TAIL, (u32)phy_free_tail);
++      sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE));
++      sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16);
++
++      ei_local->free_head = free_head;
++      ei_local->phy_free_head = phy_free_head;
++      ei_local->free_page_head = free_page_head;
++      ei_local->phy_free_page_head = phy_free_page_head;
++    return 1;
++}
++#endif
++
++int fe_dma_init(struct net_device *dev)
++{
++
++      int             i;
++      unsigned int    regVal;
++      END_DEVICE* ei_local = netdev_priv(dev);
++#if defined (CONFIG_RAETH_QOS)
++      int             j;
++#endif
++
++      while(1)
++      {
++              regVal = sysRegRead(PDMA_GLO_CFG);
++              if((regVal & RX_DMA_BUSY))
++              {
++                      printk("\n  RX_DMA_BUSY !!! ");
++                      continue;
++              }
++              if((regVal & TX_DMA_BUSY))
++              {
++                      printk("\n  TX_DMA_BUSY !!! ");
++                      continue;
++              }
++              break;
++      }
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++      pdma_dvt_set_dma_mode();
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++#if defined (CONFIG_RAETH_QOS)
++      for (i=0;i<NUM_TX_RINGS;i++){
++              for (j=0;j<NUM_TX_DESC;j++){
++                      ei_local->skb_free[i][j]=0;
++              }
++                ei_local->free_idx[i]=0;
++      }
++      /*
++       * RT2880: 2 x TX_Ring, 1 x Rx_Ring
++       * RT2883: 4 x TX_Ring, 1 x Rx_Ring
++       * RT3883: 4 x TX_Ring, 1 x Rx_Ring
++       * RT3052: 4 x TX_Ring, 1 x Rx_Ring
++       */
++      fe_tx_desc_init(dev, 0, 3, 1);
++      if (ei_local->tx_ring0 == NULL) {
++              printk("RAETH: tx ring0 allocation failed\n");
++              return 0;
++      }
++
++      fe_tx_desc_init(dev, 1, 3, 1);
++      if (ei_local->tx_ring1 == NULL) {
++              printk("RAETH: tx ring1 allocation failed\n");
++              return 0;
++      }
++
++      printk("\nphy_tx_ring0 = %08x, tx_ring0 = %p, size: %d bytes\n", ei_local->phy_tx_ring0, ei_local->tx_ring0, sizeof(struct PDMA_txdesc));
++
++      printk("\nphy_tx_ring1 = %08x, tx_ring1 = %p, size: %d bytes\n", ei_local->phy_tx_ring1, ei_local->tx_ring1, sizeof(struct PDMA_txdesc));
++
++#if ! defined (CONFIG_RALINK_RT2880)
++      fe_tx_desc_init(dev, 2, 3, 1);
++      if (ei_local->tx_ring2 == NULL) {
++              printk("RAETH: tx ring2 allocation failed\n");
++              return 0;
++      }
++
++      fe_tx_desc_init(dev, 3, 3, 1);
++      if (ei_local->tx_ring3 == NULL) {
++              printk("RAETH: tx ring3 allocation failed\n");
++              return 0;
++      }
++
++      printk("\nphy_tx_ring2 = %08x, tx_ring2 = %p, size: %d bytes\n", ei_local->phy_tx_ring2, ei_local->tx_ring2, sizeof(struct PDMA_txdesc));
++
++      printk("\nphy_tx_ring3 = %08x, tx_ring3 = %p, size: %d bytes\n", ei_local->phy_tx_ring3, ei_local->tx_ring3, sizeof(struct PDMA_txdesc));
++
++#endif // CONFIG_RALINK_RT2880 //
++#else
++      for (i=0;i<NUM_TX_DESC;i++){
++              ei_local->skb_free[i]=0;
++      }
++      ei_local->free_idx =0;
++#if defined (CONFIG_MIPS)
++      ei_local->tx_ring0 = pci_alloc_consistent(NULL, NUM_TX_DESC * sizeof(struct PDMA_txdesc), &ei_local->phy_tx_ring0);
++#else
++      ei_local->tx_ring0 = dma_alloc_coherent(NULL, NUM_TX_DESC * sizeof(struct PDMA_txdesc), &ei_local->phy_tx_ring0, GFP_KERNEL);
++#endif
++      printk("\nphy_tx_ring = 0x%08x, tx_ring = 0x%p\n", ei_local->phy_tx_ring0, ei_local->tx_ring0);
++
++      for (i=0; i < NUM_TX_DESC; i++) {
++              memset(&ei_local->tx_ring0[i],0,sizeof(struct PDMA_txdesc));
++              ei_local->tx_ring0[i].txd_info2.LS0_bit = 1;
++              ei_local->tx_ring0[i].txd_info2.DDONE_bit = 1;
++
++      }
++#endif // CONFIG_RAETH_QOS
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX     /* QDMA RX */
++
++      fq_qdma_init(dev);
++
++      while(1)
++      {
++              regVal = sysRegRead(QDMA_GLO_CFG);
++              if((regVal & RX_DMA_BUSY))
++              {
++                      printk("\n  RX_DMA_BUSY !!! ");
++                      continue;
++              }
++              if((regVal & TX_DMA_BUSY))
++              {
++                      printk("\n  TX_DMA_BUSY !!! ");
++                      continue;
++              }
++              break;
++      }
++
++      /* Initial RX Ring 0*/
++      
++#ifdef CONFIG_32B_DESC
++      ei_local->qrx_ring = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++      ei_local->phy_qrx_ring = virt_to_phys(ei_local->qrx_ring);
++#else
++      ei_local->qrx_ring = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_qrx_ring);
++#endif
++      for (i = 0; i < NUM_QRX_DESC; i++) {
++              memset(&ei_local->qrx_ring[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->qrx_ring[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              ei_local->qrx_ring[i].rxd_info2.LS0 = 0;
++              ei_local->qrx_ring[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++              ei_local->qrx_ring[i].rxd_info2.LS0 = 1;
++#endif
++              ei_local->qrx_ring[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      printk("\nphy_qrx_ring = 0x%08x, qrx_ring = 0x%p\n",ei_local->phy_qrx_ring,ei_local->qrx_ring);
++
++      regVal = sysRegRead(QDMA_GLO_CFG);
++      regVal &= 0x000000FF;
++
++      sysRegWrite(QDMA_GLO_CFG, regVal);
++      regVal=sysRegRead(QDMA_GLO_CFG);
++
++      /* Tell the adapter where the TX/RX rings are located. */
++
++      sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring));
++      sysRegWrite(QRX_MAX_CNT_0,  cpu_to_le32((u32) NUM_QRX_DESC));
++      sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_calc_idx0 = rx_dma_owner_idx0 =  sysRegRead(QRX_CRX_IDX_0);
++#endif
++      sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0);
++
++        ei_local->rx_ring0 = ei_local->qrx_ring;
++
++#else /* PDMA RX */
++
++      /* Initial RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++      ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++      ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++#if defined (CONFIG_MIPS)
++      ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#else 
++      ei_local->rx_ring0 = dma_alloc_coherent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0, GFP_KERNEL);
++#endif
++#endif
++      for (i = 0; i < NUM_RX_DESC; i++) {
++              memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++              ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++              ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++              ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      printk("\nphy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++      /* Initial RX Ring 1*/
++#ifdef CONFIG_32B_DESC
++      ei_local->rx_ring1 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++      ei_local->phy_rx_ring1 = virt_to_phys(ei_local->rx_ring1);
++#else
++#if defined (CONFIG_MIPS)
++      ei_local->rx_ring1 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1);
++#else
++      ei_local->rx_ring1 = dma_alloc_coherent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1, GFP_KERNEL);
++
++#endif
++#endif
++      for (i = 0; i < NUM_RX_DESC; i++) {
++              memset(&ei_local->rx_ring1[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              ei_local->rx_ring1[i].rxd_info2.LS0 = 0;
++              ei_local->rx_ring1[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++              ei_local->rx_ring1[i].rxd_info2.LS0 = 1;
++#endif
++              ei_local->rx_ring1[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      printk("\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",ei_local->phy_rx_ring1,ei_local->rx_ring1);
++#if defined(CONFIG_ARCH_MT7623)
++    /* Initial RX Ring 2*/
++    ei_local->rx_ring2 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring2);
++    for (i = 0; i < NUM_RX_DESC; i++) {
++        memset(&ei_local->rx_ring2[i],0,sizeof(struct PDMA_rxdesc));
++        ei_local->rx_ring2[i].rxd_info2.DDONE_bit = 0;
++        ei_local->rx_ring2[i].rxd_info2.LS0 = 0;
++        ei_local->rx_ring2[i].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_RX_LENGTH);
++        ei_local->rx_ring2[i].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_RX_LENGTH >> 14);
++        ei_local->rx_ring2[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx2_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++    }
++    printk("\nphy_rx_ring2 = 0x%08x, rx_ring2 = 0x%p\n",ei_local->phy_rx_ring2,ei_local->rx_ring2);
++    /* Initial RX Ring 3*/
++      ei_local->rx_ring3 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring3);
++      for (i = 0; i < NUM_RX_DESC; i++) {
++              memset(&ei_local->rx_ring3[i],0,sizeof(struct PDMA_rxdesc));
++      ei_local->rx_ring3[i].rxd_info2.DDONE_bit = 0;
++        ei_local->rx_ring3[i].rxd_info2.LS0 = 0;
++        ei_local->rx_ring3[i].rxd_info2.PLEN0 = SET_ADMA_RX_LEN0(MAX_RX_LENGTH);
++        ei_local->rx_ring3[i].rxd_info2.PLEN1 = SET_ADMA_RX_LEN1(MAX_RX_LENGTH >> 14);
++              ei_local->rx_ring3[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx3_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      printk("\nphy_rx_ring3 = 0x%08x, rx_ring3 = 0x%p\n",ei_local->phy_rx_ring3,ei_local->rx_ring3); 
++#endif  /* CONFIG_ARCH_MT7623 */
++#endif
++
++#endif
++
++      regVal = sysRegRead(PDMA_GLO_CFG);
++      regVal &= 0x000000FF;
++      sysRegWrite(PDMA_GLO_CFG, regVal);
++      regVal=sysRegRead(PDMA_GLO_CFG);
++
++      /* Tell the adapter where the TX/RX rings are located. */
++#if !defined (CONFIG_RAETH_QOS)
++        sysRegWrite(TX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_tx_ring0));
++      sysRegWrite(TX_MAX_CNT0, cpu_to_le32((u32) NUM_TX_DESC));
++      sysRegWrite(TX_CTX_IDX0, 0);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      tx_cpu_owner_idx0 = 0;
++#endif
++      sysRegWrite(PDMA_RST_CFG, PST_DTX_IDX0);
++#endif
++
++#ifdef CONFIG_RAETH_PDMATX_QDMARX     /* QDMA RX */
++      sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring));
++      sysRegWrite(QRX_MAX_CNT_0,  cpu_to_le32((u32) NUM_QRX_DESC));
++      sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#else /* PDMA RX */
++      sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++      sysRegWrite(RX_MAX_CNT0,  cpu_to_le32((u32) NUM_RX_DESC));
++      sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#endif
++
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_calc_idx0 =  sysRegRead(RX_CALC_IDX0);
++#endif
++      sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0);
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++      sysRegWrite(RX_BASE_PTR1, phys_to_bus((u32) ei_local->phy_rx_ring1));
++      sysRegWrite(RX_MAX_CNT1,  cpu_to_le32((u32) NUM_RX_DESC));
++      sysRegWrite(RX_CALC_IDX1, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_calc_idx1 =  sysRegRead(RX_CALC_IDX1);
++#endif
++      sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX1);
++#if defined(CONFIG_ARCH_MT7623)
++      sysRegWrite(RX_BASE_PTR2, phys_to_bus((u32) ei_local->phy_rx_ring2));
++      sysRegWrite(RX_MAX_CNT2,  cpu_to_le32((u32) NUM_RX_DESC));
++      sysRegWrite(RX_CALC_IDX2, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++      sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX2);
++    sysRegWrite(RX_BASE_PTR3, phys_to_bus((u32) ei_local->phy_rx_ring3));
++      sysRegWrite(RX_MAX_CNT3,  cpu_to_le32((u32) NUM_RX_DESC));
++      sysRegWrite(RX_CALC_IDX3, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++      sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX3);
++#endif  /* CONFIG_ARCH_MT7623 */
++#endif
++#if defined (CONFIG_RALINK_RT6855A)
++      regVal = sysRegRead(RX_DRX_IDX0);
++      regVal = (regVal == 0)? (NUM_RX_DESC - 1) : (regVal - 1);
++      sysRegWrite(RX_CALC_IDX0, cpu_to_le32(regVal));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_calc_idx0 =  sysRegRead(RX_CALC_IDX0);
++#endif
++      regVal = sysRegRead(TX_DTX_IDX0);
++      sysRegWrite(TX_CTX_IDX0, cpu_to_le32(regVal));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      tx_cpu_owner_idx0 = regVal;
++#endif
++      ei_local->free_idx = regVal;
++#endif
++
++#if defined (CONFIG_RAETH_QOS)
++      set_scheduler_weight();
++      set_schedule_pause_condition();
++      set_output_shaper();
++#endif
++
++      set_fe_dma_glo_cfg();
++
++      return 1;
++}
++
++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no)
++{
++      unsigned int    length=skb->len;
++      END_DEVICE*     ei_local = netdev_priv(dev);
++#ifndef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      unsigned long   tx_cpu_owner_idx0 = sysRegRead(TX_CTX_IDX0);
++#endif
++#if defined (CONFIG_RAETH_TSO)
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      unsigned long   ctx_idx_start_addr = tx_cpu_owner_idx0;
++#endif
++        struct iphdr *iph = NULL;
++        struct tcphdr *th = NULL;
++      struct skb_frag_struct *frag;
++      unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++      int i=0;
++      unsigned int len, size, offset, frag_txd_num, skb_txd_num ;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++      struct ipv6hdr *ip6h = NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      PSEUDO_ADAPTER *pAd;
++#endif
++
++      while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0)
++      {
++#ifdef CONFIG_PSEUDO_SUPPORT
++              if (gmac_no == 2) {
++                      if (ei_local->PseudoDev != NULL) {
++                              pAd = netdev_priv(ei_local->PseudoDev);
++                              pAd->stat.tx_errors++;
++                      }
++              } else
++#endif
++                      ei_local->stat.tx_errors++;
++      }
++
++#if !defined (CONFIG_RAETH_TSO)
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = virt_to_phys(skb->data);
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = length;
++#if defined (CONFIG_RALINK_MT7620)
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = 0;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++      if (gmac_no == 1) {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 1;
++      }else {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 2;
++      }
++#else
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = gmac_no;
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.QN = 3;
++#endif
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7628)
++      if (skb->ip_summed == CHECKSUM_PARTIAL){
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 7;
++      }else {
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 0;
++      }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++      if(vlan_tx_tag_present(skb)) {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++#else
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF);
++#endif
++      }else {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0;
++#else
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0;
++#endif
++      }
++#endif
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++    raeth_pdma_tx_vlan_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++      if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++          if(ra_sw_nat_hook_rx!= NULL){
++#if defined (CONFIG_RALINK_MT7620)
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = (1 << 7); /* PPE */
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */
++#else
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = 6; /* PPE */
++#endif
++              FOE_MAGIC_TAG(skb) = 0;
++          }
++      }
++#endif
++      
++#if defined(CONFIG_RAETH_PDMA_DVT)
++    raeth_pdma_tx_desc_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit = 0;
++
++#if 0 
++      printk("---------------\n");
++      printk("tx_info1=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1);
++      printk("tx_info2=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2);
++      printk("tx_info3=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3);
++      printk("tx_info4=%x\n",ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4);
++#endif
++
++#else
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = virt_to_phys(skb->data);
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = (length - skb->data_len);
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = nr_frags ? 0:1;
++#if defined (CONFIG_RALINK_MT7620)
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = 0;
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++      if (gmac_no == 1) {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 1;
++      }else {
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 2;
++      }
++#else
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = gmac_no;
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.QN = 3;
++#endif
++      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TSO = 0;
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined(CONFIG_RALINK_MT7628)
++      if (skb->ip_summed == CHECKSUM_PARTIAL){
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 7;
++      }else {
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.TUI_CO = 0;
++      }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++      if(vlan_tx_tag_present(skb)) {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++#else
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0x80 | (vlan_tx_tag_get(skb) >> 13) << 4 | (vlan_tx_tag_get(skb) & 0xF);
++#endif
++      }else {
++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VLAN_TAG = 0;
++#else
++          ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.VPRI_VIDX = 0;
++#endif
++      }
++#endif
++   
++#if defined(CONFIG_RAETH_PDMA_DVT)
++    raeth_pdma_tx_vlan_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++      if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++          if(ra_sw_nat_hook_rx!= NULL){
++#if defined (CONFIG_RALINK_MT7620)
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FP_BMAP = (1 << 7); /* PPE */
++#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623)
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.FPORT = 4; /* PPE */
++#else
++              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info4.PN = 6; /* PPE */
++#endif
++              FOE_MAGIC_TAG(skb) = 0;
++          }
++      }
++#endif
++
++      skb_txd_num = 1;
++
++      if(nr_frags > 0) {
++
++              for(i=0;i<nr_frags;i++) {
++                      frag = &skb_shinfo(skb)->frags[i];
++                      offset = frag->page_offset;
++                      len = frag->size;
++                      frag_txd_num = cal_frag_txd_num(len);
++
++                      while(frag_txd_num > 0){
++                              if(len < MAX_TXD_LEN)
++                                      size = len;
++                              else
++                                      size = MAX_TXD_LEN;
++                              if(skb_txd_num%2 == 0) { 
++                                      tx_cpu_owner_idx0 = (tx_cpu_owner_idx0+1) % NUM_TX_DESC; 
++
++                                      while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0)
++                                      {
++#ifdef config_pseudo_support
++                                              if (gmac_no == 2) {
++                                                      if (ei_local->pseudodev != null) {
++                                                              pad = netdev_priv(ei_local->pseudodev);
++                                                              pad->stat.tx_errors++;
++                                                      }
++                                              } else
++#endif
++                                                      ei_local->stat.tx_errors++;
++                                      }
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)                                        
++                                      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = pci_map_page(NULL, frag->page, offset, size, PCI_DMA_TODEVICE);
++#else
++                                      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = pci_map_page(NULL, frag->page.p, offset, size, PCI_DMA_TODEVICE);
++#endif
++                                      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = size;
++
++                                      if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++                                              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = 1;
++                                      else
++                                              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS0_bit = 0;
++                                      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit = 0;
++                              }else { 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)                                        
++                                      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1 = pci_map_page(NULL, frag->page, offset, size, PCI_DMA_TODEVICE);
++#else
++                                      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info3.SDP1 = pci_map_page(NULL, frag->page.p, offset, size, PCI_DMA_TODEVICE);
++
++#endif
++                                      ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL1 = size;
++                                      if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++                                              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit = 1;
++                                      else
++                                              ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.LS1_bit = 0;
++                              }
++                              offset += size;
++                              len -= size;
++                              frag_txd_num--;
++                              skb_txd_num++;
++                      }
++              }
++      }
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++    if( (pdma_dvt_get_debug_test_config() & PDMA_TEST_TSO_DEBUG) ){
++        printk("skb_shinfo(skb)->gso_segs = %d\n", skb_shinfo(skb)->gso_segs);
++    }
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++      /* fill in MSS info in tcp checksum field */
++      if(skb_shinfo(skb)->gso_segs > 1) {
++
++//            TsoLenUpdate(skb->len);
++
++              /* TCP over IPv4 */
++              iph = (struct iphdr *)skb_network_header(skb);
++#if defined (CONFIG_RAETH_TSOV6)
++              /* TCP over IPv6 */
++              ip6h = (struct ipv6hdr *)skb_network_header(skb);
++#endif                                
++              if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) {
++                      th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                      ei_local->tx_ring0[ctx_idx_start_addr].txd_info4.TSO = 1;
++#else
++                      ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info4.TSO = 1;
++#endif
++                      th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++                      dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++                      dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++              } 
++          
++#if defined (CONFIG_RAETH_TSOV6)
++              /* TCP over IPv6 */
++              else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) {
++                      th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                      ei_local->tx_ring0[ctx_idx_start_addr].txd_info4.TSO = 1;
++#else
++                      ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info4.TSO = 1;
++#endif
++                      th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)
++                      dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++                      dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++              }
++#endif // CONFIG_RAETH_TSOV6 //
++      }
++
++#if defined(CONFIG_RAETH_PDMA_DVT)
++    raeth_pdma_tx_desc_dvt( ei_local, tx_cpu_owner_idx0 );
++#endif  /* CONFIG_RAETH_PDMA_DVT */
++
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      ei_local->tx_ring0[ctx_idx_start_addr].txd_info2.DDONE_bit = 0;
++#else
++      ei_local->tx_ring0[sysRegRead(TX_CTX_IDX0)].txd_info2.DDONE_bit = 0;
++#endif
++#endif // CONFIG_RAETH_TSO //
++
++      tx_cpu_owner_idx0 = (tx_cpu_owner_idx0+1) % NUM_TX_DESC;
++      while(ei_local->tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0)
++      {
++//            printk(KERN_ERR "%s: TXD=%lu TX DMA is Busy !!\n", dev->name, tx_cpu_owner_idx0);
++#ifdef CONFIG_PSEUDO_SUPPORT
++              if (gmac_no == 2) {
++                      if (ei_local->PseudoDev != NULL) {
++                              pAd = netdev_priv(ei_local->PseudoDev);
++                              pAd->stat.tx_errors++;
++                      }
++              } else
++#endif
++                      ei_local->stat.tx_errors++;
++      }
++      sysRegWrite(TX_CTX_IDX0, cpu_to_le32((u32)tx_cpu_owner_idx0));
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      if (gmac_no == 2) {
++              if (ei_local->PseudoDev != NULL) {
++                      pAd = netdev_priv(ei_local->PseudoDev);
++                      pAd->stat.tx_packets++;
++                      pAd->stat.tx_bytes += length;
++              }
++      } else
++#endif
++      {
++              ei_local->stat.tx_packets++;
++              ei_local->stat.tx_bytes += length;
++      }
++#ifdef CONFIG_RAETH_NAPI
++      if ( ei_local->tx_full == 1) {
++              ei_local->tx_full = 0;
++              netif_wake_queue(dev);
++      }
++#endif
++
++      return length;
++}
++
++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no)
++{
++      END_DEVICE *ei_local = netdev_priv(dev);
++      unsigned long flags;
++      unsigned long tx_cpu_owner_idx;
++      unsigned int tx_cpu_owner_idx_next;
++      unsigned int num_of_txd = 0;
++#if defined (CONFIG_RAETH_TSO)
++      unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i;
++      struct skb_frag_struct *frag;
++#endif
++#if   !defined(CONFIG_RAETH_QOS)
++      unsigned int tx_cpu_owner_idx_next2;
++#else
++      int ring_no, queue_no, port_no;
++#endif
++#ifdef CONFIG_RALINK_VISTA_BASIC
++      struct vlan_ethhdr *veth;
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++      PSEUDO_ADAPTER *pAd;
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++      if(ra_sw_nat_hook_tx!= NULL)
++      {
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++          if(FOE_MAGIC_TAG(skb) != FOE_MAGIC_PPE)
++#endif
++          {
++              //spin_lock_irqsave(&ei_local->page_lock, flags);
++              if(ra_sw_nat_hook_tx(skb, gmac_no)==1){
++                  //spin_unlock_irqrestore(&ei_local->page_lock, flags);
++              }else{
++                  kfree_skb(skb);
++                  //spin_unlock_irqrestore(&ei_local->page_lock, flags);
++                  return 0;
++              }
++          }
++      }
++#endif
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++              /* Qwert+
++               */
++              if(ra_classifier_hook_tx!= NULL)
++              {
++#if defined(CONFIG_RALINK_EXTERNAL_TIMER)
++                      ra_classifier_hook_tx(skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF));
++#else                 
++                      ra_classifier_hook_tx(skb, read_c0_count());
++#endif                        
++              }
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++      mcast_tx(skb);
++#endif
++
++#if !defined (CONFIG_RALINK_RT6855) && !defined (CONFIG_RALINK_RT6855A) && \
++    !defined(CONFIG_RALINK_MT7621) && !defined (CONFIG_ARCH_MT7623)
++
++#define MIN_PKT_LEN  60
++       if (skb->len < MIN_PKT_LEN) {
++           if (skb_padto(skb, MIN_PKT_LEN)) {
++               printk("raeth: skb_padto failed\n");
++               return 0;
++           }
++           skb_put(skb, MIN_PKT_LEN - skb->len);
++       }
++#endif
++
++      dev->trans_start = jiffies;     /* save the timestamp */
++      spin_lock_irqsave(&ei_local->page_lock, flags);
++#if defined (CONFIG_MIPS)
++      dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++      dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++
++#endif
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++      veth = (struct vlan_ethhdr *)(skb->data);
++      if (is_switch_175c && veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
++              if ((veth->h_vlan_TCI & __constant_htons(VLAN_VID_MASK)) == 0) {
++                      veth->h_vlan_TCI |= htons(VLAN_DEV_INFO(dev)->vlan_id);
++              }
++      }
++#endif
++
++#if defined (CONFIG_RAETH_QOS)
++      if(pkt_classifier(skb, gmac_no, &ring_no, &queue_no, &port_no)) {
++              get_tx_ctx_idx(ring_no, &tx_cpu_owner_idx);
++              tx_cpu_owner_idx_next = (tx_cpu_owner_idx + 1) % NUM_TX_DESC;
++        if(((ei_local->skb_free[ring_no][tx_cpu_owner_idx]) ==0) && (ei_local->skb_free[ring_no][tx_cpu_owner_idx_next]==0)){
++          fe_qos_packet_send(dev, skb, ring_no, queue_no, port_no);
++        }else{
++          ei_local->stat.tx_dropped++;
++          kfree_skb(skb);
++          spin_unlock_irqrestore(&ei_local->page_lock, flags);
++          return 0;
++        }
++      }
++#else
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      tx_cpu_owner_idx = tx_cpu_owner_idx0;
++#else
++      tx_cpu_owner_idx = sysRegRead(TX_CTX_IDX0);
++#endif
++#if defined (CONFIG_RAETH_TSO)
++//    num_of_txd = (nr_frags==0) ? 1 : ((nr_frags>>1) + 1);
++//    NumOfTxdUpdate(num_of_txd);
++      if(nr_frags != 0){
++              for(i=0;i<nr_frags;i++) {
++                      frag = &skb_shinfo(skb)->frags[i];
++                      num_of_txd  += cal_frag_txd_num(frag->size);
++              }
++              num_of_txd = (num_of_txd >> 1) + 1;
++      }else
++              num_of_txd = 1;
++
++#else
++      num_of_txd = 1;
++#endif
++      tx_cpu_owner_idx_next = (tx_cpu_owner_idx + num_of_txd) % NUM_TX_DESC;
++
++      if(((ei_local->skb_free[tx_cpu_owner_idx]) ==0) && (ei_local->skb_free[tx_cpu_owner_idx_next]==0)){
++              rt2880_eth_send(dev, skb, gmac_no);
++
++              tx_cpu_owner_idx_next2 = (tx_cpu_owner_idx_next + 1) % NUM_TX_DESC;
++
++              if(ei_local->skb_free[tx_cpu_owner_idx_next2]!=0){
++#if defined (CONFIG_RAETH_SW_FC)                  
++                              netif_stop_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++                              netif_stop_queue(ei_local->PseudoDev);
++#endif
++                              tx_ring_full=1;
++#endif
++              }
++      }else {
++#ifdef CONFIG_PSEUDO_SUPPORT
++              if (gmac_no == 2) {
++                      if (ei_local->PseudoDev != NULL) {
++                              pAd = netdev_priv(ei_local->PseudoDev);
++                              pAd->stat.tx_dropped++;
++                      }
++              } else
++#endif
++                      ei_local->stat.tx_dropped++;
++#if defined (CONFIG_RAETH_SW_FC)                  
++              printk("tx_ring_full, drop packet\n");
++#endif
++              kfree_skb(skb);
++              spin_unlock_irqrestore(&ei_local->page_lock, flags);
++              return 0;
++      }
++
++#if defined (CONFIG_RAETH_TSO)
++      /* SG: use multiple TXD to send the packet (only have one skb) */
++      ei_local->skb_free[(tx_cpu_owner_idx + num_of_txd - 1) % NUM_TX_DESC] = skb;
++      while(--num_of_txd) {
++              ei_local->skb_free[(tx_cpu_owner_idx + num_of_txd -1) % NUM_TX_DESC] = (struct  sk_buff *)0xFFFFFFFF; //MAGIC ID
++      }
++#else
++      ei_local->skb_free[tx_cpu_owner_idx] = skb;
++#endif
++#endif
++      spin_unlock_irqrestore(&ei_local->page_lock, flags);
++      return 0;
++}
++
++void ei_xmit_housekeeping(unsigned long unused)
++{
++    struct net_device *dev = dev_raether;
++    END_DEVICE *ei_local = netdev_priv(dev);
++    struct PDMA_txdesc *tx_desc;
++    unsigned long skb_free_idx;
++    unsigned long tx_dtx_idx __maybe_unused;
++#ifndef CONFIG_RAETH_NAPI
++    unsigned long reg_int_mask=0;
++#endif
++
++#ifdef CONFIG_RAETH_QOS
++    int i;
++    for (i=0;i<NUM_TX_RINGS;i++){
++        skb_free_idx = ei_local->free_idx[i];
++      if((ei_local->skb_free[i][skb_free_idx])==0){
++              continue;
++      }
++
++      get_tx_desc_and_dtx_idx(ei_local, i, &tx_dtx_idx, &tx_desc);
++
++      while(tx_desc[skb_free_idx].txd_info2.DDONE_bit==1 && (ei_local->skb_free[i][skb_free_idx])!=0 ){
++              dev_kfree_skb_any((ei_local->skb_free[i][skb_free_idx]));
++
++          ei_local->skb_free[i][skb_free_idx]=0;
++          skb_free_idx = (skb_free_idx +1) % NUM_TX_DESC;
++      }
++      ei_local->free_idx[i] = skb_free_idx;
++    }
++#else
++      tx_dtx_idx = sysRegRead(TX_DTX_IDX0);
++      tx_desc = ei_local->tx_ring0;
++      skb_free_idx = ei_local->free_idx;
++      if ((ei_local->skb_free[skb_free_idx]) != 0 && tx_desc[skb_free_idx].txd_info2.DDONE_bit==1) {
++              while(tx_desc[skb_free_idx].txd_info2.DDONE_bit==1 && (ei_local->skb_free[skb_free_idx])!=0 ){
++#if defined (CONFIG_RAETH_TSO)
++          if(ei_local->skb_free[skb_free_idx]!=(struct  sk_buff *)0xFFFFFFFF) {
++                  dev_kfree_skb_any(ei_local->skb_free[skb_free_idx]);
++          }
++#else
++          dev_kfree_skb_any(ei_local->skb_free[skb_free_idx]);
++#endif
++          ei_local->skb_free[skb_free_idx]=0;
++          skb_free_idx = (skb_free_idx +1) % NUM_TX_DESC;
++      }
++
++      netif_wake_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++              netif_wake_queue(ei_local->PseudoDev);
++#endif
++              tx_ring_full=0;
++              ei_local->free_idx = skb_free_idx;
++      }  /* if skb_free != 0 */
++#endif
++
++#ifndef CONFIG_RAETH_NAPI
++    reg_int_mask=sysRegRead(FE_INT_ENABLE);
++#if defined (DELAY_INT)
++    sysRegWrite(FE_INT_ENABLE, reg_int_mask| TX_DLY_INT);
++#else
++
++    sysRegWrite(FE_INT_ENABLE, reg_int_mask | TX_DONE_INT0 \
++                                          | TX_DONE_INT1 \
++                                          | TX_DONE_INT2 \
++                                          | TX_DONE_INT3);
++#endif
++#endif //CONFIG_RAETH_NAPI//
++}
++
++
++
++EXPORT_SYMBOL(ei_start_xmit);
++EXPORT_SYMBOL(ei_xmit_housekeeping);
++EXPORT_SYMBOL(fe_dma_init);
++EXPORT_SYMBOL(rt2880_eth_send);
+diff --git a/drivers/net/ethernet/raeth/raether_qdma.c b/drivers/net/ethernet/raeth/raether_qdma.c
+new file mode 100644
+index 0000000..acf8bfe
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_qdma.c
+@@ -0,0 +1,1407 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++#if defined (CONFIG_HW_SFQ)
++#include <linux/if_vlan.h>
++#include <net/ipv6.h>
++#include <net/ip.h>
++#include <linux/if_pppox.h>
++#include <linux/ppp_defs.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++ 
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++#ifdef RA_MTD_RW_BY_NUM
++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
++#else
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
++#endif
++
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#if defined     (CONFIG_ARCH_MT7623)
++#undef DELAY_INT
++#else
++#define DELAY_INT       1
++#endif
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define       MAX_RX_LENGTH   4096
++#else
++#define       MAX_RX_LENGTH   1536
++#endif
++
++extern struct net_device              *dev_raether;
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static int rx_dma_owner_idx1;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx0;
++static unsigned long tx_cpu_owner_idx0=0;
++#endif
++extern unsigned long tx_ring_full;
++
++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER)
++#include "ra_ethtool.h"
++extern struct ethtool_ops     ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops     ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++//skb->mark to queue mapping table
++extern unsigned int M2Q_table[64];
++struct QDMA_txdesc *free_head = NULL;
++extern unsigned int lan_wan_separate;
++#if defined (CONFIG_HW_SFQ)
++extern unsigned int web_sfq_enable;
++#define HwSfqQUp 3
++#define HwSfqQDl 1
++#endif
++int dbg =0;//debug used
++#if defined (CONFIG_HW_SFQ)
++struct SFQ_table *sfq0;
++struct SFQ_table *sfq1;
++struct SFQ_table *sfq2;
++struct SFQ_table *sfq3;
++#endif
++
++#define KSEG1                   0xa0000000
++#if defined (CONFIG_MIPS)
++#define PHYS_TO_VIRT(x)         ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x)         ((unsigned long)(x) & ~KSEG1)
++#else
++#define PHYS_TO_VIRT(x)         phys_to_virt(x)
++#define VIRT_TO_PHYS(x)         virt_to_phys(x)
++#endif
++
++extern void set_fe_dma_glo_cfg(void);
++
++#if defined (CONFIG_HW_SFQ)
++ParseResult           SfqParseResult;
++#endif
++
++/**
++ *
++ * @brief: get the TXD index from its address
++ *
++ * @param: cpu_ptr
++ *
++ * @return: TXD index
++*/
++
++static unsigned int GET_TXD_OFFSET(struct QDMA_txdesc **cpu_ptr)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      int ctx_offset;
++      //ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++      //ctx_offset = (*cpu_ptr - ei_local->txd_pool);
++      ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->phy_txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++
++      return ctx_offset;
++} 
++
++
++
++
++/**
++ * @brief cal txd number for a page
++ *
++ * @parm size
++ *
++ * @return frag_txd_num
++ */
++
++unsigned int cal_frag_txd_num(unsigned int size)
++{
++      unsigned int frag_txd_num = 0;
++      if(size == 0)
++              return 0;
++      while(size > 0){
++              if(size > MAX_TXD_LEN){
++                      frag_txd_num++;
++                      size -= MAX_TXD_LEN;
++              }else{
++                      frag_txd_num++;
++                      size = 0;
++              }
++      }
++        return frag_txd_num;
++
++}
++
++/**
++ * @brief get free TXD from TXD queue
++ *
++ * @param free_txd
++ *
++ * @return 
++ */
++static int get_free_txd(struct QDMA_txdesc **free_txd)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      unsigned int tmp_idx;
++
++      if(ei_local->free_txd_num > 0){
++              tmp_idx = ei_local->free_txd_head;
++              ei_local->free_txd_head = ei_local->txd_pool_info[tmp_idx];
++              ei_local->free_txd_num -= 1;
++              //*free_txd = &ei_local->txd_pool[tmp_idx];
++              *free_txd = ei_local->phy_txd_pool + (sizeof(struct QDMA_txdesc) * tmp_idx);
++              return tmp_idx;
++      }else
++              return NUM_TX_DESC;     
++}
++
++
++/**
++ * @brief add free TXD into TXD queue
++ *
++ * @param free_txd
++ *
++ * @return 
++ */
++int put_free_txd(int free_txd_idx)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      ei_local->txd_pool_info[ei_local->free_txd_tail] = free_txd_idx;
++      ei_local->free_txd_tail = free_txd_idx;
++      ei_local->txd_pool_info[free_txd_idx] = NUM_TX_DESC;
++        ei_local->free_txd_num += 1;
++      return 1;
++}
++
++/*define qdma initial alloc*/
++/**
++ * @brief 
++ *
++ * @param net_dev
++ *
++ * @return  0: fail
++ *        1: success
++ */
++bool qdma_tx_desc_alloc(void)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      struct QDMA_txdesc *free_txd = NULL;
++      unsigned int txd_idx;
++      int i = 0;
++
++
++      ei_local->txd_pool = pci_alloc_consistent(NULL, sizeof(struct QDMA_txdesc) * NUM_TX_DESC, &ei_local->phy_txd_pool);
++      printk("txd_pool=%p phy_txd_pool=%08X\n", ei_local->txd_pool , ei_local->phy_txd_pool);
++
++      if (ei_local->txd_pool == NULL) {
++              printk("adapter->txd_pool allocation failed!\n");
++              return 0;
++      }
++      printk("ei_local->skb_free start address is 0x%p.\n", ei_local->skb_free);
++      //set all txd_pool_info to 0.
++      for ( i = 0; i < NUM_TX_DESC; i++)
++      {
++              ei_local->skb_free[i]= 0;
++              ei_local->txd_pool_info[i] = i + 1;
++              ei_local->txd_pool[i].txd_info3.LS_bit = 1;
++              ei_local->txd_pool[i].txd_info3.OWN_bit = 1;
++      }
++
++      ei_local->free_txd_head = 0;
++      ei_local->free_txd_tail = NUM_TX_DESC - 1;
++      ei_local->free_txd_num = NUM_TX_DESC;
++      
++
++      //get free txd from txd pool
++      txd_idx = get_free_txd(&free_txd);
++      if( txd_idx == NUM_TX_DESC) {
++              printk("get_free_txd fail\n");
++              return 0;
++      }
++      
++      //add null TXD for transmit
++      //ei_local->tx_dma_ptr = VIRT_TO_PHYS(free_txd);
++      //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++      ei_local->tx_dma_ptr = free_txd;
++      ei_local->tx_cpu_ptr = free_txd;
++      sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++      sysRegWrite(QTX_DTX_PTR, ei_local->tx_dma_ptr);
++      
++      //get free txd from txd pool
++
++      txd_idx = get_free_txd(&free_txd);
++      if( txd_idx == NUM_TX_DESC) {
++              printk("get_free_txd fail\n");
++              return 0;
++      }
++      // add null TXD for release
++      //sysRegWrite(QTX_CRX_PTR, VIRT_TO_PHYS(free_txd));
++      //sysRegWrite(QTX_DRX_PTR, VIRT_TO_PHYS(free_txd));
++      sysRegWrite(QTX_CRX_PTR, free_txd);
++      sysRegWrite(QTX_DRX_PTR, free_txd);
++      printk("free_txd: %p, ei_local->cpu_ptr: %08X\n", free_txd, ei_local->tx_cpu_ptr);
++      
++      printk(" POOL  HEAD_PTR | DMA_PTR | CPU_PTR \n");
++      printk("----------------+---------+--------\n");
++      printk("     0x%p 0x%08X 0x%08X\n",ei_local->txd_pool, ei_local->tx_dma_ptr, ei_local->tx_cpu_ptr);
++      return 1;
++}
++#if defined (CONFIG_HW_SFQ)
++bool sfq_init(void)
++{
++      unsigned int regVal;
++      
++      unsigned int sfq_phy0;
++      unsigned int sfq_phy1;
++      unsigned int sfq_phy2;
++      unsigned int sfq_phy3;  
++  struct SFQ_table *sfq0;
++      struct SFQ_table *sfq1;
++      struct SFQ_table *sfq2;
++      struct SFQ_table *sfq3;
++      int i = 0;
++      regVal = sysRegRead(VQTX_GLO);
++      regVal = regVal | VQTX_MIB_EN |(1<<16) ;
++      sysRegWrite(VQTX_GLO, regVal);// Virtual table extends to 32bytes
++      regVal = sysRegRead(VQTX_GLO);
++      sysRegWrite(VQTX_NUM, (VQTX_NUM_0) | (VQTX_NUM_1) | (VQTX_NUM_2) | (VQTX_NUM_3));
++      sysRegWrite(VQTX_HASH_CFG, 0xF002710); //10 s change hash algorithm
++  sysRegWrite(VQTX_VLD_CFG, 0x00);
++      sysRegWrite(VQTX_HASH_SD, 0x0D);
++      sysRegWrite(QDMA_FC_THRES, 0x9b9b4444);
++      sysRegWrite(QDMA_HRED1, 0);
++      sysRegWrite(QDMA_HRED2, 0);
++      sysRegWrite(QDMA_SRED1, 0);
++      sysRegWrite(QDMA_SRED2, 0);
++      sfq0 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy0);
++      memset(sfq0, 0x0, 256*sizeof(struct SFQ_table) );
++      for (i=0; i < 256; i++) {
++                      sfq0[i].sfq_info1.VQHPTR = 0xdeadbeef;
++      sfq0[i].sfq_info2.VQTPTR = 0xdeadbeef;
++      }
++#if(1)
++      sfq1 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy1);
++
++      memset(sfq1, 0x0, 256*sizeof(struct SFQ_table) );
++      for (i=0; i < 256; i++) {
++                      sfq1[i].sfq_info1.VQHPTR = 0xdeadbeef;
++      sfq1[i].sfq_info2.VQTPTR = 0xdeadbeef;
++      }
++      
++      sfq2 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy2);
++      memset(sfq2, 0x0, 256*sizeof(struct SFQ_table) );
++      for (i=0; i < 256; i++) {
++                      sfq2[i].sfq_info1.VQHPTR = 0xdeadbeef;
++      sfq2[i].sfq_info2.VQTPTR = 0xdeadbeef;
++      }
++
++      sfq3 = pci_alloc_consistent(NULL, 256*sizeof(struct SFQ_table), &sfq_phy3);
++      memset(sfq3, 0x0, 256*sizeof(struct SFQ_table) );
++      for (i=0; i < 256; i++) {
++                      sfq3[i].sfq_info1.VQHPTR = 0xdeadbeef;
++      sfq3[i].sfq_info2.VQTPTR = 0xdeadbeef;
++      }
++
++#endif
++              printk("*****sfq_phy0 is 0x%x!!!*******\n", sfq_phy0);
++              printk("*****sfq_phy1 is 0x%x!!!*******\n", sfq_phy1);
++              printk("*****sfq_phy2 is 0x%x!!!*******\n", sfq_phy2);
++              printk("*****sfq_phy3 is 0x%x!!!*******\n", sfq_phy3);
++              printk("*****sfq_virt0 is 0x%x!!!*******\n", sfq0);
++              printk("*****sfq_virt1 is 0x%x!!!*******\n", sfq1);
++              printk("*****sfq_virt2 is 0x%x!!!*******\n", sfq2);
++              printk("*****sfq_virt3 is 0x%x!!!*******\n", sfq3);
++              printk("*****sfq_virt0 is 0x%x!!!*******\n", sfq0);
++              sysRegWrite(VQTX_TB_BASE0, (u32)sfq_phy0);
++              sysRegWrite(VQTX_TB_BASE1, (u32)sfq_phy1);
++              sysRegWrite(VQTX_TB_BASE2, (u32)sfq_phy2);
++              sysRegWrite(VQTX_TB_BASE3, (u32)sfq_phy3);
++
++       return 1;
++}
++#endif
++bool fq_qdma_init(struct net_device *dev)
++{
++      END_DEVICE* ei_local = netdev_priv(dev);
++      //struct QDMA_txdesc *free_head = NULL;
++      unsigned int phy_free_head;
++      unsigned int phy_free_tail;
++      unsigned int *free_page_head = NULL;
++      unsigned int phy_free_page_head;
++      int i;
++    
++      free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &phy_free_head);
++      if (unlikely(free_head == NULL)){
++              printk(KERN_ERR "QDMA FQ decriptor not available...\n");
++              return 0;
++      }
++      memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE);
++
++      free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &phy_free_page_head);
++      if (unlikely(free_page_head == NULL)){
++              printk(KERN_ERR "QDMA FQ page not available...\n");
++              return 0;
++      }       
++      for (i=0; i < NUM_QDMA_PAGE; i++) {
++              free_head[i].txd_info1.SDP = (phy_free_page_head + (i * QDMA_PAGE_SIZE));
++              if(i < (NUM_QDMA_PAGE-1)){
++                      free_head[i].txd_info2.NDP = (phy_free_head + ((i+1) * sizeof(struct QDMA_txdesc)));
++
++
++#if 0
++                      printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) );
++                      printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] );
++                      printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP );
++                      printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP );
++#endif
++              }
++              free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE;
++
++      }
++      phy_free_tail = (phy_free_head + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc)));
++
++      printk("phy_free_head is 0x%x!!!\n", phy_free_head);
++      printk("phy_free_tail_phy is 0x%x!!!\n", phy_free_tail);
++      sysRegWrite(QDMA_FQ_HEAD, (u32)phy_free_head);
++      sysRegWrite(QDMA_FQ_TAIL, (u32)phy_free_tail);
++      sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE));
++      sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16);
++
++      ei_local->free_head = free_head;
++      ei_local->phy_free_head = phy_free_head;
++      ei_local->free_page_head = free_page_head;
++      ei_local->phy_free_page_head = phy_free_page_head;
++    return 1;
++}
++
++int fe_dma_init(struct net_device *dev)
++{
++
++      int i;
++      unsigned int    regVal;
++      END_DEVICE* ei_local = netdev_priv(dev);
++      
++      
++      #if defined (CONFIG_HW_SFQ)
++      sfq_init();
++  #endif
++      fq_qdma_init(dev);
++
++      while(1)
++      {
++              regVal = sysRegRead(QDMA_GLO_CFG);
++              if((regVal & RX_DMA_BUSY))
++              {
++                      printk("\n  RX_DMA_BUSY !!! ");
++                      continue;
++              }
++              if((regVal & TX_DMA_BUSY))
++              {
++                      printk("\n  TX_DMA_BUSY !!! ");
++                      continue;
++              }
++              break;
++      }
++      /*tx desc alloc, add a NULL TXD to HW*/
++
++      qdma_tx_desc_alloc();
++
++      /* Initial RX Ring 0*/
++      
++#ifdef CONFIG_32B_DESC
++      ei_local->qrx_ring = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++      ei_local->phy_qrx_ring = virt_to_phys(ei_local->qrx_ring);
++#else
++      ei_local->qrx_ring = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_qrx_ring);
++#endif
++      for (i = 0; i < NUM_QRX_DESC; i++) {
++              memset(&ei_local->qrx_ring[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->qrx_ring[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              ei_local->qrx_ring[i].rxd_info2.LS0 = 0;
++              ei_local->qrx_ring[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++              ei_local->qrx_ring[i].rxd_info2.LS0 = 1;
++#endif
++              ei_local->qrx_ring[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      printk("\nphy_qrx_ring = 0x%08x, qrx_ring = 0x%p\n",ei_local->phy_qrx_ring,ei_local->qrx_ring);
++
++      regVal = sysRegRead(QDMA_GLO_CFG);
++      regVal &= 0x000000FF;
++
++      sysRegWrite(QDMA_GLO_CFG, regVal);
++      regVal=sysRegRead(QDMA_GLO_CFG);
++
++      /* Tell the adapter where the TX/RX rings are located. */
++
++      sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_qrx_ring));
++      sysRegWrite(QRX_MAX_CNT_0,  cpu_to_le32((u32) NUM_QRX_DESC));
++      sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_calc_idx0 = rx_dma_owner_idx0 =  sysRegRead(QRX_CRX_IDX_0);
++#endif
++      sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0);
++
++        ei_local->rx_ring0 = ei_local->qrx_ring;
++#if !defined (CONFIG_RAETH_QDMATX_QDMARX)     
++      /* Initial PDMA RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++        ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++        ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++        ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#endif
++        for (i = 0; i < NUM_RX_DESC; i++) {
++              memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++      ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++      ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++      ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++      ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++                                                              }
++        printk("\nphy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++        regVal = sysRegRead(PDMA_GLO_CFG);
++        regVal &= 0x000000FF;
++        sysRegWrite(PDMA_GLO_CFG, regVal);
++        regVal=sysRegRead(PDMA_GLO_CFG);
++
++        sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++        sysRegWrite(RX_MAX_CNT0,  cpu_to_le32((u32) NUM_RX_DESC));
++        sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++        rx_calc_idx0 =  sysRegRead(RX_CALC_IDX0);
++#endif
++        sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0);
++#endif        
++#if !defined (CONFIG_HW_SFQ)
++        /* Enable randon early drop and set drop threshold automatically */
++      sysRegWrite(QDMA_FC_THRES, 0x174444);
++#endif
++      sysRegWrite(QDMA_HRED2, 0x0);
++      set_fe_dma_glo_cfg();
++#if defined   (CONFIG_ARCH_MT7623)
++      printk("Enable QDMA TX NDP coherence check and re-read mechanism\n");
++      regVal=sysRegRead(QDMA_GLO_CFG);
++      regVal = regVal | 0x400;
++      sysRegWrite(QDMA_GLO_CFG, regVal);
++      printk("***********QDMA_GLO_CFG=%x\n", sysRegRead(QDMA_GLO_CFG));
++#endif        
++
++      return 1;
++}
++
++#if defined (CONFIG_HW_SFQ)
++
++int sfq_prot = 0;
++int proto_id=0;
++int udp_source_port=0;
++int tcp_source_port=0;
++int ack_packt =0;
++int SfqParseLayerInfo(struct sk_buff * skb)
++{
++
++      struct vlan_hdr *vh_sfq = NULL;
++      struct ethhdr *eth_sfq = NULL;
++      struct iphdr *iph_sfq = NULL;
++      struct ipv6hdr *ip6h_sfq = NULL;
++      struct tcphdr *th_sfq = NULL;
++      struct udphdr *uh_sfq = NULL;
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++      struct vlan_hdr pseudo_vhdr_sfq;
++#endif
++      
++      memset(&SfqParseResult, 0, sizeof(SfqParseResult));
++
++      eth_sfq = (struct ethhdr *)skb->data;
++      memcpy(SfqParseResult.dmac, eth_sfq->h_dest, ETH_ALEN);
++      memcpy(SfqParseResult.smac, eth_sfq->h_source, ETH_ALEN);
++      SfqParseResult.eth_type = eth_sfq->h_proto;
++      
++      
++      if (SfqParseResult.eth_type == htons(ETH_P_8021Q)){
++              SfqParseResult.vlan1_gap = VLAN_HLEN;
++              vh_sfq = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++              SfqParseResult.eth_type = vh_sfq->h_vlan_encapsulated_proto;
++      }else{
++              SfqParseResult.vlan1_gap = 0;
++      }
++              
++      
++      
++      LAYER2_HEADER(skb) = skb->data;
++  LAYER3_HEADER(skb) = (skb->data + ETH_HLEN + (SfqParseResult.vlan1_gap));
++  
++
++  
++      /* set layer4 start addr */
++      if ((SfqParseResult.eth_type == htons(ETH_P_IP)) || (SfqParseResult.eth_type == htons(ETH_P_PPP_SES) 
++              && SfqParseResult.ppp_tag == htons(PPP_IP))) {
++              iph_sfq = (struct iphdr *)LAYER3_HEADER(skb);
++
++              //prepare layer3/layer4 info
++              memcpy(&SfqParseResult.iph, iph_sfq, sizeof(struct iphdr));
++              if (iph_sfq->protocol == IPPROTO_TCP) {
++
++                      LAYER4_HEADER(skb) = ((uint8_t *) iph_sfq + (iph_sfq->ihl * 4));
++                      th_sfq = (struct tcphdr *)LAYER4_HEADER(skb);
++                      memcpy(&SfqParseResult.th, th_sfq, sizeof(struct tcphdr));
++                      SfqParseResult.pkt_type = IPV4_HNAPT;
++                      //printk("tcp parsing\n");
++                      tcp_source_port = ntohs(SfqParseResult.th.source);
++                      udp_source_port = 0;
++                      #if(0) //for TCP ack, test use  
++                              if(ntohl(SfqParseResult.iph.saddr) == 0xa0a0a04){ // tcp ack packet 
++                                      ack_packt = 1;
++                              }else { 
++                                      ack_packt = 0;
++                              }
++                      #endif
++      sfq_prot = 2;//IPV4_HNAPT
++      proto_id = 1;//TCP
++                      if(iph_sfq->frag_off & htons(IP_MF|IP_OFFSET)) {
++                              //return 1;
++                      }
++              } else if (iph_sfq->protocol == IPPROTO_UDP) {
++                      LAYER4_HEADER(skb) = ((uint8_t *) iph_sfq + iph_sfq->ihl * 4);
++                      uh_sfq = (struct udphdr *)LAYER4_HEADER(skb);
++                      memcpy(&SfqParseResult.uh, uh_sfq, sizeof(struct udphdr));
++                      SfqParseResult.pkt_type = IPV4_HNAPT;
++                      udp_source_port = ntohs(SfqParseResult.uh.source);
++                      tcp_source_port = 0;
++                      ack_packt = 0;
++                      sfq_prot = 2;//IPV4_HNAPT
++                      proto_id =2;//UDP
++                      if(iph_sfq->frag_off & htons(IP_MF|IP_OFFSET)) {
++                              return 1;
++                      }
++              }else{
++                      sfq_prot = 1;
++              }
++      }else if (SfqParseResult.eth_type == htons(ETH_P_IPV6) || 
++                      (SfqParseResult.eth_type == htons(ETH_P_PPP_SES) &&
++                      SfqParseResult.ppp_tag == htons(PPP_IPV6))) {
++                      ip6h_sfq = (struct ipv6hdr *)LAYER3_HEADER(skb);
++                      memcpy(&SfqParseResult.ip6h, ip6h_sfq, sizeof(struct ipv6hdr));
++
++                      if (ip6h_sfq->nexthdr == NEXTHDR_TCP) {
++                              LAYER4_HEADER(skb) = ((uint8_t *) ip6h_sfq + sizeof(struct ipv6hdr));
++                              th_sfq = (struct tcphdr *)LAYER4_HEADER(skb);
++                              memcpy(&SfqParseResult.th, th_sfq, sizeof(struct tcphdr));
++                              SfqParseResult.pkt_type = IPV6_5T_ROUTE;
++                              sfq_prot = 4;//IPV6_5T
++                      #if(0) //for TCP ack, test use  
++           if(ntohl(SfqParseResult.ip6h.saddr.s6_addr32[3]) == 8){
++                              ack_packt = 1;
++                      }else { 
++                              ack_packt = 0;
++                      }
++                      #endif
++                      } else if (ip6h_sfq->nexthdr == NEXTHDR_UDP) {
++                              LAYER4_HEADER(skb) = ((uint8_t *) ip6h_sfq + sizeof(struct ipv6hdr));
++                              uh_sfq = (struct udphdr *)LAYER4_HEADER(skb);
++                              memcpy(&SfqParseResult.uh, uh_sfq, sizeof(struct udphdr));
++                              SfqParseResult.pkt_type = IPV6_5T_ROUTE;
++                              ack_packt = 0;
++                              sfq_prot = 4;//IPV6_5T
++      
++                      }else{
++                              sfq_prot = 3;//IPV6_3T
++                      }
++      }
++      
++      return 0;
++}
++#endif
++
++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no)
++{
++      unsigned int    length=skb->len;
++      END_DEVICE*     ei_local = netdev_priv(dev);
++      
++      struct QDMA_txdesc *cpu_ptr;
++
++      struct QDMA_txdesc *dma_ptr __maybe_unused;
++      struct QDMA_txdesc *free_txd;
++      int  ctx_offset;
++#if defined (CONFIG_RAETH_TSO)
++      struct iphdr *iph = NULL;
++        struct QDMA_txdesc *init_cpu_ptr;
++        struct tcphdr *th = NULL;
++      struct skb_frag_struct *frag;
++      unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++      unsigned int len, size, offset, frag_txd_num;
++      int init_txd_idx, i;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++      struct ipv6hdr *ip6h = NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      PSEUDO_ADAPTER *pAd;
++#endif
++      //cpu_ptr = PHYS_TO_VIRT(ei_local->tx_cpu_ptr);
++      //dma_ptr = PHYS_TO_VIRT(ei_local->tx_dma_ptr);
++      //ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++      cpu_ptr = (ei_local->tx_cpu_ptr);
++      ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++      cpu_ptr = phys_to_virt(ei_local->tx_cpu_ptr);
++      dma_ptr = phys_to_virt(ei_local->tx_dma_ptr);
++      cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++      ei_local->skb_free[ctx_offset] = skb;
++#if defined (CONFIG_RAETH_TSO)
++        init_cpu_ptr = cpu_ptr;
++        init_txd_idx = ctx_offset;
++#endif
++
++#if !defined (CONFIG_RAETH_TSO)
++
++      //2. prepare data
++      //cpu_ptr->txd_info1.SDP = VIRT_TO_PHYS(skb->data);
++      cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++      cpu_ptr->txd_info3.SDL = skb->len;
++#if defined (CONFIG_HW_SFQ)
++      SfqParseLayerInfo(skb);
++  cpu_ptr->txd_info4.VQID0 = 1;//1:HW hash 0:CPU
++
++
++#if(0)// for tcp ack use, test use  
++  if (ack_packt==1){
++      cpu_ptr->txd_info3.QID = 0x0a;
++      //cpu_ptr->txd_info3.VQID = 0;
++  }else{
++                      cpu_ptr->txd_info3.QID = 0;
++  }
++#endif  
++  cpu_ptr->txd_info3.PROT = sfq_prot;
++  cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan
++  
++#endif
++      if (gmac_no == 1) {
++              cpu_ptr->txd_info4.FPORT = 1;
++      }else {
++              cpu_ptr->txd_info4.FPORT = 2;
++      }
++      
++      cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#ifdef CONFIG_PSEUDO_SUPPORT
++      if((lan_wan_separate==1) && (gmac_no==2)){
++              cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQUp;
++              }
++#endif                        
++      }
++#if defined (CONFIG_HW_SFQ)
++      if((lan_wan_separate==1) && (gmac_no==1)){
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQDl;      
++              }
++      }
++#endif
++#endif //end CONFIG_PSEUDO_SUPPORT
++
++      if(dbg==1){
++              printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]);
++              printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID);
++      }
++#if 0 
++      iph = (struct iphdr *)skb_network_header(skb);
++        if (iph->tos == 0xe0)
++              cpu_ptr->txd_info3.QID = 3;
++      else if (iph->tos == 0xa0) 
++              cpu_ptr->txd_info3.QID = 2;     
++        else if (iph->tos == 0x20)
++              cpu_ptr->txd_info3.QID = 1;
++        else 
++              cpu_ptr->txd_info3.QID = 0;
++#endif
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++      if (skb->ip_summed == CHECKSUM_PARTIAL){
++          cpu_ptr->txd_info4.TUI_CO = 7;
++      }else {
++          cpu_ptr->txd_info4.TUI_CO = 0;
++      }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++      if(vlan_tx_tag_present(skb)) {
++          cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++      }else {
++          cpu_ptr->txd_info4.VLAN_TAG = 0;
++      }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX // QoS Web UI used
++
++      if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){
++              cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQUp;
++              }
++#endif                        
++      }
++#if defined (CONFIG_HW_SFQ)
++      if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQDl;      
++              }
++      }
++#endif
++#endif // CONFIG_RAETH_HW_VLAN_TX
++
++
++//no hw van, no GE2, web UI used
++#ifndef CONFIG_PSEUDO_SUPPORT
++#ifndef CONFIG_RAETH_HW_VLAN_TX 
++      if(lan_wan_separate==1){
++              struct vlan_hdr *vh = NULL;
++    unsigned short vlanid = 0;
++    unsigned short vlan_TCI;
++              vh = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++              vlan_TCI = vh->h_vlan_TCI;
++    vlanid = (vlan_TCI & VLAN_VID_MASK)>>8;
++              if(vlanid == 2)//to wan
++              {
++                              cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++                              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                                      cpu_ptr->txd_info3.QID = HwSfqQUp;
++                              }
++#endif                        
++              }else if(vlanid == 1){ //to lan
++#if defined (CONFIG_HW_SFQ)
++                              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                                      cpu_ptr->txd_info3.QID = HwSfqQDl;      
++                              }
++#endif
++              }
++      }
++#endif
++#endif
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++      if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++              if(ra_sw_nat_hook_rx!= NULL){
++                  cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++                  FOE_MAGIC_TAG(skb) = 0;
++          }
++  }
++#endif
++#if 0
++      cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++      cpu_ptr->txd_info4.UDF = 0x2F;
++#endif
++      
++#if defined (CONFIG_MIPS)     
++      dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++      dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++      cpu_ptr->txd_info3.SWC_bit = 1;
++
++      //3. get NULL TXD and decrease free_tx_num by 1.
++      ctx_offset = get_free_txd(&free_txd);
++      if(ctx_offset == NUM_TX_DESC) {
++          printk("get_free_txd fail\n"); // this should not happen. free_txd_num is 2 at least.
++          return 0;
++      }
++
++      //4. hook new TXD in the end of queue
++      //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd);
++      cpu_ptr->txd_info2.NDP = (free_txd);
++
++
++      //5. move CPU_PTR to new TXD
++      //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++      ei_local->tx_cpu_ptr = (free_txd);
++      cpu_ptr->txd_info3.OWN_bit = 0;
++      sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++      
++#if 0 
++      printk("----------------------------------------------\n");
++      printk("txd_info1:%08X \n",*(int *)&cpu_ptr->txd_info1);
++      printk("txd_info2:%08X \n",*(int *)&cpu_ptr->txd_info2);
++      printk("txd_info3:%08X \n",*(int *)&cpu_ptr->txd_info3);
++      printk("txd_info4:%08X \n",*(int *)&cpu_ptr->txd_info4);
++#endif                        
++
++#else //#if !defined (CONFIG_RAETH_TSO)       
++      cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++      cpu_ptr->txd_info3.SDL = (length - skb->data_len);
++      cpu_ptr->txd_info3.LS_bit = nr_frags ? 0:1;
++#if defined (CONFIG_HW_SFQ)           
++              SfqParseLayerInfo(skb);
++               // printk("tcp_source_port=%d\n", tcp_source_port);
++#if(0)
++   cpu_ptr->txd_info4.VQID0 = 0;//1:HW hash 0:CPU
++  if (tcp_source_port==1000)  cpu_ptr->txd_info3.VQID = 0;
++  else if (tcp_source_port==1100)  cpu_ptr->txd_info3.VQID = 1;
++  else if (tcp_source_port==1200)  cpu_ptr->txd_info3.VQID = 2;
++  else cpu_ptr->txd_info3.VQID = 0;
++ #else 
++      cpu_ptr->txd_info4.VQID0 = 1;
++  cpu_ptr->txd_info3.PROT = sfq_prot;
++  cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan
++#endif
++#endif
++      if (gmac_no == 1) {
++              cpu_ptr->txd_info4.FPORT = 1;
++      }else {
++              cpu_ptr->txd_info4.FPORT = 2;
++      }
++      
++      cpu_ptr->txd_info4.TSO = 0;
++        cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];        
++#ifdef CONFIG_PSEUDO_SUPPORT //web UI used tso
++      if((lan_wan_separate==1) && (gmac_no==2)){
++              cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++              if(web_sfq_enable == 1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQUp;      
++              }
++#endif                
++      }
++#if defined (CONFIG_HW_SFQ)
++      if((lan_wan_separate==1) && (gmac_no==1)){
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                              cpu_ptr->txd_info3.QID = HwSfqQDl;      
++              }
++      }
++#endif
++#endif //CONFIG_PSEUDO_SUPPORT
++      if(dbg==1){
++              printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]);
++              printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID);
++      }
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++      if (skb->ip_summed == CHECKSUM_PARTIAL){
++          cpu_ptr->txd_info4.TUI_CO = 7;
++      }else {
++          cpu_ptr->txd_info4.TUI_CO = 0;
++      }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++      if(vlan_tx_tag_present(skb)) {
++          cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++      }else {
++          cpu_ptr->txd_info4.VLAN_TAG = 0;
++      }
++#endif
++#ifdef CONFIG_RAETH_HW_VLAN_TX // QoS Web UI used tso
++
++      if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){
++      //cpu_ptr->txd_info3.QID += 8;
++              cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQUp;
++              }
++#endif                        
++      }
++#if defined (CONFIG_HW_SFQ)
++      if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQDl;      
++              }
++      }
++#endif
++#endif // CONFIG_RAETH_HW_VLAN_TX
++
++
++//no hw van, no GE2, web UI used
++#ifndef CONFIG_PSEUDO_SUPPORT
++#ifndef CONFIG_RAETH_HW_VLAN_TX 
++      if(lan_wan_separate==1){
++              struct vlan_hdr *vh = NULL;
++    unsigned short vlanid = 0;
++    unsigned short vlan_TCI;
++              vh = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++              vlan_TCI = vh->h_vlan_TCI;
++    vlanid = (vlan_TCI & VLAN_VID_MASK)>>8;
++              if(vlanid == 2)//eth2.2 to wan
++              {
++                      cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++                              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                                      cpu_ptr->txd_info3.QID = HwSfqQUp;
++                              }
++#endif                        
++              }else if(!strcmp(netdev, "eth2.1")){ // eth2.1 to lan
++#if defined (CONFIG_HW_SFQ)
++                      if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                              cpu_ptr->txd_info3.QID = HwSfqQDl;      
++                      }
++#endif
++              }
++}
++#endif
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++      if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++          if(ra_sw_nat_hook_rx!= NULL){
++                  cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++                  FOE_MAGIC_TAG(skb) = 0;
++          }
++      }
++#endif
++
++        cpu_ptr->txd_info3.SWC_bit = 1;
++
++        ctx_offset = get_free_txd(&free_txd);
++        if(ctx_offset == NUM_TX_DESC) {
++            printk("get_free_txd fail\n"); 
++        return 0;
++      }
++        //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd);
++        //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++      cpu_ptr->txd_info2.NDP = free_txd;
++      ei_local->tx_cpu_ptr = free_txd;
++
++
++      if(nr_frags > 0) {
++              for(i=0;i<nr_frags;i++) {
++                      // 1. set or get init value for current fragment
++                      offset = 0;  
++                      frag = &skb_shinfo(skb)->frags[i];
++                      len = frag->size; 
++                      frag_txd_num = cal_frag_txd_num(len); // calculate the needed TXD numbers for this fragment
++                      for(frag_txd_num = frag_txd_num;frag_txd_num > 0; frag_txd_num --){
++                              // 2. size will be assigned to SDL and can't be larger than MAX_TXD_LEN
++                              if(len < MAX_TXD_LEN)
++                                      size = len;
++                              else
++                                      size = MAX_TXD_LEN;                     
++
++                              //3. Update TXD info
++                              cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++                              cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#ifdef CONFIG_PSEUDO_SUPPORT //QoS Web UI used , nr_frags
++                              if((lan_wan_separate==1) && (gmac_no==2)){
++                                      //cpu_ptr->txd_info3.QID += 8;
++                                      cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++                                      if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                                              cpu_ptr->txd_info3.QID = HwSfqQUp;      
++                                      }
++#endif
++                              }
++#if defined (CONFIG_HW_SFQ)                           
++                              if((lan_wan_separate==1) && (gmac_no==1)){
++                                      if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                                              cpu_ptr->txd_info3.QID = HwSfqQDl;      
++                                      }
++                              }
++#endif
++#endif //CONFIG_PSEUDO_SUPPORT
++
++//QoS web used, nr_frags
++#ifdef CONFIG_RAETH_HW_VLAN_TX 
++      if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==2)){
++              cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQUp;
++              }
++#endif                        
++      }
++#if defined (CONFIG_HW_SFQ)
++      if((lan_wan_separate==1) && (vlan_tx_tag_get(skb)==1)){
++              if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                      cpu_ptr->txd_info3.QID = HwSfqQDl;      
++              }
++      }
++#endif
++#endif // CONFIG_RAETH_HW_VLAN_TX
++//no hw van, no GE2, web UI used
++#ifndef CONFIG_PSEUDO_SUPPORT
++#ifndef CONFIG_RAETH_HW_VLAN_TX 
++      if(lan_wan_separate==1){
++              struct vlan_hdr *vh = NULL;
++    unsigned short vlanid = 0;
++    unsigned short vlan_TCI;
++              vh = (struct vlan_hdr *)(skb->data + ETH_HLEN);
++              vlan_TCI = vh->h_vlan_TCI;
++    vlanid = (vlan_TCI & VLAN_VID_MASK)>>8;
++              if(vlanid == 2))//eth2.2 to wan
++              {
++                      cpu_ptr->txd_info3.QID += 8;
++#if defined (CONFIG_HW_SFQ)
++                      if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                              cpu_ptr->txd_info3.QID = HwSfqQUp;
++                      }
++#endif                        
++              }
++              }else if(vlanid == 1){ // eth2.1 to lan
++#if defined (CONFIG_HW_SFQ)   
++                      if(web_sfq_enable==1 &&(skb->mark == 2)){ 
++                              cpu_ptr->txd_info3.QID = HwSfqQDl;      
++                      }
++#endif
++              }
++      }
++#endif
++#endif
++      if(dbg==1){
++              printk("M2Q_table[%d]=%d\n", skb->mark, M2Q_table[skb->mark]);
++              printk("cpu_ptr->txd_info3.QID = %d\n", cpu_ptr->txd_info3.QID);
++      }
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
++                              cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE);
++#else
++                              cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page.p, frag->page_offset + offset, size, PCI_DMA_TODEVICE);
++//                            printk(" frag->page = %08x. frag->page_offset = %08x. frag->size = % 08x.\n", frag->page, (frag->page_offset+offset), size);
++#endif
++                              cpu_ptr->txd_info3.SDL = size;
++                              if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++                                      cpu_ptr->txd_info3.LS_bit = 1;
++                              else
++                                      cpu_ptr->txd_info3.LS_bit = 0;
++                              cpu_ptr->txd_info3.OWN_bit = 0;
++                              cpu_ptr->txd_info3.SWC_bit = 1;
++                              //4. Update skb_free for housekeeping
++                              ei_local->skb_free[ctx_offset] = (cpu_ptr->txd_info3.LS_bit == 1)?skb:(struct  sk_buff *)0xFFFFFFFF; //MAGIC ID
++
++                              //5. Get next TXD
++                              ctx_offset = get_free_txd(&free_txd);
++                              //cpu_ptr->txd_info2.NDP = VIRT_TO_PHYS(free_txd);
++                              //ei_local->tx_cpu_ptr = VIRT_TO_PHYS(free_txd);
++                              cpu_ptr->txd_info2.NDP = free_txd;
++                              ei_local->tx_cpu_ptr = free_txd;
++                              //6. Update offset and len.
++                              offset += size;
++                              len -= size;
++                      }
++              }
++              ei_local->skb_free[init_txd_idx]= (struct  sk_buff *)0xFFFFFFFF; //MAGIC ID
++      }
++
++      if(skb_shinfo(skb)->gso_segs > 1) {
++
++//            TsoLenUpdate(skb->len);
++
++              /* TCP over IPv4 */
++              iph = (struct iphdr *)skb_network_header(skb);
++#if defined (CONFIG_RAETH_TSOV6)
++              /* TCP over IPv6 */
++              ip6h = (struct ipv6hdr *)skb_network_header(skb);
++#endif                                
++              if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) {
++                      th = (struct tcphdr *)skb_transport_header(skb);
++#if defined (CONFIG_HW_SFQ)
++#if(0)
++  init_cpu_ptr->txd_info4.VQID0 = 0;//1:HW hash 0:CPU
++  if (tcp_source_port==1000)  init_cpu_ptr->txd_info3.VQID = 0;
++  else if (tcp_source_port==1100)  init_cpu_ptr->txd_info3.VQID = 1;
++  else if (tcp_source_port==1200)  init_cpu_ptr->txd_info3.VQID = 2;
++  else cpu_ptr->txd_info3.VQID = 0;
++ #else 
++ init_cpu_ptr->txd_info4.VQID0 = 1;
++  init_cpu_ptr->txd_info3.PROT = sfq_prot;
++  init_cpu_ptr->txd_info3.IPOFST = 14 + (SfqParseResult.vlan1_gap); //no vlan
++#endif
++#endif
++                      init_cpu_ptr->txd_info4.TSO = 1;
++
++                      th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)     
++                      dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++                      dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++              } 
++          
++#if defined (CONFIG_RAETH_TSOV6)
++              /* TCP over IPv6 */
++              //ip6h = (struct ipv6hdr *)skb_network_header(skb);
++              else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) {
++                      th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                      init_cpu_ptr->txd_info4.TSO = 1;
++#else
++                      init_cpu_ptr->txd_info4.TSO = 1;
++#endif
++                      th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)     
++                      dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++                      dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++              }
++#endif
++      }
++
++              
++//    dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);  
++
++      init_cpu_ptr->txd_info3.OWN_bit = 0;
++#endif // CONFIG_RAETH_TSO //
++
++      sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      if (gmac_no == 2) {
++              if (ei_local->PseudoDev != NULL) {
++                              pAd = netdev_priv(ei_local->PseudoDev);
++                              pAd->stat.tx_packets++;
++                              pAd->stat.tx_bytes += length;
++                      }
++              } else
++              
++#endif
++        {
++      ei_local->stat.tx_packets++;
++      ei_local->stat.tx_bytes += skb->len;
++      }
++#ifdef CONFIG_RAETH_NAPI
++      if ( ei_local->tx_full == 1) {
++              ei_local->tx_full = 0;
++              netif_wake_queue(dev);
++      }
++#endif
++
++      return length;
++}
++
++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no)
++{
++      END_DEVICE *ei_local = netdev_priv(dev);
++      unsigned long flags;
++      unsigned int num_of_txd = 0;
++#if defined (CONFIG_RAETH_TSO)
++      unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i;
++      struct skb_frag_struct *frag;
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++      PSEUDO_ADAPTER *pAd;
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++         if(ra_sw_nat_hook_tx!= NULL)
++         {
++//       spin_lock_irqsave(&ei_local->page_lock, flags);
++           if(ra_sw_nat_hook_tx(skb, gmac_no)==1){
++//            spin_unlock_irqrestore(&ei_local->page_lock, flags);
++         }else{
++              kfree_skb(skb);
++//            spin_unlock_irqrestore(&ei_local->page_lock, flags);
++              return 0;
++         }
++         }
++#endif
++
++
++
++      dev->trans_start = jiffies;     /* save the timestamp */
++      spin_lock_irqsave(&ei_local->page_lock, flags);
++#if defined (CONFIG_MIPS)     
++      dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++      dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++
++
++//check free_txd_num before calling rt288_eth_send()
++
++#if defined (CONFIG_RAETH_TSO)
++      //      num_of_txd = (nr_frags==0) ? 1 : (nr_frags + 1);
++      if(nr_frags != 0){
++              for(i=0;i<nr_frags;i++) {
++                      frag = &skb_shinfo(skb)->frags[i];
++                      num_of_txd  += cal_frag_txd_num(frag->size);
++              }
++      }else
++              num_of_txd = 1;
++#else
++      num_of_txd = 1;
++#endif
++   
++#if defined(CONFIG_RALINK_MT7621)
++    if((sysRegRead(0xbe00000c)&0xFFFF) == 0x0101) {
++          ei_xmit_housekeeping(0);
++    }
++#endif
++      
++
++    if ((ei_local->free_txd_num > num_of_txd + 1) && (ei_local->free_txd_num != NUM_TX_DESC))
++    {
++        rt2880_eth_send(dev, skb, gmac_no); // need to modify rt2880_eth_send() for QDMA
++              if (ei_local->free_txd_num < 3)
++              {
++#if defined (CONFIG_RAETH_STOP_RX_WHEN_TX_FULL)                   
++                  netif_stop_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++                  netif_stop_queue(ei_local->PseudoDev);
++#endif
++                  tx_ring_full = 1;
++#endif
++              }
++    } else {  
++#ifdef CONFIG_PSEUDO_SUPPORT
++              if (gmac_no == 2) 
++              {
++                      if (ei_local->PseudoDev != NULL) 
++                      {
++                          pAd = netdev_priv(ei_local->PseudoDev);
++                          pAd->stat.tx_dropped++;
++                  }
++              } else
++#endif
++              ei_local->stat.tx_dropped++;
++              kfree_skb(skb);
++                spin_unlock_irqrestore(&ei_local->page_lock, flags);
++              return 0;
++     }        
++      spin_unlock_irqrestore(&ei_local->page_lock, flags);
++      return 0;
++}
++
++void ei_xmit_housekeeping(unsigned long unused)
++{
++    struct net_device *dev = dev_raether;
++    END_DEVICE *ei_local = netdev_priv(dev);
++#ifndef CONFIG_RAETH_NAPI
++    unsigned long reg_int_mask=0;
++#endif
++    struct QDMA_txdesc *dma_ptr = NULL;
++    struct QDMA_txdesc *cpu_ptr = NULL;
++    struct QDMA_txdesc *tmp_ptr = NULL;
++    unsigned int ctx_offset = 0;
++    unsigned int dtx_offset = 0;
++
++    cpu_ptr = sysRegRead(QTX_CRX_PTR);
++    dma_ptr = sysRegRead(QTX_DRX_PTR);
++    ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++    dtx_offset = GET_TXD_OFFSET(&dma_ptr);
++    cpu_ptr     = (ei_local->txd_pool + (ctx_offset));
++    dma_ptr     = (ei_local->txd_pool + (dtx_offset));
++
++      while(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) {
++                //1. keep cpu next TXD
++              tmp_ptr = cpu_ptr->txd_info2.NDP;
++                //2. release TXD
++              put_free_txd(ctx_offset);
++                //3. update ctx_offset and free skb memory
++              ctx_offset = GET_TXD_OFFSET(&tmp_ptr);
++#if defined (CONFIG_RAETH_TSO)
++              if(ei_local->skb_free[ctx_offset]!=(struct  sk_buff *)0xFFFFFFFF) {
++                      dev_kfree_skb_any(ei_local->skb_free[ctx_offset]);
++              }
++#else
++              dev_kfree_skb_any(ei_local->skb_free[ctx_offset]);
++#endif
++              ei_local->skb_free[ctx_offset] = 0;
++
++              netif_wake_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++              netif_wake_queue(ei_local->PseudoDev);
++#endif
++              tx_ring_full=0;
++                //4. update cpu_ptr
++              cpu_ptr = (ei_local->txd_pool + ctx_offset);
++      }
++      sysRegWrite(QTX_CRX_PTR, (ei_local->phy_txd_pool + (ctx_offset << 4)));
++#ifndef CONFIG_RAETH_NAPI
++    reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#if defined (DELAY_INT)
++    sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RLS_DLY_INT);
++#else
++
++    sysRegWrite(QFE_INT_ENABLE, reg_int_mask | RLS_DONE_INT);
++#endif
++#endif //CONFIG_RAETH_NAPI//
++}
++
++EXPORT_SYMBOL(ei_start_xmit);
++EXPORT_SYMBOL(ei_xmit_housekeeping);
++EXPORT_SYMBOL(fe_dma_init);
++EXPORT_SYMBOL(rt2880_eth_send);
+diff --git a/drivers/net/ethernet/raeth/raether_qdma_mt7623.c b/drivers/net/ethernet/raeth/raether_qdma_mt7623.c
+new file mode 100644
+index 0000000..b465b75
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/raether_qdma_mt7623.c
+@@ -0,0 +1,1020 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/skbuff.h>
++#include <linux/if_vlan.h>
++#include <linux/if_ether.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/rt2880/surfboardint.h>
++#if defined (CONFIG_RAETH_TSO)
++#include <linux/tcp.h>
++#include <net/ipv6.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <linux/in.h>
++#include <linux/ppp_defs.h>
++#include <linux/if_pppox.h>
++#endif
++#include <linux/delay.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++#include <linux/sched.h>
++#endif
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
++#include <asm/rt2880/rt_mmap.h>
++#else
++#include <linux/libata-compat.h>
++#endif
++ 
++#include "ra2882ethreg.h"
++#include "raether.h"
++#include "ra_mac.h"
++#include "ra_ioctl.h"
++#include "ra_rfrw.h"
++#ifdef CONFIG_RAETH_NETLINK
++#include "ra_netlink.h"
++#endif
++#if defined (CONFIG_RAETH_QOS)
++#include "ra_qos.h"
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++#include "../../../net/nat/hw_nat/ra_nat.h"
++#endif
++
++
++#if !defined(CONFIG_RA_NAT_NONE)
++/* bruce+
++ */
++extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
++extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
++#endif
++
++#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
++/* Qwert+
++ */
++#include <asm/mipsregs.h>
++extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
++extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
++#endif /* CONFIG_RA_CLASSIFIER */
++
++#if defined (CONFIG_RALINK_RT3052_MP2)
++int32_t mcast_rx(struct sk_buff * skb);
++int32_t mcast_tx(struct sk_buff * skb);
++#endif
++
++#ifdef RA_MTD_RW_BY_NUM
++int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
++#else
++int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
++#endif
++
++/* gmac driver feature set config */
++#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
++#undef DELAY_INT
++#else
++#define DELAY_INT     1
++#endif
++
++//#define CONFIG_UNH_TEST
++/* end of config */
++
++#if defined (CONFIG_RAETH_JUMBOFRAME)
++#define       MAX_RX_LENGTH   4096
++#else
++#define       MAX_RX_LENGTH   1536
++#endif
++
++extern struct net_device              *dev_raether;
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++static int rx_dma_owner_idx1;
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx1;
++#endif
++#endif
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++static int rx_calc_idx0;
++static unsigned long tx_cpu_owner_idx0=0;
++#endif
++static unsigned long tx_ring_full=0;
++
++#if defined (CONFIG_ETHTOOL) && defined (CONFIG_RAETH_ROUTER)
++#include "ra_ethtool.h"
++extern struct ethtool_ops     ra_ethtool_ops;
++#ifdef CONFIG_PSEUDO_SUPPORT
++extern struct ethtool_ops     ra_virt_ethtool_ops;
++#endif // CONFIG_PSEUDO_SUPPORT //
++#endif // (CONFIG_ETHTOOL //
++
++#ifdef CONFIG_RALINK_VISTA_BASIC
++int is_switch_175c = 1;
++#endif
++
++//skb->mark to queue mapping table
++extern unsigned int M2Q_table[64];
++
++
++#define KSEG1                   0xa0000000
++#if defined (CONFIG_MIPS)
++#define PHYS_TO_VIRT(x)         ((void *)((x) | KSEG1))
++#define VIRT_TO_PHYS(x)         ((unsigned long)(x) & ~KSEG1)
++#else
++#define PHYS_TO_VIRT(x)         phys_to_virt(x)
++#define VIRT_TO_PHYS(x)         virt_to_phys(x)
++#endif
++
++
++extern void set_fe_dma_glo_cfg(void);
++
++
++/**
++ *
++ * @brief: get the TXD index from its address
++ *
++ * @param: cpu_ptr
++ *
++ * @return: TXD index
++*/
++
++static unsigned int GET_TXD_OFFSET(struct QDMA_txdesc **cpu_ptr)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      int ctx_offset;
++      //ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++      //ctx_offset = (*cpu_ptr - ei_local->txd_pool);
++      /*kurtis*/
++      ctx_offset = (((((u32)*cpu_ptr) <<8)>>8) - ((((u32)ei_local->phy_txd_pool)<<8)>>8))/ sizeof(struct QDMA_txdesc);
++      return ctx_offset;
++} 
++
++
++
++
++/**
++ * @brief cal txd number for a page
++ *
++ * @parm size
++ *
++ * @return frag_txd_num
++ */
++
++unsigned int cal_frag_txd_num(unsigned int size)
++{
++      unsigned int frag_txd_num = 0;
++      if(size == 0)
++              return 0;
++      while(size > 0){
++              if(size > MAX_TXD_LEN){
++                      frag_txd_num++;
++                      size -= MAX_TXD_LEN;
++              }else{
++                      frag_txd_num++;
++                      size = 0;
++              }
++      }
++        return frag_txd_num;
++
++}
++
++/**
++ * @brief get free TXD from TXD queue
++ *
++ * @param free_txd
++ *
++ * @return 
++ */
++static int get_free_txd(struct QDMA_txdesc **free_txd)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      unsigned int tmp_idx;
++
++      if(ei_local->free_txd_num > 0){
++              tmp_idx = ei_local->free_txd_head;
++              ei_local->free_txd_head = ei_local->txd_pool_info[tmp_idx];
++              ei_local->free_txd_num -= 1;
++              //*free_txd = &ei_local->txd_pool[tmp_idx];
++              *free_txd = ei_local->phy_txd_pool + (sizeof(struct QDMA_txdesc) * tmp_idx);
++              return tmp_idx;
++      }else
++              return NUM_TX_DESC;     
++}
++
++
++/**
++ * @brief add free TXD into TXD queue
++ *
++ * @param free_txd
++ *
++ * @return 
++ */
++int put_free_txd(int free_txd_idx)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      ei_local->txd_pool_info[ei_local->free_txd_tail] = free_txd_idx;
++      ei_local->free_txd_tail = free_txd_idx;
++      ei_local->txd_pool_info[free_txd_idx] = NUM_TX_DESC;
++        ei_local->free_txd_num += 1;
++      return 1;
++}
++
++/*define qdma initial alloc*/
++/**
++ * @brief 
++ *
++ * @param net_dev
++ *
++ * @return  0: fail
++ *        1: success
++ */
++bool qdma_tx_desc_alloc(void)
++{
++      struct net_device *dev = dev_raether;
++      END_DEVICE *ei_local = netdev_priv(dev);
++      struct QDMA_txdesc *free_txd = NULL;
++      unsigned int txd_idx;
++      int i = 0;
++
++
++      ei_local->txd_pool = pci_alloc_consistent(NULL, sizeof(struct QDMA_txdesc) * NUM_TX_DESC, &ei_local->phy_txd_pool);
++      printk("txd_pool=%p phy_txd_pool=%08X\n", ei_local->txd_pool , ei_local->phy_txd_pool);
++
++      if (ei_local->txd_pool == NULL) {
++              printk("adapter->txd_pool allocation failed!\n");
++              return 0;
++      }
++      printk("ei_local->skb_free start address is 0x%p.\n", ei_local->skb_free);
++      //set all txd_pool_info to 0.
++      for ( i = 0; i < NUM_TX_DESC; i++)
++      {
++              ei_local->skb_free[i]= 0;
++              ei_local->txd_pool_info[i] = i + 1;
++              ei_local->txd_pool[i].txd_info3.LS_bit = 1;
++              ei_local->txd_pool[i].txd_info3.OWN_bit = 1;
++      }
++
++      ei_local->free_txd_head = 0;
++      ei_local->free_txd_tail = NUM_TX_DESC - 1;
++      ei_local->free_txd_num = NUM_TX_DESC;
++      
++
++      //get free txd from txd pool
++      txd_idx = get_free_txd(&free_txd);
++      if( txd_idx == NUM_TX_DESC) {
++              printk("get_free_txd fail\n");
++              return 0;
++      }
++      
++      //add null TXD for transmit
++
++      /*kurtis test*/
++      ei_local->tx_dma_ptr = free_txd;
++      ei_local->tx_cpu_ptr = free_txd;
++      //ei_local->tx_dma_ptr = virt_to_phys(free_txd);
++      //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);
++      sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++      sysRegWrite(QTX_DTX_PTR, ei_local->tx_dma_ptr);
++      
++      printk("kurtis: free_txd = 0x%x!!!\n", free_txd);
++      printk("kurtis: ei_local->tx_dma_ptr = 0x%x!!!\n", ei_local->tx_dma_ptr);
++      
++      //get free txd from txd pool
++
++      txd_idx = get_free_txd(&free_txd);
++      if( txd_idx == NUM_TX_DESC) {
++              printk("get_free_txd fail\n");
++              return 0;
++      }
++      // add null TXD for release
++      //sysRegWrite(QTX_CRX_PTR, virt_to_phys(free_txd));
++      //sysRegWrite(QTX_DRX_PTR, virt_to_phys(free_txd));
++      sysRegWrite(QTX_CRX_PTR, free_txd);
++      sysRegWrite(QTX_DRX_PTR, free_txd);
++      
++      printk("free_txd: %p, ei_local->cpu_ptr: %08X\n", free_txd, ei_local->tx_cpu_ptr);
++      
++      printk(" POOL  HEAD_PTR | DMA_PTR | CPU_PTR \n");
++      printk("----------------+---------+--------\n");
++#if 1
++      printk("     0x%p 0x%08X 0x%08X\n",ei_local->txd_pool,
++                      ei_local->tx_dma_ptr, ei_local->tx_cpu_ptr);
++#endif
++      return 1;
++}
++
++bool fq_qdma_init(void)
++{
++      struct QDMA_txdesc *free_head = NULL;
++      unsigned int free_head_phy;
++      unsigned int free_tail_phy;
++      unsigned int *free_page_head = NULL;
++      unsigned int free_page_head_phy;
++      int i;
++    
++      free_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), &free_head_phy);
++      if (unlikely(free_head == NULL)){
++              printk(KERN_ERR "QDMA FQ decriptor not available...\n");
++              return 0;
++      }
++      memset(free_head, 0x0, sizeof(struct QDMA_txdesc) * NUM_QDMA_PAGE);
++
++      free_page_head = pci_alloc_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, &free_page_head_phy);
++      if (unlikely(free_page_head == NULL)){
++              printk(KERN_ERR "QDMA FQ pager not available...\n");
++              return 0;
++      }       
++      for (i=0; i < NUM_QDMA_PAGE; i++) {
++              free_head[i].txd_info1.SDP = (free_page_head_phy + (i * QDMA_PAGE_SIZE));
++              if(i < (NUM_QDMA_PAGE-1)){
++                      free_head[i].txd_info2.NDP = (free_head_phy + ((i+1) * sizeof(struct QDMA_txdesc)));
++
++
++#if 0
++                      printk("free_head_phy[%d] is 0x%x!!!\n",i, VIRT_TO_PHYS(&free_head[i]) );
++                      printk("free_head[%d] is 0x%x!!!\n",i, &free_head[i] );
++                      printk("free_head[%d].txd_info1.SDP is 0x%x!!!\n",i, free_head[i].txd_info1.SDP );
++                      printk("free_head[%d].txd_info2.NDP is 0x%x!!!\n",i, free_head[i].txd_info2.NDP );
++#endif
++              }
++              free_head[i].txd_info3.SDL = QDMA_PAGE_SIZE;
++
++      }
++      free_tail_phy = (free_head_phy + (u32)((NUM_QDMA_PAGE-1) * sizeof(struct QDMA_txdesc)));
++
++      printk("free_head_phy is 0x%x!!!\n", free_head_phy);
++      printk("free_tail_phy is 0x%x!!!\n", free_tail_phy);
++      sysRegWrite(QDMA_FQ_HEAD, (u32)free_head_phy);
++      sysRegWrite(QDMA_FQ_TAIL, (u32)free_tail_phy);
++      sysRegWrite(QDMA_FQ_CNT, ((NUM_TX_DESC << 16) | NUM_QDMA_PAGE));
++      sysRegWrite(QDMA_FQ_BLEN, QDMA_PAGE_SIZE << 16);
++    return 1;
++}
++
++int fe_dma_init(struct net_device *dev)
++{
++
++      int i;
++      unsigned int    regVal;
++      END_DEVICE* ei_local = netdev_priv(dev);
++
++      fq_qdma_init();
++
++      while(1)
++      {
++              regVal = sysRegRead(QDMA_GLO_CFG);
++              if((regVal & RX_DMA_BUSY))
++              {
++                      printk("\n  RX_DMA_BUSY !!! ");
++                      continue;
++              }
++              if((regVal & TX_DMA_BUSY))
++              {
++                      printk("\n  TX_DMA_BUSY !!! ");
++                      continue;
++              }
++              break;
++      }
++      /*tx desc alloc, add a NULL TXD to HW*/
++
++      qdma_tx_desc_alloc();
++
++
++      /* Initial RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++      ei_local->rx_ring0 = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++      ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++      ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#endif
++      for (i = 0; i < NUM_QRX_DESC; i++) {
++              memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++              ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++              ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++              ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      printk("QDMA_RX:phy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++      /* Initial RX Ring 1*/
++#ifdef CONFIG_32B_DESC
++      ei_local->rx_ring1 = kmalloc(NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++      ei_local->phy_rx_ring1 = virt_to_phys(ei_local->rx_ring1);
++#else
++      ei_local->rx_ring1 = pci_alloc_consistent(NULL, NUM_QRX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring1);
++#endif
++      for (i = 0; i < NUM_QRX_DESC; i++) {
++              memset(&ei_local->rx_ring1[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring1[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++              ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++              ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++              ei_local->rx_ring1[i].rxd_info2.LS0 = 1;
++#endif
++              ei_local->rx_ring1[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx1_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++      }
++      printk("\nphy_rx_ring1 = 0x%08x, rx_ring1 = 0x%p\n",ei_local->phy_rx_ring1,ei_local->rx_ring1);
++#endif
++
++      regVal = sysRegRead(QDMA_GLO_CFG);
++      regVal &= 0x000000FF;
++      sysRegWrite(QDMA_GLO_CFG, regVal);
++      regVal=sysRegRead(QDMA_GLO_CFG);
++
++      /* Tell the adapter where the TX/RX rings are located. */
++      
++      sysRegWrite(QRX_BASE_PTR_0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++      sysRegWrite(QRX_MAX_CNT_0,  cpu_to_le32((u32) NUM_QRX_DESC));
++      sysRegWrite(QRX_CRX_IDX_0, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_calc_idx0 = rx_dma_owner_idx0 =  sysRegRead(QRX_CRX_IDX_0);
++#endif
++      sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX0);
++#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
++      sysRegWrite(QRX_BASE_PTR_1, phys_to_bus((u32) ei_local->phy_rx_ring1));
++      sysRegWrite(QRX_MAX_CNT_1,  cpu_to_le32((u32) NUM_QRX_DESC));
++      sysRegWrite(QRX_CRX_IDX_1, cpu_to_le32((u32) (NUM_QRX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++      rx_calc_idx1 = rx_dma_owner_idx1 =  sysRegRead(QRX_CRX_IDX_1);
++#endif
++      sysRegWrite(QDMA_RST_CFG, PST_DRX_IDX1);
++#endif
++
++#if !defined (CONFIG_RAETH_QDMATX_QDMARX) 
++      /* Initial PDMA RX Ring 0*/
++#ifdef CONFIG_32B_DESC
++        ei_local->rx_ring0 = kmalloc(NUM_RX_DESC * sizeof(struct PDMA_rxdesc), GFP_KERNEL);
++        ei_local->phy_rx_ring0 = virt_to_phys(ei_local->rx_ring0);
++#else
++        ei_local->rx_ring0 = pci_alloc_consistent(NULL, NUM_RX_DESC * sizeof(struct PDMA_rxdesc), &ei_local->phy_rx_ring0);
++#endif
++        for (i = 0; i < NUM_RX_DESC; i++) {
++              memset(&ei_local->rx_ring0[i],0,sizeof(struct PDMA_rxdesc));
++              ei_local->rx_ring0[i].rxd_info2.DDONE_bit = 0;
++#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
++      ei_local->rx_ring0[i].rxd_info2.LS0 = 0;
++      ei_local->rx_ring0[i].rxd_info2.PLEN0 = MAX_RX_LENGTH;
++#else
++      ei_local->rx_ring0[i].rxd_info2.LS0 = 1;
++#endif
++      ei_local->rx_ring0[i].rxd_info1.PDP0 = dma_map_single(NULL, ei_local->netrx0_skbuf[i]->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
++                                                              }
++        printk("PDMA_RX:phy_rx_ring0 = 0x%08x, rx_ring0 = 0x%p\n",ei_local->phy_rx_ring0,ei_local->rx_ring0);
++
++        regVal = sysRegRead(PDMA_GLO_CFG);
++        regVal &= 0x000000FF;
++        sysRegWrite(PDMA_GLO_CFG, regVal);
++        regVal=sysRegRead(PDMA_GLO_CFG);
++
++        sysRegWrite(RX_BASE_PTR0, phys_to_bus((u32) ei_local->phy_rx_ring0));
++        sysRegWrite(RX_MAX_CNT0,  cpu_to_le32((u32) NUM_RX_DESC));
++        sysRegWrite(RX_CALC_IDX0, cpu_to_le32((u32) (NUM_RX_DESC - 1)));
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++        rx_calc_idx0 =  sysRegRead(RX_CALC_IDX0);
++#endif
++        sysRegWrite(PDMA_RST_CFG, PST_DRX_IDX0);
++              
++#endif/*kurtis*/
++        /* Enable randon early drop and set drop threshold automatically */
++      sysRegWrite(QDMA_FC_THRES, 0x174444);
++      sysRegWrite(QDMA_HRED2, 0x0);
++      set_fe_dma_glo_cfg();
++      
++      return 1;
++}
++
++inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no)
++{
++      unsigned int    length=skb->len;
++      END_DEVICE*     ei_local = netdev_priv(dev);
++      
++      struct QDMA_txdesc *cpu_ptr;
++
++      struct QDMA_txdesc *dma_ptr __maybe_unused;
++      struct QDMA_txdesc *free_txd;
++      unsigned int  ctx_offset = 0;
++      unsigned int  dtx_offset = 0;
++#if defined (CONFIG_RAETH_TSO)
++      struct iphdr *iph = NULL;
++        struct QDMA_txdesc *init_cpu_ptr;
++        struct tcphdr *th = NULL;
++      struct skb_frag_struct *frag;
++      unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++      unsigned int len, size, offset, frag_txd_num;
++      int init_txd_idx, i;
++#endif // CONFIG_RAETH_TSO //
++
++#if defined (CONFIG_RAETH_TSOV6)
++      struct ipv6hdr *ip6h = NULL;
++#endif
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      PSEUDO_ADAPTER *pAd;
++#endif
++      cpu_ptr = (ei_local->tx_cpu_ptr);
++      ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++      cpu_ptr = phys_to_virt(ei_local->tx_cpu_ptr);
++      dma_ptr = phys_to_virt(ei_local->tx_dma_ptr);
++/*kurtis test*/
++      //dma_ptr = (ei_local->tx_dma_ptr);
++      
++      
++      /*only modify virtual address*/
++      //cpu_ptr = (ei_local->txd_pool) + (ctx_offset * sizeof(struct QDMA_txdesc));
++      cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++      
++      //dtx_offset = GET_TXD_OFFSET(&dma_ptr);
++      //dma_ptr = (ei_local->txd_pool) + (dtx_offset * sizeof(struct QDMA_txdesc));
++      
++      //printk("eth_send  ctx_offset = 0x%x!!!\n", ctx_offset);
++      //printk("eth_send  dtx_offset = 0x%x!!!\n", dtx_offset);
++      //printk("eth_send  ei_local->txd_pool = 0x%x!!!\n", ei_local->txd_pool);
++      //printk("eth_send  cpu_ptr = 0x%x!!!\n", cpu_ptr);
++      //printk("eth_send  ctx_offset = 0x%x!!!\n", ctx_offset);
++      //printk("eth_send  ei_local->skb_free[ctx_offset] = 0x%x!!!\n", skb);
++      
++      
++      ei_local->skb_free[ctx_offset] = skb;
++#if defined (CONFIG_RAETH_TSO)
++        init_cpu_ptr = cpu_ptr;
++        init_txd_idx = ctx_offset;
++#endif
++
++#if !defined (CONFIG_RAETH_TSO)
++
++      //2. prepare data
++      cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++      cpu_ptr->txd_info3.SDL = skb->len;
++
++      if (gmac_no == 1) {
++              cpu_ptr->txd_info4.FPORT = 1;
++      }else {
++              cpu_ptr->txd_info4.FPORT = 2;
++      }
++
++
++  cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#if 0 
++      iph = (struct iphdr *)skb_network_header(skb);
++        if (iph->tos == 0xe0)
++              cpu_ptr->txd_info3.QID = 3;
++      else if (iph->tos == 0xa0) 
++              cpu_ptr->txd_info3.QID = 2;     
++        else if (iph->tos == 0x20)
++              cpu_ptr->txd_info3.QID = 1;
++        else 
++              cpu_ptr->txd_info3.QID = 0;
++#endif
++
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++      if (skb->ip_summed == CHECKSUM_PARTIAL){
++          cpu_ptr->txd_info4.TUI_CO = 7;
++      }else {
++          cpu_ptr->txd_info4.TUI_CO = 0;
++      }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++      if(vlan_tx_tag_present(skb)) {
++          cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++      }else {
++          cpu_ptr->txd_info4.VLAN_TAG = 0;
++      }
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++      if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++              if(ra_sw_nat_hook_rx!= NULL){
++                  cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++                  FOE_MAGIC_TAG(skb) = 0;
++          }
++  }
++#endif
++#if 0
++      cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++      cpu_ptr->txd_info4.UDF = 0x2F;
++#endif
++      
++#if defined (CONFIG_MIPS)     
++      dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++      dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++      cpu_ptr->txd_info3.SWC_bit = 1;
++
++      //3. get NULL TXD and decrease free_tx_num by 1.
++      ctx_offset = get_free_txd(&free_txd);
++      if(ctx_offset == NUM_TX_DESC) {
++          printk("get_free_txd fail\n"); // this should not happen. free_txd_num is 2 at least.
++          return 0;
++      }
++
++      //4. hook new TXD in the end of queue
++      //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd);
++      cpu_ptr->txd_info2.NDP = (free_txd);
++
++
++      //5. move CPU_PTR to new TXD
++      //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);        
++      ei_local->tx_cpu_ptr = (free_txd);      
++      cpu_ptr->txd_info3.OWN_bit = 0;
++      sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++      
++#if 0 
++      printk("----------------------------------------------\n");
++      printk("txd_info1:%08X \n",*(int *)&cpu_ptr->txd_info1);
++      printk("txd_info2:%08X \n",*(int *)&cpu_ptr->txd_info2);
++      printk("txd_info3:%08X \n",*(int *)&cpu_ptr->txd_info3);
++      printk("txd_info4:%08X \n",*(int *)&cpu_ptr->txd_info4);
++#endif                        
++
++#else //#if !defined (CONFIG_RAETH_TSO)       
++        cpu_ptr->txd_info1.SDP = virt_to_phys(skb->data);
++      cpu_ptr->txd_info3.SDL = (length - skb->data_len);
++      cpu_ptr->txd_info3.LS_bit = nr_frags ? 0:1;
++      if (gmac_no == 1) {
++              cpu_ptr->txd_info4.FPORT = 1;
++      }else {
++              cpu_ptr->txd_info4.FPORT = 2;
++      }
++      
++      cpu_ptr->txd_info4.TSO = 0;
++        cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];        
++#if defined (CONFIG_RAETH_CHECKSUM_OFFLOAD) && ! defined(CONFIG_RALINK_RT5350) && !defined (CONFIG_RALINK_MT7628)
++      if (skb->ip_summed == CHECKSUM_PARTIAL){
++          cpu_ptr->txd_info4.TUI_CO = 7;
++      }else {
++          cpu_ptr->txd_info4.TUI_CO = 0;
++      }
++#endif
++
++#ifdef CONFIG_RAETH_HW_VLAN_TX
++      if(vlan_tx_tag_present(skb)) {
++          cpu_ptr->txd_info4.VLAN_TAG = 0x10000 | vlan_tx_tag_get(skb);
++      }else {
++          cpu_ptr->txd_info4.VLAN_TAG = 0;
++      }
++#endif
++
++#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
++      if(FOE_MAGIC_TAG(skb) == FOE_MAGIC_PPE) {
++          if(ra_sw_nat_hook_rx!= NULL){
++                  cpu_ptr->txd_info4.FPORT = 4; /* PPE */
++                  FOE_MAGIC_TAG(skb) = 0;
++          }
++      }
++#endif
++
++        cpu_ptr->txd_info3.SWC_bit = 1;
++
++        ctx_offset = get_free_txd(&free_txd);
++        if(ctx_offset == NUM_TX_DESC) {
++            printk("get_free_txd fail\n"); 
++        return 0;
++      }
++        //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd);
++        //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);
++        cpu_ptr->txd_info2.NDP = free_txd;
++        ei_local->tx_cpu_ptr = free_txd;
++
++      if(nr_frags > 0) {
++              for(i=0;i<nr_frags;i++) {
++                      // 1. set or get init value for current fragment
++                      offset = 0;  
++                      frag = &skb_shinfo(skb)->frags[i];
++                      len = frag->size; 
++                      frag_txd_num = cal_frag_txd_num(len); // calculate the needed TXD numbers for this fragment
++                      for(frag_txd_num = frag_txd_num;frag_txd_num > 0; frag_txd_num --){
++                              // 2. size will be assigned to SDL and can't be larger than MAX_TXD_LEN
++                              if(len < MAX_TXD_LEN)
++                                      size = len;
++                              else
++                                      size = MAX_TXD_LEN;                     
++
++                              //3. Update TXD info
++                              cpu_ptr = (ei_local->txd_pool + (ctx_offset));
++                              cpu_ptr->txd_info3.QID = M2Q_table[skb->mark];
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
++                              cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE);
++#else
++                              cpu_ptr->txd_info1.SDP = pci_map_page(NULL, frag->page.p, frag->page_offset + offset, size, PCI_DMA_TODEVICE);
++//                            printk(" frag->page = %08x. frag->page_offset = %08x. frag->size = % 08x.\n", frag->page, (frag->page_offset+offset), size);
++#endif
++                              cpu_ptr->txd_info3.SDL = size;
++                              if( (i==(nr_frags-1)) && (frag_txd_num == 1))
++                                      cpu_ptr->txd_info3.LS_bit = 1;
++                              else
++                                      cpu_ptr->txd_info3.LS_bit = 0;
++                              cpu_ptr->txd_info3.OWN_bit = 0;
++                              cpu_ptr->txd_info3.SWC_bit = 1;
++                              //4. Update skb_free for housekeeping
++                              ei_local->skb_free[ctx_offset] = (cpu_ptr->txd_info3.LS_bit == 1)?skb:(struct  sk_buff *)0xFFFFFFFF; //MAGIC ID
++
++                              //5. Get next TXD
++                              ctx_offset = get_free_txd(&free_txd);
++                              //cpu_ptr->txd_info2.NDP = virt_to_phys(free_txd);
++                              //ei_local->tx_cpu_ptr = virt_to_phys(free_txd);
++                              cpu_ptr->txd_info2.NDP = free_txd;
++                              ei_local->tx_cpu_ptr = free_txd;
++                              //6. Update offset and len.
++                              offset += size;
++                              len -= size;
++                      }
++              }
++              ei_local->skb_free[init_txd_idx]= (struct  sk_buff *)0xFFFFFFFF; //MAGIC ID
++      }
++
++      if(skb_shinfo(skb)->gso_segs > 1) {
++
++//            TsoLenUpdate(skb->len);
++
++              /* TCP over IPv4 */
++              iph = (struct iphdr *)skb_network_header(skb);
++#if defined (CONFIG_RAETH_TSOV6)
++              /* TCP over IPv6 */
++              ip6h = (struct ipv6hdr *)skb_network_header(skb);
++#endif                                
++              if((iph->version == 4) && (iph->protocol == IPPROTO_TCP)) {
++                      th = (struct tcphdr *)skb_transport_header(skb);
++
++                      init_cpu_ptr->txd_info4.TSO = 1;
++
++                      th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)     
++                      dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++                      dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++              } 
++          
++#if defined (CONFIG_RAETH_TSOV6)
++              /* TCP over IPv6 */
++              //ip6h = (struct ipv6hdr *)skb_network_header(skb);
++              else if ((ip6h->version == 6) && (ip6h->nexthdr == NEXTHDR_TCP)) {
++                      th = (struct tcphdr *)skb_transport_header(skb);
++#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
++                      init_cpu_ptr->txd_info4.TSO = 1;
++#else
++                      init_cpu_ptr->txd_info4.TSO = 1;
++#endif
++                      th->check = htons(skb_shinfo(skb)->gso_size);
++#if defined (CONFIG_MIPS)     
++                      dma_cache_sync(NULL, th, sizeof(struct tcphdr), DMA_TO_DEVICE);
++#else
++                      dma_sync_single_for_device(NULL, virt_to_phys(th), sizeof(struct tcphdr), DMA_TO_DEVICE);
++#endif
++              }
++#endif
++      }
++
++              
++//    dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);  
++
++      init_cpu_ptr->txd_info3.OWN_bit = 0;
++#endif // CONFIG_RAETH_TSO //
++
++      sysRegWrite(QTX_CTX_PTR, ei_local->tx_cpu_ptr);
++
++#ifdef CONFIG_PSEUDO_SUPPORT
++      if (gmac_no == 2) {
++              if (ei_local->PseudoDev != NULL) {
++                              pAd = netdev_priv(ei_local->PseudoDev);
++                              pAd->stat.tx_packets++;
++                              pAd->stat.tx_bytes += length;
++                      }
++              } else
++              
++#endif
++        {
++      ei_local->stat.tx_packets++;
++      ei_local->stat.tx_bytes += skb->len;
++      }
++#ifdef CONFIG_RAETH_NAPI
++      if ( ei_local->tx_full == 1) {
++              ei_local->tx_full = 0;
++              netif_wake_queue(dev);
++      }
++#endif
++
++      return length;
++}
++
++int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no)
++{
++      END_DEVICE *ei_local = netdev_priv(dev);
++      unsigned long flags;
++      unsigned int num_of_txd = 0;
++#if defined (CONFIG_RAETH_TSO)
++      unsigned int nr_frags = skb_shinfo(skb)->nr_frags, i;
++      struct skb_frag_struct *frag;
++#endif
++#ifdef CONFIG_PSEUDO_SUPPORT
++      PSEUDO_ADAPTER *pAd;
++#endif
++
++#if !defined(CONFIG_RA_NAT_NONE)
++         if(ra_sw_nat_hook_tx!= NULL)
++         {
++//       spin_lock_irqsave(&ei_local->page_lock, flags);
++           if(ra_sw_nat_hook_tx(skb, gmac_no)==1){
++//            spin_unlock_irqrestore(&ei_local->page_lock, flags);
++         }else{
++              kfree_skb(skb);
++//            spin_unlock_irqrestore(&ei_local->page_lock, flags);
++              return 0;
++         }
++         }
++#endif
++
++#if defined(CONFIG_RALINK_MT7621) || defined(CONFIG_ARCH_MT7623) 
++#define MIN_PKT_LEN  64
++       if (skb->len < MIN_PKT_LEN) {
++               if (skb_padto(skb, MIN_PKT_LEN)) {
++                       printk("raeth: skb_padto failed\n");
++                       return 0;
++               }
++               skb_put(skb, MIN_PKT_LEN - skb->len);
++       }
++#endif
++
++
++      dev->trans_start = jiffies;     /* save the timestamp */
++      spin_lock_irqsave(&ei_local->page_lock, flags);
++#if defined (CONFIG_MIPS)     
++      dma_cache_sync(NULL, skb->data, skb->len, DMA_TO_DEVICE);
++#else
++      dma_sync_single_for_device(NULL, virt_to_phys(skb->data), skb->len, DMA_TO_DEVICE);
++#endif
++
++
++//check free_txd_num before calling rt288_eth_send()
++
++#if defined (CONFIG_RAETH_TSO)
++      //      num_of_txd = (nr_frags==0) ? 1 : (nr_frags + 1);
++      if(nr_frags != 0){
++              for(i=0;i<nr_frags;i++) {
++                      frag = &skb_shinfo(skb)->frags[i];
++                      num_of_txd  += cal_frag_txd_num(frag->size);
++              }
++      }else
++              num_of_txd = 1;
++#else
++      num_of_txd = 1;
++#endif
++   
++#if defined(CONFIG_RALINK_MT7621)
++    if((sysRegRead(0xbe00000c)&0xFFFF) == 0x0101) {
++          ei_xmit_housekeeping(0);
++    }
++#endif
++      
++    ei_xmit_housekeeping(0);
++
++    //if ((ei_local->free_txd_num > num_of_txd + 1) && (ei_local->free_txd_num != NUM_TX_DESC))
++    if ((ei_local->free_txd_num > num_of_txd + 5) && (ei_local->free_txd_num != NUM_TX_DESC))
++    {
++        rt2880_eth_send(dev, skb, gmac_no); // need to modify rt2880_eth_send() for QDMA
++              if (ei_local->free_txd_num < 3)
++              {
++#if defined (CONFIG_RAETH_STOP_RX_WHEN_TX_FULL)                   
++                  netif_stop_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++                  netif_stop_queue(ei_local->PseudoDev);
++#endif
++                  tx_ring_full = 1;
++#endif
++              }
++    } else {  
++#ifdef CONFIG_PSEUDO_SUPPORT
++              if (gmac_no == 2) 
++              {
++                      if (ei_local->PseudoDev != NULL) 
++                      {
++                          pAd = netdev_priv(ei_local->PseudoDev);
++                          pAd->stat.tx_dropped++;
++                  }
++              } else
++#endif
++              ei_local->stat.tx_dropped++;
++              kfree_skb(skb);
++                spin_unlock_irqrestore(&ei_local->page_lock, flags);
++              return 0;
++     }        
++      spin_unlock_irqrestore(&ei_local->page_lock, flags);
++      return 0;
++}
++
++void ei_xmit_housekeeping(unsigned long unused)
++{
++    struct net_device *dev = dev_raether;
++    END_DEVICE *ei_local = netdev_priv(dev);
++#ifndef CONFIG_RAETH_NAPI
++    unsigned long reg_int_mask=0;
++#endif
++    struct QDMA_txdesc *dma_ptr = NULL;
++    struct QDMA_txdesc *cpu_ptr = NULL;
++    struct QDMA_txdesc *tmp_ptr = NULL;
++    unsigned int htx_offset = 0;
++    unsigned int ctx_offset = 0;
++    unsigned int dtx_offset = 0;
++
++    //dma_ptr = phys_to_virt(sysRegRead(QTX_DRX_PTR));
++    //cpu_ptr = phys_to_virt(sysRegRead(QTX_CRX_PTR));
++    //printk("kurtis:housekeeping  QTX_DRX_PTR = 0x%x!!!\n", sysRegRead(QTX_DRX_PTR));
++    //printk("kurtis:housekeeping  DMA_PTR = 0x%x!!!\n", dma_ptr);
++
++    cpu_ptr = sysRegRead(QTX_CRX_PTR);    
++    dma_ptr = sysRegRead(QTX_DRX_PTR);
++
++    //printk("kurtis:housekeeping  QTX_CRX_PTR = 0x%x!!!\n", cpu_ptr);
++    //printk("kurtis:housekeeping  QTX_DRX_PTR = 0x%x!!!\n", dma_ptr);
++    ctx_offset = GET_TXD_OFFSET(&cpu_ptr);
++    dtx_offset = GET_TXD_OFFSET(&dma_ptr);
++    htx_offset = ctx_offset;
++    cpu_ptr   = (ei_local->txd_pool + (ctx_offset));
++    dma_ptr   = (ei_local->txd_pool + (dtx_offset));
++    
++
++    //printk("kurtis:housekeeping  CPU_PTR = 0x%x!!!\n", cpu_ptr);
++    //printk("kurtis:housekeeping  DMA_PTR = 0x%x!!!\n", dma_ptr);
++
++/*temp mark*/
++#if 1 
++
++
++    if(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) {
++      while(cpu_ptr != dma_ptr && (cpu_ptr->txd_info3.OWN_bit == 1)) {
++
++          //1. keep cpu next TXD                      
++          //tmp_ptr = phys_to_virt(cpu_ptr->txd_info2.NDP);
++          tmp_ptr = cpu_ptr->txd_info2.NDP;
++            htx_offset = GET_TXD_OFFSET(&tmp_ptr);
++      //printk("kurtis:housekeeping  cpu_ptr->txd_info2.NDP = 0x%x!!!\n", cpu_ptr->txd_info2.NDP);
++      //printk("kurtis:housekeeping  tmp_ptr = 0x%x!!!\n", tmp_ptr);
++      //printk("kurtis:housekeeping  htx_offset = 0x%x!!!\n", htx_offset);
++            //2. free skb meomry
++#if defined (CONFIG_RAETH_TSO)
++          if(ei_local->skb_free[htx_offset]!=(struct  sk_buff *)0xFFFFFFFF) {
++                  dev_kfree_skb_any(ei_local->skb_free[htx_offset]); 
++          }
++#else
++          dev_kfree_skb_any(ei_local->skb_free[htx_offset]); 
++#endif                        
++                
++          //3. release TXD
++          //htx_offset = GET_TXD_OFFSET(&cpu_ptr);                    
++          //put_free_txd(htx_offset);
++          put_free_txd(ctx_offset);
++
++
++
++            netif_wake_queue(dev);
++#ifdef CONFIG_PSEUDO_SUPPORT
++          netif_wake_queue(ei_local->PseudoDev);
++#endif                        
++          tx_ring_full=0;
++                
++          //4. update cpu_ptr to next ptr
++          //cpu_ptr = tmp_ptr;
++          cpu_ptr = (ei_local->txd_pool + htx_offset);
++          ctx_offset = htx_offset;
++          //cpu_ptr = (cpu_ptr + (htx_offset));
++          //printk("kurtis:housekeeping 4. update  cpu_ptr = 0x%x!!!\n", cpu_ptr);
++      }
++    }
++    //sysRegWrite(QTX_CRX_PTR, virt_to_phys(cpu_ptr));
++    //sysRegWrite(QTX_CRX_PTR, cpu_ptr);
++    tmp_ptr = (ei_local->phy_txd_pool + (htx_offset << 4));
++    //printk("kurtis:housekeeping 5. update  QTX_CRX_PTR = 0x%x!!!\n", tmp_ptr);
++    sysRegWrite(QTX_CRX_PTR, tmp_ptr);
++
++#endif
++
++#ifndef CONFIG_RAETH_NAPI
++    reg_int_mask=sysRegRead(QFE_INT_ENABLE);
++#if defined (DELAY_INT)
++    sysRegWrite(FE_INT_ENABLE, reg_int_mask| RLS_DLY_INT);
++#else
++
++    sysRegWrite(FE_INT_ENABLE, reg_int_mask | RLS_DONE_INT);
++#endif
++#endif //CONFIG_RAETH_NAPI//
++}
++
++EXPORT_SYMBOL(ei_start_xmit);
++EXPORT_SYMBOL(ei_xmit_housekeeping);
++EXPORT_SYMBOL(fe_dma_init);
++EXPORT_SYMBOL(rt2880_eth_send);
+diff --git a/drivers/net/ethernet/raeth/smb_hook.c b/drivers/net/ethernet/raeth/smb_hook.c
+new file mode 100644
+index 0000000..617139c
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/smb_hook.c
+@@ -0,0 +1,17 @@
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/skbuff.h>
++
++
++int (*smb_nf_local_in_hook)(struct sk_buff *skb) = NULL;
++int (*smb_nf_pre_routing_hook)(struct sk_buff *skb) = NULL;
++int (*smb_nf_local_out_hook)(struct sk_buff *skb) = NULL;
++int (*smb_nf_post_routing_hook)(struct sk_buff *skb) = NULL;
++EXPORT_SYMBOL(smb_nf_local_in_hook);
++EXPORT_SYMBOL(smb_nf_pre_routing_hook);
++EXPORT_SYMBOL(smb_nf_local_out_hook);
++EXPORT_SYMBOL(smb_nf_post_routing_hook);
++
++
+diff --git a/drivers/net/ethernet/raeth/smb_nf.c b/drivers/net/ethernet/raeth/smb_nf.c
+new file mode 100644
+index 0000000..86250eb
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/smb_nf.c
+@@ -0,0 +1,177 @@
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++#include <linux/inetdevice.h>
++#include <linux/tcp.h>
++#include <linux/ip.h>
++#include <net/tcp.h>
++#include <net/ip.h>
++
++extern int (*smb_nf_local_in_hook)(struct sk_buff *skb);
++extern int (*smb_nf_pre_routing_hook)(struct sk_buff *skb);
++extern int (*smb_nf_local_out_hook)(struct sk_buff *skb);
++extern int (*smb_nf_post_routing_hook)(struct sk_buff *skb);
++
++struct net_device *lan_int = NULL;
++struct in_ifaddr *lan_ifa = NULL;
++
++
++int mtk_smb_nf_local_in_hook(struct sk_buff *skb)
++{
++      struct iphdr *iph = ip_hdr(skb);
++
++      if (skb->protocol == htons(ETH_P_IP)) {
++              struct iphdr *iph = ip_hdr(skb);
++                      
++              if (iph->protocol == IPPROTO_TCP) {
++                      struct tcphdr *th = tcp_hdr(skb);
++                      unsigned short sport, dport;
++
++                      th = tcp_hdr(skb);
++                      th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++
++                      if ((iph->daddr == lan_ifa->ifa_local) 
++                              && ((th->dest == 0xbd01) || (th->dest == 0x8900) 
++                              || (th->dest == 0x8a00) || (th->dest == 0x8b00)))
++                              return 1;
++                      else
++                              return 0;
++              }
++
++      }
++      
++      return 0;
++}
++
++int mtk_smb_nf_pre_routing_hook(struct sk_buff *skb)
++{
++      struct iphdr *iph = ip_hdr(skb);
++
++      if (skb->protocol == htons(ETH_P_IP)) {
++              struct iphdr *iph = ip_hdr(skb);
++                      
++              if (iph->protocol == IPPROTO_TCP) {
++                      struct tcphdr *th = tcp_hdr(skb);
++                      unsigned short sport, dport;
++
++                      th = tcp_hdr(skb);
++                      th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++                      if ((iph->daddr == lan_ifa->ifa_local) 
++                              && ((th->dest == 0xbd01) || (th->dest == 0x8900) 
++                              || (th->dest == 0x8a00) || (th->dest == 0x8b00)))
++                              return 1;
++                      else
++                              return 0;
++              }
++
++      }       
++
++      return 0;
++}
++
++int mtk_smb_nf_local_out_hook(struct sk_buff *skb)
++{
++      struct iphdr *iph = ip_hdr(skb);
++
++      if (iph->protocol == IPPROTO_TCP) {
++              struct tcphdr *th = tcp_hdr(skb);
++
++              th = tcp_hdr(skb);
++              th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++
++              if ((iph->saddr == lan_ifa->ifa_local)
++                      && ((th->source == 0xbd01) || (th->source == 0x8900) 
++                      || (th->source == 0x8a00) || (th->source == 0x8b00)))
++                      return 1;
++              else
++                      return 0;
++      }
++
++      return 0;
++}
++
++int mtk_smb_nf_post_routing_hook(struct sk_buff *skb)
++{
++      struct iphdr *iph = ip_hdr(skb);
++
++      if (skb->protocol == htons(ETH_P_IP)) {
++              struct iphdr *iph = ip_hdr(skb);
++                      
++              if (iph->protocol == IPPROTO_TCP) {
++                      struct tcphdr *th = tcp_hdr(skb);
++
++                      th = tcp_hdr(skb);
++                      th = (struct tcphdr *)(((unsigned char *)iph) + iph->ihl*4);
++
++                      if ((iph->saddr == lan_ifa->ifa_local)
++                              && ((th->source == 0xbd01) || (th->source == 0x8900) 
++                              || (th->source == 0x8a00) || (th->source == 0x8b00)))
++                              return 1;
++                      else
++                              return 0;
++              }
++
++      }       
++
++      return 0;
++}
++
++int __init mtk_smb_hook_init(void)
++{
++      struct in_device *in_dev;
++      struct in_ifaddr **ifap = NULL;
++      struct in_ifaddr *ifa = NULL;
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
++      lan_int = dev_get_by_name(&init_net, "br0");
++#else
++      lan_int = dev_get_by_name("br0");
++#endif
++      if (lan_int)
++              in_dev = __in_dev_get_rtnl(lan_int);
++      else
++              return 0;
++
++      if (in_dev) {
++              for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
++                   ifap = &ifa->ifa_next) {
++                      if (!strcmp("br0", ifa->ifa_label))
++                      {
++                              lan_ifa = ifa;
++                              break; /* found */
++                      }
++              }
++      }
++      else
++              return 0;
++
++      if (lan_ifa) {
++              smb_nf_local_in_hook = mtk_smb_nf_local_in_hook;
++              smb_nf_pre_routing_hook = mtk_smb_nf_pre_routing_hook;
++              smb_nf_local_out_hook = mtk_smb_nf_local_out_hook;
++              smb_nf_post_routing_hook = mtk_smb_nf_post_routing_hook;
++      }
++
++      printk("Samba Netfilter Hook Enabled\n");
++
++      return 0;
++}
++
++void mtk_smb_hook_cleanup(void)
++{
++      lan_int = NULL;
++      lan_ifa = NULL;
++      smb_nf_local_in_hook = NULL;
++      smb_nf_pre_routing_hook = NULL;
++      smb_nf_local_out_hook = NULL;
++      smb_nf_post_routing_hook = NULL;
++
++      return;
++}
++
++module_init(mtk_smb_hook_init);
++module_exit(mtk_smb_hook_cleanup);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/ethernet/raeth/sync_write.h b/drivers/net/ethernet/raeth/sync_write.h
+new file mode 100644
+index 0000000..8b800e6
+--- /dev/null
++++ b/drivers/net/ethernet/raeth/sync_write.h
+@@ -0,0 +1,103 @@
++#ifndef _MT_SYNC_WRITE_H
++#define _MT_SYNC_WRITE_H
++
++#if defined(__KERNEL__)
++
++#include <linux/io.h>
++#include <asm/cacheflush.h>
++//#include <asm/system.h>
++
++/*
++ * Define macros.
++ */
++
++#define mt65xx_reg_sync_writel(v, a) \
++        do {    \
++            __raw_writel((v), IOMEM((a)));   \
++            dsb();  \
++        } while (0)
++
++#define mt65xx_reg_sync_writew(v, a) \
++        do {    \
++            __raw_writew((v), IOMEM((a)));   \
++            dsb();  \
++        } while (0)
++
++#define mt65xx_reg_sync_writeb(v, a) \
++        do {    \
++            __raw_writeb((v), IOMEM((a)));   \
++            dsb();  \
++        } while (0)
++
++#define mt_reg_sync_writel(v, a) \
++        do {    \
++            __raw_writel((v), IOMEM((a)));   \
++            dsb();  \
++        } while (0)
++
++#define mt_reg_sync_writew(v, a) \
++        do {    \
++            __raw_writew((v), IOMEM((a)));   \
++            dsb();  \
++        } while (0)
++
++#define mt_reg_sync_writeb(v, a) \
++        do {    \
++            __raw_writeb((v), IOMEM((a)));   \
++            dsb();  \
++        } while (0)
++
++
++#else   /* __KERNEL__ */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <string.h>
++
++#define dsb()   \
++        do {    \
++            __asm__ __volatile__ ("dsb" : : : "memory"); \
++        } while (0)
++
++#define mt65xx_reg_sync_writel(v, a) \
++        do {    \
++            *(volatile unsigned int *)(a) = (v);    \
++            dsb(); \
++        } while (0)
++
++#define mt65xx_reg_sync_writew(v, a) \
++        do {    \
++            *(volatile unsigned short *)(a) = (v);    \
++            dsb(); \
++        } while (0)
++
++#define mt65xx_reg_sync_writeb(v, a) \
++        do {    \
++            *(volatile unsigned char *)(a) = (v);    \
++            dsb(); \
++        } while (0)
++
++#define mt_reg_sync_writel(v, a) \
++        do {    \
++            *(volatile unsigned int *)(a) = (v);    \
++            dsb(); \
++        } while (0)
++
++#define mt_reg_sync_writew(v, a) \
++        do {    \
++            *(volatile unsigned short *)(a) = (v);    \
++            dsb(); \
++        } while (0)
++
++#define mt_reg_sync_writeb(v, a) \
++        do {    \
++            *(volatile unsigned char *)(a) = (v);    \
++            dsb(); \
++        } while (0)
++
++
++#endif  /* __KERNEL__ */
++
++#endif  /* !_MT_SYNC_WRITE_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0064-arm-mediatek-add-mt7623-pcie-support.patch b/target/linux/mediatek/patches/0064-arm-mediatek-add-mt7623-pcie-support.patch
new file mode 100644 (file)
index 0000000..ee82f9c
--- /dev/null
@@ -0,0 +1,436 @@
+From 29ceb2449cb3622ccfba9eb1c77bf2ac4162464b Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:15:29 +0200
+Subject: [PATCH 64/76] arm: mediatek: add mt7623 pcie support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/Makefile |    2 +-
+ arch/arm/mach-mediatek/pcie.c   |  383 +++++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-mediatek/pcie.h   |   14 ++
+ 3 files changed, 398 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/mach-mediatek/pcie.c
+ create mode 100644 arch/arm/mach-mediatek/pcie.h
+
+diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
+index 2116460..aca28a2 100644
+--- a/arch/arm/mach-mediatek/Makefile
++++ b/arch/arm/mach-mediatek/Makefile
+@@ -1,4 +1,4 @@
+ ifeq ($(CONFIG_SMP),y)
+ obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
+ endif
+-obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
++obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o pcie.o
+diff --git a/arch/arm/mach-mediatek/pcie.c b/arch/arm/mach-mediatek/pcie.c
+new file mode 100644
+index 0000000..8394712
+--- /dev/null
++++ b/arch/arm/mach-mediatek/pcie.c
+@@ -0,0 +1,383 @@
++/*
++ *  Mediatek MT7623 SoC PCIE support
++ *
++ *  Copyright (C) 2015 Mediatek
++ *  Copyright (C) 2015 John Crispin <blogic@openwrt.org>
++ *
++ *  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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <asm/irq.h>
++#include <asm/mach/pci.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++#include <linux/reset.h>
++#include <linux/platform_device.h>
++
++#include "pcie.h"
++
++#define PCICFG                        0x00
++#define PCIINT                        0x08
++#define PCIENA                        0x0C
++#define CFGADDR                       0x20
++#define CFGDATA                       0x24
++#define MEMBASE                       0x28
++#define IOBASE                        0x2C
++
++#define BAR0SETUP             0x10
++#define IMBASEBAR0            0x18
++#define PCIE_CLASS            0x34
++#define PCIE_SISTAT           0x50
++
++#define MTK_PCIE_HIGH_PERF    BIT(14)
++#define PCIEP0_BASE           0x2000
++#define PCIEP1_BASE           0x3000
++#define PCIEP2_BASE           0x4000
++
++#define PHY_P0_CTL            0x9000
++#define PHY_P1_CTL            0xA000
++#define PHY_P2_CTL            0x4000
++
++#define RSTCTL_PCIE0_RST      BIT(24)
++#define RSTCTL_PCIE1_RST      BIT(25)
++#define RSTCTL_PCIE2_RST      BIT(26)
++
++static void __iomem *pcie_base;
++static int pcie_card_link;
++
++static struct mtk_pcie_port {
++      int id;
++      int enable;
++      u32 base;
++      u32 phy_base;
++      u32 perst_n;
++      u32 reset;
++      u32 interrupt;
++      u32 link;
++} mtk_pcie_port[] = {
++      { 0, 1, PCIEP0_BASE, PHY_P0_CTL, BIT(1), RSTCTL_PCIE0_RST, BIT(20) },
++      { 1, 1, PCIEP1_BASE, PHY_P1_CTL, BIT(2), RSTCTL_PCIE1_RST, BIT(21) },
++      { 2, 0, PCIEP2_BASE, PHY_P2_CTL, BIT(3), RSTCTL_PCIE2_RST, BIT(22) },
++};
++
++#define mtk_foreach_port(p)           \
++      for (p = mtk_pcie_port; p != &mtk_pcie_port[ARRAY_SIZE(mtk_pcie_port)]; p++)
++
++#define mtk_foreach_port_enabled(p)   \
++      mtk_foreach_port(p)             \
++              if (p->enable)
++
++#define mtk_foreach_port_link(p)      \
++      mtk_foreach_port(p)             \
++              if (p->link)
++
++static struct mtk_phy_init {
++      uint32_t reg;
++      uint32_t mask;
++      uint32_t val;
++} mtk_phy_init[] = {
++      { 0xC00, 0x33000, 0x22000 },
++      { 0xB04, 0xe0000000, 0x40000000 },
++      { 0xB00, 0xe, 0x4 },
++      { 0xC3C, 0xffff0000, 0x3c0000 },
++      { 0xC48, 0xffff, 0x36 },
++      { 0xC0C, 0x30000000, 0x10000000 },
++      { 0xC08, 0x3800c0, 0xc0 },
++      { 0xC10, 0xf0000, 0x20000 },
++      { 0xC0C, 0xf000, 0x1000 },
++      { 0xC14, 0xf0000, 0xa0000 },
++};
++
++static inline void pcie_w32(u32 val, unsigned reg)
++{
++      iowrite32(val, pcie_base + reg);
++}
++
++static inline u32 pcie_r32(unsigned reg)
++{
++      return ioread32(pcie_base + reg);
++}
++
++static inline void pcie_m32(u32 mask, u32 val, unsigned reg)
++{
++      u32 v = pcie_r32(reg);
++
++      v &= mask;
++      v |= val;
++      pcie_w32(v, reg);
++}
++
++static int pcie_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
++{
++      unsigned int slot = PCI_SLOT(devfn);
++      u8 func = PCI_FUNC(devfn);
++      u32 address;
++      u32 data;
++      u32 num = 0;
++
++      if (bus)
++              num = bus->number;
++
++      address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc);
++      pcie_m32(0xf0000000, address, CFGADDR);
++      data = pcie_r32(CFGDATA);
++
++      switch (size) {
++      case 1:
++              *val = (data >> ((where & 3) << 3)) & 0xff;
++              break;
++      case 2:
++              *val = (data >> ((where & 3) << 3)) & 0xffff;
++              break;
++      case 4:
++              *val = data;
++              break;
++      }
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static int pcie_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
++{
++      unsigned int slot = PCI_SLOT(devfn);
++      u8 func = PCI_FUNC(devfn);
++      u32 address;
++      u32 data;
++      u32 num = 0;
++
++      if (bus)
++              num = bus->number;
++
++      address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc);
++      pcie_m32(0xf0000000, address, CFGADDR);
++      data = pcie_r32(CFGDATA);
++
++      switch (size) {
++      case 1:
++              data = (data & ~(0xff << ((where & 3) << 3))) |
++              (val << ((where & 3) << 3));
++              break;
++      case 2:
++              data = (data & ~(0xffff << ((where & 3) << 3))) |
++              (val << ((where & 3) << 3));
++              break;
++      case 4:
++              data = val;
++              break;
++      }
++
++      pcie_w32(data, CFGDATA);
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops mtk_pcie_ops = {
++      .read   = pcie_config_read,
++      .write  = pcie_config_write,
++};
++
++static struct resource pci_mem = {
++      .name   = "PCIe Memory space",
++      .start  = MEM_DIRECT1,
++      .end    = (u32) (MEM_DIRECT1 + (unsigned char *) 0x0fffffff),
++      .flags  = IORESOURCE_MEM,
++};
++
++static struct resource pci_io = {
++      .name   = "PCIe IO space",
++      .start  = IO_WIN,
++      .end    = (u32) (IO_WIN + (unsigned char *) 0x0ffff),
++      .flags  = IORESOURCE_IO,
++};
++
++static int __init mtk_pcie_setup(int nr, struct pci_sys_data *sys)
++{
++      sys->mem_offset = 0;
++      sys->io_offset = 0;
++
++      request_resource(&ioport_resource, &pci_io);
++      request_resource(&iomem_resource, &pci_mem);
++
++      pci_add_resource_offset(&sys->resources, &pci_io, sys->io_offset);
++      pci_add_resource_offset(&sys->resources, &pci_mem, sys->mem_offset);
++
++      return 1;
++}
++
++static struct pci_bus * __init mtk_pcie_scan_bus(int nr, struct pci_sys_data *sys)
++{
++      return pci_scan_root_bus(NULL, sys->busnr, &mtk_pcie_ops, sys,
++                               &sys->resources);
++}
++
++static int __init mtk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++      u16 cmd;
++      u32 val;
++
++      if (dev->bus->number == 0) {
++              pcie_config_write(NULL, slot, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE);
++              pcie_config_read(NULL, slot, 0, PCI_BASE_ADDRESS_0, &val);
++              printk("BAR0 at bus %d, slot %d\n", dev->bus->number, slot);
++      }
++
++      printk("bus=0x%x, slot = 0x%x, pin=0x%x, irq=0x%x\n", dev->bus->number, slot, pin, dev->irq);
++
++      pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14);
++      pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF);
++      pci_read_config_word(dev, PCI_COMMAND, &cmd);
++      cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
++      pci_write_config_word(dev, PCI_COMMAND, cmd);
++      pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++
++      return dev->irq;
++}
++
++static void __init mtk_pcie_preinit(void)
++{
++      struct mtk_pcie_port *port;
++      u32 val = 0;
++      int i;
++
++      pcibios_min_io = 0;
++      pcibios_min_mem = 0;
++
++#if defined (CONFIG_PCIE_PORT2)
++      printk("%s: PCIe/USB3 combo PHY mode (%x) =%x\n", __func__, SYSCFG1, REGDATA(SYSCFG1));
++      REGDATA(SYSCFG1) &= ~(0x300000);
++      printk("%s: PCIe/USB3 combo PHY mode (%x) =%x\n", __func__, SYSCFG1, REGDATA(SYSCFG1));
++#endif
++
++      /* PCIe RC Reset */
++      val = 0;
++      mtk_foreach_port_enabled(port)
++              val |= port->reset;
++      REGDATA(RSTCTL) |= val;
++      mdelay(10);
++      REGDATA(RSTCTL) &= ~val;
++      mdelay(10);
++
++      /* Configure PCIe PHY */
++      mtk_foreach_port_enabled(port) {
++              for (i = 0; i < ARRAY_SIZE(mtk_phy_init); i++) {
++                      u32 val = pcie_r32(port->phy_base + mtk_phy_init[i].reg);
++                      val &= ~mtk_phy_init[i].mask;
++                      val |= mtk_phy_init[i].val;
++                      pcie_w32(val, port->phy_base + mtk_phy_init[i].reg);
++              }
++              mdelay(10);
++      }
++
++      /* Enable RC */
++      mtk_foreach_port_enabled(port) {
++              val = 0;
++              pcie_config_read(NULL, port->id, 0, 0x73c, &val);
++              val &= ~(0x9fff)<<16;
++              val |= 0x806c<<16;
++              pcie_config_write(NULL, port->id, 0, 0x73c, val);
++      }
++
++      /* PCIe EP reset */
++      val = 0;
++      mtk_foreach_port_enabled(port)
++              val |= port->perst_n;
++      val |= MTK_PCIE_HIGH_PERF;
++      pcie_w32(pcie_r32(PCICFG) | val, PCICFG);
++      mdelay(10);
++      pcie_w32(pcie_r32(PCICFG) & ~val, PCICFG);
++      mdelay(10);
++
++      /* check the link status */
++      val = 0;
++      mtk_foreach_port_enabled(port) {
++              if ((pcie_r32(port->base + PCIE_SISTAT) & 0x1))
++                      port->link = 1;
++              else
++                      val |= port->reset;
++      }
++      REGDATA(RSTCTL) |= val;
++
++      mtk_foreach_port_link(port)
++              pcie_card_link++;
++
++      printk("PCIe Link count = %d\n", pcie_card_link);
++      if (!pcie_card_link)
++              return;
++
++      pcie_w32(MEM_WIN, MEMBASE);
++      pcie_w32(IO_WIN, IOBASE);
++
++      mtk_foreach_port_link(port) {
++              pcie_m32(0, port->interrupt, PCIENA);
++              pcie_w32(0x7FFF0001, port->base + BAR0SETUP);
++              pcie_w32(MEMORY_BASE, port->base + IMBASEBAR0);
++              pcie_w32(0x06040001, port->base + PCIE_CLASS);
++              printk("PCIE%d Setup OK\n", port->id);
++      }
++      val = 0;
++
++      pcie_config_read(NULL, pcie_card_link - 1, 0, 0x4, &val);
++      pcie_config_write(NULL, pcie_card_link - 1, 0, 0x4, val|0x4);
++      pcie_config_read(NULL, pcie_card_link - 1, 0, 0x70c, &val);
++      val &= ~(0xff3) << 8;
++      val |= 0x50 << 8;
++      pcie_config_write(NULL, pcie_card_link - 1, 0, 0x70c, val);
++      pcie_config_read(NULL, pcie_card_link - 1, 0, 0x70c, &val);
++}
++
++static struct hw_pci mtk_pci __initdata = {
++      .nr_controllers         = 1,
++      .map_irq                = mtk_pcie_map_irq,
++      .setup                  = mtk_pcie_setup,
++      .scan                   = mtk_pcie_scan_bus,
++      .preinit                = mtk_pcie_preinit,
++};
++
++extern void mt7623_ethifsys_init(void);
++static int mtk_pcie_probe(struct platform_device *pdev)
++{
++      struct resource *pcie_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++      pcie_base = devm_ioremap_resource(&pdev->dev, pcie_res);
++        if (!pcie_base)
++              return -ENOMEM;
++
++      mt7623_ethifsys_init();
++      pci_common_init_dev(&pdev->dev, &mtk_pci);
++
++      return 0;
++}
++
++static const struct of_device_id mtk_pcie_ids[] = {
++      { .compatible = "mediatek,mt7623-pcie" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
++
++static struct platform_driver mtk_pcie_driver = {
++      .probe = mtk_pcie_probe,
++      .driver = {
++              .name = "mt7623-pcie",
++              .owner = THIS_MODULE,
++              .of_match_table = of_match_ptr(mtk_pcie_ids),
++      },
++};
++
++static int __init mtk_pcie_init(void)
++{
++      return platform_driver_register(&mtk_pcie_driver);
++}
++
++late_initcall(mtk_pcie_init);
+diff --git a/arch/arm/mach-mediatek/pcie.h b/arch/arm/mach-mediatek/pcie.h
+new file mode 100644
+index 0000000..400a760e
+--- /dev/null
++++ b/arch/arm/mach-mediatek/pcie.h
+@@ -0,0 +1,14 @@
++#define SYSCTL_BASE   0xFA000000
++#define MEM_WIN               0x1A150000
++#define IO_WIN                0x1A160000
++#define MEM_DIRECT1   0x60000000
++#define MEMORY_BASE   0x80000000
++
++#define REGADDR(x, y) (x##_BASE + y)
++#define REGDATA(x)                    *((volatile unsigned int *)(x)) 
++
++#define SYSCFG1               REGADDR(SYSCTL, 0x14)
++#define RSTCTL                REGADDR(SYSCTL, 0x34)
++
++
++
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0065-arm-mediatek-add-mt7623-smp-support.patch b/target/linux/mediatek/patches/0065-arm-mediatek-add-mt7623-smp-support.patch
new file mode 100644 (file)
index 0000000..98f8acb
--- /dev/null
@@ -0,0 +1,38 @@
+From 3f181d60fcd80b0d98849076ed2aa43de2cb6d8c Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:16:27 +0200
+Subject: [PATCH 65/76] arm: mediatek: add mt7623 smp support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/platsmp.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/mach-mediatek/platsmp.c b/arch/arm/mach-mediatek/platsmp.c
+index e266b3d..81fdcff 100644
+--- a/arch/arm/mach-mediatek/platsmp.c
++++ b/arch/arm/mach-mediatek/platsmp.c
+@@ -45,6 +45,12 @@ static const struct mtk_smp_boot_info mtk_mt6589_boot = {
+       { 0x38, 0x3c, 0x40 },
+ };
++static const struct mtk_smp_boot_info mtk_mt7623_boot = {
++      0x10202000, 0x34, 0x30,
++      { 0x534c4131, 0x4c415332, 0x41534c33 },
++      { 0x38, 0x3c, 0x40 },
++};
++
+ static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
+       { .compatible   = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
+       { .compatible   = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
+@@ -52,6 +58,7 @@ static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
+ static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
+       { .compatible   = "mediatek,mt6589", .data = &mtk_mt6589_boot },
++      { .compatible   = "mediatek,mt7623", .data = &mtk_mt7623_boot },
+ };
+ static void __iomem *mtk_smp_base;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0066-arm-mediatek-add-m7623-devicetree.patch b/target/linux/mediatek/patches/0066-arm-mediatek-add-m7623-devicetree.patch
new file mode 100644 (file)
index 0000000..4516561
--- /dev/null
@@ -0,0 +1,551 @@
+From a6bf117b5fe3acd76bbc45cc87fd80f589136e59 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:14:42 +0200
+Subject: [PATCH 66/76] arm: mediatek: add m7623 devicetree
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/boot/dts/Makefile       |    1 +
+ arch/arm/boot/dts/mt7623-evb.dts |  162 ++++++++++++++++++
+ arch/arm/boot/dts/mt7623.dtsi    |  348 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 511 insertions(+)
+ create mode 100644 arch/arm/boot/dts/mt7623-evb.dts
+ create mode 100644 arch/arm/boot/dts/mt7623.dtsi
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 992736b..525392e 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -658,6 +658,7 @@ dtb-$(CONFIG_MACH_DOVE) += \
+ dtb-$(CONFIG_ARCH_MEDIATEK) += \
+       mt6589-aquaris5.dtb \
+       mt6592-evb.dtb \
++      mt7623-evb.dtb \
+       mt8127-moose.dtb \
+       mt8135-evbp1.dtb
+ endif
+diff --git a/arch/arm/boot/dts/mt7623-evb.dts b/arch/arm/boot/dts/mt7623-evb.dts
+new file mode 100644
+index 0000000..759142f
+--- /dev/null
++++ b/arch/arm/boot/dts/mt7623-evb.dts
+@@ -0,0 +1,162 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Joe.C <yingjoe.chen@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.
++ */
++
++/dts-v1/;
++#include <dt-bindings/gpio/gpio.h>
++#include "mt7623.dtsi"
++
++/ {
++      model = "MediaTek MT7623 Evaluation Board";
++      compatible = "mediatek,mt7623-evb", "mediatek,mt7623";
++
++      chosen {
++              stdout-path = &uart2;
++      };
++
++      memory {
++              reg = <0 0x80000000 0 0x10000000>;
++      };
++
++      usb_p1_vbus: fixedregulator@0 {
++              compatible = "regulator-fixed";
++              regulator-name = "usb_vbus";
++              regulator-min-microvolt = <5000000>;
++              regulator-max-microvolt = <5000000>;
++              gpio = <&pio 130 GPIO_ACTIVE_HIGH>;
++              enable-active-high;
++      };
++};
++
++
++&pio {
++      pinctrl_uart2_default: uart2@0 {
++              pins {
++                      pinmux = <MT7623_PIN_14_GPIO14_FUNC_URXD2>,
++                               <MT7623_PIN_15_GPIO15_FUNC_UTXD2>;
++              };
++      };
++
++      pinctrl_i2c0_default: i2c@0 {
++              pins {
++                      pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
++                               <MT7623_PIN_76_SCL0_FUNC_SCL0>;
++              };
++      };
++
++      pinctrl_pcie_default: pcie@0 {
++              pins {
++                      pinmux = <MT7623_PIN_24_EINT2_FUNC_PCIE2_PERST_N>,
++                               <MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N>,
++                               <MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N>,
++                               <MT7623_PIN_250_GPIO250_FUNC_PCIE0_CLKREQ_N>,
++                               <MT7623_PIN_251_GPIO251_FUNC_PCIE0_WAKE_N>,
++                               <MT7623_PIN_252_GPIO252_FUNC_PCIE1_CLKREQ_N>,
++                               <MT7623_PIN_253_GPIO253_FUNC_PCIE1_WAKE_N>,
++                               <MT7623_PIN_254_GPIO254_FUNC_PCIE2_CLKREQ_N>,
++                               <MT7623_PIN_255_GPIO255_FUNC_PCIE2_WAKE_N>;
++              };
++      };
++
++      pinctrl_spi_default: spi@0 {
++              pins {
++                      pinmux = <MT7623_PIN_7_SPI1_CSN_FUNC_SPI1_CS>,
++                               <MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MI>,
++                               <MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MO>,
++                               <MT7623_PIN_199_SPI1_CK_FUNC_SPI1_CK>;
++                      bias-disable;
++              };
++      };
++};
++
++&thermal {
++      status = "okay";
++};
++
++&uart2 {
++      status = "okay";
++
++      pinctrl-names = "default";
++        pinctrl-0 = <&pinctrl_uart2_default>;
++};
++
++&i2c0 {
++      status = "okay";
++
++      pinctrl-names = "default";
++        pinctrl-0 = <&pinctrl_i2c0_default>;
++};
++
++&spi {
++      status = "okay";
++
++      pinctrl-names = "default";
++        pinctrl-0 = <&pinctrl_spi_default>;
++
++      m25p80@0 {
++              #address-cells = <1>;
++              #size-cells = <1>;
++              compatible = "mx25l12805d";
++              reg = <0 0 0 0>;
++              linux,modalias = "m25p80", "w25q128";
++              spi-max-frequency = <10000000>;
++
++              partition@0 {
++                      label = "u-boot";
++                      reg = <0x0 0x30000>;
++                      read-only;
++              };
++
++              partition@30000 {
++                      label = "u-boot-env";
++                      reg = <0x30000 0x10000>;
++                      read-only;
++              };
++
++              factory: partition@40000 {
++                      label = "factory";
++                      reg = <0x40000 0x10000>;
++                      read-only;
++              };
++
++              partition@50000 {
++                      label = "firmware";
++                      reg = <0x50000 0xfb0000>;
++              };
++      };
++};
++
++&mmc0 {
++      status = "okay";
++
++//    pinctrl-names = "default", "state_uhs";
++//    pinctrl-0 = <&mmc0_pins_default>;
++//    pinctrl-1 = <&mmc0_pins_uhs>;
++      bus-width = <8>;
++      max-frequency = <50000000>;
++      cap-mmc-highspeed;
++//    vmmc-supply = <&mt6397_vemc_3v3_reg>;
++//    vqmmc-supply = <&mt6397_vio18_reg>;
++      non-removable;
++};
++
++&u3phy {
++      reg-p1-vbus-supply = <&usb_p1_vbus>;
++};
++
++&pcie {
++      status = "okay";
++
++      pinctrl-names = "default";
++        pinctrl-0 = <&pinctrl_pcie_default>;
++};
+diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi
+new file mode 100644
+index 0000000..ba74ed9
+--- /dev/null
++++ b/arch/arm/boot/dts/mt7623.dtsi
+@@ -0,0 +1,348 @@
++/*
++ * Copyright (c) 2014 MediaTek Inc.
++ * Author: Joe.C <yingjoe.chen@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 <dt-bindings/clock/mt7623-clk.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/pinctrl/mt7623-pinfunc.h>
++#include <dt-bindings/reset-controller/mt7623-resets.h>
++#include "skeleton64.dtsi"
++
++/ {
++      compatible = "mediatek,mt7623";
++      interrupt-parent = <&sysirq>;
++
++      cpus {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              enable-method = "mediatek,mt65xx-smp";
++              cpu@0 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a7";
++                      reg = <0x0>;
++              };
++              cpu@1 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a7";
++                      reg = <0x1>;
++              };
++              cpu@2 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a7";
++                      reg = <0x2>;
++              };
++              cpu@3 {
++                      device_type = "cpu";
++                      compatible = "arm,cortex-a7";
++                      reg = <0x3>;
++              };
++
++      };
++
++      clk26m: oscillator@0 {
++              compatible = "fixed-clock";
++              #clock-cells = <0>;
++              clock-frequency = <26000000>;
++              clock-output-names = "clk26m";
++      };
++
++      clk32k: oscillator@1 {
++              compatible = "fixed-clock";
++              #clock-cells = <0>;
++              clock-frequency = <32000>;
++              clock-output-names = "clk32k";
++      };
++
++      timer {
++              compatible = "arm,armv7-timer";
++              interrupt-parent = <&gic>;
++              interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>,
++                           <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
++                                        IRQ_TYPE_LEVEL_LOW)>;
++              clock-frequency = <13000000>;
++              arm,cpu-registers-not-fw-configured;
++      };
++
++      thermal-zones {
++              cpu_thermal: cpu_thermal {
++                      polling-delay-passive = <1000>;
++                      polling-delay = <5000>;
++
++                      thermal-sensors = <&thermal 1>;
++              };
++      };
++
++      soc {
++              #address-cells = <2>;
++              #size-cells = <2>;
++              compatible = "simple-bus";
++              ranges;
++
++              topckgen: topckgen@10000000 {
++                      compatible = "mediatek,mt7623-topckgen";
++                      reg = <0 0x10000000 0 0x1000>;
++                      #clock-cells = <1>;
++              };
++
++              infracfg: infracfg@10001000 {
++                      compatible = "mediatek,mt7623-infracfg", "syscon";
++                      reg = <0 0x10001000 0 0x1000>;
++                      #clock-cells = <1>;
++                      #reset-cells = <1>;
++              };
++
++              pericfg: pericfg@10003000 {
++                      compatible = "mediatek,mt7623-pericfg", "syscon";
++                      reg = <0 0x10003000 0 0x1000>;
++                      #clock-cells = <1>;
++                      #reset-cells = <1>;
++              };
++
++              /*
++               * Pinctrl access register at 0x10005000 through regmap.
++               * Register 0x1000b000 is used by EINT.
++               */
++              pio: pinctrl@10005000 {
++                      compatible = "mediatek,mt7623-pinctrl";
++                      reg = <0 0x1000b000 0 0x1000>;
++                      mediatek,pctl-regmap = <&syscfg_pctl_a>;
++                      pins-are-numbered;
++                      gpio-controller;
++                      #gpio-cells = <2>;
++                      interrupt-controller;
++                      #interrupt-cells = <2>;
++                      interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
++              };
++
++              syscfg_pctl_a: syscfg_pctl_a@10005000 {
++                      compatible = "mediatek,mt7623-pctl-a-syscfg", "syscon";
++                      reg = <0 0x10005000 0 0x1000>;
++              };
++
++              wdt: watchdog@10007000 {
++                      compatible = "mediatek,mt7623-wdt", "mediatek,mt6589-wdt";
++                      reg = <0 0x10007000 0 0x18>;
++              };
++      
++              timer: timer@10008000 {
++                      compatible = "mediatek,mt7623-timer",
++                                      "mediatek,mt6577-timer";
++                      reg = <0 0x10008000 0 0x80>;
++                      interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&topckgen CLK_TOP_AXI_SEL>,
++                               <&topckgen CLK_TOP_RTC_SEL>;
++                      clock-names = "system-clk", "rtc-clk";
++              };
++
++              sysirq: interrupt-controller@10200100 {
++                      compatible = "mediatek,mt7623-sysirq",
++                                   "mediatek,mt6577-sysirq";
++                      interrupt-controller;
++                      #interrupt-cells = <3>;
++                      interrupt-parent = <&gic>;
++                      reg = <0 0x10200100 0 0x1c>;
++              };
++
++              apmixedsys: apmixedsys@10209000 {
++                      compatible = "mediatek,mt7623-apmixedsys";
++                      reg = <0 0x10209000 0 0x1000>;
++                      #clock-cells = <1>;
++              };
++
++              gic: interrupt-controller@10211000 {
++                      compatible = "arm,cortex-a7-gic";
++                      interrupt-controller;
++                      #interrupt-cells = <3>;
++                      interrupt-parent = <&gic>;
++                      reg = <0 0x10211000 0 0x1000>,
++                            <0 0x10212000 0 0x1000>,
++                            <0 0x10214000 0 0x2000>,
++                            <0 0x10216000 0 0x2000>;
++              };
++
++              auxadc: auxadc@11001000 {
++                      compatible = "mediatek,mt7623-auxadc", "mediatek,mt8173-auxadc";
++                      reg = <0 0x11001000 0 0x1000>;
++              };
++
++              uart0: serial@11006000 {
++                      compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++                      reg = <0 0x11002000 0 0x400>;
++                      interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
++                      clock-names = "baud", "bus";
++      
++                      status = "disabled";
++              };
++
++              uart1: serial@11007000 {
++                      compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++                      reg = <0 0x11003000 0 0x400>;
++                      interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_UART1_SEL>, <&pericfg CLK_PERI_UART1>;
++                      clock-names = "baud", "bus";
++      
++                      status = "disabled";
++              };
++
++              uart2: serial@11008000 {
++                      compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++                      reg = <0 0x11004000 0 0x400>;
++                      interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_UART2_SEL>, <&pericfg CLK_PERI_UART2>;
++                      clock-names = "baud", "bus";
++      
++                      status = "disabled";
++              };
++
++              uart3: serial@11009000 {
++                      compatible = "mediatek,mt7623-uart","mediatek,mt6577-uart";
++                      reg = <0 0x11005000 0 0x400>;
++                      interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_UART3_SEL>, <&pericfg CLK_PERI_UART3>;
++                      clock-names = "baud", "bus";
++              
++                      status = "disabled";
++              };
++
++              spi: spi@1100a000 {
++                      compatible = "medi/THEatek,mt7623-spi", "mediatek,mt6589-spi";
++                      reg = <0 0x1100a000 0 0x1000>;
++                      interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_SPI0>;
++                      clock-names = "main";
++      
++                      status = "disabled";
++              };
++      
++              thermal: thermal@1100b000 {
++                      #thermal-sensor-cells = <1>;
++                      compatible = "mediatek,mt7623-thermal", "mediatek,mt8173-thermal";
++                      reg = <0 0x1100b000 0 0x1000>;
++                      interrupts = <0 38 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
++                      clock-names = "therm", "auxadc";
++                      resets = <&pericfg MT7623_PERI_THERM_SW_RST>;
++                      reset-names = "therm";
++                      auxadc = <&auxadc>;
++                      apmixedsys = <&apmixedsys>;
++
++                      status = "disabled";
++              };
++
++              i2c0: i2c@11007000 {
++                      compatible = "mediatek,mt7623-i2c", "mediatek,mt6577-i2c";
++                      reg = <0 0x11007000 0 0x70>,
++                            <0 0x11000300 0 0x80>;
++                      interrupts = <0 44 IRQ_TYPE_LEVEL_LOW>;
++                      clock-frequency = <400000>;
++                      clock-div = <16>;
++                      clocks = <&pericfg CLK_PERI_I2C0>, <&pericfg CLK_PERI_AP_DMA>;
++                      clock-names = "main", "dma";
++                      
++                      status = "disabled";
++              };
++
++              mmc0: mmc@11230000 {
++                      compatible = "mediatek,mt7623-mmc",
++                                   "mediatek,mt8135-mmc";
++                      reg = <0 0x11230000 0 0x1000>;
++                      interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_LOW>;
++                      clocks = <&pericfg CLK_PERI_MSDC20_1>,
++                               <&topckgen CLK_TOP_MSDC30_0_SEL>;
++                      clock-names = "source", "hclk";
++                      status = "disabled";
++              };
++
++              usb: usb30@11270000 {
++                      compatible = "mediatek,mt7623-xhci", "mediatek,mt8173-xhci", "generic-xhci";
++                      reg = <0 0x11270000 0 0x1000>;
++                      interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
++                      usb-phy = <&u3phy>;
++                      usb3-lpm-capable;
++              };
++
++              u3phy: usb-phy@11271000 {
++                      compatible = "mediatek,mt7623-u3phy", "mediatek,mt8173-u3phy";
++                      reg = <0 0x11271000 0 0x3000>,
++                            <0 0x11280000 0 0x20000>;
++//                    power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
++//                    reg-vusb33-supply = <&mt6397_vusb_reg>;
++                      clocks = <&pericfg CLK_PERI_USB0>,
++                               <&pericfg CLK_PERI_USB1>,
++                               <&topckgen CLK_TOP_USB20_SEL>;
++//                             <&apmixedsys CLK_APMIXED_REF2USB_TX>;
++                      clock-names = "wakeup_deb_p0",
++                                    "wakeup_deb_p1",
++                                    "sys_mac";
++//                                  "u3phya_ref";
++                      disable-usb2-p1;
++              };
++      };
++
++      ethernet@1B100000 {
++              compatible = "mediatek,mt7623-net";
++              interrupts = <0 200 IRQ_TYPE_LEVEL_LOW>;
++      };
++
++      pcie: pcie@1a140000 {
++              compatible = "mediatek,mt7623-pcie";
++              reg = <0 0x1a140000 0 0x10000>;
++
++              #address-cells = <3>;
++              #size-cells = <2>;
++
++              device_type = "pci";
++
++              bus-range = <0 255>;
++              ranges = <
++                      0x02000000 0 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */
++                      0x01000000 0 0 0x00000000 0x1A160000 0 0x00010000 /* io space */
++              >;
++
++              pcie0 {
++                      reg = <0x0000 0 0 0 0>;
++
++                      #address-cells = <3>;
++                      #size-cells = <2>;
++
++                      device_type = "pci";
++              };
++
++              pcie1 {
++                      reg = <0x0800 0 0 0 0>;
++
++                      #address-cells = <3>;
++                      #size-cells = <2>;
++
++                      device_type = "pci";
++              };
++
++              pcie2 {
++                      reg = <0x1000 0 0 0 0>;
++
++                      #address-cells = <3>;
++                      #size-cells = <2>;
++
++                      device_type = "pci";
++              };
++
++              status = "disabled";
++      };
++};
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0067-arm-mediatek-add-mt7623-support.patch b/target/linux/mediatek/patches/0067-arm-mediatek-add-mt7623-support.patch
new file mode 100644 (file)
index 0000000..28193cc
--- /dev/null
@@ -0,0 +1,118 @@
+From 89556b1a4d98fbfe498c8f26e988cbb8266f7dfe Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 13:17:35 +0200
+Subject: [PATCH 67/76] arm: mediatek: add mt7623 support
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/arm/mach-mediatek/Kconfig                     |    6 ++
+ arch/arm/mach-mediatek/mediatek.c                  |    2 +
+ .../dt-bindings/reset-controller/mt7623-resets.h   |   59 ++++++++++++++++++++
+ 3 files changed, 67 insertions(+)
+ create mode 100644 include/dt-bindings/reset-controller/mt7623-resets.h
+
+diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
+index 7704818..5393d25 100644
+--- a/arch/arm/mach-mediatek/Kconfig
++++ b/arch/arm/mach-mediatek/Kconfig
+@@ -17,6 +17,12 @@ config MACH_MT6592
+       bool "MediaTek MT6592 SoCs support"
+       default ARCH_MEDIATEK
++config MACH_MT7623
++      bool "MediaTek MT7623 SoCs support"
++      default ARCH_MEDIATEK
++      select ARCH_HAS_PCI
++      select PCI
++
+ config MACH_MT8127
+       bool "MediaTek MT8127 SoCs support"
+       default ARCH_MEDIATEK
+diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c
+index 6b38d67..ab8cf21 100644
+--- a/arch/arm/mach-mediatek/mediatek.c
++++ b/arch/arm/mach-mediatek/mediatek.c
+@@ -29,6 +29,7 @@ static void __init mediatek_timer_init(void)
+       void __iomem *gpt_base = 0;
+       if (of_machine_is_compatible("mediatek,mt6589") ||
++          of_machine_is_compatible("mediatek,mt7623") ||
+           of_machine_is_compatible("mediatek,mt8135") ||
+           of_machine_is_compatible("mediatek,mt8127")) {
+               /* turn on GPT6 which ungates arch timer clocks */
+@@ -48,6 +49,7 @@ static void __init mediatek_timer_init(void)
+ static const char * const mediatek_board_dt_compat[] = {
+       "mediatek,mt6589",
+       "mediatek,mt6592",
++      "mediatek,mt7623",
+       "mediatek,mt8127",
+       "mediatek,mt8135",
+       NULL,
+diff --git a/include/dt-bindings/reset-controller/mt7623-resets.h b/include/dt-bindings/reset-controller/mt7623-resets.h
+new file mode 100644
+index 0000000..28a7d69
+--- /dev/null
++++ b/include/dt-bindings/reset-controller/mt7623-resets.h
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (c) 2015 OpenWrt
++ * Author: John Crispin
++ *
++ * 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_MT7623
++#define _DT_BINDINGS_RESET_CONTROLLER_MT7623
++
++/* INFRACFG resets */
++#define MT7623_INFRA_EMI_REG_RST      0
++#define MT7623_INFRA_DRAMC0_A0_RST    1
++#define MT7623_INFRA_FHCTL_RST                2
++#define MT7623_INFRA_APCIRQ_EINT_RST  3
++#define MT7623_INFRA_APXGPT_RST               4
++#define MT7623_INFRA_SCPSYS_RST               5
++#define MT7623_INFRA_KP_RST           6
++#define MT7623_INFRA_PMIC_WRAP_RST    7
++#define MT7623_INFRA_MIPI_RST         8
++#define MT7623_INFRA_IRRX_RST         9
++#define MT7623_INFRA_CEC_RST          10
++#define MT7623_INFRA_EMI_RST          32
++#define MT7623_INFRA_DRAMC0_RST               34
++#define MT7623_INFRA_SMI_RST          37
++#define MT7623_INFRA_M4U_RST          38
++
++/* PERICFG resets */
++#define MT7623_PERI_UART0_SW_RST      0
++#define MT7623_PERI_UART1_SW_RST      1
++#define MT7623_PERI_UART2_SW_RST      2
++#define MT7623_PERI_UART3_SW_RST      3
++#define MT7623_PERI_GCPU_SW_RST               5
++#define MT7623_PERI_BTIF_SW_RST               6
++#define MT7623_PERI_PWM_SW_RST                8
++#define MT7623_PERI_AUXADC_SW_RST     10
++#define MT7623_PERI_DMA_SW_RST                11
++#define MT7623_PERI_NFI_SW_RST                14
++#define MT7623_PERI_NLI_SW_RST                15
++#define MT7623_PERI_THERM_SW_RST      16
++#define MT7623_PERI_MSDC0_SW_RST      17
++#define MT7623_PERI_MSDC1_SW_RST      19
++#define MT7623_PERI_MSDC2_SW_RST      20
++#define MT7623_PERI_I2C0_SW_RST               22
++#define MT7623_PERI_I2C1_SW_RST               23
++#define MT7623_PERI_I2C2_SW_RST               24
++#define MT7623_PERI_I2C3_SW_RST               25
++#define MT7623_PERI_USB_SW_RST                28
++#define MT7623_PERI_ETH_SW_RST                29
++#define MT7623_PERI_SPI0_SW_RST               33
++
++#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7623 */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0068-SDK_compat.patch b/target/linux/mediatek/patches/0068-SDK_compat.patch
new file mode 100644 (file)
index 0000000..2800dbd
--- /dev/null
@@ -0,0 +1,1579 @@
+From 4c48177826502673737609ffa04b66051a1e0f75 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Jun 2015 17:05:12 +0200
+Subject: [PATCH 68/76] SDK_compat
+
+---
+ arch/arm/include/asm/mach/mt_irq.h         |  174 ++++++++
+ arch/arm/include/asm/rt2880/mt_irq.h       |  174 ++++++++
+ arch/arm/include/asm/rt2880/rt_mmap.h      |   58 +++
+ arch/arm/include/asm/rt2880/surfboardint.h |   42 ++
+ arch/arm/include/asm/rt2880/x_define_irq.h |  160 +++++++
+ arch/arm/mach-mediatek/mediatek.c          |  186 ++++++++
+ arch/arm/mach-mediatek/mt_reg_base.h       |  640 ++++++++++++++++++++++++++++
+ arch/arm/mach-mediatek/rt_mmap.h           |   58 +++
+ 8 files changed, 1492 insertions(+)
+ create mode 100644 arch/arm/include/asm/mach/mt_irq.h
+ create mode 100644 arch/arm/include/asm/rt2880/mt_irq.h
+ create mode 100644 arch/arm/include/asm/rt2880/rt_mmap.h
+ create mode 100644 arch/arm/include/asm/rt2880/surfboardint.h
+ create mode 100644 arch/arm/include/asm/rt2880/x_define_irq.h
+ create mode 100644 arch/arm/mach-mediatek/mt_reg_base.h
+ create mode 100644 arch/arm/mach-mediatek/rt_mmap.h
+
+diff --git a/arch/arm/include/asm/mach/mt_irq.h b/arch/arm/include/asm/mach/mt_irq.h
+new file mode 100644
+index 0000000..ff265e0
+--- /dev/null
++++ b/arch/arm/include/asm/mach/mt_irq.h
+@@ -0,0 +1,174 @@
++#ifndef __MT_IRQ_H
++#define __MT_IRQ_H
++
++#define GIC_PRIVATE_SIGNALS     (32)
++#define NR_GIC_SGI              (16)
++#define NR_GIC_PPI              (16)
++#define GIC_PPI_OFFSET          (27)
++#define MT_NR_PPI               (5)
++#define MT_NR_SPI               (224)
++#define NR_MT_IRQ_LINE          (GIC_PPI_OFFSET + MT_NR_PPI + MT_NR_SPI)
++
++#define MT65xx_EDGE_SENSITIVE 0
++#define MT65xx_LEVEL_SENSITIVE 1
++
++#define MT65xx_POLARITY_LOW   0
++#define MT65xx_POLARITY_HIGH  1
++
++#define GIC_PPI_GLOBAL_TIMER      (GIC_PPI_OFFSET + 0)
++#define GIC_PPI_LEGACY_FIQ        (GIC_PPI_OFFSET + 1)
++#define GIC_PPI_PRIVATE_TIMER     (GIC_PPI_OFFSET + 2)
++#define GIC_PPI_NS_PRIVATE_TIMER  (GIC_PPI_OFFSET + 3)
++#define GIC_PPI_LEGACY_IRQ        (GIC_PPI_OFFSET + 4)
++
++#define MT_BTIF_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 50)
++#define MT_DMA_BTIF_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 71)
++#define MT_DMA_BTIF_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 72)
++
++#if !defined(CONFIG_MT8127_FPGA)
++
++#if !defined(__ASSEMBLY__)
++#define X_DEFINE_IRQ(__name, __num, __pol, __sens)  __name = __num,
++enum 
++{
++#include "x_define_irq.h"
++};
++#undef X_DEFINE_IRQ
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID         WF_HIF_IRQ_ID /* FIXME */
++
++#endif
++
++#else
++
++#define MT6582_USB0_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 32)
++#define MT6582_USB1_IRQ_ID                                    (GIC_PRIVATE_SIGNALS + 33)
++#define MT_PTP_THERM_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 38)
++#define MT_MSDC0_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 39)
++#define MT_MSDC1_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 40)
++//#define MT_MSDC2_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 41) //6582 take off
++//#define MT_MSDC3_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 42) //6582 take off
++#define MT6582_AP_HIF_IRQ_ID                (GIC_PRIVATE_SIGNALS + 43)
++#define MT_I2C0_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 44)
++#define MT_I2C1_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 45)
++#define MT_I2C2_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 46)
++#define MT_UART1_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 51)
++#define MT_UART2_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 52)
++#define MT_UART3_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 53)
++#define MT_UART4_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 54)
++#define MT_NFIECC_IRQ_ID                    (GIC_PRIVATE_SIGNALS + 55)
++#define MT_NFI_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 56)
++#define MT_GDMA1_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 57)
++#define MT_GDMA2_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 58)
++#define MT_DMA_UART0_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 63)
++#define MT_DMA_UART0_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 64)
++#define MT_DMA_UART1_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 65)
++#define MT_DMA_UART1_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 66)
++#define MT_DMA_UART2_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 67)
++#define MT_DMA_UART2_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 68)
++#define MT6582_SPI1_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 78)
++//#define MT_MSDC4_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 83) //6582 take off
++#define MT_PTP_FSM_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 85)
++#define MT_WDT_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 88)//TBD:For build pass
++#define MT_APARM_DOMAIN_IRQ_ID              (GIC_PRIVATE_SIGNALS + 94)
++#define MT_APARM_DECERR_IRQ_ID              (GIC_PRIVATE_SIGNALS + 95)
++#if 1 //cliff
++#define MT6582_GPT_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 112)//10.2 update
++#define MT_EINT_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#else
++#define MT6582_GPT_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#define MT_EINT_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 116)//10.2 update
++#endif
++#define MT6582_PMIC_WRAP_IRQ_ID             (GIC_PRIVATE_SIGNALS + 115)//0x80
++#define MT_KP_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 116)
++#define MT_SPM_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 117)
++#define MT_SPM1_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 118)
++#define MT_VENC_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 139)
++#define MT_VDEC_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 140)
++#define CAMERA_ISP_IRQ0_ID                  (GIC_PRIVATE_SIGNALS + 143) // cam_irq_b
++#define CAMERA_ISP_IRQ1_ID                  (GIC_PRIVATE_SIGNALS + 144) // cam_irq1_b
++#define CAMERA_ISP_IRQ2_ID                  (GIC_PRIVATE_SIGNALS + 145) // cam_irq2_b
++//#define CAMERA_ISP_IRQ3_ID                  (GIC_PRIVATE_SIGNALS + 144) // cam_irq3_b 6582 take off
++#define MT6582_JPEG_ENC_IRQ_ID              (GIC_PRIVATE_SIGNALS + 141)
++//#define MT6582_JPEG_DEC_IRQ_ID              (GIC_PRIVATE_SIGNALS + 148) //6582 take off
++/* Not sure and comments for early porting */
++#define MT_EINT_DIRECT0_IRQ_ID              (GIC_PRIVATE_SIGNALS + 121)
++
++#if 0
++#define MT_MFG_IRQ_GP_ID                     (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ_GPMMU_ID                  (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ_PP0_ID                    (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ_PPMMU0_ID                 (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ_PP1_ID                    (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ_PPMMU1_ID                 (GIC_PRIVATE_SIGNALS + 175)
++#else
++#define MT_MFG_IRQ0_ID                     (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ1_ID                     (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ2_ID                     (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ3_ID                     (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ4_ID                     (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ5_ID                     (GIC_PRIVATE_SIGNALS + 175)
++#define MT_MFG_IRQ6_ID                     (GIC_PRIVATE_SIGNALS + 176)
++#define MT_MFG_IRQ7_ID                     (GIC_PRIVATE_SIGNALS + 177)
++#define MT_MFG_IRQ8_ID                     (GIC_PRIVATE_SIGNALS + 178)
++#define MT_MFG_IRQ9_ID                     (GIC_PRIVATE_SIGNALS + 179)
++#define MT_MFG_IRQ10_ID                    (GIC_PRIVATE_SIGNALS + 180)
++#endif
++
++
++#if 0
++#define MT6582_DISP_MUTEX_IRQ_ID            (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_DISP_ROT_IRQ_ID              (GIC_PRIVATE_SIGNALS + 161)
++#define MT6582_DISP_SCL_IRQ_ID              (GIC_PRIVATE_SIGNALS + 162)
++#define MT6582_DISP_OVL_IRQ_ID              (GIC_PRIVATE_SIGNALS + 163)
++#define MT6582_DISP_WDMA0_IRQ_ID            (GIC_PRIVATE_SIGNALS + 164)
++#define MT6582_DISP_WDMA1_IRQ_ID            (GIC_PRIVATE_SIGNALS + 165)
++#define MT6582_DISP_RDMA0_IRQ_ID            (GIC_PRIVATE_SIGNALS + 166)
++#define MT6582_DISP_RDMA1_IRQ_ID            (GIC_PRIVATE_SIGNALS + 167)
++#define MT6582_DISP_BLS_IRQ_ID              (GIC_PRIVATE_SIGNALS + 168)
++#define MT6582_DISP_COLOR_IRQ_ID            (GIC_PRIVATE_SIGNALS + 169)
++#define MT6582_DISP_TDSHP_IRQ_ID            (GIC_PRIVATE_SIGNALS + 170)
++#define MT6582_DISP_DBI_IRQ_ID              (GIC_PRIVATE_SIGNALS + 171)
++#define MT6582_DISP_DSI_IRQ_ID              (GIC_PRIVATE_SIGNALS + 172)
++#define MT6582_DISP_DPI0_IRQ_ID             (GIC_PRIVATE_SIGNALS + 173)
++#define MT6582_DISP_DPI1_IRQ_ID             (GIC_PRIVATE_SIGNALS + 174)
++#define MT6582_DISP_CMDQ_IRQ_ID             (GIC_PRIVATE_SIGNALS + 176)
++#else
++#define MT6582_DISP_MDP_RDMA_IRQ_ID       (GIC_PRIVATE_SIGNALS+146)  
++#define MT6582_DISP_MDP_RSZ0_IRQ_ID       (GIC_PRIVATE_SIGNALS+147)  
++#define MT6582_DISP_MDP_RSZ1_IRQ_ID       (GIC_PRIVATE_SIGNALS+148)  
++#define MT6582_DISP_MDP_TDSHP_IRQ_ID      (GIC_PRIVATE_SIGNALS+149)  
++#define MT6582_DISP_MDP_WDMA_IRQ_ID       (GIC_PRIVATE_SIGNALS+150)  
++#define MT6582_DISP_MDP_WROT_IRQ_ID       (GIC_PRIVATE_SIGNALS+151)  
++#define MT6582_DISP_RDMA_IRQ_ID           (GIC_PRIVATE_SIGNALS+152)  
++#define MT6582_DISP_OVL_IRQ_ID            (GIC_PRIVATE_SIGNALS+153)  
++#define MT6582_DISP_WDMA_IRQ_ID           (GIC_PRIVATE_SIGNALS+154)  
++#define MT6582_DISP_BLS_IRQ_ID            (GIC_PRIVATE_SIGNALS+155)  
++#define MT6582_DISP_COLOR_IRQ_ID          (GIC_PRIVATE_SIGNALS+156)  
++#define MT6582_DISP_DSI_IRQ_ID            (GIC_PRIVATE_SIGNALS+157)  
++#define MT6582_DISP_DPI0_IRQ_ID           (GIC_PRIVATE_SIGNALS+158)  
++#define MT6582_DISP_CMDQ_IRQ_ID           (GIC_PRIVATE_SIGNALS+159)  
++#define MT6582_DISP_CMDQ_SECURE_IRQ_ID    (GIC_PRIVATE_SIGNALS+160)  
++#define MT6582_DISP_MUTEX_IRQ_ID          (GIC_PRIVATE_SIGNALS+161)  
++#define MT6582_DISP_SMI_LARB0_IRQ_ID      (GIC_PRIVATE_SIGNALS+162)
++#define MT_CIRQ_IRQ_ID                      (GIC_PRIVATE_SIGNALS+187)
++#endif
++#define MT6582_APARM_GPTTIMER_IRQ_LINE      MT6582_GPT_IRQ_ID
++
++// MT6582 Wifi AHB Slave HIF
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID         (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_HIF_PDMA_IRQ_ID              (GIC_PRIVATE_SIGNALS + 59)
++
++/* These are defined for solving compile errors only. They are not existing on FPGA */
++#define TS_IRQ_ID                         (GIC_PRIVATE_SIGNALS + 163)
++#define CONN_WDT_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 163)
++#define LOWBATTERY_IRQ_ID                 (GIC_PRIVATE_SIGNALS + 163)
++#define MD_WDT_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 163)
++
++#define WF_HIF_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 184)
++#define MT_CONN2AP_BTIF_WAKEUP_IRQ_ID    (GIC_PRIVATE_SIGNALS + 185)
++#define BT_CVSD_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 186)
++
++#define CCIF0_AP_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 100)
++#endif
++
++#endif
+diff --git a/arch/arm/include/asm/rt2880/mt_irq.h b/arch/arm/include/asm/rt2880/mt_irq.h
+new file mode 100644
+index 0000000..ff265e0
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/mt_irq.h
+@@ -0,0 +1,174 @@
++#ifndef __MT_IRQ_H
++#define __MT_IRQ_H
++
++#define GIC_PRIVATE_SIGNALS     (32)
++#define NR_GIC_SGI              (16)
++#define NR_GIC_PPI              (16)
++#define GIC_PPI_OFFSET          (27)
++#define MT_NR_PPI               (5)
++#define MT_NR_SPI               (224)
++#define NR_MT_IRQ_LINE          (GIC_PPI_OFFSET + MT_NR_PPI + MT_NR_SPI)
++
++#define MT65xx_EDGE_SENSITIVE 0
++#define MT65xx_LEVEL_SENSITIVE 1
++
++#define MT65xx_POLARITY_LOW   0
++#define MT65xx_POLARITY_HIGH  1
++
++#define GIC_PPI_GLOBAL_TIMER      (GIC_PPI_OFFSET + 0)
++#define GIC_PPI_LEGACY_FIQ        (GIC_PPI_OFFSET + 1)
++#define GIC_PPI_PRIVATE_TIMER     (GIC_PPI_OFFSET + 2)
++#define GIC_PPI_NS_PRIVATE_TIMER  (GIC_PPI_OFFSET + 3)
++#define GIC_PPI_LEGACY_IRQ        (GIC_PPI_OFFSET + 4)
++
++#define MT_BTIF_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 50)
++#define MT_DMA_BTIF_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 71)
++#define MT_DMA_BTIF_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 72)
++
++#if !defined(CONFIG_MT8127_FPGA)
++
++#if !defined(__ASSEMBLY__)
++#define X_DEFINE_IRQ(__name, __num, __pol, __sens)  __name = __num,
++enum 
++{
++#include "x_define_irq.h"
++};
++#undef X_DEFINE_IRQ
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID         WF_HIF_IRQ_ID /* FIXME */
++
++#endif
++
++#else
++
++#define MT6582_USB0_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 32)
++#define MT6582_USB1_IRQ_ID                                    (GIC_PRIVATE_SIGNALS + 33)
++#define MT_PTP_THERM_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 38)
++#define MT_MSDC0_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 39)
++#define MT_MSDC1_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 40)
++//#define MT_MSDC2_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 41) //6582 take off
++//#define MT_MSDC3_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 42) //6582 take off
++#define MT6582_AP_HIF_IRQ_ID                (GIC_PRIVATE_SIGNALS + 43)
++#define MT_I2C0_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 44)
++#define MT_I2C1_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 45)
++#define MT_I2C2_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 46)
++#define MT_UART1_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 51)
++#define MT_UART2_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 52)
++#define MT_UART3_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 53)
++#define MT_UART4_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 54)
++#define MT_NFIECC_IRQ_ID                    (GIC_PRIVATE_SIGNALS + 55)
++#define MT_NFI_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 56)
++#define MT_GDMA1_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 57)
++#define MT_GDMA2_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 58)
++#define MT_DMA_UART0_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 63)
++#define MT_DMA_UART0_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 64)
++#define MT_DMA_UART1_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 65)
++#define MT_DMA_UART1_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 66)
++#define MT_DMA_UART2_TX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 67)
++#define MT_DMA_UART2_RX_IRQ_ID              (GIC_PRIVATE_SIGNALS + 68)
++#define MT6582_SPI1_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 78)
++//#define MT_MSDC4_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 83) //6582 take off
++#define MT_PTP_FSM_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 85)
++#define MT_WDT_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 88)//TBD:For build pass
++#define MT_APARM_DOMAIN_IRQ_ID              (GIC_PRIVATE_SIGNALS + 94)
++#define MT_APARM_DECERR_IRQ_ID              (GIC_PRIVATE_SIGNALS + 95)
++#if 1 //cliff
++#define MT6582_GPT_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 112)//10.2 update
++#define MT_EINT_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#else
++#define MT6582_GPT_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 113)//10.2 update
++#define MT_EINT_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 116)//10.2 update
++#endif
++#define MT6582_PMIC_WRAP_IRQ_ID             (GIC_PRIVATE_SIGNALS + 115)//0x80
++#define MT_KP_IRQ_ID                  (GIC_PRIVATE_SIGNALS + 116)
++#define MT_SPM_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 117)
++#define MT_SPM1_IRQ_ID                       (GIC_PRIVATE_SIGNALS + 118)
++#define MT_VENC_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 139)
++#define MT_VDEC_IRQ_ID                      (GIC_PRIVATE_SIGNALS + 140)
++#define CAMERA_ISP_IRQ0_ID                  (GIC_PRIVATE_SIGNALS + 143) // cam_irq_b
++#define CAMERA_ISP_IRQ1_ID                  (GIC_PRIVATE_SIGNALS + 144) // cam_irq1_b
++#define CAMERA_ISP_IRQ2_ID                  (GIC_PRIVATE_SIGNALS + 145) // cam_irq2_b
++//#define CAMERA_ISP_IRQ3_ID                  (GIC_PRIVATE_SIGNALS + 144) // cam_irq3_b 6582 take off
++#define MT6582_JPEG_ENC_IRQ_ID              (GIC_PRIVATE_SIGNALS + 141)
++//#define MT6582_JPEG_DEC_IRQ_ID              (GIC_PRIVATE_SIGNALS + 148) //6582 take off
++/* Not sure and comments for early porting */
++#define MT_EINT_DIRECT0_IRQ_ID              (GIC_PRIVATE_SIGNALS + 121)
++
++#if 0
++#define MT_MFG_IRQ_GP_ID                     (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ_GPMMU_ID                  (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ_PP0_ID                    (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ_PPMMU0_ID                 (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ_PP1_ID                    (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ_PPMMU1_ID                 (GIC_PRIVATE_SIGNALS + 175)
++#else
++#define MT_MFG_IRQ0_ID                     (GIC_PRIVATE_SIGNALS + 170)
++#define MT_MFG_IRQ1_ID                     (GIC_PRIVATE_SIGNALS + 171)
++#define MT_MFG_IRQ2_ID                     (GIC_PRIVATE_SIGNALS + 172)
++#define MT_MFG_IRQ3_ID                     (GIC_PRIVATE_SIGNALS + 173)
++#define MT_MFG_IRQ4_ID                     (GIC_PRIVATE_SIGNALS + 174)
++#define MT_MFG_IRQ5_ID                     (GIC_PRIVATE_SIGNALS + 175)
++#define MT_MFG_IRQ6_ID                     (GIC_PRIVATE_SIGNALS + 176)
++#define MT_MFG_IRQ7_ID                     (GIC_PRIVATE_SIGNALS + 177)
++#define MT_MFG_IRQ8_ID                     (GIC_PRIVATE_SIGNALS + 178)
++#define MT_MFG_IRQ9_ID                     (GIC_PRIVATE_SIGNALS + 179)
++#define MT_MFG_IRQ10_ID                    (GIC_PRIVATE_SIGNALS + 180)
++#endif
++
++
++#if 0
++#define MT6582_DISP_MUTEX_IRQ_ID            (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_DISP_ROT_IRQ_ID              (GIC_PRIVATE_SIGNALS + 161)
++#define MT6582_DISP_SCL_IRQ_ID              (GIC_PRIVATE_SIGNALS + 162)
++#define MT6582_DISP_OVL_IRQ_ID              (GIC_PRIVATE_SIGNALS + 163)
++#define MT6582_DISP_WDMA0_IRQ_ID            (GIC_PRIVATE_SIGNALS + 164)
++#define MT6582_DISP_WDMA1_IRQ_ID            (GIC_PRIVATE_SIGNALS + 165)
++#define MT6582_DISP_RDMA0_IRQ_ID            (GIC_PRIVATE_SIGNALS + 166)
++#define MT6582_DISP_RDMA1_IRQ_ID            (GIC_PRIVATE_SIGNALS + 167)
++#define MT6582_DISP_BLS_IRQ_ID              (GIC_PRIVATE_SIGNALS + 168)
++#define MT6582_DISP_COLOR_IRQ_ID            (GIC_PRIVATE_SIGNALS + 169)
++#define MT6582_DISP_TDSHP_IRQ_ID            (GIC_PRIVATE_SIGNALS + 170)
++#define MT6582_DISP_DBI_IRQ_ID              (GIC_PRIVATE_SIGNALS + 171)
++#define MT6582_DISP_DSI_IRQ_ID              (GIC_PRIVATE_SIGNALS + 172)
++#define MT6582_DISP_DPI0_IRQ_ID             (GIC_PRIVATE_SIGNALS + 173)
++#define MT6582_DISP_DPI1_IRQ_ID             (GIC_PRIVATE_SIGNALS + 174)
++#define MT6582_DISP_CMDQ_IRQ_ID             (GIC_PRIVATE_SIGNALS + 176)
++#else
++#define MT6582_DISP_MDP_RDMA_IRQ_ID       (GIC_PRIVATE_SIGNALS+146)  
++#define MT6582_DISP_MDP_RSZ0_IRQ_ID       (GIC_PRIVATE_SIGNALS+147)  
++#define MT6582_DISP_MDP_RSZ1_IRQ_ID       (GIC_PRIVATE_SIGNALS+148)  
++#define MT6582_DISP_MDP_TDSHP_IRQ_ID      (GIC_PRIVATE_SIGNALS+149)  
++#define MT6582_DISP_MDP_WDMA_IRQ_ID       (GIC_PRIVATE_SIGNALS+150)  
++#define MT6582_DISP_MDP_WROT_IRQ_ID       (GIC_PRIVATE_SIGNALS+151)  
++#define MT6582_DISP_RDMA_IRQ_ID           (GIC_PRIVATE_SIGNALS+152)  
++#define MT6582_DISP_OVL_IRQ_ID            (GIC_PRIVATE_SIGNALS+153)  
++#define MT6582_DISP_WDMA_IRQ_ID           (GIC_PRIVATE_SIGNALS+154)  
++#define MT6582_DISP_BLS_IRQ_ID            (GIC_PRIVATE_SIGNALS+155)  
++#define MT6582_DISP_COLOR_IRQ_ID          (GIC_PRIVATE_SIGNALS+156)  
++#define MT6582_DISP_DSI_IRQ_ID            (GIC_PRIVATE_SIGNALS+157)  
++#define MT6582_DISP_DPI0_IRQ_ID           (GIC_PRIVATE_SIGNALS+158)  
++#define MT6582_DISP_CMDQ_IRQ_ID           (GIC_PRIVATE_SIGNALS+159)  
++#define MT6582_DISP_CMDQ_SECURE_IRQ_ID    (GIC_PRIVATE_SIGNALS+160)  
++#define MT6582_DISP_MUTEX_IRQ_ID          (GIC_PRIVATE_SIGNALS+161)  
++#define MT6582_DISP_SMI_LARB0_IRQ_ID      (GIC_PRIVATE_SIGNALS+162)
++#define MT_CIRQ_IRQ_ID                      (GIC_PRIVATE_SIGNALS+187)
++#endif
++#define MT6582_APARM_GPTTIMER_IRQ_LINE      MT6582_GPT_IRQ_ID
++
++// MT6582 Wifi AHB Slave HIF
++#define MT6582_AHB_SLAVE_HIF_IRQ_ID         (GIC_PRIVATE_SIGNALS + 160)
++#define MT6582_HIF_PDMA_IRQ_ID              (GIC_PRIVATE_SIGNALS + 59)
++
++/* These are defined for solving compile errors only. They are not existing on FPGA */
++#define TS_IRQ_ID                         (GIC_PRIVATE_SIGNALS + 163)
++#define CONN_WDT_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 163)
++#define LOWBATTERY_IRQ_ID                 (GIC_PRIVATE_SIGNALS + 163)
++#define MD_WDT_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 163)
++
++#define WF_HIF_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 184)
++#define MT_CONN2AP_BTIF_WAKEUP_IRQ_ID    (GIC_PRIVATE_SIGNALS + 185)
++#define BT_CVSD_IRQ_ID                     (GIC_PRIVATE_SIGNALS + 186)
++
++#define CCIF0_AP_IRQ_ID                   (GIC_PRIVATE_SIGNALS + 100)
++#endif
++
++#endif
+diff --git a/arch/arm/include/asm/rt2880/rt_mmap.h b/arch/arm/include/asm/rt2880/rt_mmap.h
+new file mode 100644
+index 0000000..e86b3bb
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/rt_mmap.h
+@@ -0,0 +1,58 @@
++#define HIFSYS_BASE                   0xFA000000 //for PCIe/USB
++#define ETHDMASYS_BASE                        0xFB000000 //for I2S/PCM/GDMA/HSDMA/FE/GMAC
++
++#define HIFSYS_PCI_BASE                 0xFA140000
++#define HIFSYS_USB_HOST_BASE            0xFA1C0000
++#define HIFSYS_USB_HOST2_BASE           0xFA240000
++
++#define ETHDMASYS_SYSCTL_BASE           0xFB000000
++#define ETHDMASYS_RBUS_MATRIXCTL_BASE   0xFB000400
++#define ETHDMASYS_I2S_BASE              0xFB000A00
++#define ETHDMASYS_PCM_BASE              0xFB002000
++#define ETHDMASYS_GDMA_BASE             0xFB002800
++#define ETHDMASYS_HS_DMA_BASE           0xFB007000
++#define ETHDMASYS_FRAME_ENGINE_BASE     0xFB100000
++#define ETHDMASYS_PPE_BASE            0xFB100C00
++#define ETHDMASYS_ETH_SW_BASE         0xFB110000
++#define ETHDMASYS_CRYPTO_ENGINE_BASE  0xFB240000
++
++//for backward-compatible
++#define RALINK_FRAME_ENGINE_BASE      ETHDMASYS_FRAME_ENGINE_BASE
++#define RALINK_PPE_BASE                 ETHDMASYS_PPE_BASE
++#define RALINK_SYSCTL_BASE            ETHDMASYS_SYSCTL_BASE
++#define RALINK_ETH_SW_BASE            ETHDMASYS_ETH_SW_BASE
++#define RALINK_GDMA_BASE      ETHDMASYS_GDMA_BASE
++#define RALINK_HS_DMA_BASE    ETHDMASYS_HS_DMA_BASE
++#define RALINK_11N_MAC_BASE           0       //unused for rt_rdm usage
++
++//Reset Control Register
++#define RSTCTL_SYS_RST                        (1<<0)
++#define RSTCTL_MCM_RST                        (1<<2)
++#define RSTCTL_HSDMA_RST              (1<<5)
++#define RSTCTL_FE_RST                 (1<<6)
++#define RSTCTL_SPDIF_RST              (1<<7)
++#define RSTCTL_TIMER_RST              (1<<8)
++#define RSTCTL_CIRQ_RST                       (1<<9)
++#define RSTCTL_MC_RST                 (1<<10)
++#define RSTCTL_PCM_RST                        (1<<11)
++#define RSTCTL_GPIO_RST                       (1<<13)
++#define RSTCTL_GDMA_RST                       (1<<14)
++#define RSTCTL_NAND_RST                       (1<<15)
++#define RSTCTL_I2C_RST                        (1<<16)
++#define RSTCTL_I2S_RST                        (1<<17)
++#define RSTCTL_SPI_RST                        (1<<18)
++#define RSTCTL_UART0_RST              (1<<19)
++#define RSTCTL_UART1_RST              (1<<20)
++#define RSTCTL_UART2_RST              (1<<21)
++#define RSTCTL_UPHY_RST                       (1<<22)
++#define RSTCTL_ETH_RST                        (1<<23)
++#define RSTCTL_PCIE0_RST              (1<<24)
++#define RSTCTL_PCIE1_RST              (1<<25)
++#define RSTCTL_PCIE2_RST              (1<<26)
++#define RSTCTL_AUX_STCK_RST           (1<<28)
++#define RSTCTL_CRYPT_RST              (1<<29)
++#define RSTCTL_SDXC_RST                       (1<<30)
++#define RSTCTL_PWM_RST                        (1<<31)
++
++//for backward-compatible
++#define RALINK_FE_RST                 RSTCTL_FE_RST
+diff --git a/arch/arm/include/asm/rt2880/surfboardint.h b/arch/arm/include/asm/rt2880/surfboardint.h
+new file mode 100644
+index 0000000..4581598
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/surfboardint.h
+@@ -0,0 +1,42 @@
++#include "mt_irq.h"
++
++//#define SURFBOARDINT_SYSCTL      0      /* SYSCTL */
++#define SURFBOARDINT_FE          MT_FE_ORIG_IRQ_ID    /* FE */
++#define SURFBOARDINT_PCM         MT_PCM_IRQ_ID      /* PCM */
++//#define SURFBOARDINT_GPIO        6      /* GPIO */
++#define SURFBOARDINT_HSGDMA      MT_HSDMA_IRQ_ID      /* HSGDMA */
++#define SURFBOARDINT_DMA         MT_GDMA_IRQ_ID      /* DMA */
++//#define SURFBOARDINT_PC          9      /* Performance counter */
++#define SURFBOARDINT_I2S         MT_I2S_IRQ_ID     /* I2S */
++//#define SURFBOARDINT_SPI         11     /* SPI */
++//#define SURFBOARDINT_AES         13     /* AES */
++//#define SURFBOARDINT_AESENGINE      13     /* AES Engine */
++#define SURFBOARDINT_CRYPTO      MT_CRYPTO_IRQ_ID     /* CryptoEngine */
++//#define SURFBOARDINT_SDXC        14     /* SDXC */
++//#define SURFBOARDINT_ESW         17     /* ESW */
++#define SURFBOARDINT_USB0         MT_SSUSB_XHCI0_IRQ_ID     /* USB0 */
++#define SURFBOARDINT_USB1         MT_SSUSB_XHCI1_IRQ_ID     /* USB1 */
++//#define SURFBOARDINT_UART_LITE1  20     /* UART Lite */
++//#define SURFBOARDINT_UART_LITE2  21     /* UART Lite */
++//#define SURFBOARDINT_UART_LITE3  22     /* UART Lite */
++//#define SURFBOARDINT_UART1       SURFBOARDINT_UART_LITE1
++//#define SURFBOARDINT_UART        SURFBOARDINT_UART_LITE2
++//#define SURFBOARDINT_WDG         23     /* WDG timer */
++//#define SURFBOARDINT_TIMER0      24     /* Timer0 */
++//#define SURFBOARDINT_TIMER1      25     /* Timer1 */
++//#define SURFBOARDINT_ILL_ACC     35     /* illegal access */
++#define RALINK_INT_PCIE0         MT_PCIE0_IRQ_ID     /* PCIE0 */
++#define RALINK_INT_PCIE1         MT_PCIE1_IRQ_ID     /* PCIE1 */
++#define RALINK_INT_PCIE2         MT_PCIE2_IRQ_ID     /* PCIE2 */
++
++// Wait for RD to define IRQ source
++
++//#define RALINK_INT_xxx         MT_CRYPTO_RING0_IRQ_ID     /*  */
++//#define RALINK_INT_xxx         MT_CRYPTO_RING1_IRQ_ID     /*  */
++//#define RALINK_INT_xxx         MT_CRYPTO_RING2_IRQ_ID     /*  */
++//#define RALINK_INT_xxx         MT_FE_PDMA_IRQ_ID     /*  */
++//#define RALINK_INT_xxx         MT_FE_QDMA_IRQ_ID     /*  */
++//#define RALINK_INT_xxx         MT_PCIE_LINK_DOWN_RST_IRQ_ID     /*  */
++
++
++
+diff --git a/arch/arm/include/asm/rt2880/x_define_irq.h b/arch/arm/include/asm/rt2880/x_define_irq.h
+new file mode 100644
+index 0000000..4b2e669
+--- /dev/null
++++ b/arch/arm/include/asm/rt2880/x_define_irq.h
+@@ -0,0 +1,160 @@
++/*
++ * This file is generated automatically according to the design of silicon.
++ * Don't modify it directly.
++ */
++
++X_DEFINE_IRQ(MT6582_USB0_IRQ_ID            , 64, L,LEVEL)
++X_DEFINE_IRQ(MT6582_USB1_IRQ_ID            , 65, L,LEVEL)
++X_DEFINE_IRQ(TS_IRQ_ID                     , 66, L,EDGE)
++X_DEFINE_IRQ(TS_BATCH_IRQ_ID               , 67, L,EDGE)
++X_DEFINE_IRQ(LOWBATTERY_IRQ_ID             , 68, L,EDGE)
++X_DEFINE_IRQ(PWM_IRQ_ID                    , 69, L,LEVEL)
++X_DEFINE_IRQ(THERM_CTRL_IRQ_ID             , 70, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC0_IRQ_ID               , 71, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC1_IRQ_ID               , 72, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC2_IRQ_ID               , 73, L,LEVEL)
++X_DEFINE_IRQ(MT_MSDC3_IRQ_ID               , 74, L,LEVEL)
++X_DEFINE_IRQ(MT_I2C0_IRQ_ID                , 76, L,LEVEL)
++X_DEFINE_IRQ(MT_I2C1_IRQ_ID                , 77, L,LEVEL)
++X_DEFINE_IRQ(MT_I2C2_IRQ_ID                , 78, L,LEVEL)
++X_DEFINE_IRQ(BITF_IRQ_ID                   , 82, L,LEVEL)
++X_DEFINE_IRQ(MT_UART1_IRQ_ID               , 83, L,LEVEL)
++X_DEFINE_IRQ(MT_UART2_IRQ_ID               , 84, L,LEVEL)
++X_DEFINE_IRQ(MT_UART3_IRQ_ID               , 85, L,LEVEL)
++X_DEFINE_IRQ(MT_UART4_IRQ_ID               , 86, L,LEVEL)
++X_DEFINE_IRQ(MT_NFIECC_IRQ_ID              , 87, L,LEVEL)
++X_DEFINE_IRQ(MT_NFI_IRQ_ID                 , 88, L,LEVEL)
++X_DEFINE_IRQ(MT_GDMA1_IRQ_ID               , 89, L,LEVEL)
++X_DEFINE_IRQ(MT_GDMA2_IRQ_ID               , 90, L,LEVEL)
++X_DEFINE_IRQ(MT6582_HIF_PDMA_IRQ_ID        , 91, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_I2C0_IRQ_ID            , 92, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_I2C1_IRQ_ID            , 93, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_I2C2_IRQ_ID            , 94, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART0_TX_IRQ_ID        , 95, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART0_RX_IRQ_ID        , 96, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART1_TX_IRQ_ID        , 97, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART1_RX_IRQ_ID        , 98, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART2_TX_IRQ_ID        , 99, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART2_RX_IRQ_ID        , 100, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART3_TX_IRQ_ID        , 101, L,LEVEL)
++X_DEFINE_IRQ(MT_DMA_UART3_RX_IRQ_ID        , 102, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_BTIF_TX_IRQ_ID         , 103, L,LEVEL)
++X_DEFINE_IRQ(AP_DMA_BTIF_RX_IRQ_ID         , 104, L,LEVEL)
++X_DEFINE_IRQ(MT_GCPU_IRQ_ID                , 105, L,LEVEL) 
++X_DEFINE_IRQ(MT_GCPU_DMX_IRQ_ID            , 106, L,LEVEL)
++X_DEFINE_IRQ(MT_GCPU_MMU_IRQ_ID            , 107, L,LEVEL)
++X_DEFINE_IRQ(MT_GCPU_MMU_SEC_IRQ_ID        , 108, L,LEVEL)
++X_DEFINE_IRQ(MT_ETHER_NIC_WRAP_IRQ_ID      , 109, L,LEVEL)
++X_DEFINE_IRQ(MT6582_SPI1_IRQ_ID            , 110, L,LEVEL)
++X_DEFINE_IRQ(MSDC0_WAKEUP_PS_IRQ_ID        , 111, H,EDGE)
++X_DEFINE_IRQ(MSDC1_WAKEUP_PS_IRQ_ID        , 112, H,EDGE)
++X_DEFINE_IRQ(MSDC2_WAKEUP_PS_IRQ_ID        , 113, H,EDGE)
++X_DEFINE_IRQ(MT_CRYPTO_RING0_IRQ_ID        , 114, H,LEVEL)
++X_DEFINE_IRQ(MT_CRYPTO_RING1_IRQ_ID        , 115, H,LEVEL)
++X_DEFINE_IRQ(MT_CRYPTO_RING2_IRQ_ID        , 116, H,LEVEL)
++X_DEFINE_IRQ(MT_PTP_FSM_IRQ_ID             , 117, L,LEVEL)
++X_DEFINE_IRQ(BTIF_WAKEUP_IRQ_ID            , 118, L,LEVEL)
++X_DEFINE_IRQ(MT_IRRX_IRQ_ID                , 119, L,LEVEL) 
++X_DEFINE_IRQ(MT_WDT_IRQ_ID                 , 120, L,EDGE)
++X_DEFINE_IRQ(MT_CRYPTO_RING3_IRQ_ID        , 123, H,LEVEL)
++X_DEFINE_IRQ(DCC_APARM_IRQ_ID              , 124, L,LEVEL)
++X_DEFINE_IRQ(APARM_CTI_IRQ_ID              , 125, L,LEVEL)
++X_DEFINE_IRQ(MT_APARM_DOMAIN_IRQ_ID        , 126, L,LEVEL)
++X_DEFINE_IRQ(MT_APARM_DECERR_IRQ_ID        , 127, L,LEVEL)
++X_DEFINE_IRQ(DOMAIN_ABORT_IRQ_ID0          , 128, L,LEVEL)
++X_DEFINE_IRQ(MT_CRYPTO_IRQ_ID              , 129, H,LEVEL)
++X_DEFINE_IRQ(MT_HSDMA_IRQ_ID               , 130, H,LEVEL)
++X_DEFINE_IRQ(MT_GDMA_IRQ_ID                , 131, H,LEVEL)
++X_DEFINE_IRQ(CCIF0_AP_IRQ_ID               , 132, L,LEVEL)
++X_DEFINE_IRQ(MT_I2S_IRQ_ID                 , 134, H,LEVEL)
++X_DEFINE_IRQ(MT_PCM_IRQ_ID                 , 135, H,LEVEL)
++X_DEFINE_IRQ(AFE_MCU_IRQ_ID                , 136, L,LEVEL)
++X_DEFINE_IRQ(M4U1_IRQ_ID                   , 138, L,LEVEL)
++X_DEFINE_IRQ(M4UL2_IRQ_ID                  , 139, L,LEVEL)
++X_DEFINE_IRQ(M4UL2_SEC_IRQ_ID              , 140, L,LEVEL)
++X_DEFINE_IRQ(REFRESH_RATE_IRQ_ID           , 141, L,EDGE)
++X_DEFINE_IRQ(MT6582_APARM_GPTTIMER_IRQ_LINE, 144, L,LEVEL)
++X_DEFINE_IRQ(MT_EINT_IRQ_ID                , 145, H,LEVEL)
++X_DEFINE_IRQ(EINT_EVENT_IRQ_ID             , 146, L,LEVEL)
++X_DEFINE_IRQ(MT6582_PMIC_WRAP_IRQ_ID       , 147, H,LEVEL)
++X_DEFINE_IRQ(MT_KP_IRQ_ID                  , 148, L,EDGE)
++X_DEFINE_IRQ(MT_SPM_IRQ_ID                 , 149, L,LEVEL)
++X_DEFINE_IRQ(MT_SPM1_IRQ_ID                , 150, L,LEVEL)
++X_DEFINE_IRQ(MT_SPM2_IRQ_ID                , 151, L,LEVEL)
++X_DEFINE_IRQ(MT_SPM3_IRQ_ID                , 152, L,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT0_IRQ_ID        , 153, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT1_IRQ_ID        , 154, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT2_IRQ_ID        , 155, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT3_IRQ_ID        , 156, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT4_IRQ_ID        , 157, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT5_IRQ_ID        , 158, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT6_IRQ_ID        , 159, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT7_IRQ_ID        , 160, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT8_IRQ_ID        , 161, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT9_IRQ_ID        , 162, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT10_IRQ_ID       , 163, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT11_IRQ_ID       , 164, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT12_IRQ_ID       , 165, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT13_IRQ_ID       , 166, H,LEVEL)
++X_DEFINE_IRQ(MT_EINT_DIRECT14_IRQ_ID       , 167, H,LEVEL)
++X_DEFINE_IRQ(SMI_LARB0_IRQ_ID              , 168, L,LEVEL)
++X_DEFINE_IRQ(SMI_LARB1_IRQ_ID              , 169, L,LEVEL)
++X_DEFINE_IRQ(SMI_LARB2_IRQ_ID              , 170, L,LEVEL)
++X_DEFINE_IRQ(MT_VDEC_IRQ_ID                , 171, L,LEVEL)
++X_DEFINE_IRQ(MT_VENC_IRQ_ID                , 172, L,LEVEL)
++X_DEFINE_IRQ(MT6582_JPEG_ENC_IRQ_ID        , 173, L,LEVEL)
++X_DEFINE_IRQ(SENINF_IRQ_ID                 , 174, L,LEVEL)
++X_DEFINE_IRQ(CAMERA_ISP_IRQ0_ID            , 175, L,LEVEL)
++X_DEFINE_IRQ(CAMERA_ISP_IRQ1_ID            , 176, L,LEVEL)
++X_DEFINE_IRQ(CAMERA_ISP_IRQ2_ID            , 177, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_RDMA_IRQ_ID   , 178, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_RSZ0_IRQ_ID   , 179, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_RSZ1_IRQ_ID   , 180, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_TDSHP_IRQ_ID  , 181, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_WDMA_IRQ_ID   , 182, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MDP_WROT_IRQ_ID   , 183, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_RDMA_IRQ_ID       , 184, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_OVL_IRQ_ID        , 185, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_WDMA_IRQ_ID       , 186, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_BLS_IRQ_ID        , 187, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_COLOR_IRQ_ID      , 188, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_DSI_IRQ_ID        , 189, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_DPI0_IRQ_ID       , 190, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_CMDQ_IRQ_ID       , 191, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_CMDQ_SECURE_IRQ_ID, 192, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_MUTEX_IRQ_ID      , 193, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY0_IRQ_ID              , 194, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY1_IRQ_ID              , 195, L,LEVEL)
++X_DEFINE_IRQ(MT6582_DISP_RDMA1_IRQ_ID      , 196, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY3_IRQ_ID              , 197, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY4_IRQ_ID              , 198, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY5_IRQ_ID              , 199, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY6_IRQ_ID              , 200, L,LEVEL)
++X_DEFINE_IRQ(MM_DUMMY7_IRQ_ID              , 201, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ0_ID                , 202, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ1_ID                , 203, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ2_ID                , 204, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ3_ID                , 205, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ4_ID                , 206, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ5_ID                , 207, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ6_ID                , 208, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ7_ID                , 209, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ8_ID                , 210, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ9_ID                , 211, L,LEVEL)
++X_DEFINE_IRQ(MT_MFG_IRQ10_ID               , 212, L,LEVEL)
++X_DEFINE_IRQ(MT_APXGPT_SECURE_IRQ_ID       , 213, L,LEVEL)
++X_DEFINE_IRQ(MT_CEC_IRQ_ID                 , 214, L,LEVEL)
++X_DEFINE_IRQ(CONN_WDT_IRQ_ID               , 215, L,EDGE)
++X_DEFINE_IRQ(WF_HIF_IRQ_ID                 , 216, L,LEVEL)
++X_DEFINE_IRQ(MT_CONN2AP_BTIF_WAKEUP_IRQ_ID , 217, L,LEVEL)
++X_DEFINE_IRQ(BT_CVSD_IRQ_ID                , 218, L,LEVEL)
++X_DEFINE_IRQ(MT_CIRQ_IRQ_ID                , 219, L,LEVEL)
++X_DEFINE_IRQ(MT_PCIE_LINK_DOWN_RST_IRQ_ID  , 224, H,EDGE)
++X_DEFINE_IRQ(MT_PCIE0_IRQ_ID               , 225, H,LEVEL)
++X_DEFINE_IRQ(MT_PCIE1_IRQ_ID               , 226, H,LEVEL)
++X_DEFINE_IRQ(MT_PCIE2_IRQ_ID               , 227, H,LEVEL)
++X_DEFINE_IRQ(MT_SSUSB_XHCI0_IRQ_ID         , 228, H,LEVEL)
++X_DEFINE_IRQ(MT_SSUSB_XHCI1_IRQ_ID         , 229, H,LEVEL)
++X_DEFINE_IRQ(MT_FE_PDMA_IRQ_ID             , 230, H,LEVEL)
++X_DEFINE_IRQ(MT_FE_QDMA_IRQ_ID             , 231, H,LEVEL)
++X_DEFINE_IRQ(MT_FE_ORIG_IRQ_ID             , 232, H,LEVEL)
+diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c
+index ab8cf21..c0e373b 100644
+--- a/arch/arm/mach-mediatek/mediatek.c
++++ b/arch/arm/mach-mediatek/mediatek.c
+@@ -19,6 +19,186 @@
+ #include <linux/of.h>
+ #include <linux/clk-provider.h>
+ #include <linux/clocksource.h>
++#include <asm/mach/map.h>
++#include "rt_mmap.h"
++#include "mt_reg_base.h"
++
++#define IO_VIRT_TO_PHYS(v) (0x10000000 | ((v) & 0x0fffffff))
++
++static struct map_desc mt_io_desc[] __initdata =
++{
++#if !defined(CONFIG_MT8127_FPGA)
++    {
++        .virtual = INFRA_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(INFRA_BASE)),
++        .length = (SZ_1M - SZ_4K),
++        .type = MT_DEVICE
++    },
++    /* Skip the mapping of 0xF0130000~0xF013FFFF to protect access from APMCU */
++    {
++        .virtual = (DEBUGTOP_BASE - SZ_4K),
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS((DEBUGTOP_BASE - SZ_4K))),
++        .length = (0x30000 + SZ_4K),
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = (DEBUGTOP_BASE + 0x40000),
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(DEBUGTOP_BASE + 0x40000)),
++        .length = 0xC0000,
++        .type = MT_DEVICE
++    },            
++    {
++        .virtual = MCUSYS_CFGREG_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(MCUSYS_CFGREG_BASE)),
++        .length = SZ_2M,
++        .type = MT_DEVICE
++    },
++    /* //// */
++    {
++        .virtual = AP_DMA_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(AP_DMA_BASE)),
++        .length = SZ_2M + SZ_1M,
++        .type = MT_DEVICE
++    },
++    {
++        /* virtual 0xF2000000, physical 0x00200000 */
++        .virtual = SYSRAM_BASE,
++        .pfn = __phys_to_pfn(0x00200000),
++        .length = SZ_128K,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = G3D_CONFIG_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(G3D_CONFIG_BASE)),
++        .length = SZ_128K,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = DISPSYS_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(DISPSYS_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = IMGSYS_CONFG_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(IMGSYS_CONFG_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = VDEC_GCON_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(VDEC_GCON_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++    {
++        /* virtual 0xF7000000, physical 0x08000000 */
++        .virtual = DEVINFO_BASE,
++        .pfn = __phys_to_pfn(0x08000000),
++        .length = SZ_64K,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = CONN_BTSYS_PKV_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(CONN_BTSYS_PKV_BASE)),
++        .length = SZ_1M,
++        .type = MT_DEVICE
++    },
++    {
++        /* virtual 0xF9000000, physical 0x00100000 */
++        .virtual = INTER_SRAM,
++        .pfn = __phys_to_pfn(0x00100000),
++        .length = SZ_64K,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = HIFSYS_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(HIFSYS_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = ETHDMASYS_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(ETHDMASYS_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++#if 0
++    {
++        .virtual = BDP_DISPSYS_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(BDP_DISPSYS_BASE)),
++        .length = SZ_32K + SZ_16K,
++        .type = MT_DEVICE
++    },
++#endif
++#else
++    {
++        .virtual = INFRA_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(INFRA_BASE)),
++        .length = SZ_4M,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = AP_DMA_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(AP_DMA_BASE)),
++        .length = SZ_2M + SZ_1M,
++        .type = MT_DEVICE
++    },
++    #if 0
++    {
++        .virtual = MMSYS1_CONFIG_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(MMSYS1_CONFIG_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++    #endif
++    {
++        /* From: 0xF2000000 to 0xF2020000*/
++        .virtual = SYSRAM_BASE,
++        .pfn = __phys_to_pfn(0x00200000),
++        .length = SZ_128K,
++        .type = MT_DEVICE
++    },    
++    {
++        .virtual = DISPSYS_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(DISPSYS_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = IMGSYS_CONFG_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(IMGSYS_CONFG_BASE)),
++        .length = SZ_16M,
++        .type = MT_DEVICE
++    },
++    /* G3DSYS */
++    {
++        .virtual = G3D_CONFIG_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(G3D_CONFIG_BASE)),
++        .length = SZ_4K,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = DEVINFO_BASE,
++        .pfn = __phys_to_pfn(0x08000000),
++        .length = SZ_64K,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = MALI_BASE,
++        .pfn = __phys_to_pfn(IO_VIRT_TO_PHYS(MALI_BASE)),
++        .length = SZ_64K,
++        .type = MT_DEVICE
++    },
++    {
++        .virtual = INTER_SRAM,
++        .pfn = __phys_to_pfn(0x00100000),
++        .length = SZ_64K,
++        .type = MT_DEVICE
++    },
++#endif
++};
++
+ #define GPT6_CON_MT65xx 0x10008060
+@@ -55,7 +235,13 @@ static const char * const mediatek_board_dt_compat[] = {
+       NULL,
+ };
++void __init mt_map_io(void)
++{
++    iotable_init(mt_io_desc, ARRAY_SIZE(mt_io_desc));
++}
++
+ DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
+       .dt_compat      = mediatek_board_dt_compat,
+       .init_time      = mediatek_timer_init,
++      .map_io         = mt_map_io,
+ MACHINE_END
+diff --git a/arch/arm/mach-mediatek/mt_reg_base.h b/arch/arm/mach-mediatek/mt_reg_base.h
+new file mode 100644
+index 0000000..cf2bb9e
+--- /dev/null
++++ b/arch/arm/mach-mediatek/mt_reg_base.h
+@@ -0,0 +1,640 @@
++/*
++ * This file is generated automatically according to the design of silicon.
++ * Don't modify it directly.
++ */
++
++#ifndef __MT_REG_BASE
++#define __MT_REG_BASE
++
++#if !defined(CONFIG_MT8127_FPGA)
++
++// APB Module cksys
++#define INFRA_BASE (0xF0000000)
++
++// APB Module infracfg_ao
++#define INFRACFG_AO_BASE (0xF0001000)
++
++// APB Module fhctl
++#define FHCTL_BASE (0xF0002000)
++
++// APB Module pericfg
++#define PERICFG_BASE (0xF0003000)
++
++// APB Module dramc
++#define DRAMC0_BASE (0xF0004000)
++
++// APB Module gpio
++#define GPIO_BASE (0xF0005000)
++
++// APB Module sleep
++#define SPM_BASE (0xF0006000)
++
++// APB Module toprgu
++#define TOPRGU_BASE (0xF0007000)
++#define AP_RGU_BASE TOPRGU_BASE
++
++// APB Module apxgpt
++#define APMCU_GPTIMER_BASE (0xF0008000)
++
++// APB Module rsvd
++#define RSVD_BASE (0xF0009000)
++
++// APB Module sej
++#define HACC_BASE (0xF000A000)
++
++// APB Module ap_cirq_eint
++#define AP_CIRQ_EINT (0xF000B000)
++
++// APB Module ap_cirq_eint
++#define EINT_BASE (0xF000B000)
++
++// APB Module smi
++#define SMI1_BASE (0xF000C000)
++
++// APB Module pmic_wrap
++#define PWRAP_BASE (0xF000D000)
++
++// APB Module device_apc_ao
++#define DEVAPC_AO_BASE (0xF000E000)
++
++// APB Module ddrphy
++#define DDRPHY_BASE (0xF000F000)
++
++// APB Module vencpll
++#define VENCPLL_BASE (0xF000F000)
++
++// APB Module mipi_tx_config
++#define MIPI_CONFIG_BASE (0xF0010000)
++
++// APB Module LVDS ANA
++#define LVDS_ANA_BASE (0xF0010400)
++
++// APB Module mipi_rx_ana
++#define MIPI_RX_ANA_BASE (0xF0215000)
++
++// APB Module kp
++#define KP_BASE (0xF0011000)
++
++// APB Module dbgapb
++#define DEBUGTOP_BASE (0xF0100000)
++
++// APB Module mcucfg
++#define MCUSYS_CFGREG_BASE (0xF0200000)
++
++// APB Module infracfg
++#define INFRACFG_BASE (0xF0201000)
++
++// APB Module sramrom
++#define SRAMROM_BASE (0xF0202000)
++
++// APB Module emi
++#define EMI_BASE (0xF0203000)
++
++// APB Module sys_cirq
++#define SYS_CIRQ_BASE (0xF0204000)
++
++// APB Module m4u
++#define SMI_MMU_TOP_BASE (0xF0205000)
++
++// APB Module nb_mmu
++#define NB_MMU0_BASE (0xF0205200)
++
++// APB Module nb_mmu
++#define NB_MMU1_BASE (0xF0205800)
++
++// APB Module efusec
++#define EFUSEC_BASE (0xF0206000)
++
++// APB Module device_apc
++#define DEVAPC_BASE (0xF0207000)
++
++// APB Module mcu_biu_cfg
++#define MCU_BIU_BASE (0xF0208000)
++
++// APB Module apmixed
++#define APMIXEDSYS_BASE (0xF0209000)
++
++// APB Module ccif
++#define AP_CCIF_BASE (0xF020A000)
++
++// APB Module ccif
++#define MD_CCIF_BASE (0xF020B000)
++
++// APB Module gpio1
++#define GPIO1_BASE (0xF020C000)
++
++// APB Module infra_mbist
++#define INFRA_TOP_MBIST_CTRL_BASE (0xF020D000)
++
++// APB Module dramc_conf_nao
++#define DRAMC_NAO_BASE (0xF020E000)
++
++// APB Module trng
++#define TRNG_BASE (0xF020F000)
++
++// APB Module ca9
++#define CORTEXA7MP_BASE (0xF0210000)
++
++// APB Module ap_dma
++#define AP_DMA_BASE (0xF1000000)
++
++// APB Module auxadc
++#define AUXADC_BASE (0xF1001000)
++
++// APB Module uart
++#define UART1_BASE (0xF1002000)
++
++// APB Module uart
++#define UART2_BASE (0xF1003000)
++
++// APB Module uart
++#define UART3_BASE (0xF1004000)
++
++// APB Module uart
++#define UART4_BASE (0xF1005000)
++
++// APB Module pwm
++#define PWM_BASE (0xF1006000)
++
++// APB Module i2c
++#define I2C0_BASE (0xF1007000)
++
++// APB Module i2c
++#define I2C1_BASE (0xF1008000)
++
++// APB Module i2c
++#define I2C2_BASE (0xF1009000)
++
++// APB Module spi
++#define SPI0_BASE (0xF100A000)
++#define SPI1_BASE (0xF100A000)
++
++// APB Module therm_ctrl
++#define THERMAL_BASE (0xF100B000)
++
++// APB Module btif
++#define BTIF_BASE (0xF100C000)
++
++// APB Module nfi
++#define NFI_BASE (0xF100D000)
++
++// APB Module nfiecc_16bit
++#define NFIECC_BASE (0xF100E000)
++
++// APB Module nli_arb
++#define NLI_ARB_BASE (0xF100F000)
++
++// APB Module peri_pwrap_bridge
++#define PERI_PWRAP_BRIDGE_BASE (0xF1017000)
++
++// APB Module usb2
++#define USB_BASE (0xF1200000)
++#define USB1_BASE   (0xF1270000)
++
++// APB Module usb_sif
++#define USB_SIF_BASE (0xF1210000)
++
++// APB Module msdc
++#define MSDC_0_BASE (0xF1230000)
++
++// APB Module msdc
++#define MSDC_1_BASE (0xF1240000)
++
++// APB Module msdc
++#define MSDC_2_BASE (0xF1250000)
++
++// APB Module msdc
++#define MSDC_3_BASE (0xF12C0000)
++
++// APB Module wcn_ahb
++#define WCN_AHB_BASE (0xF1260000)
++
++// ARB Module ethernet
++#define ETHERNET_BASE (0xF1280000)
++// APB Module mfg_top
++#define G3D_CONFIG_BASE (0xF3000000)
++
++// APB Module mali
++#define MALI_BASE (0xF3040000)
++
++// APB Module mali_tb_cmd
++#define MALI_TB_BASE (0xF301f000)
++
++// APB Module mmsys_config
++#define DISPSYS_BASE (0xF4000000)
++
++// APB Module mdp_rdma
++#define MDP_RDMA_BASE (0xF4001000)
++
++// APB Module mdp_rsz
++#define MDP_RSZ0_BASE (0xF4002000)
++
++// APB Module mdp_rsz
++#define MDP_RSZ1_BASE (0xF4003000)
++
++// APB Module disp_wdma
++#define MDP_WDMA_BASE (0xF4004000)
++
++// APB Module disp_wdma
++#define WDMA1_BASE (0xF4004000)
++
++// APB Module mdp_wrot
++#define MDP_WROT_BASE (0xF4005000)
++
++// APB Module mdp_tdshp
++#define MDP_TDSHP_BASE (0xF4006000)
++
++// APB Module ovl
++#define DISP_OVL_BASE (0xF4007000)
++
++// APB Module ovl
++#define OVL0_BASE (0xF4007000)
++
++// APB Module ovl
++#define OVL1_BASE (0xF4007000)
++
++// APB Module disp_rdma
++#define DISP_RDMA_BASE (0xF4008000)
++
++// APB Module disp_rdma
++#define R_DMA1_BASE (0xF4008000)
++
++// APB Module disp_rdma
++#define R_DMA0_BASE (0xF4008000)
++
++// APB Module disp_wdma
++#define DISP_WDMA_BASE (0xF4009000)
++
++// APB Module disp_wdma
++#define WDMA0_BASE (0xF4009000)
++
++// APB Module disp_bls
++#define DISP_BLS_BASE (0xF400A000)
++
++// APB Module disp_color_config
++#define DISP_COLOR_BASE (0xF400B000)
++
++// APB Module dsi
++#define DSI_BASE (0xF400C000)
++
++// APB Module disp_dpi
++#define DPI_BASE (0xF400D000)
++
++// APB Module disp_mutex
++#define MMSYS_MUTEX_BASE (0xF400E000)
++
++// APB Module mm_cmdq
++#define MMSYS_CMDQ_BASE (0xF400F000)
++
++#define DPI1_BASE (0xF4014000)
++
++
++// APB Module smi_larb
++#define SMI_LARB0_BASE (0xF4010000)
++
++// APB Module smi
++#define SMI_BASE (0xF4011000)
++
++// LVDS TX 
++#define LVDS_TX_BASE (0xF4016200)
++
++// APB Module smi_larb
++#define SMILARB2_BASE (0xF5001000)
++
++// APB Module smi_larb
++#define SMI_LARB3_BASE (0xF5001000)
++
++// APB Module mmu
++#define SMI_LARB3_MMU_BASE (0xF5001800)
++
++// APB Module smi_larb
++#define SMI_LARB4_BASE (0xF5002000)
++
++// APB Module fake_eng
++#define FAKE_ENG_BASE (0xF5002000)
++
++// APB Module mmu
++#define SMI_LARB4_MMU_BASE (0xF5002800)
++
++// APB Module smi
++#define VENC_BASE (0xF5009000)
++
++// APB Module jpgenc
++#define JPGENC_BASE (0xF500A000)
++
++// APB Module vdecsys_config
++#define VDEC_GCON_BASE (0xF6000000)
++
++// APB Module smi_larb
++#define SMI_LARB1_BASE (0xF6010000)
++
++// APB Module mmu
++#define SMI_LARB1_MMU_BASE (0xF6010800)
++
++// APB Module vdtop
++#define VDEC_BASE (0xF6020000)
++
++// APB Module vdtop
++#define VDTOP_BASE (0xF6020000)
++
++// APB Module vld
++#define VLD_BASE (0xF6021000)
++
++// APB Module vld_top
++#define VLD_TOP_BASE (0xF6021800)
++
++// APB Module mc
++#define MC_BASE (0xF6022000)
++
++// APB Module avc_vld
++#define AVC_VLD_BASE (0xF6023000)
++
++// APB Module avc_mv
++#define AVC_MV_BASE (0xF6024000)
++
++// APB Module vdec_pp
++#define VDEC_PP_BASE (0xF6025000)
++
++// APB Module vp8_vld
++#define VP8_VLD_BASE (0xF6026800)
++
++// APB Module vp6
++#define VP6_BASE (0xF6027000)
++
++// APB Module vld2
++#define VLD2_BASE (0xF6027800)
++
++// APB Module mc_vmmu
++#define MC_VMMU_BASE (0xF6028000)
++
++// APB Module pp_vmmu
++#define PP_VMMU_BASE (0xF6029000)
++
++// APB Module imgsys
++#define IMGSYS_CONFG_BASE (0xF5000000)
++
++// APB Module cam
++#define CAMINF_BASE (0xF5000000)
++
++// APB Module csi2
++#define CSI2_BASE (0xF5000000)
++
++// APB Module seninf
++#define SENINF_BASE (0xF5000000)
++
++// APB Module seninf_tg
++#define SENINF_TG_BASE (0xF5000000)
++
++// APB Module seninf_top
++#define SENINF_TOP_BASE (0xF5000000)
++
++// APB Module mipi_rx_config
++#define MIPI_RX_CONFIG_BASE (0xF500C000)
++
++// APB Module scam
++#define SCAM_BASE (0xF5008000)
++
++// APB Module ncsi2
++#define NCSI2_BASE (0xF5008000)
++
++// APB Module ccir656
++#define CCIR656_BASE (0xF5000000)
++
++// APB Module n3d_ctl
++#define N3D_CTL_BASE (0xF5000000)
++
++// APB Module fdvt
++#define FDVT_BASE (0xF500B000)
++
++// APB Module audiosys
++#define AUDIO_BASE (0xF1221000)
++#define AUDIO_REG_BASE (0xF1220000)
++
++// CONNSYS
++#define CONN_BTSYS_PKV_BASE (0xF8000000)
++#define CONN_BTSYS_TIMCON_BASE (0xF8010000)
++#define CONN_BTSYS_RF_CONTROL_BASE (0xF8020000)
++#define CONN_BTSYS_MODEM_BASE (0xF8030000)
++#define CONN_BTSYS_BT_CONFIG_BASE (0xF8040000)
++#define CONN_MCU_CONFIG_BASE (0xF8070000)
++#define CONN_TOP_CR_BASE (0xF80B0000)
++#define CONN_HIF_CR_BASE (0xF80F0000)
++
++/*
++ * Addresses below are added manually.
++ * They cannot be mapped via IO_VIRT_TO_PHYS().
++ */
++
++#define GIC_CPU_BASE (CORTEXA7MP_BASE + 0x2000)
++#define GIC_DIST_BASE (CORTEXA7MP_BASE + 0x1000)
++#define SYSRAM_BASE 0xF2000000  /* L2 cache shared RAM */
++#define DEVINFO_BASE 0xF7000000
++#define INTER_SRAM 0xF9000000
++
++#else 
++
++#define SMI_MMU_TOP_BASE            0xF0205000
++#define SMILARB2_BASE               0xF5001000
++
++/* on-chip SRAM */
++#define INTER_SRAM                  0xF9000000
++
++/* infrasys */
++//#define TOPRGU_BASE                 0xF0000000
++#define INFRA_BASE                  0xF0000000
++#define INFRACFG_BASE               0xF0001000
++#define INFRACFG_AO_BASE            0xF0001000
++#define FHCTL_BASE                  0xF0002000
++#define PERICFG_BASE                0xF0003000
++#define DRAMC0_BASE                 0xF0004000
++#define DDRPHY_BASE                 0xF000F000
++#define DRAMC_NAO_BASE              0xF020E000
++#define GPIO_BASE                   0xF0005000
++#define GPIO1_BASE                  0xF020C000
++#define TOPSM_BASE                  0xF0006000
++#define SPM_BASE                    0xF0006000
++#define TOPRGU_BASE                 0xF0007000
++#define AP_RGU_BASE                 TOPRGU_BASE
++#define APMCU_GPTIMER_BASE          0xF0008000
++#define HACC_BASE                   0xF000A000
++#define AP_CIRQ_EINT                0xF000B000
++#define SMI1_BASE                   0xF000C000
++#define MIPI_CONFIG_BASE            0xF0010000
++// APB Module LVDS ANA
++#define LVDS_ANA_BASE (0xF0010400)
++
++
++#define KP_BASE                     0xF0011000
++#if 0
++#define DEVICE_APC_0_BASE           0xF0010000
++#define DEVICE_APC_1_BASE           0xF0011000
++#define DEVICE_APC_2_BASE           0xF0012000
++#define DEVICE_APC_3_BASE           0xF0013000
++#define DEVICE_APC_4_BASE           0xF0014000
++#define SMI0_BASE                   0xF0208000
++#endif
++#define EINT_BASE                   0xF000B000
++
++
++#define DEBUGTOP_BASE               0xF0100000
++#define MCUSYS_CFGREG_BASE          0xF0200000
++#define SRAMROM_BASE                0xF0202000
++#define EMI_BASE                    0xF0203000
++#define EFUSEC_BASE                 0xF0206000
++#define MCU_BIU_BASE                0xF0208000
++#define APMIXED_BASE                0xF0209000
++#define APMIXEDSYS_BASE             0xF0209000
++#define AP_CCIF_BASE                0xF020A000
++#define MD_CCIF_BASE                0xF020B000
++#define INFRA_TOP_MBIST_CTRL_BASE   0xF020D000
++#define DRAMC_NAO_BASE              0xF020E000
++#define CORTEXA7MP_BASE             0xF0210000
++#define GIC_CPU_BASE    (CORTEXA7MP_BASE + 0x2000)
++#define GIC_DIST_BASE   (CORTEXA7MP_BASE + 0x1000)
++//#define SMI_LARB_BASE             0xF0211000
++//#define MCUSYS_AVS_BASE           0xF0212000
++
++/* perisys */
++/*avalaible*/
++#define AP_DMA_BASE                 0xF1000000
++#define AUXADC_BASE                 0xF1001000
++#define UART1_BASE                  0xF1002000
++#define UART2_BASE                  0xF1003000
++#define UART3_BASE                  0xF1004000
++#define UART4_BASE                  0xF1005000
++#define PWM_BASE                    0xF1006000
++#define I2C0_BASE                   0xF1007000
++#define I2C1_BASE                   0xF1008000
++#define I2C2_BASE                   0xF1009000
++#define SPI0_BASE                   0xF100A000
++#define BTIF_BASE                   (0xF100C000)
++#define NFI_BASE                    0xF100D000
++#define NFIECC_BASE                 0xF100E000
++#define NLI_ARB_BASE                0xF100F000
++#define I2C3_BASE                   0xF1010000 //FIXME 6582 take off
++#define SPI1_BASE                   0xF100A000 
++#define THERMAL_BASE                0xF100B000
++
++// APB Module pmic_wrap
++#define PWRAP_BASE (0xF000D000)
++
++#if 0
++//#define IRDA_BASE                 0xF1007000
++#define I2C4_BASE                   0xF1014000
++#define I2CDUAL_BASE                0xF1015000
++#define ACCDET_BASE                 0xF1016000
++#define AP_HIF_BASE                 0xF1017000
++#define MD_HIF_BASE                 0xF1018000
++#define GCPU_BASE                   0xF101B000
++#define GCPU_NS_BASE                0xF01C000
++#define GCPU_MMU_BASE               0xF01D000
++#define SATA_BASE                   0xF01E000
++#define CEC_BASE                    0xF01F000
++//#define SPI1_BASE                 0xF1022000
++#endif
++
++#define USB1_BASE                   0xF1270000
++#define USB2_BASE                   0xF1200000
++#define USB_BASE                    0xF1200000
++#define USB_SIF_BASE                0xF1210000
++//#define USB3_BASE                 0xF1220000
++#define MSDC_0_BASE                 0xF1230000
++#define MSDC_1_BASE                 0xF1240000
++#define MSDC_2_BASE                 0xF1250000
++#define MSDC_3_BASE                 0xF12C0000
++#define MSDC_4_BASE                 0xF1270000
++//#define ETHERNET_BASE             0xF1290000
++
++//#define ETB_BASE                  0xF0111000
++//#define ETM_BASE                  0xF017C000
++
++
++/* SMI common subsystem */
++#define SYSRAM_BASE                 0xF2000000
++#define AUDIO_REG_BASE              0xF2030000
++#define MFG_AXI_BASE                0xF2060000
++#define CONN_MCU_CONFIG_BASE       0xF8070000
++#define AUDIO_BASE                  0xF1200000 //0xF2071000
++#define MMSYS1_CONFIG_BASE          0xF2080000
++#define SMI_LARB0_BASE              0xF2081000
++// APB Module smi
++#define SMI_BASE (0xF4011000)
++#define SMI_LARB1_BASE              0xF2082000
++#define SMI_LARB2_BASE              0xF2083000
++#define VDEC_GCON_BASE              0xF6000000 //0xF4000000
++#define VDEC_BASE                   0xF4020000
++#define VENC_TOP_BASE               0xF7000000
++#define VENC_BASE                   0xF7002000
++#define JPGENC_BASE                 0xF500A000
++#define R_DMA0_BASE                 0xF2086000
++#define R_DMA1_BASE                 0xF2087000
++#define VDO_ROT0_BASE               0xF2088000
++#define RGB_ROT0_BASE               0xF2089000
++#define VDO_ROT1_BASE               0xF208A000
++#define RGB_ROT1_BASE               0xF208B000
++//#define DPI_BASE                    0xF208C000
++#define BRZ_BASE                    0xF208D000
++#define JPG_DMA_BASE                0xF208E000
++#define OVL_DMA_BASE                0xF208F000
++#define CSI2_BASE                   0xF2092000
++#define CRZ_BASE                    0xF2093000
++#define VRZ0_BASE                   0xF2094000
++#define IMGPROC_BASE                0xF2095000
++#define EIS_BASE                    0xF2096000
++#define SPI_BASE                    0xF2097000
++#define SCAM_BASE                   0xF2098000
++#define PRZ0_BASE                   0xF2099000
++#define PRZ1_BASE                   0xF209A000
++#define JPG_CODEC_BASE              0xF209B000
++//#define DSI_BASE                    0xF209C000
++#define TVC_BASE                    0xF209D000
++#define TVE_BASE                    0xF209E000
++#define TV_ROT_BASE                 0xF209F000
++#define RGB_ROT2_BASE               0xF20A0000
++//#define LCD_BASE                    0xF20A1000
++#define FD_BASE                     0xF20A2000
++#define MIPI_CONFG_BASE             0xF20A3000
++#define VRZ1_BASE                   0xF20A4000
++#define MMSYS2_CONFG_BASE           0xF20C0000
++#define SMI_LARB3_BASE              0xF20C1000
++#define MFG_APB_BASE                0xF20C4000
++#define G2D_BASE                    0xF20C6000
++
++#define DISPSYS_BASE                          0xF4000000
++#define ROT_BASE                                      0xF4001000
++#define SCL_BASE                                      0xF4002000
++#define OVL_BASE                                      0xF4007000
++#define WDMA0_BASE                                    0xF4009000
++#define WDMA1_BASE                                    0xF4005000
++#define RDMA0_BASE                                    0xF4008000
++//#define RDMA1_BASE                                  0xF4007000
++#define BLS_BASE                                      0xF400A000
++//#define GAMMA_BASE                                  0xF400000
++#define COLOR_BASE                                    0xF400B000
++#define TDSHP_BASE                                    0xF4006000
++#define LCD_BASE                                      0xF4012000// only exist on FPGA
++#define DSI_BASE                                      0xF400C000
++#define DPI_BASE                                      0xF400D000
++
++#define DPI1_BASE                                0xF4014000
++
++// LVDS TX 
++#define LVDS_TX_BASE (0xF4016200)
++
++#define SMILARB1_BASE                         0xF4010000
++#define DISP_MUTEX_BASE                               0xF400E000
++#define DISP_CMDQ_BASE                                0xF400F000
++
++/* imgsys */
++#define IMGSYS_CONFG_BASE           0xF5000000
++#define CAMINF_BASE                 IMGSYS_CONFG_BASE
++
++/* G3DSYS */
++#define G3D_CONFIG_BASE             0xF3000000
++#define MALI_BASE                   0xF3040000
++
++#define DEVINFO_BASE                0xF8000000
++
++#endif
++
++#endif
+diff --git a/arch/arm/mach-mediatek/rt_mmap.h b/arch/arm/mach-mediatek/rt_mmap.h
+new file mode 100644
+index 0000000..e86b3bb
+--- /dev/null
++++ b/arch/arm/mach-mediatek/rt_mmap.h
+@@ -0,0 +1,58 @@
++#define HIFSYS_BASE                   0xFA000000 //for PCIe/USB
++#define ETHDMASYS_BASE                        0xFB000000 //for I2S/PCM/GDMA/HSDMA/FE/GMAC
++
++#define HIFSYS_PCI_BASE                 0xFA140000
++#define HIFSYS_USB_HOST_BASE            0xFA1C0000
++#define HIFSYS_USB_HOST2_BASE           0xFA240000
++
++#define ETHDMASYS_SYSCTL_BASE           0xFB000000
++#define ETHDMASYS_RBUS_MATRIXCTL_BASE   0xFB000400
++#define ETHDMASYS_I2S_BASE              0xFB000A00
++#define ETHDMASYS_PCM_BASE              0xFB002000
++#define ETHDMASYS_GDMA_BASE             0xFB002800
++#define ETHDMASYS_HS_DMA_BASE           0xFB007000
++#define ETHDMASYS_FRAME_ENGINE_BASE     0xFB100000
++#define ETHDMASYS_PPE_BASE            0xFB100C00
++#define ETHDMASYS_ETH_SW_BASE         0xFB110000
++#define ETHDMASYS_CRYPTO_ENGINE_BASE  0xFB240000
++
++//for backward-compatible
++#define RALINK_FRAME_ENGINE_BASE      ETHDMASYS_FRAME_ENGINE_BASE
++#define RALINK_PPE_BASE                 ETHDMASYS_PPE_BASE
++#define RALINK_SYSCTL_BASE            ETHDMASYS_SYSCTL_BASE
++#define RALINK_ETH_SW_BASE            ETHDMASYS_ETH_SW_BASE
++#define RALINK_GDMA_BASE      ETHDMASYS_GDMA_BASE
++#define RALINK_HS_DMA_BASE    ETHDMASYS_HS_DMA_BASE
++#define RALINK_11N_MAC_BASE           0       //unused for rt_rdm usage
++
++//Reset Control Register
++#define RSTCTL_SYS_RST                        (1<<0)
++#define RSTCTL_MCM_RST                        (1<<2)
++#define RSTCTL_HSDMA_RST              (1<<5)
++#define RSTCTL_FE_RST                 (1<<6)
++#define RSTCTL_SPDIF_RST              (1<<7)
++#define RSTCTL_TIMER_RST              (1<<8)
++#define RSTCTL_CIRQ_RST                       (1<<9)
++#define RSTCTL_MC_RST                 (1<<10)
++#define RSTCTL_PCM_RST                        (1<<11)
++#define RSTCTL_GPIO_RST                       (1<<13)
++#define RSTCTL_GDMA_RST                       (1<<14)
++#define RSTCTL_NAND_RST                       (1<<15)
++#define RSTCTL_I2C_RST                        (1<<16)
++#define RSTCTL_I2S_RST                        (1<<17)
++#define RSTCTL_SPI_RST                        (1<<18)
++#define RSTCTL_UART0_RST              (1<<19)
++#define RSTCTL_UART1_RST              (1<<20)
++#define RSTCTL_UART2_RST              (1<<21)
++#define RSTCTL_UPHY_RST                       (1<<22)
++#define RSTCTL_ETH_RST                        (1<<23)
++#define RSTCTL_PCIE0_RST              (1<<24)
++#define RSTCTL_PCIE1_RST              (1<<25)
++#define RSTCTL_PCIE2_RST              (1<<26)
++#define RSTCTL_AUX_STCK_RST           (1<<28)
++#define RSTCTL_CRYPT_RST              (1<<29)
++#define RSTCTL_SDXC_RST                       (1<<30)
++#define RSTCTL_PWM_RST                        (1<<31)
++
++//for backward-compatible
++#define RALINK_FE_RST                 RSTCTL_FE_RST
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0069-arm-mediatek-add-mt7623-support-to-pmic-wrapper.patch b/target/linux/mediatek/patches/0069-arm-mediatek-add-mt7623-support-to-pmic-wrapper.patch
new file mode 100644 (file)
index 0000000..b724682
--- /dev/null
@@ -0,0 +1,554 @@
+From 0ec1ddd9233579b6d6dc0df325e870c5560344be Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 28 Jun 2015 19:50:51 +0200
+Subject: [PATCH 69/76] arm: mediatek: add mt7623 support to pmic-wrapper
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/soc/mediatek/mtk-pmic-wrap.c |  345 +++++++++++++++++++++++++++++-----
+ 1 file changed, 296 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
+index f432291..9ff02a1 100644
+--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
++++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
+@@ -31,6 +31,13 @@
+ #define PWRAP_MT8135_BRIDGE_WDT_UNIT          0x50
+ #define PWRAP_MT8135_BRIDGE_WDT_SRC_EN                0x54
++#define PWRAP_MT7623_AUXADC_CON21             0x076C
++#define PWRAP_MT7623_AUXADC_ADC12             0x072C
++#define PWRAP_MT7623_AUXADC_ADC13             0x072E
++#define PWRAP_MT7623_AUXADC_ADC14             0x0730
++#define PWRAP_MT7623_AUXADC_CON2              0x0746
++#define PWRAP_MT7623_AUXADC_CON3              0x0748
++
+ /* macro for wrapper status */
+ #define PWRAP_GET_WACS_RDATA(x)               (((x) >> 0) & 0x0000ffff)
+ #define PWRAP_GET_WACS_FSM(x)         (((x) >> 16) & 0x00000007)
+@@ -61,32 +68,104 @@
+ #define PWRAP_MAN_CMD_OP_OUTQ         (0xa << 8)
+ /* macro for slave device wrapper registers */
+-#define PWRAP_DEW_BASE                        0xbc00
+-#define PWRAP_DEW_EVENT_OUT_EN                (PWRAP_DEW_BASE + 0x0)
+-#define PWRAP_DEW_DIO_EN              (PWRAP_DEW_BASE + 0x2)
+-#define PWRAP_DEW_EVENT_SRC_EN                (PWRAP_DEW_BASE + 0x4)
+-#define PWRAP_DEW_EVENT_SRC           (PWRAP_DEW_BASE + 0x6)
+-#define PWRAP_DEW_EVENT_FLAG          (PWRAP_DEW_BASE + 0x8)
+-#define PWRAP_DEW_READ_TEST           (PWRAP_DEW_BASE + 0xa)
+-#define PWRAP_DEW_WRITE_TEST          (PWRAP_DEW_BASE + 0xc)
+-#define PWRAP_DEW_CRC_EN              (PWRAP_DEW_BASE + 0xe)
+-#define PWRAP_DEW_CRC_VAL             (PWRAP_DEW_BASE + 0x10)
+-#define PWRAP_DEW_MON_GRP_SEL         (PWRAP_DEW_BASE + 0x12)
+-#define PWRAP_DEW_MON_FLAG_SEL                (PWRAP_DEW_BASE + 0x14)
+-#define PWRAP_DEW_EVENT_TEST          (PWRAP_DEW_BASE + 0x16)
+-#define PWRAP_DEW_CIPHER_KEY_SEL      (PWRAP_DEW_BASE + 0x18)
+-#define PWRAP_DEW_CIPHER_IV_SEL               (PWRAP_DEW_BASE + 0x1a)
+-#define PWRAP_DEW_CIPHER_LOAD         (PWRAP_DEW_BASE + 0x1c)
+-#define PWRAP_DEW_CIPHER_START                (PWRAP_DEW_BASE + 0x1e)
+-#define PWRAP_DEW_CIPHER_RDY          (PWRAP_DEW_BASE + 0x20)
+-#define PWRAP_DEW_CIPHER_MODE         (PWRAP_DEW_BASE + 0x22)
+-#define PWRAP_DEW_CIPHER_SWRST                (PWRAP_DEW_BASE + 0x24)
+-#define PWRAP_MT8173_DEW_CIPHER_IV0   (PWRAP_DEW_BASE + 0x26)
+-#define PWRAP_MT8173_DEW_CIPHER_IV1   (PWRAP_DEW_BASE + 0x28)
+-#define PWRAP_MT8173_DEW_CIPHER_IV2   (PWRAP_DEW_BASE + 0x2a)
+-#define PWRAP_MT8173_DEW_CIPHER_IV3   (PWRAP_DEW_BASE + 0x2c)
+-#define PWRAP_MT8173_DEW_CIPHER_IV4   (PWRAP_DEW_BASE + 0x2e)
+-#define PWRAP_MT8173_DEW_CIPHER_IV5   (PWRAP_DEW_BASE + 0x30)
++enum pwrap_dew_regs {
++      PWRAP_DEW_EVENT_OUT_EN,
++      PWRAP_DEW_DIO_EN,
++      PWRAP_DEW_EVENT_SRC_EN,
++      PWRAP_DEW_EVENT_SRC,
++      PWRAP_DEW_EVENT_FLAG,
++      PWRAP_DEW_READ_TEST,
++      PWRAP_DEW_WRITE_TEST,
++      PWRAP_DEW_CRC_EN,
++      PWRAP_DEW_CRC_VAL,
++      PWRAP_DEW_MON_GRP_SEL,
++      PWRAP_DEW_MON_FLAG_SEL,
++      PWRAP_DEW_EVENT_TEST,
++      PWRAP_DEW_CIPHER_KEY_SEL,
++      PWRAP_DEW_CIPHER_IV_SEL,
++      PWRAP_DEW_CIPHER_LOAD,
++      PWRAP_DEW_CIPHER_START,
++      PWRAP_DEW_CIPHER_RDY,
++      PWRAP_DEW_CIPHER_MODE,
++      PWRAP_DEW_CIPHER_SWRST,
++
++      /* MT7623 only regs */
++      PWRAP_DEW_CIPHER_EN,
++      PWRAP_DEW_RDDMY_NO,
++
++      /* MT8173 only regs */
++      PWRAP_DEW_CIPHER_IV0,
++      PWRAP_DEW_CIPHER_IV1,
++      PWRAP_DEW_CIPHER_IV2,
++      PWRAP_DEW_CIPHER_IV3,
++      PWRAP_DEW_CIPHER_IV4,
++      PWRAP_DEW_CIPHER_IV5,
++};
++
++static int mt7623_dew_regs[] = {
++      [PWRAP_DEW_DIO_EN]              = 0x18a,
++      [PWRAP_DEW_READ_TEST]           = 0x18c,
++      [PWRAP_DEW_WRITE_TEST]          = 0x18e,
++      [PWRAP_DEW_CRC_EN]              = 0x192,
++      [PWRAP_DEW_CRC_VAL]             = 0x194,
++      [PWRAP_DEW_CIPHER_KEY_SEL]      = 0x198,
++      [PWRAP_DEW_CIPHER_IV_SEL]       = 0x19a,
++      [PWRAP_DEW_CIPHER_EN]           = 0x19c,
++      [PWRAP_DEW_CIPHER_RDY]          = 0x19e,
++      [PWRAP_DEW_CIPHER_MODE]         = 0x1a0,
++      [PWRAP_DEW_CIPHER_SWRST]        = 0x1a2,
++      [PWRAP_DEW_RDDMY_NO]            = 0x1a4,
++};
++
++static int mt8135_dew_regs[] = {
++      [PWRAP_DEW_EVENT_OUT_EN]        = 0x0,
++      [PWRAP_DEW_DIO_EN]              = 0x2,
++      [PWRAP_DEW_EVENT_SRC_EN]        = 0x4,
++      [PWRAP_DEW_EVENT_SRC]           = 0x6,
++      [PWRAP_DEW_EVENT_FLAG]          = 0x8,
++      [PWRAP_DEW_READ_TEST]           = 0xa,
++      [PWRAP_DEW_WRITE_TEST]          = 0xc,
++      [PWRAP_DEW_CRC_EN]              = 0xe,
++      [PWRAP_DEW_CRC_VAL]             = 0x10,
++      [PWRAP_DEW_MON_GRP_SEL]         = 0x12,
++      [PWRAP_DEW_MON_FLAG_SEL]        = 0x14,
++      [PWRAP_DEW_EVENT_TEST]          = 0x16,
++      [PWRAP_DEW_CIPHER_KEY_SEL]      = 0x18,
++      [PWRAP_DEW_CIPHER_IV_SEL]       = 0x1a,
++      [PWRAP_DEW_CIPHER_LOAD]         = 0x1c,
++      [PWRAP_DEW_CIPHER_START]        = 0x1e,
++      [PWRAP_DEW_CIPHER_RDY]          = 0x20,
++      [PWRAP_DEW_CIPHER_MODE]         = 0x22,
++      [PWRAP_DEW_CIPHER_SWRST]        = 0x24,
++};
++
++static int mt8173_dew_regs[] = {
++      [PWRAP_DEW_EVENT_OUT_EN]        = 0x0,
++      [PWRAP_DEW_DIO_EN]              = 0x2,
++      [PWRAP_DEW_EVENT_SRC_EN]        = 0x4,
++      [PWRAP_DEW_EVENT_SRC]           = 0x6,
++      [PWRAP_DEW_EVENT_FLAG]          = 0x8,
++      [PWRAP_DEW_READ_TEST]           = 0xa,
++      [PWRAP_DEW_WRITE_TEST]          = 0xc,
++      [PWRAP_DEW_CRC_EN]              = 0xe,
++      [PWRAP_DEW_CRC_VAL]             = 0x10,
++      [PWRAP_DEW_MON_GRP_SEL]         = 0x12,
++      [PWRAP_DEW_MON_FLAG_SEL]        = 0x14,
++      [PWRAP_DEW_EVENT_TEST]          = 0x16,
++      [PWRAP_DEW_CIPHER_KEY_SEL]      = 0x18,
++      [PWRAP_DEW_CIPHER_IV_SEL]       = 0x1a,
++      [PWRAP_DEW_CIPHER_LOAD]         = 0x1c,
++      [PWRAP_DEW_CIPHER_START]        = 0x1e,
++      [PWRAP_DEW_CIPHER_RDY]          = 0x20,
++      [PWRAP_DEW_CIPHER_MODE]         = 0x22,
++      [PWRAP_DEW_CIPHER_SWRST]        = 0x24,
++      [PWRAP_DEW_CIPHER_IV0]          = 0x26,
++      [PWRAP_DEW_CIPHER_IV1]          = 0x28,
++      [PWRAP_DEW_CIPHER_IV2]          = 0x2a,
++      [PWRAP_DEW_CIPHER_IV3]          = 0x2c,
++      [PWRAP_DEW_CIPHER_IV4]          = 0x2e,
++      [PWRAP_DEW_CIPHER_IV5]          = 0x30,
++};
+ enum pwrap_regs {
+       PWRAP_MUX_SEL,
+@@ -162,7 +241,7 @@ enum pwrap_regs {
+       PWRAP_CIPHER_LOAD,
+       PWRAP_CIPHER_START,
+-      /* MT8173 only regs */
++      /* MT7623/MT8173 only regs */
+       PWRAP_RDDMY,
+       PWRAP_SI_CK_CON,
+       PWRAP_DVFS_ADR0,
+@@ -183,6 +262,107 @@ enum pwrap_regs {
+       PWRAP_DVFS_WDATA7,
+       PWRAP_SPMINF_STA,
+       PWRAP_CIPHER_EN,
++
++      /* MT7623 only regs */
++      PWRAP_OP_TYPE,
++      PWRAP_MSB_FIRST,
++      PWRAP_TOP_CKCON1,
++      PWRAP_TOP_CKCON1_CLR,
++      PWRAP_ADC_CMD_ADDR,
++      PWRAP_ADC_CMD,
++      PWRAP_ADC_RDY_ADDR,
++      PWRAP_ADC_RDATA_ADDR1,
++      PWRAP_ADC_RDATA_ADDR2,
++};
++
++static int mt7623_regs[] = {
++      [PWRAP_MUX_SEL] =               0x0,
++      [PWRAP_WRAP_EN] =               0x4,
++      [PWRAP_DIO_EN] =                0x8,
++      [PWRAP_SIDLY] =                 0xc,
++      [PWRAP_OP_TYPE] =               0x10,
++      [PWRAP_MSB_FIRST] =             0x14,
++      [PWRAP_RDDMY] =                 0x18,
++      [PWRAP_SI_CK_CON] =             0x1c,
++      [PWRAP_CSHEXT_WRITE] =          0x20,
++      [PWRAP_CSHEXT_READ] =           0x24,
++      [PWRAP_CSLEXT_START] =          0x28,
++      [PWRAP_CSLEXT_END] =            0x2c,
++      [PWRAP_STAUPD_PRD] =            0x30,
++      [PWRAP_STAUPD_GRPEN] =          0x34,
++      [PWRAP_STAUPD_MAN_TRIG] =       0x38,
++      [PWRAP_STAUPD_STA] =            0x3C,
++      [PWRAP_WRAP_STA] =              0x44,
++      [PWRAP_HARB_INIT] =             0x48,
++      [PWRAP_HARB_HPRIO] =            0x4c,
++      [PWRAP_HIPRIO_ARB_EN] =         0x50,
++      [PWRAP_HARB_STA0] =             0x54,
++      [PWRAP_HARB_STA1] =             0x58,
++      [PWRAP_MAN_EN] =                0x5c,
++      [PWRAP_MAN_CMD] =               0x60,
++      [PWRAP_MAN_RDATA] =             0x6c,
++      [PWRAP_MAN_VLDCLR] =            0x68,
++      [PWRAP_WACS0_EN] =              0x6c,
++      [PWRAP_INIT_DONE0] =            0x70,
++      [PWRAP_WACS0_CMD] =             0x74,
++      [PWRAP_WACS0_RDATA] =           0x78,
++      [PWRAP_WACS0_VLDCLR] =          0x7c,
++      [PWRAP_WACS1_EN] =              0x80,
++      [PWRAP_INIT_DONE1] =            0x84,
++      [PWRAP_WACS1_CMD] =             0x88,
++      [PWRAP_WACS1_RDATA] =           0x9c,
++      [PWRAP_WACS1_VLDCLR] =          0x90,
++      [PWRAP_WACS2_EN] =              0x94,
++      [PWRAP_INIT_DONE2] =            0x98,
++      [PWRAP_WACS2_CMD] =             0x9c,
++      [PWRAP_WACS2_RDATA] =           0xa0,
++      [PWRAP_WACS2_VLDCLR] =          0xa4,
++      [PWRAP_INT_EN] =                0xa8,
++      [PWRAP_INT_FLG_RAW] =           0xac,
++      [PWRAP_INT_FLG] =               0xb0,
++      [PWRAP_INT_CLR] =               0xb4,
++      [PWRAP_SIG_ADR] =               0xb8,
++      [PWRAP_SIG_MODE] =              0xbc,
++      [PWRAP_SIG_VALUE] =             0xc0,
++      [PWRAP_SIG_ERRVAL] =            0xc4,
++      [PWRAP_CRC_EN] =                0xc8,
++      [PWRAP_TIMER_EN] =              0xcc,
++      [PWRAP_TIMER_STA] =             0xd0,
++      [PWRAP_WDT_UNIT] =              0xd4,
++      [PWRAP_WDT_SRC_EN] =            0xd8,
++      [PWRAP_WDT_FLG] =               0xdc,
++      [PWRAP_DEBUG_INT_SEL] =         0xe0,
++      [PWRAP_DVFS_ADR0] =             0xe4,
++      [PWRAP_DVFS_WDATA0] =           0xe8,
++      [PWRAP_DVFS_ADR1] =             0xec,
++      [PWRAP_DVFS_WDATA1] =           0xf0,
++      [PWRAP_DVFS_ADR2] =             0xf4,
++      [PWRAP_DVFS_WDATA2] =           0xf8,
++      [PWRAP_DVFS_ADR3] =             0xfc,
++      [PWRAP_DVFS_WDATA3] =           0x100,
++      [PWRAP_DVFS_ADR4] =             0x104,
++      [PWRAP_DVFS_WDATA4] =           0x108,
++      [PWRAP_DVFS_ADR5] =             0x10c,
++      [PWRAP_DVFS_WDATA5] =           0x110,
++      [PWRAP_DVFS_ADR6] =             0x114,
++      [PWRAP_DVFS_WDATA6] =           0x118,
++      [PWRAP_DVFS_ADR7] =             0x11c,
++      [PWRAP_DVFS_WDATA7] =           0x120,
++      [PWRAP_CIPHER_KEY_SEL] =        0x124,
++      [PWRAP_TOP_CKCON1] =            0x126,
++      [PWRAP_CIPHER_IV_SEL] =         0x128,
++      [PWRAP_TOP_CKCON1_CLR] =        0x12a,
++      [PWRAP_CIPHER_EN] =             0x12c,
++      [PWRAP_CIPHER_RDY] =            0x130,
++      [PWRAP_CIPHER_MODE] =           0x134,
++      [PWRAP_CIPHER_SWRST] =          0x138,
++      [PWRAP_DCM_EN] =                0x13c,
++      [PWRAP_DCM_DBC_PRD] =           0x140,
++      [PWRAP_ADC_CMD_ADDR] =  0x144,
++      [PWRAP_ADC_CMD] =               0x148,
++      [PWRAP_ADC_RDY_ADDR] =  0x14C,
++      [PWRAP_ADC_RDATA_ADDR1] =       0x150,
++      [PWRAP_ADC_RDATA_ADDR2] =       0x154,
+ };
+ static int mt8173_regs[] = {
+@@ -341,24 +521,39 @@ static int mt8135_regs[] = {
+ };
+ enum pwrap_type {
++      PWRAP_MT7623,
+       PWRAP_MT8135,
+       PWRAP_MT8173,
+ };
+ struct pmic_wrapper_type {
+       int *regs;
++      int *dew_regs;
++      u32 dew_base;
+       enum pwrap_type type;
+       u32 arb_en_all;
+ };
++static struct pmic_wrapper_type pwrap_mt7623 = {
++      .regs = mt7623_regs,
++      .dew_regs = mt7623_dew_regs,
++      .dew_base = 0x0,
++      .type = PWRAP_MT7623,
++      .arb_en_all = 0x3f,
++};
++
+ static struct pmic_wrapper_type pwrap_mt8135 = {
+       .regs = mt8135_regs,
++      .dew_regs = mt8135_dew_regs,
++      .dew_base = 0xbc00,
+       .type = PWRAP_MT8135,
+       .arb_en_all = 0x1ff,
+ };
+ static struct pmic_wrapper_type pwrap_mt8173 = {
+       .regs = mt8173_regs,
++      .dew_regs = mt8173_dew_regs,
++      .dew_base = 0xbc00,
+       .type = PWRAP_MT8173,
+       .arb_en_all = 0x3f,
+ };
+@@ -368,6 +563,8 @@ struct pmic_wrapper {
+       void __iomem *base;
+       struct regmap *regmap;
+       int *regs;
++      int *dew_regs;
++      u32 dew_base;
+       enum pwrap_type type;
+       u32 arb_en_all;
+       struct clk *clk_spi;
+@@ -378,6 +575,11 @@ struct pmic_wrapper {
+       void __iomem *bridge_base;
+ };
++static inline int pwrap_is_mt7623(struct pmic_wrapper *wrp)
++{
++      return wrp->type == PWRAP_MT7623;
++}
++
+ static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp)
+ {
+       return wrp->type == PWRAP_MT8135;
+@@ -475,6 +677,16 @@ static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
+       return 0;
+ }
++static int pwrap_dew_write(struct pmic_wrapper *wrp, enum pwrap_dew_regs reg, u32 wdata)
++{
++      return pwrap_write(wrp, wrp->dew_base + wrp->dew_regs[reg], wdata);
++}
++
++static int pwrap_dew_read(struct pmic_wrapper *wrp, enum pwrap_dew_regs reg, u32 *rdata)
++{
++      return pwrap_read(wrp, wrp->dew_base + wrp->dew_regs[reg], rdata);
++}
++
+ static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata)
+ {
+       return pwrap_read(context, adr, rdata);
+@@ -535,7 +747,7 @@ static int pwrap_init_sidly(struct pmic_wrapper *wrp)
+       for (i = 0; i < 4; i++) {
+               pwrap_writel(wrp, i, PWRAP_SIDLY);
+-              pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
++              pwrap_dew_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+               if (rdata == PWRAP_DEW_READ_TEST_VAL) {
+                       dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
+                       pass |= 1 << i;
+@@ -561,6 +773,14 @@ static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
+               pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
+               pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+               pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
++      } else if (pwrap_is_mt7623(wrp)) {
++              pwrap_writel(wrp, 0x3, PWRAP_TOP_CKCON1_CLR);
++              pwrap_dew_write(wrp, 0x8, PWRAP_DEW_RDDMY_NO);
++              pwrap_writel(wrp, 0x8, PWRAP_RDDMY);
++              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);
+       } else {
+               pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE);
+               pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
+@@ -581,7 +801,7 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+       u32 rdata;
+       int ret;
+-      ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
++      ret = pwrap_dew_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
+       if (ret)
+               return 0;
+@@ -606,12 +826,16 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+       }
+       /* Config cipher mode @PMIC */
+-      pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
+-      pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
+-      pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
+-      pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
+-      pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
+-      pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
++      pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
++      pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
++      pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
++      pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
++      if (pwrap_is_mt7623(wrp)) {
++              pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_EN, 0x1);
++      } else {
++              pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
++              pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
++      }
+       /* wait for cipher data ready@AP */
+       ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
+@@ -628,7 +852,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+       }
+       /* wait for cipher mode idle */
+-      pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
++      pwrap_dew_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
+       ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+       if (ret) {
+               dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret);
+@@ -638,8 +862,8 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+       pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE);
+       /* Write Test */
+-      if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
+-          pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
++      if (pwrap_dew_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
++          pwrap_dew_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
+                       (rdata != PWRAP_DEW_WRITE_TEST_VAL)) {
+               dev_err(wrp->dev, "rdata=0x%04X\n", rdata);
+               return -EFAULT;
+@@ -657,12 +881,17 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+       if (wrp->rstc_bridge)
+               reset_control_reset(wrp->rstc_bridge);
+-      if (pwrap_is_mt8173(wrp)) {
++      if (pwrap_is_mt7623(wrp) || pwrap_is_mt8173(wrp)) {
+               /* Enable DCM */
+               pwrap_writel(wrp, 3, PWRAP_DCM_EN);
+               pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+       }
++      if (pwrap_is_mt7623(wrp)) {
++              pwrap_writel(wrp, 0, PWRAP_OP_TYPE);
++              pwrap_writel(wrp, 1, PWRAP_MSB_FIRST);
++      }
++
+       /* Reset SPI slave */
+       ret = pwrap_reset_spislave(wrp);
+       if (ret)
+@@ -674,6 +903,9 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+       pwrap_writel(wrp, 1, PWRAP_WACS2_EN);
++      if (pwrap_is_mt7623(wrp))
++              pwrap_writel(wrp, 0xf, PWRAP_RDDMY);
++
+       ret = pwrap_init_reg_clock(wrp);
+       if (ret)
+               return ret;
+@@ -684,7 +916,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+               return ret;
+       /* Enable dual IO mode */
+-      pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1);
++      pwrap_dew_write(wrp, PWRAP_DEW_DIO_EN, 1);
+       /* Check IDLE & INIT_DONE in advance */
+       ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+@@ -696,7 +928,7 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+       pwrap_writel(wrp, 1, PWRAP_DIO_EN);
+       /* Read Test */
+-      pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
++      pwrap_dew_read(wrp, 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);
+@@ -709,12 +941,13 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+               return ret;
+       /* Signature checking - using CRC */
+-      if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
++      if (pwrap_dew_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
+               return -EFAULT;
+       pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
+       pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
+-      pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR);
++      pwrap_writel(wrp, wrp->dew_base + wrp->dew_regs[PWRAP_DEW_CRC_VAL],
++                   PWRAP_SIG_ADR);
+       pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+       if (pwrap_is_mt8135(wrp))
+@@ -728,7 +961,16 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+       pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
+       pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
+       pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+-      pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
++//    pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
++      pwrap_writel(wrp, ~(BIT(31) | BIT(2)), PWRAP_INT_EN);
++
++      if (pwrap_is_mt7623(wrp)) {
++              pwrap_writel(wrp, PWRAP_MT7623_AUXADC_CON21, PWRAP_ADC_CMD_ADDR);
++              pwrap_writel(wrp, 0x8000, PWRAP_ADC_CMD);
++              pwrap_writel(wrp, PWRAP_MT7623_AUXADC_ADC12, PWRAP_ADC_RDY_ADDR);
++              pwrap_writel(wrp, PWRAP_MT7623_AUXADC_ADC13, PWRAP_ADC_RDATA_ADDR1);
++              pwrap_writel(wrp, PWRAP_MT7623_AUXADC_ADC14, PWRAP_ADC_RDATA_ADDR2);
++      }
+       if (pwrap_is_mt8135(wrp)) {
+               /* enable pwrap events and pwrap bridge in AP side */
+@@ -743,15 +985,15 @@ static int pwrap_init(struct pmic_wrapper *wrp)
+               writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN);
+               /* enable PMIC event out and sources */
+-              if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+-                              pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
++              if (pwrap_dew_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
++                              pwrap_dew_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+                       dev_err(wrp->dev, "enable dewrap fail\n");
+                       return -EFAULT;
+               }
+-      } else {
++      } else if (!pwrap_is_mt7623(wrp)) {
+               /* PMIC_DEWRAP enables */
+-              if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+-                              pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
++              if (pwrap_dew_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
++                              pwrap_dew_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+                       dev_err(wrp->dev, "enable dewrap fail\n");
+                       return -EFAULT;
+               }
+@@ -795,6 +1037,9 @@ static const struct regmap_config pwrap_regmap_config = {
+ static struct of_device_id of_pwrap_match_tbl[] = {
+       {
++              .compatible = "mediatek,mt7623-pwrap",
++              .data = &pwrap_mt7623,
++      }, {
+               .compatible = "mediatek,mt8135-pwrap",
+               .data = &pwrap_mt8135,
+       }, {
+@@ -824,6 +1069,8 @@ static int pwrap_probe(struct platform_device *pdev)
+       type = of_id->data;
+       wrp->regs = type->regs;
++      wrp->dew_regs = type->dew_regs;
++      wrp->dew_base = type->dew_base;
+       wrp->type = type->type;
+       wrp->arb_en_all = type->arb_en_all;
+       wrp->dev = &pdev->dev;
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0070-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch b/target/linux/mediatek/patches/0070-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch
new file mode 100644 (file)
index 0000000..87de0f9
--- /dev/null
@@ -0,0 +1,199 @@
+From ac825c0dd7370ae1b9a1a4346f895728e09d9cc7 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 1 Jul 2015 07:58:44 +0200
+Subject: [PATCH 70/76] clk: mediatek: Export CPU mux clocks for CPU frequency
+ control
+
+This patch adds CPU mux clocks which are used by Mediatek cpufreq driver
+for intermediate clock source switching.
+
+Changes in v3:
+- Rebase to 4.2-rc1
+- Fix some issues of v2
+
+Changes in v2:
+- Remove use of .determine_rate callback
+
+Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
+---
+ drivers/clk/mediatek/Makefile     |    2 +-
+ drivers/clk/mediatek/clk-cpumux.c |  119 +++++++++++++++++++++++++++++++++++++
+ drivers/clk/mediatek/clk-cpumux.h |   30 ++++++++++
+ 3 files changed, 150 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/clk/mediatek/clk-cpumux.c
+ create mode 100644 drivers/clk/mediatek/clk-cpumux.h
+
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index 19a3763..fe07e26 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -1,4 +1,4 @@
+-obj-y += clk-mtk.o clk-pll.o clk-gate.o
++obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-cpumux.o
+ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+ obj-y += clk-mt7623.o
+ obj-y += clk-mt8135.o
+diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c
+new file mode 100644
+index 0000000..593df45
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-cpumux.c
+@@ -0,0 +1,119 @@
++/*
++ * Copyright (c) 2015 Linaro Ltd.
++ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
++ *
++ * 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/mfd/syscon.h>
++#include <linux/slab.h>
++
++#include "clk-mtk.h"
++#include "clk-cpumux.h"
++
++static inline struct mtk_clk_cpumux *to_clk_mux(struct clk_hw *_hw)
++{
++      return container_of(_hw, struct mtk_clk_cpumux, hw);
++}
++
++static u8 clk_cpumux_get_parent(struct clk_hw *hw)
++{
++      struct mtk_clk_cpumux *mux = to_clk_mux(hw);
++      int num_parents = __clk_get_num_parents(hw->clk);
++      unsigned int val;
++
++      regmap_read(mux->regmap, mux->reg, &val);
++
++      val >>= mux->shift;
++      val &= mux->mask;
++
++      if (val >= num_parents)
++              return -EINVAL;
++
++      return val;
++}
++
++static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct mtk_clk_cpumux *mux = to_clk_mux(hw);
++      u32 mask, val;
++
++      val = index << mux->shift;
++      mask = mux->mask << mux->shift;
++
++      return regmap_update_bits(mux->regmap, mux->reg, mask, val);
++}
++
++static const struct clk_ops clk_cpumux_ops = {
++      .get_parent = clk_cpumux_get_parent,
++      .set_parent = clk_cpumux_set_parent,
++};
++
++static struct clk *mtk_clk_register_cpumux(const struct mtk_composite *mux,
++                                         struct regmap *regmap)
++{
++      struct mtk_clk_cpumux *cpumux;
++      struct clk *clk;
++      struct clk_init_data init;
++
++      cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL);
++      if (!cpumux)
++              return ERR_PTR(-ENOMEM);
++
++      init.name = mux->name;
++      init.ops = &clk_cpumux_ops;
++      init.parent_names = mux->parent_names;
++      init.num_parents = mux->num_parents;
++      init.flags = mux->flags;
++
++      cpumux->reg = mux->mux_reg;
++      cpumux->shift = mux->mux_shift;
++      cpumux->mask = BIT(mux->mux_width) - 1;
++      cpumux->regmap = regmap;
++      cpumux->hw.init = &init;
++
++      clk = clk_register(NULL, &cpumux->hw);
++      if (IS_ERR(clk))
++              kfree(cpumux);
++
++      return clk;
++}
++
++int mtk_clk_register_cpumuxes(struct device_node *node,
++                            const struct mtk_composite *clks, int num,
++                            struct clk_onecell_data *clk_data)
++{
++      int i;
++      struct clk *clk;
++      struct regmap *regmap;
++
++      regmap = syscon_node_to_regmap(node);
++      if (IS_ERR(regmap)) {
++              pr_err("Cannot find regmap for %s: %d\n", node->full_name,
++                     PTR_ERR(regmap));
++              return PTR_ERR(regmap);
++      }
++
++      for (i = 0; i < num; i++) {
++              const struct mtk_composite *mux = &clks[i];
++
++              clk = mtk_clk_register_cpumux(mux, regmap);
++              if (IS_ERR(clk)) {
++                      pr_err("Failed to register clk %s: %ld\n",
++                             mux->name, PTR_ERR(clk));
++                      continue;
++              }
++
++              clk_data->clks[mux->id] = clk;
++      }
++
++      return 0;
++}
+diff --git a/drivers/clk/mediatek/clk-cpumux.h b/drivers/clk/mediatek/clk-cpumux.h
+new file mode 100644
+index 0000000..dddaad5
+--- /dev/null
++++ b/drivers/clk/mediatek/clk-cpumux.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (c) 2015 Linaro Ltd.
++ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
++ *
++ * 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 __DRV_CLK_CPUMUX_H
++#define __DRV_CLK_CPUMUX_H
++
++struct mtk_clk_cpumux {
++      struct clk_hw   hw;
++      struct regmap   *regmap;
++      u32             reg;
++      u32             mask;
++      u8              shift;
++};
++
++int mtk_clk_register_cpumuxes(struct device_node *node,
++                            const struct mtk_composite *clks, int num,
++                            struct clk_onecell_data *clk_data);
++
++#endif /* __DRV_CLK_CPUMUX_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0071-clk.patch b/target/linux/mediatek/patches/0071-clk.patch
new file mode 100644 (file)
index 0000000..f920dce
--- /dev/null
@@ -0,0 +1,342 @@
+From c3a3617a8c37b43db7ff622a31f171d3ce870173 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:44:57 +0200
+Subject: [PATCH 71/76] clk
+
+---
+ drivers/clk/mediatek/clk-mt7623.c |  194 ++++++++++++++++---------------------
+ 1 file changed, 83 insertions(+), 111 deletions(-)
+
+diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c
+index 07843bb..d46b2ad 100644
+--- a/drivers/clk/mediatek/clk-mt7623.c
++++ b/drivers/clk/mediatek/clk-mt7623.c
+@@ -20,6 +20,7 @@
+ #include "clk-mtk.h"
+ #include "clk-gate.h"
++#include "clk-cpumux.h"
+ static DEFINE_SPINLOCK(mt7623_clk_lock);
+@@ -37,18 +38,11 @@ static void mtk_clk_enable_critical(void)
+       clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_RTC_SEL]);
+ }
+-static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+-      FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
+-      FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
+-      FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
+-      FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
+-};
+-
+ static const struct mtk_fixed_factor top_divs[] __initconst = {
+-      FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_650m", "mainpll", 1, 2),
+-      FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_433p3m", "mainpll", 1, 3),
+-      FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_260m", "mainpll", 1, 5),
+-      FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_185p6m", "mainpll", 1, 7),
++      FACTOR(CLK_TOP_MAINPLL_650M, "mainpll_650m", "mainpll", 1, 2),
++      FACTOR(CLK_TOP_MAINPLL_433P3M, "mainpll_433p3m", "mainpll", 1, 3),
++      FACTOR(CLK_TOP_MAINPLL_260M, "mainpll_260m", "mainpll", 1, 5),
++      FACTOR(CLK_TOP_MAINPLL_185P6M, "mainpll_185p6m", "mainpll", 1, 7),
+       FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
+@@ -61,13 +55,6 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
+       FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll", 1, 16),
+       FACTOR(CLK_TOP_AUDPLL_24, "audpll_d24", "audpll", 1, 24),
+-      FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+-      FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+-      FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+-      FACTOR(CLK_TOP_LVDS_ETH, "lvdspll_eth", "lvdspll", 1, 16),
+-
+-      FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+-
+       FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll_650m", 1, 2),
+@@ -85,9 +72,6 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
+       FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_260m", 1, 1),
+       FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll_185p6m", 1, 1),
+-      FACTOR(CLK_TOP_TVDPLL_d2, "tvdpll_d2", "tvdpll", 1, 2),
+-      FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+-
+       FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
+@@ -110,9 +94,6 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
+       FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
+       FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
+-
+-
+-      FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
+ };
+ static const char * const axi_parents[] __initconst = {
+@@ -155,18 +136,6 @@ static const char * const pwm_parents[] __initconst = {
+       "univpll1_d4",
+ };
+-static const char * const vdec_parents[] __initconst = {
+-      "clk26m",
+-      "syspll1_d2",
+-      "syspll_d5",
+-      "syspll1_d4",
+-      "univpll_d5",
+-      "univpll2_d2",
+-      "univpll2_d4",
+-      "msdcpll_d2",
+-      "mmpll_d2",
+-};
+-
+ static const char * const mfg_parents[] __initconst = {
+       "clk26m",
+       "mmpll_ck",
+@@ -178,17 +147,6 @@ static const char * const mfg_parents[] __initconst = {
+       "univpll1_d2",
+ };
+-static const char * const cam_parents[] __initconst = {
+-      "clk26m",
+-      "univpll_d26",
+-      "univpll2_d2",
+-      "syspll3_d2",
+-      "syspll3_d4",
+-      "msdcpll_d2",
+-      "mmpll_d2",
+-      "clk26m",
+-};
+-
+ static const char * const uart_parents[] __initconst = {
+       "clk26m",
+       "univpll2_d8",
+@@ -277,35 +235,6 @@ static const char * const scp_parents[] __initconst = {
+       "dmpll_d4",
+ };
+-static const char * const dpi0_parents[] __initconst = {
+-      "clk26m",
+-      "mipipll",
+-      "mipipll_d2",
+-      "mipipll_d4",
+-      "lvdspll",
+-      "lvdspll_d2",
+-      "lvdspll_d4",
+-      "lvdspll_d8",
+-};
+-
+-static const char * const dpi1_parents[] __initconst = {
+-      "clk26m",
+-      "tvdpll",
+-      "tvdpll_d2",
+-      "tvdpll_d4",
+-};
+-
+-static const char * const tve_parents[] __initconst = {
+-      "clk26m",
+-      "mipipll",
+-      "mipipll_d2",
+-      "mipipll_d4",
+-      "clk26m",
+-      "tvdpll",
+-      "tvdpll_d2",
+-      "tvdpll_d4",
+-};
+-
+ static const char * const apll_parents[] __initconst = {
+       "clk26m",
+       "audpll",
+@@ -317,17 +246,6 @@ static const char * const apll_parents[] __initconst = {
+       "clk26m",
+ };
+-static const char * const dpilvds_parents[] __initconst = {
+-      "clk26m",
+-      "lvdspll",
+-      "lvdspll_d2",
+-      "lvdspll_d4",
+-      "lvdspll_d8",
+-      "fpc_ck",
+-      "clk26m",
+-      "clk26m",
+-};
+-
+ static const char * const rtc_parents[] __initconst = {
+       "clk32k",
+       "external_32k",
+@@ -367,9 +285,7 @@ static const struct mtk_composite top_muxes[] __initconst = {
+               0x0140, 24, 3, INVALID_MUX_GATE_BIT),
+       /* CLK_CFG_1 */
+       MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
+-      MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
+       MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 16, 3, 23),
+-      MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0050, 24, 3, 31),
+       /* CLK_CFG_2 */
+       MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 0, 1, 7),
+       MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 8, 3, 15),
+@@ -384,12 +300,8 @@ static const struct mtk_composite top_muxes[] __initconst = {
+       /* CLK_CFG_4 */
+       MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmic_spi_parents, 0x0080, 0, 4, 7),
+       MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0080, 8, 2, 15),
+-      MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x0080, 16, 3, 23),
+-      MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0080, 24, 2, 31),
+       /* CLK_CFG_5 */
+-      MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents, 0x0090, 0, 3, 7),
+       MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0090, 16, 3, 23),
+-      MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x0090, 24, 3, 31),
+       /* CLK_CFG_6 */
+       MUX_GATE(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00a0, 0, 2, 7),
+       MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents, 0x00a0, 8, 3, 15),
+@@ -428,6 +340,17 @@ static const struct mtk_gate infra_clks[] __initconst = {
+       GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
+ };
++static const char * const ca7_parents[] __initconst = {
++      "clk26m",
++      "armpll",
++      "mainpll",
++      "univpll"
++};
++
++static struct mtk_composite cpu_muxes[] __initdata = {
++      MUX(CLK_INFRA_CA7SEL, "infra_ca7_sel", ca7_parents, 0x0000, 2, 2),
++};
++
+ static const struct mtk_gate_regs peri0_cg_regs = {
+       .set_ofs = 0x0008,
+       .clr_ofs = 0x0010,
+@@ -499,6 +422,29 @@ static const struct mtk_gate peri_gates[] __initconst = {
+       GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "axi_sel", 2),
+ };
++static const struct mtk_gate_regs hifsys_cg_regs = {
++      .set_ofs = 0x0034,
++      .clr_ofs = 0x0014,
++      .sta_ofs = 0x0038,
++};
++
++#define GATE_HIFSYS(_id, _name, _parent, _shift) {            \
++              .id = _id,                                      \
++              .name = _name,                                  \
++              .parent_name = _parent,                         \
++              .regs = &hifsys_cg_regs,                        \
++              .shift = _shift,                                \
++              .ops = &mtk_clk_gate_ops_setclr,                \
++      }
++
++static const struct mtk_gate hifsys_gates[] __initconst = {
++      GATE_HIFSYS(CLK_HIFSYS_USB0_PHY, "usb0_phy_ck", "axi_sel", 21),
++      GATE_HIFSYS(CLK_HIFSYS_USB1_PHY, "usb1_phy_ck", "axi_sel", 22),
++      GATE_HIFSYS(CLK_HIFSYS_PCIE0, "pcie0_ck", "axi_sel", 24),
++      GATE_HIFSYS(CLK_HIFSYS_PCIE1, "pcie1_ck", "axi_sel", 25),
++      GATE_HIFSYS(CLK_HIFSYS_PCIE2, "pcie2_ck", "axi_sel", 26),
++};
++
+ static const char * const uart_ck_sel_parents[] __initconst = {
+       "clk26m",
+       "uart_sel",
+@@ -525,10 +471,9 @@ static void __init mtk_topckgen_init(struct device_node *node)
+       mt7623_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+-      mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), 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,
+-                      &mt7623_clk_lock, clk_data);
++                                      &mt7623_clk_lock, clk_data);
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+@@ -547,7 +492,10 @@ static void __init mtk_infrasys_init(struct device_node *node)
+       clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+       mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+-                                              clk_data);
++                              clk_data);
++
++      mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes),
++                                 clk_data);
+       clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
+@@ -588,35 +536,59 @@ static void __init mtk_pericfg_init(struct device_node *node)
+ }
+ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt7623-pericfg", mtk_pericfg_init);
+-#define MT7623_PLL_FMAX               (2000 * MHZ)
+-#define CON0_MT7623_RST_BAR   BIT(27)
++static void __init mtk_hifsys_init(struct device_node *node)
++{
++      struct clk_onecell_data *clk_data;
++      int r;
++      void __iomem *base;
++
++      base = of_iomap(node, 0);
++      if (!base) {
++              pr_err("%s(): ioremap failed\n", __func__);
++              return;
++      }
++
++      clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR_CLK);
++
++      mtk_clk_register_gates(node, hifsys_gates, ARRAY_SIZE(hifsys_gates),
++                                              clk_data);
++
++      r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++      if (r)
++              pr_err("%s(): could not register clock provider: %d\n",
++                      __func__, r);
++
++      mtk_register_reset_controller(node, 1, 0x34);
++}
++CLK_OF_DECLARE(mtk_hifsys, "mediatek,mt7623-hifsys", mtk_hifsys_init);
++
++#define MT7623_PLL_FMAX               (1300 * MHZ)
++#define CON0_MT7623_RST_BAR   BIT(24)
+-#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
++#define PLL(_id, _name, _con0_reg, _con1_reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pcw_shift, _pd_shift) { \
+               .id = _id,                                              \
+               .name = _name,                                          \
+-              .reg = _reg,                                            \
++              .reg = _con0_reg,                                               \
+               .pwr_reg = _pwr_reg,                                    \
+               .en_mask = _en_mask,                                    \
+               .flags = _flags,                                        \
+               .rst_bar_mask = CON0_MT7623_RST_BAR,                    \
+               .fmax = MT7623_PLL_FMAX,                                \
+               .pcwbits = _pcwbits,                                    \
+-              .pd_reg = _pd_reg,                                      \
++              .pd_reg = _con0_reg,                                    \
+               .pd_shift = _pd_shift,                                  \
+-              .tuner_reg = _tuner_reg,                                \
+-              .pcw_reg = _pcw_reg,                                    \
++              .pcw_reg = _con1_reg,                                   \
+               .pcw_shift = _pcw_shift,                                \
+       }
+ static const struct mtk_pll_data plls[] = {
+-      PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+-      PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0x78000001, HAVE_RST_BAR, 21, 0x214, 6, 0x0, 0x214, 0),
+-      PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xFC000001, HAVE_RST_BAR, 7, 0x224, 6, 0x0, 0x224, 0),
+-      PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0, 21, 0x254, 6, 0x0, 0x258, 0),
+-      PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 6, 0x0, 0x244, 0),
+-      PLL(CLK_APMIXED_AUDPLL, "audpll", 0x250, 0x25c, 0x00000001, 0, 31, 0x2e8, 6, 0x2f8, 0x254, 0),
+-      PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x260, 0x26c, 0x00000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
+-      PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x270, 0x27c, 0x00000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
++      PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x204, 0x20c, 0x00000001, 0, 21, 0, 4 ),
++      PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x214, 0x21c, 0x78000001, HAVE_RST_BAR, 21, 0, 4 ),
++      PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x224, 0x22c, 0xFC000001, HAVE_RST_BAR, 7, 14, 4 ),
++      PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x244, 0x24c, 0x00000001, 0, 21, 0, 4 ),
++      PLL(CLK_APMIXED_AUDPLL, "audpll", 0x270, 0x274, 0x27c, 0x00000001, 0, 31, 0, 4 ),
++      PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x284, 0x28c, 0x00000001, 0, 31, 0, 4 ),
++      PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x294, 0x29c, 0x00000001, 0, 31, 0, 4 ),
+ };
+ static void __init mtk_apmixedsys_init(struct device_node *node)
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0072-mfd.patch b/target/linux/mediatek/patches/0072-mfd.patch
new file mode 100644 (file)
index 0000000..cbcadb7
--- /dev/null
@@ -0,0 +1,1591 @@
+From 1a4dcc30578512d687528adcf963203faee50d83 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:45:17 +0200
+Subject: [PATCH 72/76] mfd
+
+---
+ drivers/mfd/mt6323-core.c                  |  168 +++----
+ drivers/regulator/mt6323-regulator.c       |  218 ++++----
+ include/linux/mfd/mt6323/core.h            |   76 +--
+ include/linux/mfd/mt6323/registers.h       |  745 +++++++++++++++-------------
+ include/linux/regulator/mt6323-regulator.h |   37 ++
+ 5 files changed, 636 insertions(+), 608 deletions(-)
+ create mode 100644 include/linux/regulator/mt6323-regulator.h
+
+diff --git a/drivers/mfd/mt6323-core.c b/drivers/mfd/mt6323-core.c
+index 012c620..9b7f5b9 100644
+--- a/drivers/mfd/mt6323-core.c
++++ b/drivers/mfd/mt6323-core.c
+@@ -18,111 +18,99 @@
+ #include <linux/of_irq.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/core.h>
+-#include <linux/mfd/mt6397/core.h>
+-#include <linux/mfd/mt6397/registers.h>
++#include <linux/mfd/mt6323/core.h>
++#include <linux/mfd/mt6323/registers.h>
+-static const struct mfd_cell mt6397_devs[] = {
++static const struct mfd_cell mt6323_devs[] = {
+       {
+-              .name = "mt6397-rtc",
+-              .of_compatible = "mediatek,mt6397-rtc",
+-      }, {
+-              .name = "mt6397-regulator",
+-              .of_compatible = "mediatek,mt6397-regulator",
+-      }, {
+-              .name = "mt6397-codec",
+-              .of_compatible = "mediatek,mt6397-codec",
+-      }, {
+-              .name = "mt6397-clk",
+-              .of_compatible = "mediatek,mt6397-clk",
+-      }, {
+-              .name = "mediatek-mt6397-pinctrl",
+-              .of_compatible = "mediatek,mt6397-pinctrl",
++              .name = "mt6323-regulator",
++              .of_compatible = "mediatek,mt6323-regulator",
+       },
+ };
+-static void mt6397_irq_lock(struct irq_data *data)
++static void mt6323_irq_lock(struct irq_data *data)
+ {
+-      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++      struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+-      mutex_lock(&mt6397->irqlock);
++      mutex_lock(&mt6323->irqlock);
+ }
+-static void mt6397_irq_sync_unlock(struct irq_data *data)
++static void mt6323_irq_sync_unlock(struct irq_data *data)
+ {
+-      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++      struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+-      regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
+-      regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
++      regmap_write(mt6323->regmap, MT6323_INT_CON0, mt6323->irq_masks_cur[0]);
++      regmap_write(mt6323->regmap, MT6323_INT_CON1, mt6323->irq_masks_cur[1]);
+-      mutex_unlock(&mt6397->irqlock);
++      mutex_unlock(&mt6323->irqlock);
+ }
+-static void mt6397_irq_disable(struct irq_data *data)
++static void mt6323_irq_disable(struct irq_data *data)
+ {
+-      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++      struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+       int shift = data->hwirq & 0xf;
+       int reg = data->hwirq >> 4;
+-      mt6397->irq_masks_cur[reg] &= ~BIT(shift);
++      mt6323->irq_masks_cur[reg] &= ~BIT(shift);
+ }
+-static void mt6397_irq_enable(struct irq_data *data)
++static void mt6323_irq_enable(struct irq_data *data)
+ {
+-      struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
++      struct mt6323_chip *mt6323 = irq_get_chip_data(data->irq);
+       int shift = data->hwirq & 0xf;
+       int reg = data->hwirq >> 4;
+-      mt6397->irq_masks_cur[reg] |= BIT(shift);
++      mt6323->irq_masks_cur[reg] |= BIT(shift);
+ }
+-static struct irq_chip mt6397_irq_chip = {
+-      .name = "mt6397-irq",
+-      .irq_bus_lock = mt6397_irq_lock,
+-      .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
+-      .irq_enable = mt6397_irq_enable,
+-      .irq_disable = mt6397_irq_disable,
++static struct irq_chip mt6323_irq_chip = {
++      .name = "mt6323-irq",
++      .irq_bus_lock = mt6323_irq_lock,
++      .irq_bus_sync_unlock = mt6323_irq_sync_unlock,
++      .irq_enable = mt6323_irq_enable,
++      .irq_disable = mt6323_irq_disable,
+ };
+-static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
++static void mt6323_irq_handle_reg(struct mt6323_chip *mt6323, int reg,
+               int irqbase)
+ {
+       unsigned int status;
+       int i, irq, ret;
+-      ret = regmap_read(mt6397->regmap, reg, &status);
++      ret = regmap_read(mt6323->regmap, reg, &status);
+       if (ret) {
+-              dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
++              dev_err(mt6323->dev, "Failed to read irq status: %d\n", ret);
+               return;
+       }
+       for (i = 0; i < 16; i++) {
+               if (status & BIT(i)) {
+-                      irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
++                      irq = irq_find_mapping(mt6323->irq_domain, irqbase + i);
+                       if (irq)
+                               handle_nested_irq(irq);
+               }
+       }
+-      regmap_write(mt6397->regmap, reg, status);
++      regmap_write(mt6323->regmap, reg, status);
+ }
+-static irqreturn_t mt6397_irq_thread(int irq, void *data)
++static irqreturn_t mt6323_irq_thread(int irq, void *data)
+ {
+-      struct mt6397_chip *mt6397 = data;
++      struct mt6323_chip *mt6323 = data;
+-      mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
+-      mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
++      mt6323_irq_handle_reg(mt6323, MT6323_INT_STATUS0, 0);
++      mt6323_irq_handle_reg(mt6323, MT6323_INT_STATUS1, 16);
+       return IRQ_HANDLED;
+ }
+-static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
++static int mt6323_irq_domain_map(struct irq_domain *d, unsigned int irq,
+                                       irq_hw_number_t hw)
+ {
+-      struct mt6397_chip *mt6397 = d->host_data;
++      struct mt6323_chip *mt6323 = d->host_data;
+-      irq_set_chip_data(irq, mt6397);
+-      irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
++      irq_set_chip_data(irq, mt6323);
++      irq_set_chip_and_handler(irq, &mt6323_irq_chip, handle_level_irq);
+       irq_set_nested_thread(irq, 1);
+ #ifdef CONFIG_ARM
+       set_irq_flags(irq, IRQF_VALID);
+@@ -133,98 +121,98 @@ static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
+       return 0;
+ }
+-static struct irq_domain_ops mt6397_irq_domain_ops = {
+-      .map = mt6397_irq_domain_map,
++static struct irq_domain_ops mt6323_irq_domain_ops = {
++      .map = mt6323_irq_domain_map,
+ };
+-static int mt6397_irq_init(struct mt6397_chip *mt6397)
++static int mt6323_irq_init(struct mt6323_chip *mt6323)
+ {
+       int ret;
+-      mutex_init(&mt6397->irqlock);
++      mutex_init(&mt6323->irqlock);
+       /* Mask all interrupt sources */
+-      regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
+-      regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
++      regmap_write(mt6323->regmap, MT6323_INT_CON0, 0x0);
++      regmap_write(mt6323->regmap, MT6323_INT_CON1, 0x0);
+-      mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
+-              MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
+-      if (!mt6397->irq_domain) {
+-              dev_err(mt6397->dev, "could not create irq domain\n");
++      mt6323->irq_domain = irq_domain_add_linear(mt6323->dev->of_node,
++              MT6323_IRQ_NR, &mt6323_irq_domain_ops, mt6323);
++      if (!mt6323->irq_domain) {
++              dev_err(mt6323->dev, "could not create irq domain\n");
+               return -ENOMEM;
+       }
+-      ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
+-              mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
++      ret = devm_request_threaded_irq(mt6323->dev, mt6323->irq, NULL,
++              mt6323_irq_thread, IRQF_ONESHOT, "mt6323-pmic", mt6323);
+       if (ret) {
+-              dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
+-                      mt6397->irq, ret);
++              dev_err(mt6323->dev, "failed to register irq=%d; err: %d\n",
++                      mt6323->irq, ret);
+               return ret;
+       }
+       return 0;
+ }
+-static int mt6397_probe(struct platform_device *pdev)
++static int mt6323_probe(struct platform_device *pdev)
+ {
+       int ret;
+-      struct mt6397_chip *mt6397;
++      struct mt6323_chip *mt6323;
+-      mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
+-      if (!mt6397)
++      mt6323 = devm_kzalloc(&pdev->dev, sizeof(*mt6323), GFP_KERNEL);
++      if (!mt6323)
+               return -ENOMEM;
+-      mt6397->dev = &pdev->dev;
++      mt6323->dev = &pdev->dev;
+       /*
+-       * mt6397 MFD is child device of soc pmic wrapper.
++       * mt6323 MFD is child device of soc pmic wrapper.
+        * Regmap is set from its parent.
+        */
+-      mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+-      if (!mt6397->regmap)
++      mt6323->regmap = dev_get_regmap(pdev->dev.parent, NULL);
++      if (!mt6323->regmap)
+               return -ENODEV;
+-      platform_set_drvdata(pdev, mt6397);
++      platform_set_drvdata(pdev, mt6323);
+-      mt6397->irq = platform_get_irq(pdev, 0);
+-      if (mt6397->irq > 0) {
+-              ret = mt6397_irq_init(mt6397);
++      mt6323->irq = platform_get_irq(pdev, 0);
++      if (mt6323->irq > 0) {
++              ret = mt6323_irq_init(mt6323);
+               if (ret)
+                       return ret;
+       }
+-      ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
+-                      ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
++      ret = mfd_add_devices(&pdev->dev, -1, mt6323_devs,
++                      ARRAY_SIZE(mt6323_devs), NULL, 0, NULL);
+       if (ret)
+               dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
+       return ret;
+ }
+-static int mt6397_remove(struct platform_device *pdev)
++static int mt6323_remove(struct platform_device *pdev)
+ {
+       mfd_remove_devices(&pdev->dev);
+       return 0;
+ }
+-static const struct of_device_id mt6397_of_match[] = {
+-      { .compatible = "mediatek,mt6397" },
++static const struct of_device_id mt6323_of_match[] = {
++      { .compatible = "mediatek,mt6323" },
+       { }
+ };
+-MODULE_DEVICE_TABLE(of, mt6397_of_match);
++MODULE_DEVICE_TABLE(of, mt6323_of_match);
+-static struct platform_driver mt6397_driver = {
+-      .probe = mt6397_probe,
+-      .remove = mt6397_remove,
++static struct platform_driver mt6323_driver = {
++      .probe = mt6323_probe,
++      .remove = mt6323_remove,
+       .driver = {
+-              .name = "mt6397",
+-              .of_match_table = of_match_ptr(mt6397_of_match),
++              .name = "mt6323",
++              .of_match_table = of_match_ptr(mt6323_of_match),
+       },
+ };
+-module_platform_driver(mt6397_driver);
++module_platform_driver(mt6323_driver);
+ MODULE_AUTHOR("Flora Fu, MediaTek");
+-MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
++MODULE_DESCRIPTION("Driver for MediaTek MT6323 PMIC");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:mt6397");
++MODULE_ALIAS("platform:mt6323");
+diff --git a/drivers/regulator/mt6323-regulator.c b/drivers/regulator/mt6323-regulator.c
+index a5b2f47..f5e3f67 100644
+--- a/drivers/regulator/mt6323-regulator.c
++++ b/drivers/regulator/mt6323-regulator.c
+@@ -16,15 +16,15 @@
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+-#include <linux/mfd/mt6397/core.h>
+-#include <linux/mfd/mt6397/registers.h>
++#include <linux/mfd/mt6323/core.h>
++#include <linux/mfd/mt6323/registers.h>
+ #include <linux/regulator/driver.h>
+ #include <linux/regulator/machine.h>
+-#include <linux/regulator/mt6397-regulator.h>
++#include <linux/regulator/mt6323-regulator.h>
+ #include <linux/regulator/of_regulator.h>
+ /*
+- * MT6397 regulators' information
++ * MT6323 regulators' information
+  *
+  * @desc: standard fields of regulator description.
+  * @qi: Mask for query enable signal status of regulators
+@@ -32,7 +32,7 @@
+  * @vselctrl_reg: Register for controlling the buck control mode.
+  * @vselctrl_mask: Mask for query buck's voltage control mode.
+  */
+-struct mt6397_regulator_info {
++struct mt6323_regulator_info {
+       struct regulator_desc desc;
+       u32 qi;
+       u32 vselon_reg;
+@@ -40,15 +40,15 @@ struct mt6397_regulator_info {
+       u32 vselctrl_mask;
+ };
+-#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg,  \
++#define MT6323_BUCK(match, vreg, min, max, step, volt_ranges, enreg,  \
+               vosel, vosel_mask, voselon, vosel_ctrl)                 \
+-[MT6397_ID_##vreg] = {                                                        \
++[MT6323_ID_##vreg] = {                                                        \
+       .desc = {                                                       \
+               .name = #vreg,                                          \
+               .of_match = of_match_ptr(match),                        \
+-              .ops = &mt6397_volt_range_ops,                          \
++              .ops = &mt6323_volt_range_ops,                          \
+               .type = REGULATOR_VOLTAGE,                              \
+-              .id = MT6397_ID_##vreg,                                 \
++              .id = MT6323_ID_##vreg,                                 \
+               .owner = THIS_MODULE,                                   \
+               .n_voltages = (max - min)/step + 1,                     \
+               .linear_ranges = volt_ranges,                           \
+@@ -64,15 +64,15 @@ struct mt6397_regulator_info {
+       .vselctrl_mask = BIT(1),                                        \
+ }
+-#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,  \
++#define MT6323_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,  \
+               vosel_mask)                                             \
+-[MT6397_ID_##vreg] = {                                                        \
++[MT6323_ID_##vreg] = {                                                        \
+       .desc = {                                                       \
+               .name = #vreg,                                          \
+               .of_match = of_match_ptr(match),                        \
+-              .ops = &mt6397_volt_table_ops,                          \
++              .ops = &mt6323_volt_table_ops,                          \
+               .type = REGULATOR_VOLTAGE,                              \
+-              .id = MT6397_ID_##vreg,                                 \
++              .id = MT6323_ID_##vreg,                                 \
+               .owner = THIS_MODULE,                                   \
+               .n_voltages = ARRAY_SIZE(ldo_volt_table),               \
+               .volt_table = ldo_volt_table,                           \
+@@ -84,14 +84,14 @@ struct mt6397_regulator_info {
+       .qi = BIT(15),                                                  \
+ }
+-#define MT6397_REG_FIXED(match, vreg, enreg, enbit, volt)             \
+-[MT6397_ID_##vreg] = {                                                        \
++#define MT6323_REG_FIXED(match, vreg, enreg, enbit, volt)             \
++[MT6323_ID_##vreg] = {                                                        \
+       .desc = {                                                       \
+               .name = #vreg,                                          \
+               .of_match = of_match_ptr(match),                        \
+-              .ops = &mt6397_volt_fixed_ops,                          \
++              .ops = &mt6323_volt_fixed_ops,                          \
+               .type = REGULATOR_VOLTAGE,                              \
+-              .id = MT6397_ID_##vreg,                                 \
++              .id = MT6323_ID_##vreg,                                 \
+               .owner = THIS_MODULE,                                   \
+               .n_voltages = 1,                                        \
+               .enable_reg = enreg,                                    \
+@@ -106,50 +106,34 @@ static const struct regulator_linear_range buck_volt_range1[] = {
+ };
+ static const struct regulator_linear_range buck_volt_range2[] = {
+-      REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
++      REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
+ };
+ static const struct regulator_linear_range buck_volt_range3[] = {
+-      REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),
++      REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
+ };
+ static const u32 ldo_volt_table1[] = {
+-      1500000, 1800000, 2500000, 2800000,
++      1800000, 3300000,
+ };
+ static const u32 ldo_volt_table2[] = {
+-      1800000, 3300000,
++      3000000, 3300000,
+ };
+ static const u32 ldo_volt_table3[] = {
+-      3000000, 3300000,
++      1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000,
+ };
+ static const u32 ldo_volt_table4[] = {
+-      1220000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+-};
+-
+-static const u32 ldo_volt_table5[] = {
+       1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+ };
+-static const u32 ldo_volt_table5_v2[] = {
+-      1200000, 1000000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+-};
+-
+-static const u32 ldo_volt_table6[] = {
+-      1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
+-};
+-
+-static const u32 ldo_volt_table7[] = {
+-      1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
+-};
+-
+-static int mt6397_get_status(struct regulator_dev *rdev)
++static int mt6323_get_status(struct regulator_dev *rdev)
+ {
+       int ret;
+       u32 regval;
+-      struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
++      struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
+       ret = regmap_read(rdev->regmap, info->desc.enable_reg, &regval);
+       if (ret != 0) {
+@@ -160,7 +144,7 @@ static int mt6397_get_status(struct regulator_dev *rdev)
+       return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
+ }
+-static struct regulator_ops mt6397_volt_range_ops = {
++static struct regulator_ops mt6323_volt_range_ops = {
+       .list_voltage = regulator_list_voltage_linear_range,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+@@ -169,10 +153,10 @@ static struct regulator_ops mt6397_volt_range_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+-      .get_status = mt6397_get_status,
++      .get_status = mt6323_get_status,
+ };
+-static struct regulator_ops mt6397_volt_table_ops = {
++static struct regulator_ops mt6323_volt_table_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .map_voltage = regulator_map_voltage_iterate,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+@@ -181,90 +165,68 @@ static struct regulator_ops mt6397_volt_table_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+-      .get_status = mt6397_get_status,
++      .get_status = mt6323_get_status,
+ };
+-static struct regulator_ops mt6397_volt_fixed_ops = {
++static struct regulator_ops mt6323_volt_fixed_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+-      .get_status = mt6397_get_status,
++      .get_status = mt6323_get_status,
+ };
+-/* The array is indexed by id(MT6397_ID_XXX) */
+-static struct mt6397_regulator_info mt6397_regulators[] = {
+-      MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
+-              buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
+-              MT6397_VCA15_CON10, MT6397_VCA15_CON5),
+-      MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
+-              buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
+-              MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
+-      MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
+-              buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
+-              0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
+-      MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
+-              buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
+-              0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
+-      MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
+-              buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
+-              MT6397_VCORE_CON10, MT6397_VCORE_CON5),
+-      MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
+-              MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
+-              MT6397_VGPU_CON10, MT6397_VGPU_CON5),
+-      MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
+-              MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
+-              MT6397_VDRM_CON10, MT6397_VDRM_CON5),
+-      MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
+-              buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
+-              MT6397_VIO18_CON10, MT6397_VIO18_CON5),
+-      MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
+-      MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
+-      MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
+-              MT6397_ANALDO_CON2, 15, MT6397_ANALDO_CON6, 0xC0),
+-      MT6397_REG_FIXED("ldo_vio28", VIO28, MT6397_DIGLDO_CON0, 14, 2800000),
+-      MT6397_REG_FIXED("ldo_vusb", VUSB, MT6397_DIGLDO_CON1, 14, 3300000),
+-      MT6397_LDO("ldo_vmc", VMC, ldo_volt_table2,
+-              MT6397_DIGLDO_CON2, 12, MT6397_DIGLDO_CON29, 0x10),
+-      MT6397_LDO("ldo_vmch", VMCH, ldo_volt_table3,
+-              MT6397_DIGLDO_CON3, 14, MT6397_DIGLDO_CON17, 0x80),
+-      MT6397_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table3,
+-              MT6397_DIGLDO_CON4, 14, MT6397_DIGLDO_CON18, 0x10),
+-      MT6397_LDO("ldo_vgp1", VGP1, ldo_volt_table4,
+-              MT6397_DIGLDO_CON5, 15, MT6397_DIGLDO_CON19, 0xE0),
+-      MT6397_LDO("ldo_vgp2", VGP2, ldo_volt_table5,
+-              MT6397_DIGLDO_CON6, 15, MT6397_DIGLDO_CON20, 0xE0),
+-      MT6397_LDO("ldo_vgp3", VGP3, ldo_volt_table5,
+-              MT6397_DIGLDO_CON7, 15, MT6397_DIGLDO_CON21, 0xE0),
+-      MT6397_LDO("ldo_vgp4", VGP4, ldo_volt_table5,
+-              MT6397_DIGLDO_CON8, 15, MT6397_DIGLDO_CON22, 0xE0),
+-      MT6397_LDO("ldo_vgp5", VGP5, ldo_volt_table6,
+-              MT6397_DIGLDO_CON9, 15, MT6397_DIGLDO_CON23, 0xE0),
+-      MT6397_LDO("ldo_vgp6", VGP6, ldo_volt_table5,
+-              MT6397_DIGLDO_CON10, 15, MT6397_DIGLDO_CON33, 0xE0),
+-      MT6397_LDO("ldo_vibr", VIBR, ldo_volt_table7,
+-              MT6397_DIGLDO_CON24, 15, MT6397_DIGLDO_CON25, 0xE00),
++/* The array is indexed by id(MT6323_ID_XXX) */
++static struct mt6323_regulator_info mt6323_regulators[] = {
++      /* buck */
++      MT6323_BUCK("buck_vproc", VPROC, 700000, 1493750, 6250,
++              buck_volt_range1, MT6323_VPROC_CON7, MT6323_VPROC_CON9, 0x7f,
++              MT6323_VPROC_CON10, MT6323_VPROC_CON5),
++      MT6323_BUCK("buck_vsys", VSYS, 1400000, 3000000, 12500,
++              buck_volt_range2, MT6323_VSYS_CON7, MT6323_VSYS_CON9,
++              0x7f, MT6323_VSYS_CON10, MT6323_VSYS_CON5),
++      MT6323_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
++              buck_volt_range3, MT6323_VPA_CON7, MT6323_VPA_CON9, 0x7f,
++              MT6323_VPA_CON10, MT6323_VPA_CON5),
++
++      /* analog */
++      MT6323_REG_FIXED("ldo_vtcxo", VTCXO, MT6323_ANALDO_CON1, 10, 2800000),
++      MT6323_REG_FIXED("ldo_va", VA, MT6323_ANALDO_CON2, 14, 2800000),
++      MT6323_REG_FIXED("ldo_vcn28", VCN28, MT6323_ANALDO_CON19, 12, 2800000),
++      MT6323_REG_FIXED("ldo_vcn33", VCN33, MT6323_ANALDO_CON21, 12, 3300000),
++
++      /* digital */
++      MT6323_REG_FIXED("ldo_vio28", VIO28, MT6323_DIGLDO_CON0, 15, 2800000),
++      MT6323_REG_FIXED("ldo_vusb", VUSB, MT6323_DIGLDO_CON2, 15, 3300000),
++      MT6323_LDO("ldo_vmc", VMC, ldo_volt_table1,
++              MT6323_DIGLDO_CON3, 12, MT6323_DIGLDO_CON24, 0x10),
++      MT6323_LDO("ldo_vmch", VMCH, ldo_volt_table2,
++              MT6323_DIGLDO_CON5, 14, MT6323_DIGLDO_CON26, 0x80),
++      MT6323_LDO("ldo_vgp1", VGP1, ldo_volt_table3,
++              MT6323_DIGLDO_CON7, 15, MT6323_DIGLDO_CON28, 0xE0),
++      MT6323_LDO("ldo_vgp2", VGP2, ldo_volt_table4,
++              MT6323_DIGLDO_CON8, 15, MT6323_DIGLDO_CON29, 0xE0),
+ };
+-static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)
++static int mt6323_set_buck_vosel_reg(struct platform_device *pdev)
+ {
+-      struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++      struct mt6323_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
+       int i;
+       u32 regval;
+-      for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
+-              if (mt6397_regulators[i].vselctrl_reg) {
+-                      if (regmap_read(mt6397->regmap,
+-                              mt6397_regulators[i].vselctrl_reg,
++      for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
++              if (mt6323_regulators[i].vselctrl_reg) {
++                      if (regmap_read(mt6323->regmap,
++                              mt6323_regulators[i].vselctrl_reg,
+                               &regval) < 0) {
+                               dev_err(&pdev->dev,
+                                       "Failed to read buck ctrl\n");
+                               return -EIO;
+                       }
+-                      if (regval & mt6397_regulators[i].vselctrl_mask) {
+-                              mt6397_regulators[i].desc.vsel_reg =
+-                              mt6397_regulators[i].vselon_reg;
++                      if (regval & mt6323_regulators[i].vselctrl_mask) {
++                              mt6323_regulators[i].desc.vsel_reg =
++                              mt6323_regulators[i].vselon_reg;
+                       }
+               }
+       }
+@@ -272,44 +234,34 @@ static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)
+       return 0;
+ }
+-static int mt6397_regulator_probe(struct platform_device *pdev)
++static int mt6323_regulator_probe(struct platform_device *pdev)
+ {
+-      struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
++      struct mt6323_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_config config = {};
+       struct regulator_dev *rdev;
+       int i;
+-      u32 reg_value, version;
++      u32 reg_value;
+       /* Query buck controller to select activated voltage register part */
+-      if (mt6397_set_buck_vosel_reg(pdev))
++      if (mt6323_set_buck_vosel_reg(pdev))
+               return -EIO;
+       /* Read PMIC chip revision to update constraints and voltage table */
+-      if (regmap_read(mt6397->regmap, MT6397_CID, &reg_value) < 0) {
++      if (regmap_read(mt6323->regmap, MT6323_CID, &reg_value) < 0) {
+               dev_err(&pdev->dev, "Failed to read Chip ID\n");
+               return -EIO;
+       }
+       dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
+-      version = (reg_value & 0xFF);
+-      switch (version) {
+-      case MT6397_REGULATOR_ID91:
+-              mt6397_regulators[MT6397_ID_VGP2].desc.volt_table =
+-              ldo_volt_table5_v2;
+-              break;
+-      default:
+-              break;
+-      }
+-
+-      for (i = 0; i < MT6397_MAX_REGULATOR; i++) {
++      for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
+               config.dev = &pdev->dev;
+-              config.driver_data = &mt6397_regulators[i];
+-              config.regmap = mt6397->regmap;
++              config.driver_data = &mt6323_regulators[i];
++              config.regmap = mt6323->regmap;
+               rdev = devm_regulator_register(&pdev->dev,
+-                              &mt6397_regulators[i].desc, &config);
++                              &mt6323_regulators[i].desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register %s\n",
+-                              mt6397_regulators[i].desc.name);
++                              mt6323_regulators[i].desc.name);
+                       return PTR_ERR(rdev);
+               }
+       }
+@@ -317,16 +269,16 @@ static int mt6397_regulator_probe(struct platform_device *pdev)
+       return 0;
+ }
+-static struct platform_driver mt6397_regulator_driver = {
++static struct platform_driver mt6323_regulator_driver = {
+       .driver = {
+-              .name = "mt6397-regulator",
++              .name = "mt6323-regulator",
+       },
+-      .probe = mt6397_regulator_probe,
++      .probe = mt6323_regulator_probe,
+ };
+-module_platform_driver(mt6397_regulator_driver);
++module_platform_driver(mt6323_regulator_driver);
+ MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");
+-MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
++MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6323 PMIC");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:mt6397-regulator");
++MODULE_ALIAS("platform:mt6323-regulator");
+diff --git a/include/linux/mfd/mt6323/core.h b/include/linux/mfd/mt6323/core.h
+index cf5265b..5bb2d32 100644
+--- a/include/linux/mfd/mt6323/core.h
++++ b/include/linux/mfd/mt6323/core.h
+@@ -12,46 +12,46 @@
+  * GNU General Public License for more details.
+  */
+-#ifndef __MFD_MT6397_CORE_H__
+-#define __MFD_MT6397_CORE_H__
++#ifndef __MFD_MT6323_CORE_H__
++#define __MFD_MT6323_CORE_H__
+-enum mt6397_irq_numbers {
+-      MT6397_IRQ_SPKL_AB = 0,
+-      MT6397_IRQ_SPKR_AB,
+-      MT6397_IRQ_SPKL,
+-      MT6397_IRQ_SPKR,
+-      MT6397_IRQ_BAT_L,
+-      MT6397_IRQ_BAT_H,
+-      MT6397_IRQ_FG_BAT_L,
+-      MT6397_IRQ_FG_BAT_H,
+-      MT6397_IRQ_WATCHDOG,
+-      MT6397_IRQ_PWRKEY,
+-      MT6397_IRQ_THR_L,
+-      MT6397_IRQ_THR_H,
+-      MT6397_IRQ_VBATON_UNDET,
+-      MT6397_IRQ_BVALID_DET,
+-      MT6397_IRQ_CHRDET,
+-      MT6397_IRQ_OV,
+-      MT6397_IRQ_LDO,
+-      MT6397_IRQ_HOMEKEY,
+-      MT6397_IRQ_ACCDET,
+-      MT6397_IRQ_AUDIO,
+-      MT6397_IRQ_RTC,
+-      MT6397_IRQ_PWRKEY_RSTB,
+-      MT6397_IRQ_HDMI_SIFM,
+-      MT6397_IRQ_HDMI_CEC,
+-      MT6397_IRQ_VCA15,
+-      MT6397_IRQ_VSRMCA15,
+-      MT6397_IRQ_VCORE,
+-      MT6397_IRQ_VGPU,
+-      MT6397_IRQ_VIO18,
+-      MT6397_IRQ_VPCA7,
+-      MT6397_IRQ_VSRMCA7,
+-      MT6397_IRQ_VDRM,
+-      MT6397_IRQ_NR,
++enum mt6323_irq_numbers {
++      MT6323_IRQ_SPKL_AB = 0,
++      MT6323_IRQ_SPKR_AB,
++      MT6323_IRQ_SPKL,
++      MT6323_IRQ_SPKR,
++      MT6323_IRQ_BAT_L,
++      MT6323_IRQ_BAT_H,
++      MT6323_IRQ_FG_BAT_L,
++      MT6323_IRQ_FG_BAT_H,
++      MT6323_IRQ_WATCHDOG,
++      MT6323_IRQ_PWRKEY,
++      MT6323_IRQ_THR_L,
++      MT6323_IRQ_THR_H,
++      MT6323_IRQ_VBATON_UNDET,
++      MT6323_IRQ_BVALID_DET,
++      MT6323_IRQ_CHRDET,
++      MT6323_IRQ_OV,
++      MT6323_IRQ_LDO,
++      MT6323_IRQ_HOMEKEY,
++      MT6323_IRQ_ACCDET,
++      MT6323_IRQ_AUDIO,
++      MT6323_IRQ_RTC,
++      MT6323_IRQ_PWRKEY_RSTB,
++      MT6323_IRQ_HDMI_SIFM,
++      MT6323_IRQ_HDMI_CEC,
++      MT6323_IRQ_VCA15,
++      MT6323_IRQ_VSRMCA15,
++      MT6323_IRQ_VCORE,
++      MT6323_IRQ_VGPU,
++      MT6323_IRQ_VIO18,
++      MT6323_IRQ_VPCA7,
++      MT6323_IRQ_VSRMCA7,
++      MT6323_IRQ_VDRM,
++      MT6323_IRQ_NR,
+ };
+-struct mt6397_chip {
++struct mt6323_chip {
+       struct device *dev;
+       struct regmap *regmap;
+       int irq;
+@@ -61,4 +61,4 @@ struct mt6397_chip {
+       u16 irq_masks_cache[2];
+ };
+-#endif /* __MFD_MT6397_CORE_H__ */
++#endif /* __MFD_MT6323_CORE_H__ */
+diff --git a/include/linux/mfd/mt6323/registers.h b/include/linux/mfd/mt6323/registers.h
+index f23a0a6..4ee5e1f0 100644
+--- a/include/linux/mfd/mt6323/registers.h
++++ b/include/linux/mfd/mt6323/registers.h
+@@ -1,6 +1,5 @@
+ /*
+- * Copyright (c) 2014 MediaTek Inc.
+- * Author: Flora Fu, MediaTek
++ * Copyright (c) 2015 - John Crispin <blogic@openwrt.org>
+  *
+  * 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
+@@ -12,351 +11,403 @@
+  * GNU General Public License for more details.
+  */
+-#ifndef __MFD_MT6397_REGISTERS_H__
+-#define __MFD_MT6397_REGISTERS_H__
++#ifndef __MFD_MT6323_REGISTERS_H__
++#define __MFD_MT6323_REGISTERS_H__
+ /* PMIC Registers */
+-#define MT6397_CID                    0x0100
+-#define MT6397_TOP_CKPDN              0x0102
+-#define MT6397_TOP_CKPDN_SET          0x0104
+-#define MT6397_TOP_CKPDN_CLR          0x0106
+-#define MT6397_TOP_CKPDN2             0x0108
+-#define MT6397_TOP_CKPDN2_SET         0x010A
+-#define MT6397_TOP_CKPDN2_CLR         0x010C
+-#define MT6397_TOP_GPIO_CKPDN         0x010E
+-#define MT6397_TOP_RST_CON            0x0114
+-#define MT6397_WRP_CKPDN              0x011A
+-#define MT6397_WRP_RST_CON            0x0120
+-#define MT6397_TOP_RST_MISC           0x0126
+-#define MT6397_TOP_CKCON1             0x0128
+-#define MT6397_TOP_CKCON2             0x012A
+-#define MT6397_TOP_CKTST1             0x012C
+-#define MT6397_TOP_CKTST2             0x012E
+-#define MT6397_OC_DEG_EN              0x0130
+-#define MT6397_OC_CTL0                        0x0132
+-#define MT6397_OC_CTL1                        0x0134
+-#define MT6397_OC_CTL2                        0x0136
+-#define MT6397_INT_RSV                        0x0138
+-#define MT6397_TEST_CON0              0x013A
+-#define MT6397_TEST_CON1              0x013C
+-#define MT6397_STATUS0                        0x013E
+-#define MT6397_STATUS1                        0x0140
+-#define MT6397_PGSTATUS                       0x0142
+-#define MT6397_CHRSTATUS              0x0144
+-#define MT6397_OCSTATUS0              0x0146
+-#define MT6397_OCSTATUS1              0x0148
+-#define MT6397_OCSTATUS2              0x014A
+-#define MT6397_HDMI_PAD_IE            0x014C
+-#define MT6397_TEST_OUT_L             0x014E
+-#define MT6397_TEST_OUT_H             0x0150
+-#define MT6397_TDSEL_CON              0x0152
+-#define MT6397_RDSEL_CON              0x0154
+-#define MT6397_GPIO_SMT_CON0          0x0156
+-#define MT6397_GPIO_SMT_CON1          0x0158
+-#define MT6397_GPIO_SMT_CON2          0x015A
+-#define MT6397_GPIO_SMT_CON3          0x015C
+-#define MT6397_DRV_CON0                       0x015E
+-#define MT6397_DRV_CON1                       0x0160
+-#define MT6397_DRV_CON2                       0x0162
+-#define MT6397_DRV_CON3                       0x0164
+-#define MT6397_DRV_CON4                       0x0166
+-#define MT6397_DRV_CON5                       0x0168
+-#define MT6397_DRV_CON6                       0x016A
+-#define MT6397_DRV_CON7                       0x016C
+-#define MT6397_DRV_CON8                       0x016E
+-#define MT6397_DRV_CON9                       0x0170
+-#define MT6397_DRV_CON10              0x0172
+-#define MT6397_DRV_CON11              0x0174
+-#define MT6397_DRV_CON12              0x0176
+-#define MT6397_INT_CON0                       0x0178
+-#define MT6397_INT_CON1                       0x017E
+-#define MT6397_INT_STATUS0            0x0184
+-#define MT6397_INT_STATUS1            0x0186
+-#define MT6397_FQMTR_CON0             0x0188
+-#define MT6397_FQMTR_CON1             0x018A
+-#define MT6397_FQMTR_CON2             0x018C
+-#define MT6397_EFUSE_DOUT_0_15                0x01C4
+-#define MT6397_EFUSE_DOUT_16_31               0x01C6
+-#define MT6397_EFUSE_DOUT_32_47               0x01C8
+-#define MT6397_EFUSE_DOUT_48_63               0x01CA
+-#define MT6397_SPI_CON                        0x01CC
+-#define MT6397_TOP_CKPDN3             0x01CE
+-#define MT6397_TOP_CKCON3             0x01D4
+-#define MT6397_EFUSE_DOUT_64_79               0x01D6
+-#define MT6397_EFUSE_DOUT_80_95               0x01D8
+-#define MT6397_EFUSE_DOUT_96_111      0x01DA
+-#define MT6397_EFUSE_DOUT_112_127     0x01DC
+-#define MT6397_EFUSE_DOUT_128_143     0x01DE
+-#define MT6397_EFUSE_DOUT_144_159     0x01E0
+-#define MT6397_EFUSE_DOUT_160_175     0x01E2
+-#define MT6397_EFUSE_DOUT_176_191     0x01E4
+-#define MT6397_EFUSE_DOUT_192_207     0x01E6
+-#define MT6397_EFUSE_DOUT_208_223     0x01E8
+-#define MT6397_EFUSE_DOUT_224_239     0x01EA
+-#define MT6397_EFUSE_DOUT_240_255     0x01EC
+-#define MT6397_EFUSE_DOUT_256_271     0x01EE
+-#define MT6397_EFUSE_DOUT_272_287     0x01F0
+-#define MT6397_EFUSE_DOUT_288_300     0x01F2
+-#define MT6397_EFUSE_DOUT_304_319     0x01F4
+-#define MT6397_BUCK_CON0              0x0200
+-#define MT6397_BUCK_CON1              0x0202
+-#define MT6397_BUCK_CON2              0x0204
+-#define MT6397_BUCK_CON3              0x0206
+-#define MT6397_BUCK_CON4              0x0208
+-#define MT6397_BUCK_CON5              0x020A
+-#define MT6397_BUCK_CON6              0x020C
+-#define MT6397_BUCK_CON7              0x020E
+-#define MT6397_BUCK_CON8              0x0210
+-#define MT6397_BUCK_CON9              0x0212
+-#define MT6397_VCA15_CON0             0x0214
+-#define MT6397_VCA15_CON1             0x0216
+-#define MT6397_VCA15_CON2             0x0218
+-#define MT6397_VCA15_CON3             0x021A
+-#define MT6397_VCA15_CON4             0x021C
+-#define MT6397_VCA15_CON5             0x021E
+-#define MT6397_VCA15_CON6             0x0220
+-#define MT6397_VCA15_CON7             0x0222
+-#define MT6397_VCA15_CON8             0x0224
+-#define MT6397_VCA15_CON9             0x0226
+-#define MT6397_VCA15_CON10            0x0228
+-#define MT6397_VCA15_CON11            0x022A
+-#define MT6397_VCA15_CON12            0x022C
+-#define MT6397_VCA15_CON13            0x022E
+-#define MT6397_VCA15_CON14            0x0230
+-#define MT6397_VCA15_CON15            0x0232
+-#define MT6397_VCA15_CON16            0x0234
+-#define MT6397_VCA15_CON17            0x0236
+-#define MT6397_VCA15_CON18            0x0238
+-#define MT6397_VSRMCA15_CON0          0x023A
+-#define MT6397_VSRMCA15_CON1          0x023C
+-#define MT6397_VSRMCA15_CON2          0x023E
+-#define MT6397_VSRMCA15_CON3          0x0240
+-#define MT6397_VSRMCA15_CON4          0x0242
+-#define MT6397_VSRMCA15_CON5          0x0244
+-#define MT6397_VSRMCA15_CON6          0x0246
+-#define MT6397_VSRMCA15_CON7          0x0248
+-#define MT6397_VSRMCA15_CON8          0x024A
+-#define MT6397_VSRMCA15_CON9          0x024C
+-#define MT6397_VSRMCA15_CON10         0x024E
+-#define MT6397_VSRMCA15_CON11         0x0250
+-#define MT6397_VSRMCA15_CON12         0x0252
+-#define MT6397_VSRMCA15_CON13         0x0254
+-#define MT6397_VSRMCA15_CON14         0x0256
+-#define MT6397_VSRMCA15_CON15         0x0258
+-#define MT6397_VSRMCA15_CON16         0x025A
+-#define MT6397_VSRMCA15_CON17         0x025C
+-#define MT6397_VSRMCA15_CON18         0x025E
+-#define MT6397_VSRMCA15_CON19         0x0260
+-#define MT6397_VSRMCA15_CON20         0x0262
+-#define MT6397_VSRMCA15_CON21         0x0264
+-#define MT6397_VCORE_CON0             0x0266
+-#define MT6397_VCORE_CON1             0x0268
+-#define MT6397_VCORE_CON2             0x026A
+-#define MT6397_VCORE_CON3             0x026C
+-#define MT6397_VCORE_CON4             0x026E
+-#define MT6397_VCORE_CON5             0x0270
+-#define MT6397_VCORE_CON6             0x0272
+-#define MT6397_VCORE_CON7             0x0274
+-#define MT6397_VCORE_CON8             0x0276
+-#define MT6397_VCORE_CON9             0x0278
+-#define MT6397_VCORE_CON10            0x027A
+-#define MT6397_VCORE_CON11            0x027C
+-#define MT6397_VCORE_CON12            0x027E
+-#define MT6397_VCORE_CON13            0x0280
+-#define MT6397_VCORE_CON14            0x0282
+-#define MT6397_VCORE_CON15            0x0284
+-#define MT6397_VCORE_CON16            0x0286
+-#define MT6397_VCORE_CON17            0x0288
+-#define MT6397_VCORE_CON18            0x028A
+-#define MT6397_VGPU_CON0              0x028C
+-#define MT6397_VGPU_CON1              0x028E
+-#define MT6397_VGPU_CON2              0x0290
+-#define MT6397_VGPU_CON3              0x0292
+-#define MT6397_VGPU_CON4              0x0294
+-#define MT6397_VGPU_CON5              0x0296
+-#define MT6397_VGPU_CON6              0x0298
+-#define MT6397_VGPU_CON7              0x029A
+-#define MT6397_VGPU_CON8              0x029C
+-#define MT6397_VGPU_CON9              0x029E
+-#define MT6397_VGPU_CON10             0x02A0
+-#define MT6397_VGPU_CON11             0x02A2
+-#define MT6397_VGPU_CON12             0x02A4
+-#define MT6397_VGPU_CON13             0x02A6
+-#define MT6397_VGPU_CON14             0x02A8
+-#define MT6397_VGPU_CON15             0x02AA
+-#define MT6397_VGPU_CON16             0x02AC
+-#define MT6397_VGPU_CON17             0x02AE
+-#define MT6397_VGPU_CON18             0x02B0
+-#define MT6397_VIO18_CON0             0x0300
+-#define MT6397_VIO18_CON1             0x0302
+-#define MT6397_VIO18_CON2             0x0304
+-#define MT6397_VIO18_CON3             0x0306
+-#define MT6397_VIO18_CON4             0x0308
+-#define MT6397_VIO18_CON5             0x030A
+-#define MT6397_VIO18_CON6             0x030C
+-#define MT6397_VIO18_CON7             0x030E
+-#define MT6397_VIO18_CON8             0x0310
+-#define MT6397_VIO18_CON9             0x0312
+-#define MT6397_VIO18_CON10            0x0314
+-#define MT6397_VIO18_CON11            0x0316
+-#define MT6397_VIO18_CON12            0x0318
+-#define MT6397_VIO18_CON13            0x031A
+-#define MT6397_VIO18_CON14            0x031C
+-#define MT6397_VIO18_CON15            0x031E
+-#define MT6397_VIO18_CON16            0x0320
+-#define MT6397_VIO18_CON17            0x0322
+-#define MT6397_VIO18_CON18            0x0324
+-#define MT6397_VPCA7_CON0             0x0326
+-#define MT6397_VPCA7_CON1             0x0328
+-#define MT6397_VPCA7_CON2             0x032A
+-#define MT6397_VPCA7_CON3             0x032C
+-#define MT6397_VPCA7_CON4             0x032E
+-#define MT6397_VPCA7_CON5             0x0330
+-#define MT6397_VPCA7_CON6             0x0332
+-#define MT6397_VPCA7_CON7             0x0334
+-#define MT6397_VPCA7_CON8             0x0336
+-#define MT6397_VPCA7_CON9             0x0338
+-#define MT6397_VPCA7_CON10            0x033A
+-#define MT6397_VPCA7_CON11            0x033C
+-#define MT6397_VPCA7_CON12            0x033E
+-#define MT6397_VPCA7_CON13            0x0340
+-#define MT6397_VPCA7_CON14            0x0342
+-#define MT6397_VPCA7_CON15            0x0344
+-#define MT6397_VPCA7_CON16            0x0346
+-#define MT6397_VPCA7_CON17            0x0348
+-#define MT6397_VPCA7_CON18            0x034A
+-#define MT6397_VSRMCA7_CON0           0x034C
+-#define MT6397_VSRMCA7_CON1           0x034E
+-#define MT6397_VSRMCA7_CON2           0x0350
+-#define MT6397_VSRMCA7_CON3           0x0352
+-#define MT6397_VSRMCA7_CON4           0x0354
+-#define MT6397_VSRMCA7_CON5           0x0356
+-#define MT6397_VSRMCA7_CON6           0x0358
+-#define MT6397_VSRMCA7_CON7           0x035A
+-#define MT6397_VSRMCA7_CON8           0x035C
+-#define MT6397_VSRMCA7_CON9           0x035E
+-#define MT6397_VSRMCA7_CON10          0x0360
+-#define MT6397_VSRMCA7_CON11          0x0362
+-#define MT6397_VSRMCA7_CON12          0x0364
+-#define MT6397_VSRMCA7_CON13          0x0366
+-#define MT6397_VSRMCA7_CON14          0x0368
+-#define MT6397_VSRMCA7_CON15          0x036A
+-#define MT6397_VSRMCA7_CON16          0x036C
+-#define MT6397_VSRMCA7_CON17          0x036E
+-#define MT6397_VSRMCA7_CON18          0x0370
+-#define MT6397_VSRMCA7_CON19          0x0372
+-#define MT6397_VSRMCA7_CON20          0x0374
+-#define MT6397_VSRMCA7_CON21          0x0376
+-#define MT6397_VDRM_CON0              0x0378
+-#define MT6397_VDRM_CON1              0x037A
+-#define MT6397_VDRM_CON2              0x037C
+-#define MT6397_VDRM_CON3              0x037E
+-#define MT6397_VDRM_CON4              0x0380
+-#define MT6397_VDRM_CON5              0x0382
+-#define MT6397_VDRM_CON6              0x0384
+-#define MT6397_VDRM_CON7              0x0386
+-#define MT6397_VDRM_CON8              0x0388
+-#define MT6397_VDRM_CON9              0x038A
+-#define MT6397_VDRM_CON10             0x038C
+-#define MT6397_VDRM_CON11             0x038E
+-#define MT6397_VDRM_CON12             0x0390
+-#define MT6397_VDRM_CON13             0x0392
+-#define MT6397_VDRM_CON14             0x0394
+-#define MT6397_VDRM_CON15             0x0396
+-#define MT6397_VDRM_CON16             0x0398
+-#define MT6397_VDRM_CON17             0x039A
+-#define MT6397_VDRM_CON18             0x039C
+-#define MT6397_BUCK_K_CON0            0x039E
+-#define MT6397_BUCK_K_CON1            0x03A0
+-#define MT6397_ANALDO_CON0            0x0400
+-#define MT6397_ANALDO_CON1            0x0402
+-#define MT6397_ANALDO_CON2            0x0404
+-#define MT6397_ANALDO_CON3            0x0406
+-#define MT6397_ANALDO_CON4            0x0408
+-#define MT6397_ANALDO_CON5            0x040A
+-#define MT6397_ANALDO_CON6            0x040C
+-#define MT6397_ANALDO_CON7            0x040E
+-#define MT6397_DIGLDO_CON0            0x0410
+-#define MT6397_DIGLDO_CON1            0x0412
+-#define MT6397_DIGLDO_CON2            0x0414
+-#define MT6397_DIGLDO_CON3            0x0416
+-#define MT6397_DIGLDO_CON4            0x0418
+-#define MT6397_DIGLDO_CON5            0x041A
+-#define MT6397_DIGLDO_CON6            0x041C
+-#define MT6397_DIGLDO_CON7            0x041E
+-#define MT6397_DIGLDO_CON8            0x0420
+-#define MT6397_DIGLDO_CON9            0x0422
+-#define MT6397_DIGLDO_CON10           0x0424
+-#define MT6397_DIGLDO_CON11           0x0426
+-#define MT6397_DIGLDO_CON12           0x0428
+-#define MT6397_DIGLDO_CON13           0x042A
+-#define MT6397_DIGLDO_CON14           0x042C
+-#define MT6397_DIGLDO_CON15           0x042E
+-#define MT6397_DIGLDO_CON16           0x0430
+-#define MT6397_DIGLDO_CON17           0x0432
+-#define MT6397_DIGLDO_CON18           0x0434
+-#define MT6397_DIGLDO_CON19           0x0436
+-#define MT6397_DIGLDO_CON20           0x0438
+-#define MT6397_DIGLDO_CON21           0x043A
+-#define MT6397_DIGLDO_CON22           0x043C
+-#define MT6397_DIGLDO_CON23           0x043E
+-#define MT6397_DIGLDO_CON24           0x0440
+-#define MT6397_DIGLDO_CON25           0x0442
+-#define MT6397_DIGLDO_CON26           0x0444
+-#define MT6397_DIGLDO_CON27           0x0446
+-#define MT6397_DIGLDO_CON28           0x0448
+-#define MT6397_DIGLDO_CON29           0x044A
+-#define MT6397_DIGLDO_CON30           0x044C
+-#define MT6397_DIGLDO_CON31           0x044E
+-#define MT6397_DIGLDO_CON32           0x0450
+-#define MT6397_DIGLDO_CON33           0x045A
+-#define MT6397_SPK_CON0                       0x0600
+-#define MT6397_SPK_CON1                       0x0602
+-#define MT6397_SPK_CON2                       0x0604
+-#define MT6397_SPK_CON3                       0x0606
+-#define MT6397_SPK_CON4                       0x0608
+-#define MT6397_SPK_CON5                       0x060A
+-#define MT6397_SPK_CON6                       0x060C
+-#define MT6397_SPK_CON7                       0x060E
+-#define MT6397_SPK_CON8                       0x0610
+-#define MT6397_SPK_CON9                       0x0612
+-#define MT6397_SPK_CON10              0x0614
+-#define MT6397_SPK_CON11              0x0616
+-#define MT6397_AUDDAC_CON0            0x0700
+-#define MT6397_AUDBUF_CFG0            0x0702
+-#define MT6397_AUDBUF_CFG1            0x0704
+-#define MT6397_AUDBUF_CFG2            0x0706
+-#define MT6397_AUDBUF_CFG3            0x0708
+-#define MT6397_AUDBUF_CFG4            0x070A
+-#define MT6397_IBIASDIST_CFG0         0x070C
+-#define MT6397_AUDACCDEPOP_CFG0               0x070E
+-#define MT6397_AUD_IV_CFG0            0x0710
+-#define MT6397_AUDCLKGEN_CFG0         0x0712
+-#define MT6397_AUDLDO_CFG0            0x0714
+-#define MT6397_AUDLDO_CFG1            0x0716
+-#define MT6397_AUDNVREGGLB_CFG0               0x0718
+-#define MT6397_AUD_NCP0                       0x071A
+-#define MT6397_AUDPREAMP_CON0         0x071C
+-#define MT6397_AUDADC_CON0            0x071E
+-#define MT6397_AUDADC_CON1            0x0720
+-#define MT6397_AUDADC_CON2            0x0722
+-#define MT6397_AUDADC_CON3            0x0724
+-#define MT6397_AUDADC_CON4            0x0726
+-#define MT6397_AUDADC_CON5            0x0728
+-#define MT6397_AUDADC_CON6            0x072A
+-#define MT6397_AUDDIGMI_CON0          0x072C
+-#define MT6397_AUDLSBUF_CON0          0x072E
+-#define MT6397_AUDLSBUF_CON1          0x0730
+-#define MT6397_AUDENCSPARE_CON0               0x0732
+-#define MT6397_AUDENCCLKSQ_CON0               0x0734
+-#define MT6397_AUDPREAMPGAIN_CON0     0x0736
+-#define MT6397_ZCD_CON0                       0x0738
+-#define MT6397_ZCD_CON1                       0x073A
+-#define MT6397_ZCD_CON2                       0x073C
+-#define MT6397_ZCD_CON3                       0x073E
+-#define MT6397_ZCD_CON4                       0x0740
+-#define MT6397_ZCD_CON5                       0x0742
+-#define MT6397_NCP_CLKDIV_CON0                0x0744
+-#define MT6397_NCP_CLKDIV_CON1                0x0746
++#define MT6323_CHR_CON0                       0x0000
++#define MT6323_CHR_CON1                       0x0002
++#define MT6323_CHR_CON2                       0x0004
++#define MT6323_CHR_CON3                       0x0006
++#define MT6323_CHR_CON4                       0x0008
++#define MT6323_CHR_CON5                       0x000A
++#define MT6323_CHR_CON6                       0x000C
++#define MT6323_CHR_CON7                       0x000E
++#define MT6323_CHR_CON8                       0x0010
++#define MT6323_CHR_CON9                       0x0012
++#define MT6323_CHR_CON10              0x0014
++#define MT6323_CHR_CON11              0x0016
++#define MT6323_CHR_CON12              0x0018
++#define MT6323_CHR_CON13              0x001A
++#define MT6323_CHR_CON14              0x001C
++#define MT6323_CHR_CON15              0x001E
++#define MT6323_CHR_CON16              0x0020
++#define MT6323_CHR_CON17              0x0022
++#define MT6323_CHR_CON18              0x0024
++#define MT6323_CHR_CON19              0x0026
++#define MT6323_CHR_CON20              0x0028
++#define MT6323_CHR_CON21              0x002A
++#define MT6323_CHR_CON22              0x002C
++#define MT6323_CHR_CON23              0x002E
++#define MT6323_CHR_CON24              0x0030
++#define MT6323_CHR_CON25              0x0032
++#define MT6323_CHR_CON26              0x0034
++#define MT6323_CHR_CON27              0x0036
++#define MT6323_CHR_CON28              0x0038
++#define MT6323_CHR_CON29              0x003A
++#define MT6323_STRUP_CON0             0x003C
++#define MT6323_STRUP_CON2             0x003E
++#define MT6323_STRUP_CON3             0x0040
++#define MT6323_STRUP_CON4             0x0042
++#define MT6323_STRUP_CON5             0x0044
++#define MT6323_STRUP_CON6             0x0046
++#define MT6323_STRUP_CON7             0x0048
++#define MT6323_STRUP_CON8             0x004A
++#define MT6323_STRUP_CON9             0x004C
++#define MT6323_STRUP_CON10            0x004E
++#define MT6323_STRUP_CON11            0x0050
++#define MT6323_SPK_CON0                       0x0052
++#define MT6323_SPK_CON1                       0x0054
++#define MT6323_SPK_CON2                       0x0056
++#define MT6323_SPK_CON6                       0x005E
++#define MT6323_SPK_CON7                       0x0060
++#define MT6323_SPK_CON8                       0x0062
++#define MT6323_SPK_CON9                       0x0064
++#define MT6323_SPK_CON10              0x0066
++#define MT6323_SPK_CON11              0x0068
++#define MT6323_SPK_CON12              0x006A
++#define MT6323_CID                    0x0100
++#define MT6323_TOP_CKPDN0             0x0102
++#define MT6323_TOP_CKPDN0_SET         0x0104
++#define MT6323_TOP_CKPDN0_CLR         0x0106
++#define MT6323_TOP_CKPDN1             0x0108
++#define MT6323_TOP_CKPDN1_SET         0x010A
++#define MT6323_TOP_CKPDN1_CLR         0x010C
++#define MT6323_TOP_CKPDN2             0x010E
++#define MT6323_TOP_CKPDN2_SET         0x0110
++#define MT6323_TOP_CKPDN2_CLR         0x0112
++#define MT6323_TOP_RST_CON            0x0114
++#define MT6323_TOP_RST_CON_SET                0x0116
++#define MT6323_TOP_RST_CON_CLR                0x0118
++#define MT6323_TOP_RST_MISC           0x011A
++#define MT6323_TOP_RST_MISC_SET               0x011C
++#define MT6323_TOP_RST_MISC_CLR               0x011E
++#define MT6323_TOP_CKCON0             0x0120
++#define MT6323_TOP_CKCON0_SET         0x0122
++#define MT6323_TOP_CKCON0_CLR         0x0124
++#define MT6323_TOP_CKCON1             0x0126
++#define MT6323_TOP_CKCON1_SET         0x0128
++#define MT6323_TOP_CKCON1_CLR         0x012A
++#define MT6323_TOP_CKTST0             0x012C
++#define MT6323_TOP_CKTST1             0x012E
++#define MT6323_TOP_CKTST2             0x0130
++#define MT6323_TEST_OUT                       0x0132
++#define MT6323_TEST_CON0              0x0134
++#define MT6323_TEST_CON1              0x0136
++#define MT6323_EN_STATUS0             0x0138
++#define MT6323_EN_STATUS1             0x013A
++#define MT6323_OCSTATUS0              0x013C
++#define MT6323_OCSTATUS1              0x013E
++#define MT6323_PGSTATUS                       0x0140
++#define MT6323_CHRSTATUS              0x0142
++#define MT6323_TDSEL_CON              0x0144
++#define MT6323_RDSEL_CON              0x0146
++#define MT6323_SMT_CON0                       0x0148
++#define MT6323_SMT_CON1                       0x014A
++#define MT6323_SMT_CON2                       0x014C
++#define MT6323_SMT_CON3                       0x014E
++#define MT6323_SMT_CON4                       0x0150
++#define MT6323_DRV_CON0                       0x0152
++#define MT6323_DRV_CON1                       0x0154
++#define MT6323_DRV_CON2                       0x0156
++#define MT6323_DRV_CON3                       0x0158
++#define MT6323_DRV_CON4                       0x015A
++#define MT6323_SIMLS1_CON             0x015C
++#define MT6323_SIMLS2_CON             0x015E
++#define MT6323_INT_CON0                       0x0160
++#define MT6323_INT_CON0_SET           0x0162
++#define MT6323_INT_CON0_CLR           0x0164
++#define MT6323_INT_CON1                       0x0166
++#define MT6323_INT_CON1_SET           0x0168
++#define MT6323_INT_CON1_CLR           0x016A
++#define MT6323_INT_MISC_CON           0x016C
++#define MT6323_INT_MISC_CON_SET               0x016E
++#define MT6323_INT_MISC_CON_CLR               0x0170
++#define MT6323_INT_STATUS0            0x0172
++#define MT6323_INT_STATUS1            0x0174
++#define MT6323_OC_GEAR_0              0x0176
++#define MT6323_OC_GEAR_1              0x0178
++#define MT6323_OC_GEAR_2              0x017A
++#define MT6323_OC_CTL_VPROC           0x017C
++#define MT6323_OC_CTL_VSYS            0x017E
++#define MT6323_OC_CTL_VPA             0x0180
++#define MT6323_FQMTR_CON0             0x0182
++#define MT6323_FQMTR_CON1             0x0184
++#define MT6323_FQMTR_CON2             0x0186
++#define MT6323_RG_SPI_CON             0x0188
++#define MT6323_DEW_DIO_EN             0x018A
++#define MT6323_DEW_READ_TEST          0x018C
++#define MT6323_DEW_WRITE_TEST         0x018E
++#define MT6323_DEW_CRC_SWRST          0x0190
++#define MT6323_DEW_CRC_EN             0x0192
++#define MT6323_DEW_CRC_VAL            0x0194
++#define MT6323_DEW_DBG_MON_SEL                0x0196
++#define MT6323_DEW_CIPHER_KEY_SEL     0x0198
++#define MT6323_DEW_CIPHER_IV_SEL      0x019A
++#define MT6323_DEW_CIPHER_EN          0x019C
++#define MT6323_DEW_CIPHER_RDY         0x019E
++#define MT6323_DEW_CIPHER_MODE                0x01A0
++#define MT6323_DEW_CIPHER_SWRST               0x01A2
++#define MT6323_DEW_RDDMY_NO           0x01A4
++#define MT6323_DEW_RDATA_DLY_SEL      0x01A6
++#define MT6323_BUCK_CON0              0x0200
++#define MT6323_BUCK_CON1              0x0202
++#define MT6323_BUCK_CON2              0x0204
++#define MT6323_BUCK_CON3              0x0206
++#define MT6323_BUCK_CON4              0x0208
++#define MT6323_BUCK_CON5              0x020A
++#define MT6323_VPROC_CON0             0x020C
++#define MT6323_VPROC_CON1             0x020E
++#define MT6323_VPROC_CON2             0x0210
++#define MT6323_VPROC_CON3             0x0212
++#define MT6323_VPROC_CON4             0x0214
++#define MT6323_VPROC_CON5             0x0216
++#define MT6323_VPROC_CON7             0x021A
++#define MT6323_VPROC_CON8             0x021C
++#define MT6323_VPROC_CON9             0x021E
++#define MT6323_VPROC_CON10            0x0220
++#define MT6323_VPROC_CON11            0x0222
++#define MT6323_VPROC_CON12            0x0224
++#define MT6323_VPROC_CON13            0x0226
++#define MT6323_VPROC_CON14            0x0228
++#define MT6323_VPROC_CON15            0x022A
++#define MT6323_VPROC_CON18            0x0230
++#define MT6323_VSYS_CON0              0x0232
++#define MT6323_VSYS_CON1              0x0234
++#define MT6323_VSYS_CON2              0x0236
++#define MT6323_VSYS_CON3              0x0238
++#define MT6323_VSYS_CON4              0x023A
++#define MT6323_VSYS_CON5              0x023C
++#define MT6323_VSYS_CON7              0x0240
++#define MT6323_VSYS_CON8              0x0242
++#define MT6323_VSYS_CON9              0x0244
++#define MT6323_VSYS_CON10             0x0246
++#define MT6323_VSYS_CON11             0x0248
++#define MT6323_VSYS_CON12             0x024A
++#define MT6323_VSYS_CON13             0x024C
++#define MT6323_VSYS_CON14             0x024E
++#define MT6323_VSYS_CON15             0x0250
++#define MT6323_VSYS_CON18             0x0256
++#define MT6323_VPA_CON0                       0x0300
++#define MT6323_VPA_CON1                       0x0302
++#define MT6323_VPA_CON2                       0x0304
++#define MT6323_VPA_CON3                       0x0306
++#define MT6323_VPA_CON4                       0x0308
++#define MT6323_VPA_CON5                       0x030A
++#define MT6323_VPA_CON7                       0x030E
++#define MT6323_VPA_CON8                       0x0310
++#define MT6323_VPA_CON9                       0x0312
++#define MT6323_VPA_CON10              0x0314
++#define MT6323_VPA_CON11              0x0316
++#define MT6323_VPA_CON12              0x0318
++#define MT6323_VPA_CON14              0x031C
++#define MT6323_VPA_CON16              0x0320
++#define MT6323_VPA_CON17              0x0322
++#define MT6323_VPA_CON18              0x0324
++#define MT6323_VPA_CON19              0x0326
++#define MT6323_VPA_CON20              0x0328
++#define MT6323_BUCK_K_CON0            0x032A
++#define MT6323_BUCK_K_CON1            0x032C
++#define MT6323_BUCK_K_CON2            0x032E
++#define MT6323_ISINK0_CON0            0x0330
++#define MT6323_ISINK0_CON1            0x0332
++#define MT6323_ISINK0_CON2            0x0334
++#define MT6323_ISINK0_CON3            0x0336
++#define MT6323_ISINK1_CON0            0x0338
++#define MT6323_ISINK1_CON1            0x033A
++#define MT6323_ISINK1_CON2            0x033C
++#define MT6323_ISINK1_CON3            0x033E
++#define MT6323_ISINK2_CON0            0x0340
++#define MT6323_ISINK2_CON1            0x0342
++#define MT6323_ISINK2_CON2            0x0344
++#define MT6323_ISINK2_CON3            0x0346
++#define MT6323_ISINK3_CON0            0x0348
++#define MT6323_ISINK3_CON1            0x034A
++#define MT6323_ISINK3_CON2            0x034C
++#define MT6323_ISINK3_CON3            0x034E
++#define MT6323_ISINK_ANA0             0x0350
++#define MT6323_ISINK_ANA1             0x0352
++#define MT6323_ISINK_PHASE_DLY                0x0354
++#define MT6323_ISINK_EN_CTRL          0x0356
++#define MT6323_ANALDO_CON0            0x0400
++#define MT6323_ANALDO_CON1            0x0402
++#define MT6323_ANALDO_CON2            0x0404
++#define MT6323_ANALDO_CON3            0x0406
++#define MT6323_ANALDO_CON4            0x0408
++#define MT6323_ANALDO_CON5            0x040A
++#define MT6323_ANALDO_CON6            0x040C
++#define MT6323_ANALDO_CON7            0x040E
++#define MT6323_ANALDO_CON8            0x0410
++#define MT6323_ANALDO_CON10           0x0412
++#define MT6323_ANALDO_CON15           0x0414
++#define MT6323_ANALDO_CON16           0x0416
++#define MT6323_ANALDO_CON17           0x0418
++#define MT6323_ANALDO_CON18           0x041A
++#define MT6323_ANALDO_CON19           0x041C
++#define MT6323_ANALDO_CON20           0x041E
++#define MT6323_ANALDO_CON21           0x0420
++#define MT6323_DIGLDO_CON0            0x0500
++#define MT6323_DIGLDO_CON2            0x0502
++#define MT6323_DIGLDO_CON3            0x0504
++#define MT6323_DIGLDO_CON5            0x0506
++#define MT6323_DIGLDO_CON6            0x0508
++#define MT6323_DIGLDO_CON7            0x050A
++#define MT6323_DIGLDO_CON8            0x050C
++#define MT6323_DIGLDO_CON9            0x050E
++#define MT6323_DIGLDO_CON10           0x0510
++#define MT6323_DIGLDO_CON11           0x0512
++#define MT6323_DIGLDO_CON12           0x0514
++#define MT6323_DIGLDO_CON13           0x0516
++#define MT6323_DIGLDO_CON14           0x0518
++#define MT6323_DIGLDO_CON15           0x051A
++#define MT6323_DIGLDO_CON16           0x051C
++#define MT6323_DIGLDO_CON17           0x051E
++#define MT6323_DIGLDO_CON18           0x0520
++#define MT6323_DIGLDO_CON19           0x0522
++#define MT6323_DIGLDO_CON20           0x0524
++#define MT6323_DIGLDO_CON21           0x0526
++#define MT6323_DIGLDO_CON23           0x0528
++#define MT6323_DIGLDO_CON24           0x052A
++#define MT6323_DIGLDO_CON26           0x052C
++#define MT6323_DIGLDO_CON27           0x052E
++#define MT6323_DIGLDO_CON28           0x0530
++#define MT6323_DIGLDO_CON29           0x0532
++#define MT6323_DIGLDO_CON30           0x0534
++#define MT6323_DIGLDO_CON31           0x0536
++#define MT6323_DIGLDO_CON32           0x0538
++#define MT6323_DIGLDO_CON33           0x053A
++#define MT6323_DIGLDO_CON34           0x053C
++#define MT6323_DIGLDO_CON35           0x053E
++#define MT6323_DIGLDO_CON36           0x0540
++#define MT6323_DIGLDO_CON39           0x0542
++#define MT6323_DIGLDO_CON40           0x0544
++#define MT6323_DIGLDO_CON41           0x0546
++#define MT6323_DIGLDO_CON42           0x0548
++#define MT6323_DIGLDO_CON43           0x054A
++#define MT6323_DIGLDO_CON44           0x054C
++#define MT6323_DIGLDO_CON45           0x054E
++#define MT6323_DIGLDO_CON46           0x0550
++#define MT6323_DIGLDO_CON47           0x0552
++#define MT6323_DIGLDO_CON48           0x0554
++#define MT6323_DIGLDO_CON49           0x0556
++#define MT6323_DIGLDO_CON50           0x0558
++#define MT6323_DIGLDO_CON51           0x055A
++#define MT6323_DIGLDO_CON52           0x055C
++#define MT6323_DIGLDO_CON53           0x055E
++#define MT6323_DIGLDO_CON54           0x0560
++#define MT6323_EFUSE_CON0             0x0600
++#define MT6323_EFUSE_CON1             0x0602
++#define MT6323_EFUSE_CON2             0x0604
++#define MT6323_EFUSE_CON3             0x0606
++#define MT6323_EFUSE_CON4             0x0608
++#define MT6323_EFUSE_CON5             0x060A
++#define MT6323_EFUSE_CON6             0x060C
++#define MT6323_EFUSE_VAL_0_15         0x060E
++#define MT6323_EFUSE_VAL_16_31                0x0610
++#define MT6323_EFUSE_VAL_32_47                0x0612
++#define MT6323_EFUSE_VAL_48_63                0x0614
++#define MT6323_EFUSE_VAL_64_79                0x0616
++#define MT6323_EFUSE_VAL_80_95                0x0618
++#define MT6323_EFUSE_VAL_96_111               0x061A
++#define MT6323_EFUSE_VAL_112_127      0x061C
++#define MT6323_EFUSE_VAL_128_143      0x061E
++#define MT6323_EFUSE_VAL_144_159      0x0620
++#define MT6323_EFUSE_VAL_160_175      0x0622
++#define MT6323_EFUSE_VAL_176_191      0x0624
++#define MT6323_EFUSE_DOUT_0_15                0x0626
++#define MT6323_EFUSE_DOUT_16_31               0x0628
++#define MT6323_EFUSE_DOUT_32_47               0x062A
++#define MT6323_EFUSE_DOUT_48_63               0x062C
++#define MT6323_EFUSE_DOUT_64_79               0x062E
++#define MT6323_EFUSE_DOUT_80_95               0x0630
++#define MT6323_EFUSE_DOUT_96_111      0x0632
++#define MT6323_EFUSE_DOUT_112_127     0x0634
++#define MT6323_EFUSE_DOUT_128_143     0x0636
++#define MT6323_EFUSE_DOUT_144_159     0x0638
++#define MT6323_EFUSE_DOUT_160_175     0x063A
++#define MT6323_EFUSE_DOUT_176_191     0x063C
++#define MT6323_EFUSE_CON7             0x063E
++#define MT6323_EFUSE_CON8             0x0640
++#define MT6323_EFUSE_CON9             0x0642
++#define MT6323_RTC_MIX_CON0           0x0644
++#define MT6323_RTC_MIX_CON1           0x0646
++#define MT6323_AUDTOP_CON0            0x0700
++#define MT6323_AUDTOP_CON1            0x0702
++#define MT6323_AUDTOP_CON2            0x0704
++#define MT6323_AUDTOP_CON3            0x0706
++#define MT6323_AUDTOP_CON4            0x0708
++#define MT6323_AUDTOP_CON5            0x070A
++#define MT6323_AUDTOP_CON6            0x070C
++#define MT6323_AUDTOP_CON7            0x070E
++#define MT6323_AUDTOP_CON8            0x0710
++#define MT6323_AUDTOP_CON9            0x0712
++#define MT6323_AUXADC_ADC0            0x0714
++#define MT6323_AUXADC_ADC1            0x0716
++#define MT6323_AUXADC_ADC2            0x0718
++#define MT6323_AUXADC_ADC3            0x071A
++#define MT6323_AUXADC_ADC4            0x071C
++#define MT6323_AUXADC_ADC5            0x071E
++#define MT6323_AUXADC_ADC6            0x0720
++#define MT6323_AUXADC_ADC7            0x0722
++#define MT6323_AUXADC_ADC8            0x0724
++#define MT6323_AUXADC_ADC9            0x0726
++#define MT6323_AUXADC_ADC10           0x0728
++#define MT6323_AUXADC_ADC11           0x072A
++#define MT6323_AUXADC_ADC12           0x072C
++#define MT6323_AUXADC_ADC13           0x072E
++#define MT6323_AUXADC_ADC14           0x0730
++#define MT6323_AUXADC_ADC15           0x0732
++#define MT6323_AUXADC_ADC16           0x0734
++#define MT6323_AUXADC_ADC17           0x0736
++#define MT6323_AUXADC_ADC18           0x0738
++#define MT6323_AUXADC_ADC19           0x073A
++#define MT6323_AUXADC_ADC20           0x073C
++#define MT6323_AUXADC_RSV1            0x073E
++#define MT6323_AUXADC_RSV2            0x0740
++#define MT6323_AUXADC_CON0            0x0742
++#define MT6323_AUXADC_CON1            0x0744
++#define MT6323_AUXADC_CON2            0x0746
++#define MT6323_AUXADC_CON3            0x0748
++#define MT6323_AUXADC_CON4            0x074A
++#define MT6323_AUXADC_CON5            0x074C
++#define MT6323_AUXADC_CON6            0x074E
++#define MT6323_AUXADC_CON7            0x0750
++#define MT6323_AUXADC_CON8            0x0752
++#define MT6323_AUXADC_CON9            0x0754
++#define MT6323_AUXADC_CON10           0x0756
++#define MT6323_AUXADC_CON11           0x0758
++#define MT6323_AUXADC_CON12           0x075A
++#define MT6323_AUXADC_CON13           0x075C
++#define MT6323_AUXADC_CON14           0x075E
++#define MT6323_AUXADC_CON15           0x0760
++#define MT6323_AUXADC_CON16           0x0762
++#define MT6323_AUXADC_CON17           0x0764
++#define MT6323_AUXADC_CON18           0x0766
++#define MT6323_AUXADC_CON19           0x0768
++#define MT6323_AUXADC_CON20           0x076A
++#define MT6323_AUXADC_CON21           0x076C
++#define MT6323_AUXADC_CON22           0x076E
++#define MT6323_AUXADC_CON23           0x0770
++#define MT6323_AUXADC_CON24           0x0772
++#define MT6323_AUXADC_CON25           0x0774
++#define MT6323_AUXADC_CON26           0x0776
++#define MT6323_AUXADC_CON27           0x0778
++#define MT6323_ACCDET_CON0            0x077A
++#define MT6323_ACCDET_CON1            0x077C
++#define MT6323_ACCDET_CON2            0x077E
++#define MT6323_ACCDET_CON3            0x0780
++#define MT6323_ACCDET_CON4            0x0782
++#define MT6323_ACCDET_CON5            0x0784
++#define MT6323_ACCDET_CON6            0x0786
++#define MT6323_ACCDET_CON7            0x0788
++#define MT6323_ACCDET_CON8            0x078A
++#define MT6323_ACCDET_CON9            0x078C
++#define MT6323_ACCDET_CON10           0x078E
++#define MT6323_ACCDET_CON11           0x0790
++#define MT6323_ACCDET_CON12           0x0792
++#define MT6323_ACCDET_CON13           0x0794
++#define MT6323_ACCDET_CON14           0x0796
++#define MT6323_ACCDET_CON15           0x0798
++#define MT6323_ACCDET_CON16           0x079A
+-#endif /* __MFD_MT6397_REGISTERS_H__ */
++#endif
+diff --git a/include/linux/regulator/mt6323-regulator.h b/include/linux/regulator/mt6323-regulator.h
+new file mode 100644
+index 0000000..620b0e3
+--- /dev/null
++++ b/include/linux/regulator/mt6323-regulator.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: John Crispin <blogic@openwrt.org>
++ *
++ * 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 __LINUX_REGULATOR_MT6323_H
++#define __LINUX_REGULATOR_MT6323_H
++
++enum {
++      MT6323_ID_VPROC = 0,
++      MT6323_ID_VSYS,
++      MT6323_ID_VPA,
++      MT6323_ID_VTCXO,
++      MT6323_ID_VA,
++      MT6323_ID_VCN28,
++      MT6323_ID_VCN33,
++      MT6323_ID_VIO28,
++      MT6323_ID_VUSB,
++      MT6323_ID_VMC,
++      MT6323_ID_VMCH,
++      MT6323_ID_VGP1,
++      MT6323_ID_VGP2,
++      MT6323_ID_RG_MAX,
++};
++
++#define MT6323_MAX_REGULATOR  MT6323_ID_RG_MAX
++
++#endif /* __LINUX_REGULATOR_MT6323_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0073-clk.patch b/target/linux/mediatek/patches/0073-clk.patch
new file mode 100644 (file)
index 0000000..a3b36a5
--- /dev/null
@@ -0,0 +1,200 @@
+From a4df453fbfa6199ad33435cee6ce2dfcc65321b0 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:45:58 +0200
+Subject: [PATCH 73/76] clk
+
+---
+ include/dt-bindings/clock/mt7623-clk.h |  158 +++++++++++++++-----------------
+ 1 file changed, 73 insertions(+), 85 deletions(-)
+
+diff --git a/include/dt-bindings/clock/mt7623-clk.h b/include/dt-bindings/clock/mt7623-clk.h
+index cb1e8a9..410ef31 100644
+--- a/include/dt-bindings/clock/mt7623-clk.h
++++ b/include/dt-bindings/clock/mt7623-clk.h
+@@ -17,96 +17,76 @@
+ /* TOPCKGEN */
+-#define CLK_TOP_AUDPLL_24             1
+-#define CLK_TOP_AUDPLL_D16            2
+-#define CLK_TOP_AUDPLL_D4             3
+-#define CLK_TOP_AUDPLL_D8             4
+-#define CLK_TOP_CLKPH_MCK             5
+-#define CLK_TOP_CPUM_TCK_IN           6
+-#define CLK_TOP_DSI0_LNTC_DSICLK      7
+-#define CLK_TOP_HDMITX_CLKDIG_CTS     8
+-#define CLK_TOP_LVDS_ETH              9
+-#define CLK_TOP_LVDSPLL_D2            10
+-#define CLK_TOP_LVDSPLL_D4            11
+-#define CLK_TOP_LVDSPLL_D8            12
+-#define CLK_TOP_MAINPLL_230P3M                13
+-#define CLK_TOP_MAINPLL_322P4M                14
+-#define CLK_TOP_MAINPLL_537P3M                15
+-#define CLK_TOP_MAINPLL_806M          16
+-#define CLK_TOP_MEMPLL_MCK_D4         17
+-#define CLK_TOP_MMPLL_D2              18
+-#define CLK_TOP_MSDCPLL_D2            19
+-#define CLK_TOP_SYSPLL1_D16           20
+-#define CLK_TOP_SYSPLL1_D2            21
+-#define CLK_TOP_SYSPLL1_D4            22
+-#define CLK_TOP_SYSPLL1_D8            23
+-#define CLK_TOP_SYSPLL2_D2            24
+-#define CLK_TOP_SYSPLL2_D4            25
+-#define CLK_TOP_SYSPLL2_D8            26
+-#define CLK_TOP_SYSPLL3_D2            27
+-#define CLK_TOP_SYSPLL3_D4            28
+-#define CLK_TOP_SYSPLL4_D2            29
+-#define CLK_TOP_SYSPLL4_D4            30
+-#define CLK_TOP_SYSPLL_D3             31
+-#define CLK_TOP_SYSPLL_D5             32
+-#define CLK_TOP_SYSPLL_D7             33
+-#define CLK_TOP_TVDPLL_d2             34
+-#define CLK_TOP_TVDPLL_D4             35
+-#define CLK_TOP_UNIVPLL_178P3M                36
+-#define CLK_TOP_UNIVPLL1_D10          37
+-#define CLK_TOP_UNIVPLL1_D2           38
+-#define CLK_TOP_UNIVPLL1_D4           39
+-#define CLK_TOP_UNIVPLL1_D6           40
+-#define CLK_TOP_UNIVPLL1_D8           41
+-#define CLK_TOP_UNIVPLL_249P6M                42
+-#define CLK_TOP_UNIVPLL2_D2           43
+-#define CLK_TOP_UNIVPLL2_D4           44
+-#define CLK_TOP_UNIVPLL2_D6           45
+-#define CLK_TOP_UNIVPLL2_D8           46
+-#define CLK_TOP_UNIVPLL_416M          47
+-#define CLK_TOP_UNIVPLL_48M           48
+-#define CLK_TOP_UNIVPLL_624M          49
+-#define CLK_TOP_UNIVPLL_D26           50
+-#define CLK_TOP_UNIVPLL_D5            51
+-#define CLK_TOP_APLL_SEL              52
++#define CLK_TOP_MAINPLL_650M          1
++#define CLK_TOP_MAINPLL_433P3M                2
++#define CLK_TOP_MAINPLL_260M          3
++#define CLK_TOP_MAINPLL_185P6M                4
++#define CLK_TOP_UNIVPLL_624M          5
++#define CLK_TOP_UNIVPLL_416M          6
++#define CLK_TOP_UNIVPLL_249P6M                7
++#define CLK_TOP_UNIVPLL_178P3M                8
++#define CLK_TOP_UNIVPLL_48M           9
++#define CLK_TOP_AUDPLL_D4             10
++#define CLK_TOP_AUDPLL_D8             11
++#define CLK_TOP_AUDPLL_D16            12
++#define CLK_TOP_AUDPLL_24             13
++#define CLK_TOP_MSDCPLL_D2            14
++#define CLK_TOP_SYSPLL1_D2            15
++#define CLK_TOP_SYSPLL1_D4            16
++#define CLK_TOP_SYSPLL1_D8            17
++#define CLK_TOP_SYSPLL1_D16           18
++#define CLK_TOP_SYSPLL2_D2            19
++#define CLK_TOP_SYSPLL2_D4            20
++#define CLK_TOP_SYSPLL2_D8            21
++#define CLK_TOP_SYSPLL3_D2            22
++#define CLK_TOP_SYSPLL3_D4            23
++#define CLK_TOP_SYSPLL4_D2            24
++#define CLK_TOP_SYSPLL4_D4            25
++#define CLK_TOP_SYSPLL_D3             26
++#define CLK_TOP_SYSPLL_D5             27
++#define CLK_TOP_SYSPLL_D7             28
++#define CLK_TOP_UNIVPLL1_D2           29
++#define CLK_TOP_UNIVPLL1_D4           30
++#define CLK_TOP_UNIVPLL1_D6           31
++#define CLK_TOP_UNIVPLL1_D8           32
++#define CLK_TOP_UNIVPLL1_D10          33
++#define CLK_TOP_UNIVPLL2_D2           34
++#define CLK_TOP_UNIVPLL2_D4           35
++#define CLK_TOP_UNIVPLL2_D6           36
++#define CLK_TOP_UNIVPLL2_D8           37
++#define CLK_TOP_UNIVPLL_D5            38
++#define CLK_TOP_UNIVPLL_D26           39
++#define CLK_TOP_AXI_SEL                       40
++#define CLK_TOP_MEM_SEL                       41
++#define CLK_TOP_DDR_SEL                       42
++#define CLK_TOP_MM_SEL                        43
++#define CLK_TOP_PWM_SEL                       44
++#define CLK_TOP_MFG_SEL                       45
++#define CLK_TOP_UART_SEL              46
++#define CLK_TOP_SPI_SEL                       47
++#define CLK_TOP_USB20_SEL             48
++#define CLK_TOP_MSDC30_0_SEL          49
++#define CLK_TOP_MSDC30_1_SEL          50
++#define CLK_TOP_MSDC30_2_SEL          51
++#define CLK_TOP_AUDIO_SEL             52
+ #define CLK_TOP_AUDIO_INTBUS_SEL      53
+-#define CLK_TOP_AUDIO_SEL             54
+-#define CLK_TOP_AXI_SEL                       55
+-#define CLK_TOP_CAM_SEL                       56
+-#define CLK_TOP_DDR_SEL                       57
+-#define CLK_TOP_DPI0_SEL              58
+-#define CLK_TOP_DPI1_SEL              59
+-#define CLK_TOP_DPILVDS_SEL           60
+-#define CLK_TOP_ETH_SEL                       61
+-#define CLK_TOP_MEM_SEL                       62
+-#define CLK_TOP_MFG_SEL                       63
+-#define CLK_TOP_MM_SEL                        64
+-#define CLK_TOP_MSDC30_0_SEL          65
+-#define CLK_TOP_MSDC30_1_SEL          66
+-#define CLK_TOP_MSDC30_2_SEL          67
+-#define CLK_TOP_NFI2X_SEL             68
+-#define CLK_TOP_PMICSPI_SEL           69
+-#define CLK_TOP_PWM_SEL                       70
+-#define CLK_TOP_RTC_SEL                       71
+-#define CLK_TOP_SCP_SEL                       72
+-#define CLK_TOP_SPI_SEL                       73
+-#define CLK_TOP_TVE_SEL                       74
+-#define CLK_TOP_UART_SEL              75
+-#define CLK_TOP_USB20_SEL             76
+-#define CLK_TOP_VDEC_SEL              77
+-#define CLK_TOP_NR_CLK                        78
++#define CLK_TOP_PMICSPI_SEL           54
++#define CLK_TOP_SCP_SEL                       55
++#define CLK_TOP_APLL_SEL              56
++#define CLK_TOP_RTC_SEL                       57
++#define CLK_TOP_NFI2X_SEL             58
++#define CLK_TOP_ETH_SEL                       59
++#define CLK_TOP_NR_CLK                        60
+ /* APMIXED_SYS */
+ #define CLK_APMIXED_ARMPLL            1
+ #define CLK_APMIXED_MAINPLL           2
+-#define CLK_APMIXED_MSDCPLL           3
+-#define CLK_APMIXED_UNIVPLL           4
+-#define CLK_APMIXED_MMPLL             5
+-#define CLK_APMIXED_VENCPLL           6
+-#define CLK_APMIXED_TVDPLL            7
+-#define CLK_APMIXED_LVDSPLL           8
+-#define CLK_APMIXED_AUDPLL            9
++#define CLK_APMIXED_UNIVPLL           3
++#define CLK_APMIXED_MSDCPLL           4
++#define CLK_APMIXED_AUDPLL            5
++#define CLK_APMIXED_TRGPLL            6
++#define CLK_APMIXED_ETHPLL            7
+ /* INFRA_SYS */
+@@ -124,7 +104,8 @@
+ #define CLK_INFRA_IRRX                        19
+ #define CLK_INFRA_PMICSPI             22
+ #define CLK_INFRA_PMIC_WRAP           23
+-#define CLK_INFRA_NR_CLK              24
++#define CLK_INFRA_CA7SEL              24
++#define CLK_INFRA_NR_CLK              25
+ /* PERI_SYS */
+@@ -169,5 +150,12 @@
+ #define CLK_PERI_UART3_SEL            38
+ #define CLK_PERI_NR_CLK                       39
++#define CLK_HIFSYS_USB0_PHY           1
++#define CLK_HIFSYS_USB1_PHY           2
++#define CLK_HIFSYS_PCIE0              3
++#define CLK_HIFSYS_PCIE1              4
++#define CLK_HIFSYS_PCIE2              5
++#define CLK_HIFSYS_NR_CLK             6
++
+ #endif /* _DT_BINDINGS_CLK_MT7623_H */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0074-dts.patch b/target/linux/mediatek/patches/0074-dts.patch
new file mode 100644 (file)
index 0000000..eddafb6
--- /dev/null
@@ -0,0 +1,182 @@
+From df59c3b7030b6d7802fe5e5abda81467fcdf2178 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:46:13 +0200
+Subject: [PATCH 74/76] dts
+
+---
+ arch/arm/boot/dts/mt7623-evb.dts |  124 +++++++++++++++++++++++++++++++++++++-
+ arch/arm/boot/dts/mt7623.dtsi    |   11 ++++
+ 2 files changed, 133 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/mt7623-evb.dts
++++ b/arch/arm/boot/dts/mt7623-evb.dts
+@@ -145,8 +145,8 @@
+       bus-width = <8>;
+       max-frequency = <50000000>;
+       cap-mmc-highspeed;
+-//    vmmc-supply = <&mt6397_vemc_3v3_reg>;
+-//    vqmmc-supply = <&mt6397_vio18_reg>;
++//    vmmc-supply = <&mt6323_vemc_3v3_reg>;
++//    vqmmc-supply = <&mt6323_vio18_reg>;
+       non-removable;
+ };
+@@ -160,3 +160,123 @@
+       pinctrl-names = "default";
+         pinctrl-0 = <&pinctrl_pcie_default>;
+ };
++
++&pwrap {
++      pmic: mt6323 {
++              compatible = "mediatek,mt6323";
++
++              mt6323regulator: mt6323regulator {
++                      compatible = "mediatek,mt6323-regulator";
++
++                      mt6323_vproc_reg: buck_vproc {
++                              regulator-compatible = "buck_vproc";
++                              regulator-name = "vproc";
++                              regulator-min-microvolt = < 700000>;
++                              regulator-max-microvolt = <1493750>;
++                              regulator-ramp-delay = <6250>;
++                              regulator-always-on;
++                      };
++
++                      mt6323_vsys_reg: buck_vsys {
++                              regulator-compatible = "buck_vsys";
++                              regulator-name = "vsys";
++                              regulator-min-microvolt = <1400000>;
++                              regulator-max-microvolt = <3000000>;
++                              regulator-ramp-delay = <12500>;
++                              regulator-always-on;
++                      };
++
++                      mt6323_vpa_reg: buck_vpa {
++                              regulator-compatible = "buck_vpa";
++                              regulator-name = "vpa";
++                              regulator-min-microvolt = < 500000>;
++                              regulator-max-microvolt = <3650000>;
++                              regulator-ramp-delay = <50000>;
++                              regulator-always-on;
++                      };
++
++                      mt6323_vtcxo_reg: ldo_vtcxo {
++                              regulator-compatible = "ldo_vtcxo";
++                              regulator-name = "vtcxo";
++                              regulator-always-on;
++                      };
++
++                      mt6323_va_reg: ldo_va {
++                              regulator-compatible = "ldo_va";
++                              regulator-name = "va";
++                              regulator-always-on;
++                      };
++
++                      mt6323_vcn28_reg: ldo_vcn28 {
++                              regulator-compatible = "ldo_vcn28";
++                              regulator-name = "vcn28";
++                              regulator-always-on;
++                      };
++
++                      mt6323_vcn33_reg: ldo_vcn33 {
++                              regulator-compatible = "ldo_vcn33";
++                              regulator-name = "vcn33";
++                              regulator-always-on;
++                      };
++
++                      mt6323_vcama_reg: ldo_vcama {
++                              regulator-compatible = "ldo_vcama";
++                              regulator-name = "vcama";
++                              regulator-min-microvolt = <1500000>;
++                              regulator-max-microvolt = <2800000>;
++                              regulator-enable-ramp-delay = <218>;
++                      };
++
++                      mt6323_vio28_reg: ldo_vio28 {
++                              regulator-compatible = "ldo_vio28";
++                              regulator-name = "vio28";
++                              regulator-always-on;
++                      };
++
++                      mt6323_vusb_reg: ldo_vusb {
++                              regulator-compatible = "ldo_vusb";
++                              regulator-name = "vusb";
++                      };
++
++                      mt6323_vmc_reg: ldo_vmc {
++                              regulator-compatible = "ldo_vmc";
++                              regulator-name = "vmc";
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <3300000>;
++                              regulator-enable-ramp-delay = <218>;
++                      };
++
++                      mt6323_vmch_reg: ldo_vmch {
++                              regulator-compatible = "ldo_vmch";
++                              regulator-name = "vmch";
++                              regulator-min-microvolt = <3000000>;
++                              regulator-max-microvolt = <3300000>;
++                              regulator-enable-ramp-delay = <218>;
++                      };
++
++                      mt6323_vemc_3v3_reg: ldo_vemc3v3 {
++                              regulator-compatible = "ldo_vemc3v3";
++                              regulator-name = "vemc_3v3";
++                              regulator-min-microvolt = <3000000>;
++                              regulator-max-microvolt = <3300000>;
++                              regulator-enable-ramp-delay = <218>;
++                      };
++
++                      mt6323_vgp1_reg: ldo_vgp1 {
++                              regulator-compatible = "ldo_vgp1";
++                              regulator-name = "vcamd";
++                              regulator-min-microvolt = <1220000>;
++                              regulator-max-microvolt = <3300000>;
++                              regulator-enable-ramp-delay = <240>;
++                      };
++
++                      mt6323_vgp2_reg: ldo_vgp2 {
++                              regulator-compatible = "ldo_vgp2";
++                              regulator-name = "vcamio";
++                              regulator-min-microvolt = <1000000>;
++                              regulator-max-microvolt = <3300000>;
++                              regulator-enable-ramp-delay = <218>;
++                      };
++              };
++      };
++};
+--- a/arch/arm/boot/dts/mt7623.dtsi
++++ b/arch/arm/boot/dts/mt7623.dtsi
+@@ -150,6 +150,17 @@
+                       clock-names = "system-clk", "rtc-clk";
+               };
++              pwrap: pwrap@1000f000 {
++                      compatible = "mediatek,mt7623-pwrap";
++                      reg = <0 0x1000f000 0 0x1000>;
++                      reg-names = "pwrap";
++                      interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
++                      resets = <&infracfg MT7623_INFRA_PMIC_WRAP_RST>;
++                      reset-names = "pwrap";
++                      clocks = <&clk26m>, <&clk26m>;
++                      clock-names = "spi", "wrap";
++              };
++
+               sysirq: interrupt-controller@10200100 {
+                       compatible = "mediatek,mt7623-sysirq",
+                                    "mediatek,mt6577-sysirq";
+@@ -311,6 +322,7 @@
+               device_type = "pci";
+               bus-range = <0 255>;
++              status = "disabled";
+               ranges = <
+                       0x02000000 0 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */
+                       0x01000000 0 0 0x00000000 0x1A160000 0 0x00010000 /* io space */
+@@ -343,6 +355,5 @@
+                       device_type = "pci";
+               };
+-              status = "disabled";
+       };
+ };
diff --git a/target/linux/mediatek/patches/0075-sd.patch b/target/linux/mediatek/patches/0075-sd.patch
new file mode 100644 (file)
index 0000000..1dcfae3
--- /dev/null
@@ -0,0 +1,55 @@
+From a5982c5e4b58c4335e789969e04f9e24b894f510 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:46:39 +0200
+Subject: [PATCH 75/76] sd
+
+---
+ drivers/mmc/host/mtk-sd.c |   12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 7c20f28..be2b00c 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -227,11 +227,13 @@ struct mt_gpdma_desc {
+ #define GPDMA_DESC_BDP                (0x1 << 1)
+ #define GPDMA_DESC_CHECKSUM   (0xff << 8) /* bit8 ~ bit15 */
+ #define GPDMA_DESC_INT                (0x1 << 16)
++#define GPDMA_DESC_GPDH4B     (0x1 << 24)
++#define GPDMA_DESC_BDH4B      (0x1 << 28)
+       u32 next;
+       u32 ptr;
+       u32 gpd_data_len;
+-#define GPDMA_DESC_BUFLEN     (0xffff) /* bit0 ~ bit15 */
+-#define GPDMA_DESC_EXTLEN     (0xff << 16) /* bit16 ~ bit23 */
++#define GPDMA_DESC_BUFLEN     (0xffffff) /* bit0 ~ bit15 */
++#define GPDMA_DESC_EXTLEN     (0xff << 24) /* bit16 ~ bit23 */
+       u32 arg;
+       u32 blknum;
+       u32 cmd;
+@@ -243,10 +245,12 @@ struct mt_bdma_desc {
+ #define BDMA_DESC_CHECKSUM    (0xff << 8) /* bit8 ~ bit15 */
+ #define BDMA_DESC_BLKPAD      (0x1 << 17)
+ #define BDMA_DESC_DWPAD               (0x1 << 18)
++#define BDMA_DESC_GPDH4B      (0x1 << 24)
++#define BDMA_DESC_BDH4B               (0x1 << 28)
+       u32 next;
+       u32 ptr;
+       u32 bd_data_len;
+-#define BDMA_DESC_BUFLEN      (0xffff) /* bit0 ~ bit15 */
++#define BDMA_DESC_BUFLEN      (0xffffff) /* bit0 ~ bit15 */
+ };
+ struct msdc_dma {
+@@ -1115,7 +1119,7 @@ static void msdc_init_hw(struct msdc_host *host)
+       sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+       writel(0x403c004f, 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(0xffff0089, host->base + MSDC_PATCH_BIT1);
+       /* Configure to enable SDIO mode.
+        * it's must otherwise sdio cmd5 failed
+        */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/patches/0076-reset.patch b/target/linux/mediatek/patches/0076-reset.patch
new file mode 100644 (file)
index 0000000..6157779
--- /dev/null
@@ -0,0 +1,30 @@
+From 1671d902f8dcfce70f920ad3dfebb1031a7a38de Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 3 Jul 2015 05:46:51 +0200
+Subject: [PATCH 76/76] reset
+
+---
+ include/dt-bindings/reset-controller/mt7623-resets.h |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/include/dt-bindings/reset-controller/mt7623-resets.h b/include/dt-bindings/reset-controller/mt7623-resets.h
+index 28a7d69..3e0f39a 100644
+--- a/include/dt-bindings/reset-controller/mt7623-resets.h
++++ b/include/dt-bindings/reset-controller/mt7623-resets.h
+@@ -56,4 +56,13 @@
+ #define MT7623_PERI_ETH_SW_RST                29
+ #define MT7623_PERI_SPI0_SW_RST               33
++/* high speed interface resets */
++#define MT7623_HIFSYS_UHOST0_SW_RST   3
++#define MT7623_HIFSYS_UHOST1_SW_RST   4
++#define MT7623_HIFSYS_UPHY0_SW_RST    21
++#define MT7623_HIFSYS_UPHY1_SW_RST    22
++#define MT7623_HIFSYS_PCIE0_SW_RST    24
++#define MT7623_HIFSYS_PCIE0_SW_RST    25
++#define MT7623_HIFSYS_PCIE0_SW_RST    26
++
+ #endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7623 */
+-- 
+1.7.10.4
+
diff --git a/target/linux/mediatek/profiles/default.mk b/target/linux/mediatek/profiles/default.mk
new file mode 100644 (file)
index 0000000..b83792a
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Default
+       NAME:=Default Profile (minimum package set)
+       PACKAGES:= \
+               kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \
+               kmod-usb3
+endef
+
+define Profile/Default/Description
+       Default package set compatible with most boards.
+endef
+$(eval $(call Profile,Default))