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..