diff --git a/target/linux/ipq806x/Makefile b/target/linux/ipq806x/Makefile index 875bb9cee9..f07c87dbbd 100644 --- a/target/linux/ipq806x/Makefile +++ b/target/linux/ipq806x/Makefile @@ -9,7 +9,7 @@ FEATURES:=squashfs CPU_TYPE:=cortex-a7 MAINTAINER:=John Crispin -KERNEL_PATCHVER:=3.14 +KERNEL_PATCHVER:=3.18 KERNELNAME:=Image dtbs diff --git a/target/linux/ipq806x/config-3.18 b/target/linux/ipq806x/config-3.18 new file mode 100644 index 0000000000..22d8092f51 --- /dev/null +++ b/target/linux/ipq806x/config-3.18 @@ -0,0 +1,371 @@ +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_AMBA_PL08X is not set +# CONFIG_APM_EMULATION is not set +CONFIG_APQ_GCC_8084=y +CONFIG_APQ_MMCC_8084=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=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_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MSM8960=y +CONFIG_ARCH_MSM8974=y +CONFIG_ARCH_MSM8X60=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_NEEDS_CPU_IDLE_COUPLED is not set +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +# 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_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_CPU_SUSPEND=y +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_SP805_WATCHDOG is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_AUTO_ZRELADDR=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_BOUNCE=y +CONFIG_BUILD_BIN2C=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_CLEANCACHE=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_QCOM=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_QCOM=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_SHA1_ARM_NEON is not set +# CONFIG_CRYPTO_SHA512_ARM_NEON is not set +CONFIG_CRYPTO_XZ=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_GPIO=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_UART_PL01X is not set +# CONFIG_DEBUG_USER is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +# CONFIG_DW_DMAC_CORE is not set +# CONFIG_DW_DMAC_PCI is not set +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_FREEZER=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=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_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_DEVRES=y +# CONFIG_GPIO_MSM_V2 is not set +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_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_ARM_ARCH_TIMER=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_HW_BREAKPOINT=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_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=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HWMON=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM=y +CONFIG_HZ_FIXED=0 +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_QUP=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IOMMU_API=y +CONFIG_IOMMU_HELPER=y +CONFIG_IOMMU_PGTABLES_L2=y +CONFIG_IOMMU_SUPPORT=y +CONFIG_IPQ_GCC_806X=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +CONFIG_KERNFS=y +# CONFIG_LEDS_REGULATOR is not set +CONFIG_LIBFDT=y +CONFIG_LOCKUP_DETECTOR=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MDIO_GPIO=y +# CONFIG_MFD_SPMI_PMIC is not set +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_MIGRATION=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MSM_GCC_8660=y +CONFIG_MSM_GCC_8960=y +CONFIG_MSM_GCC_8974=y +CONFIG_MSM_IOMMU=y +CONFIG_MSM_MMCC_8960=y +CONFIG_MSM_MMCC_8974=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_SUPPORT=y +CONFIG_MULTI_IRQ_HANDLER=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_VENDOR_WIZNET=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_IOMMU=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_PCI_MSI=y +CONFIG_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +# CONFIG_PHY_QCOM_APQ8064_SATA is not set +CONFIG_PHY_QCOM_IPQ806X_SATA=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_APQ8064=y +# CONFIG_PINCTRL_APQ8084 is not set +CONFIG_PINCTRL_IPQ8064=y +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_MSM8960 is not set +CONFIG_PINCTRL_MSM8X74=y +# CONFIG_PL330_DMA is not set +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_MSM=y +# CONFIG_POWER_RESET_SYSCON 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_PROC_PAGE_MONITOR=y +CONFIG_QCOM_BAM_DMA=y +CONFIG_QCOM_GSBI=y +CONFIG_QCOM_SCM=y +# CONFIG_QCOM_WDT is not set +# CONFIG_RCU_BOOST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_VERBOSE=y +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_CMOS is not set +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_SCHED_HRTICK=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_QUP=y +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB=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_TREE_PREEMPT_RCU=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UID16=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_USE_OF=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_VFIO is not set +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_WL_TI is not set +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +# 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/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile index 977e674011..77d191f9a9 100644 --- a/target/linux/ipq806x/image/Makefile +++ b/target/linux/ipq806x/image/Makefile @@ -24,6 +24,10 @@ define Image/BuildKernel $(call Image/BuildKernel/FIT,qcom-ipq8064-ap148) endef +define Image/Build/squashfs + $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) +endef + define Image/Build $(call Image/Build/$(1),$(1)) dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-$(1)-root.img bs=2k conv=sync diff --git a/target/linux/ipq806x/patches/0001-ARM-dts-msm-split-out-msm8660-and-msm8960-soc-into-d.patch b/target/linux/ipq806x/patches/0001-ARM-dts-msm-split-out-msm8660-and-msm8960-soc-into-d.patch deleted file mode 100644 index 97c89b219a..0000000000 --- a/target/linux/ipq806x/patches/0001-ARM-dts-msm-split-out-msm8660-and-msm8960-soc-into-d.patch +++ /dev/null @@ -1,300 +0,0 @@ -From 3cdba35369b404875849008ea97cf1705e6060ed Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 23 Jan 2014 14:09:54 -0600 -Subject: [PATCH 001/182] ARM: dts: msm: split out msm8660 and msm8960 soc - into dts include - -Pull the SoC device tree bits into their own files so other boards based -on these SoCs can include them and reduce duplication across a number of -boards. - -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-msm8660-surf.dts | 59 +------------------------- - arch/arm/boot/dts/qcom-msm8660.dtsi | 63 ++++++++++++++++++++++++++++ - arch/arm/boot/dts/qcom-msm8960-cdp.dts | 66 +---------------------------- - arch/arm/boot/dts/qcom-msm8960.dtsi | 70 +++++++++++++++++++++++++++++++ - 4 files changed, 135 insertions(+), 123 deletions(-) - create mode 100644 arch/arm/boot/dts/qcom-msm8660.dtsi - create mode 100644 arch/arm/boot/dts/qcom-msm8960.dtsi - ---- a/arch/arm/boot/dts/qcom-msm8660-surf.dts -+++ b/arch/arm/boot/dts/qcom-msm8660-surf.dts -@@ -1,63 +1,6 @@ --/dts-v1/; -- --/include/ "skeleton.dtsi" -- --#include -+#include "qcom-msm8660.dtsi" - - / { - model = "Qualcomm MSM8660 SURF"; - compatible = "qcom,msm8660-surf", "qcom,msm8660"; -- interrupt-parent = <&intc>; -- -- intc: interrupt-controller@2080000 { -- compatible = "qcom,msm-8660-qgic"; -- interrupt-controller; -- #interrupt-cells = <3>; -- reg = < 0x02080000 0x1000 >, -- < 0x02081000 0x1000 >; -- }; -- -- timer@2000000 { -- compatible = "qcom,scss-timer", "qcom,msm-timer"; -- interrupts = <1 0 0x301>, -- <1 1 0x301>, -- <1 2 0x301>; -- reg = <0x02000000 0x100>; -- clock-frequency = <27000000>, -- <32768>; -- cpu-offset = <0x40000>; -- }; -- -- msmgpio: gpio@800000 { -- compatible = "qcom,msm-gpio"; -- reg = <0x00800000 0x4000>; -- gpio-controller; -- #gpio-cells = <2>; -- ngpio = <173>; -- interrupts = <0 16 0x4>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -- -- gcc: clock-controller@900000 { -- compatible = "qcom,gcc-msm8660"; -- #clock-cells = <1>; -- #reset-cells = <1>; -- reg = <0x900000 0x4000>; -- }; -- -- serial@19c40000 { -- compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -- reg = <0x19c40000 0x1000>, -- <0x19c00000 0x1000>; -- interrupts = <0 195 0x0>; -- clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>; -- clock-names = "core", "iface"; -- }; -- -- qcom,ssbi@500000 { -- compatible = "qcom,ssbi"; -- reg = <0x500000 0x1000>; -- qcom,controller-type = "pmic-arbiter"; -- }; - }; ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi -@@ -0,0 +1,63 @@ -+/dts-v1/; -+ -+/include/ "skeleton.dtsi" -+ -+#include -+ -+/ { -+ model = "Qualcomm MSM8660"; -+ compatible = "qcom,msm8660"; -+ interrupt-parent = <&intc>; -+ -+ intc: interrupt-controller@2080000 { -+ compatible = "qcom,msm-8660-qgic"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = < 0x02080000 0x1000 >, -+ < 0x02081000 0x1000 >; -+ }; -+ -+ timer@2000000 { -+ compatible = "qcom,scss-timer", "qcom,msm-timer"; -+ interrupts = <1 0 0x301>, -+ <1 1 0x301>, -+ <1 2 0x301>; -+ reg = <0x02000000 0x100>; -+ clock-frequency = <27000000>, -+ <32768>; -+ cpu-offset = <0x40000>; -+ }; -+ -+ msmgpio: gpio@800000 { -+ compatible = "qcom,msm-gpio"; -+ reg = <0x00800000 0x4000>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ ngpio = <173>; -+ interrupts = <0 16 0x4>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gcc: clock-controller@900000 { -+ compatible = "qcom,gcc-msm8660"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ reg = <0x900000 0x4000>; -+ }; -+ -+ serial@19c40000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x19c40000 0x1000>, -+ <0x19c00000 0x1000>; -+ interrupts = <0 195 0x0>; -+ clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>; -+ clock-names = "core", "iface"; -+ }; -+ -+ qcom,ssbi@500000 { -+ compatible = "qcom,ssbi"; -+ reg = <0x500000 0x1000>; -+ qcom,controller-type = "pmic-arbiter"; -+ }; -+}; ---- a/arch/arm/boot/dts/qcom-msm8960-cdp.dts -+++ b/arch/arm/boot/dts/qcom-msm8960-cdp.dts -@@ -1,70 +1,6 @@ --/dts-v1/; -- --/include/ "skeleton.dtsi" -- --#include -+#include "qcom-msm8960.dtsi" - - / { - model = "Qualcomm MSM8960 CDP"; - compatible = "qcom,msm8960-cdp", "qcom,msm8960"; -- interrupt-parent = <&intc>; -- -- intc: interrupt-controller@2000000 { -- compatible = "qcom,msm-qgic2"; -- interrupt-controller; -- #interrupt-cells = <3>; -- reg = < 0x02000000 0x1000 >, -- < 0x02002000 0x1000 >; -- }; -- -- timer@200a000 { -- compatible = "qcom,kpss-timer", "qcom,msm-timer"; -- interrupts = <1 1 0x301>, -- <1 2 0x301>, -- <1 3 0x301>; -- reg = <0x0200a000 0x100>; -- clock-frequency = <27000000>, -- <32768>; -- cpu-offset = <0x80000>; -- }; -- -- msmgpio: gpio@800000 { -- compatible = "qcom,msm-gpio"; -- gpio-controller; -- #gpio-cells = <2>; -- ngpio = <150>; -- interrupts = <0 16 0x4>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x800000 0x4000>; -- }; -- -- gcc: clock-controller@900000 { -- compatible = "qcom,gcc-msm8960"; -- #clock-cells = <1>; -- #reset-cells = <1>; -- reg = <0x900000 0x4000>; -- }; -- -- clock-controller@4000000 { -- compatible = "qcom,mmcc-msm8960"; -- reg = <0x4000000 0x1000>; -- #clock-cells = <1>; -- #reset-cells = <1>; -- }; -- -- serial@16440000 { -- compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -- reg = <0x16440000 0x1000>, -- <0x16400000 0x1000>; -- interrupts = <0 154 0x0>; -- clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>; -- clock-names = "core", "iface"; -- }; -- -- qcom,ssbi@500000 { -- compatible = "qcom,ssbi"; -- reg = <0x500000 0x1000>; -- qcom,controller-type = "pmic-arbiter"; -- }; - }; ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi -@@ -0,0 +1,70 @@ -+/dts-v1/; -+ -+/include/ "skeleton.dtsi" -+ -+#include -+ -+/ { -+ model = "Qualcomm MSM8960"; -+ compatible = "qcom,msm8960"; -+ interrupt-parent = <&intc>; -+ -+ intc: interrupt-controller@2000000 { -+ compatible = "qcom,msm-qgic2"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = < 0x02000000 0x1000 >, -+ < 0x02002000 0x1000 >; -+ }; -+ -+ timer@200a000 { -+ compatible = "qcom,kpss-timer", "qcom,msm-timer"; -+ interrupts = <1 1 0x301>, -+ <1 2 0x301>, -+ <1 3 0x301>; -+ reg = <0x0200a000 0x100>; -+ clock-frequency = <27000000>, -+ <32768>; -+ cpu-offset = <0x80000>; -+ }; -+ -+ msmgpio: gpio@800000 { -+ compatible = "qcom,msm-gpio"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ ngpio = <150>; -+ interrupts = <0 16 0x4>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x800000 0x4000>; -+ }; -+ -+ gcc: clock-controller@900000 { -+ compatible = "qcom,gcc-msm8960"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ reg = <0x900000 0x4000>; -+ }; -+ -+ clock-controller@4000000 { -+ compatible = "qcom,mmcc-msm8960"; -+ reg = <0x4000000 0x1000>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; -+ -+ serial@16440000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x16440000 0x1000>, -+ <0x16400000 0x1000>; -+ interrupts = <0 154 0x0>; -+ clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>; -+ clock-names = "core", "iface"; -+ }; -+ -+ qcom,ssbi@500000 { -+ compatible = "qcom,ssbi"; -+ reg = <0x500000 0x1000>; -+ qcom,controller-type = "pmic-arbiter"; -+ }; -+}; diff --git a/target/linux/ipq806x/patches/0002-ARM-msm-Remove-pen_release-usage.patch b/target/linux/ipq806x/patches/0002-ARM-msm-Remove-pen_release-usage.patch deleted file mode 100644 index 19eaae62e5..0000000000 --- a/target/linux/ipq806x/patches/0002-ARM-msm-Remove-pen_release-usage.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 18d53dfa103e63154fb8e548d55016d6ad210d28 Mon Sep 17 00:00:00 2001 -From: Rohit Vaswani -Date: Fri, 21 Jun 2013 12:17:37 -0700 -Subject: [PATCH 002/182] ARM: msm: Remove pen_release usage - -pen_release is no longer required as the synchronization -is now managed by generic arm code. -This is done as suggested in https://lkml.org/lkml/2013/6/4/184 - -Cc: Russell King -Signed-off-by: Rohit Vaswani -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/mach-msm/Makefile | 2 +- - arch/arm/mach-msm/headsmp.S | 39 --------------------------------------- - arch/arm/mach-msm/hotplug.c | 31 ++++--------------------------- - arch/arm/mach-msm/platsmp.c | 37 +++---------------------------------- - 4 files changed, 8 insertions(+), 101 deletions(-) - delete mode 100644 arch/arm/mach-msm/headsmp.S - ---- a/arch/arm/mach-msm/Makefile -+++ b/arch/arm/mach-msm/Makefile -@@ -19,7 +19,7 @@ obj-$(CONFIG_MSM_SCM) += scm.o scm-boot. - CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) - - obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o --obj-$(CONFIG_SMP) += headsmp.o platsmp.o -+obj-$(CONFIG_SMP) += platsmp.o - - obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o - obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o ---- a/arch/arm/mach-msm/headsmp.S -+++ /dev/null -@@ -1,39 +0,0 @@ --/* -- * linux/arch/arm/mach-realview/headsmp.S -- * -- * Copyright (c) 2003 ARM Limited -- * All Rights Reserved -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ --#include --#include -- --/* -- * MSM specific entry point for secondary CPUs. This provides -- * a "holding pen" into which all secondary cores are held until we're -- * ready for them to initialise. -- */ --ENTRY(msm_secondary_startup) -- mrc p15, 0, r0, c0, c0, 5 -- and r0, r0, #15 -- adr r4, 1f -- ldmia r4, {r5, r6} -- sub r4, r4, r5 -- add r6, r6, r4 --pen: ldr r7, [r6] -- cmp r7, r0 -- bne pen -- -- /* -- * we've been released from the holding pen: secondary_stack -- * should now contain the SVC stack for this core -- */ -- b secondary_startup --ENDPROC(msm_secondary_startup) -- -- .align --1: .long . -- .long pen_release ---- a/arch/arm/mach-msm/hotplug.c -+++ b/arch/arm/mach-msm/hotplug.c -@@ -24,33 +24,10 @@ static inline void cpu_leave_lowpower(vo - - static inline void platform_do_lowpower(unsigned int cpu) - { -- /* Just enter wfi for now. TODO: Properly shut off the cpu. */ -- for (;;) { -- /* -- * here's the WFI -- */ -- asm("wfi" -- : -- : -- : "memory", "cc"); -- -- if (pen_release == cpu_logical_map(cpu)) { -- /* -- * OK, proper wakeup, we're done -- */ -- break; -- } -- -- /* -- * getting here, means that we have come out of WFI without -- * having been woken up - this shouldn't happen -- * -- * The trouble is, letting people know about this is not really -- * possible, since we are currently running incoherently, and -- * therefore cannot safely call printk() or anything else -- */ -- pr_debug("CPU%u: spurious wakeup call\n", cpu); -- } -+ asm("wfi" -+ : -+ : -+ : "memory", "cc"); - } - - /* ---- a/arch/arm/mach-msm/platsmp.c -+++ b/arch/arm/mach-msm/platsmp.c -@@ -12,13 +12,10 @@ - #include - #include - #include --#include - #include - #include - --#include - #include --#include - #include - - #include "scm-boot.h" -@@ -28,7 +25,7 @@ - #define SCSS_CPU1CORE_RESET 0xD80 - #define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 - --extern void msm_secondary_startup(void); -+extern void secondary_startup(void); - - static DEFINE_SPINLOCK(boot_lock); - -@@ -41,13 +38,6 @@ static inline int get_core_count(void) - static void msm_secondary_init(unsigned int cpu) - { - /* -- * let the primary processor know we're out of the -- * pen, then head off into the C entry point -- */ -- pen_release = -1; -- smp_wmb(); -- -- /* - * Synchronise with the boot thread. - */ - spin_lock(&boot_lock); -@@ -57,7 +47,7 @@ static void msm_secondary_init(unsigned - static void prepare_cold_cpu(unsigned int cpu) - { - int ret; -- ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup), -+ ret = scm_set_boot_addr(virt_to_phys(secondary_startup), - SCM_FLAG_COLDBOOT_CPU1); - if (ret == 0) { - void __iomem *sc1_base_ptr; -@@ -75,7 +65,6 @@ static void prepare_cold_cpu(unsigned in - - static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle) - { -- unsigned long timeout; - static int cold_boot_done; - - /* Only need to bring cpu out of reset this way once */ -@@ -91,39 +80,19 @@ static int msm_boot_secondary(unsigned i - spin_lock(&boot_lock); - - /* -- * The secondary processor is waiting to be released from -- * the holding pen - release it, then wait for it to flag -- * that it has been released by resetting pen_release. -- * -- * Note that "pen_release" is the hardware CPU ID, whereas -- * "cpu" is Linux's internal ID. -- */ -- pen_release = cpu_logical_map(cpu); -- sync_cache_w(&pen_release); -- -- /* - * Send the secondary CPU a soft interrupt, thereby causing - * the boot monitor to read the system wide flags register, - * and branch to the address found there. - */ - arch_send_wakeup_ipi_mask(cpumask_of(cpu)); - -- timeout = jiffies + (1 * HZ); -- while (time_before(jiffies, timeout)) { -- smp_rmb(); -- if (pen_release == -1) -- break; -- -- udelay(10); -- } -- - /* - * now the secondary core is starting up let it run its - * calibrations, then wait for it to finish - */ - spin_unlock(&boot_lock); - -- return pen_release != -1 ? -ENOSYS : 0; -+ return 0; - } - - /* diff --git a/target/linux/ipq806x/patches/0003-ARM-msm-kill-off-hotplug.c.patch b/target/linux/ipq806x/patches/0003-ARM-msm-kill-off-hotplug.c.patch deleted file mode 100644 index 79aa96f24a..0000000000 --- a/target/linux/ipq806x/patches/0003-ARM-msm-kill-off-hotplug.c.patch +++ /dev/null @@ -1,108 +0,0 @@ -From b5a3a19e3efa6238c6a00a8f36a8ab2c25eeebc3 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 31 Jan 2014 13:48:29 -0600 -Subject: [PATCH 003/182] ARM: msm: kill off hotplug.c - -Right now hotplug.c only really implements msm_cpu_die as a wfi. Just -move that implementation into platsmp.c. At the same time we use the -existing wfi() instead of inline asm. - -Signed-off-by: Kumar Gala ---- - arch/arm/mach-msm/Makefile | 1 - - arch/arm/mach-msm/common.h | 1 - - arch/arm/mach-msm/hotplug.c | 51 ------------------------------------------- - arch/arm/mach-msm/platsmp.c | 7 ++++++ - 4 files changed, 7 insertions(+), 53 deletions(-) - delete mode 100644 arch/arm/mach-msm/hotplug.c - ---- a/arch/arm/mach-msm/Makefile -+++ b/arch/arm/mach-msm/Makefile -@@ -18,7 +18,6 @@ obj-$(CONFIG_MSM_SCM) += scm.o scm-boot. - - CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) - --obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o - obj-$(CONFIG_SMP) += platsmp.o - - obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o ---- a/arch/arm/mach-msm/common.h -+++ b/arch/arm/mach-msm/common.h -@@ -24,7 +24,6 @@ extern void __iomem *__msm_ioremap_calle - unsigned int mtype, void *caller); - - extern struct smp_operations msm_smp_ops; --extern void msm_cpu_die(unsigned int cpu); - - struct msm_mmc_platform_data; - ---- a/arch/arm/mach-msm/hotplug.c -+++ /dev/null -@@ -1,51 +0,0 @@ --/* -- * Copyright (C) 2002 ARM Ltd. -- * All Rights Reserved -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ --#include --#include --#include -- --#include -- --#include "common.h" -- --static inline void cpu_enter_lowpower(void) --{ --} -- --static inline void cpu_leave_lowpower(void) --{ --} -- --static inline void platform_do_lowpower(unsigned int cpu) --{ -- asm("wfi" -- : -- : -- : "memory", "cc"); --} -- --/* -- * platform-specific code to shutdown a CPU -- * -- * Called with IRQs disabled -- */ --void __ref msm_cpu_die(unsigned int cpu) --{ -- /* -- * we're ready for shutdown now, so do it -- */ -- cpu_enter_lowpower(); -- platform_do_lowpower(cpu); -- -- /* -- * bring this CPU back into the world of cache -- * coherency, and then restore interrupts -- */ -- cpu_leave_lowpower(); --} ---- a/arch/arm/mach-msm/platsmp.c -+++ b/arch/arm/mach-msm/platsmp.c -@@ -29,6 +29,13 @@ extern void secondary_startup(void); - - static DEFINE_SPINLOCK(boot_lock); - -+#ifdef CONFIG_HOTPLUG_CPU -+static void __ref msm_cpu_die(unsigned int cpu) -+{ -+ wfi(); -+} -+#endif -+ - static inline int get_core_count(void) - { - /* 1 + the PART[1:0] field of MIDR */ diff --git a/target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch b/target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch deleted file mode 100644 index c726d3f982..0000000000 --- a/target/linux/ipq806x/patches/0004-clocksource-qcom-Move-clocksource-code-out-of-mach-m.patch +++ /dev/null @@ -1,771 +0,0 @@ -From 00009eabeb2074bef5c89e576a7a6d827c12c3d9 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Wed, 29 Jan 2014 16:17:30 -0600 -Subject: [PATCH 004/182] clocksource: qcom: Move clocksource code out of - mach-msm - -We intend to share the clocksource code for MSM platforms between legacy -and multiplatform supported qcom SoCs. - -Acked-by: Olof Johansson -Signed-off-by: Kumar Gala ---- - arch/arm/mach-msm/Kconfig | 13 +- - arch/arm/mach-msm/Makefile | 1 - - arch/arm/mach-msm/timer.c | 333 -------------------------------------- - drivers/clocksource/Kconfig | 3 + - drivers/clocksource/Makefile | 1 + - drivers/clocksource/qcom-timer.c | 329 +++++++++++++++++++++++++++++++++++++ - 6 files changed, 338 insertions(+), 342 deletions(-) - delete mode 100644 arch/arm/mach-msm/timer.c - create mode 100644 drivers/clocksource/qcom-timer.c - ---- a/arch/arm/mach-msm/Kconfig -+++ b/arch/arm/mach-msm/Kconfig -@@ -21,7 +21,7 @@ config ARCH_MSM8X60 - select CPU_V7 - select HAVE_SMP - select MSM_SCM if SMP -- select MSM_TIMER -+ select CLKSRC_QCOM - - config ARCH_MSM8960 - bool "Enable support for MSM8960" -@@ -29,7 +29,7 @@ config ARCH_MSM8960 - select CPU_V7 - select HAVE_SMP - select MSM_SCM if SMP -- select MSM_TIMER -+ select CLKSRC_QCOM - - config ARCH_MSM8974 - bool "Enable support for MSM8974" -@@ -54,7 +54,7 @@ config ARCH_MSM7X00A - select MACH_TROUT if !MACH_HALIBUT - select MSM_PROC_COMM - select MSM_SMD -- select MSM_TIMER -+ select CLKSRC_QCOM - select MSM_SMD_PKG3 - - config ARCH_MSM7X30 -@@ -66,7 +66,7 @@ config ARCH_MSM7X30 - select MSM_GPIOMUX - select MSM_PROC_COMM - select MSM_SMD -- select MSM_TIMER -+ select CLKSRC_QCOM - select MSM_VIC - - config ARCH_QSD8X50 -@@ -78,7 +78,7 @@ config ARCH_QSD8X50 - select MSM_GPIOMUX - select MSM_PROC_COMM - select MSM_SMD -- select MSM_TIMER -+ select CLKSRC_QCOM - select MSM_VIC - - endchoice -@@ -153,7 +153,4 @@ config MSM_GPIOMUX - config MSM_SCM - bool - --config MSM_TIMER -- bool -- - endif ---- a/arch/arm/mach-msm/Makefile -+++ b/arch/arm/mach-msm/Makefile -@@ -1,4 +1,3 @@ --obj-$(CONFIG_MSM_TIMER) += timer.o - obj-$(CONFIG_MSM_PROC_COMM) += clock.o - - obj-$(CONFIG_MSM_VIC) += irq-vic.o ---- a/arch/arm/mach-msm/timer.c -+++ /dev/null -@@ -1,333 +0,0 @@ --/* -- * -- * Copyright (C) 2007 Google, Inc. -- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. -- * -- * This software is licensed under the terms of the GNU General Public -- * License version 2, as published by the Free Software Foundation, and -- * may be copied, distributed, and modified under those terms. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include "common.h" -- --#define TIMER_MATCH_VAL 0x0000 --#define TIMER_COUNT_VAL 0x0004 --#define TIMER_ENABLE 0x0008 --#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) --#define TIMER_ENABLE_EN BIT(0) --#define TIMER_CLEAR 0x000C --#define DGT_CLK_CTL 0x10 --#define DGT_CLK_CTL_DIV_4 0x3 --#define TIMER_STS_GPT0_CLR_PEND BIT(10) -- --#define GPT_HZ 32768 -- --#define MSM_DGT_SHIFT 5 -- --static void __iomem *event_base; --static void __iomem *sts_base; -- --static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) --{ -- struct clock_event_device *evt = dev_id; -- /* Stop the timer tick */ -- if (evt->mode == CLOCK_EVT_MODE_ONESHOT) { -- u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -- ctrl &= ~TIMER_ENABLE_EN; -- writel_relaxed(ctrl, event_base + TIMER_ENABLE); -- } -- evt->event_handler(evt); -- return IRQ_HANDLED; --} -- --static int msm_timer_set_next_event(unsigned long cycles, -- struct clock_event_device *evt) --{ -- u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -- -- ctrl &= ~TIMER_ENABLE_EN; -- writel_relaxed(ctrl, event_base + TIMER_ENABLE); -- -- writel_relaxed(ctrl, event_base + TIMER_CLEAR); -- writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); -- -- if (sts_base) -- while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) -- cpu_relax(); -- -- writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); -- return 0; --} -- --static void msm_timer_set_mode(enum clock_event_mode mode, -- struct clock_event_device *evt) --{ -- u32 ctrl; -- -- ctrl = readl_relaxed(event_base + TIMER_ENABLE); -- ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); -- -- switch (mode) { -- case CLOCK_EVT_MODE_RESUME: -- case CLOCK_EVT_MODE_PERIODIC: -- break; -- case CLOCK_EVT_MODE_ONESHOT: -- /* Timer is enabled in set_next_event */ -- break; -- case CLOCK_EVT_MODE_UNUSED: -- case CLOCK_EVT_MODE_SHUTDOWN: -- break; -- } -- writel_relaxed(ctrl, event_base + TIMER_ENABLE); --} -- --static struct clock_event_device __percpu *msm_evt; -- --static void __iomem *source_base; -- --static notrace cycle_t msm_read_timer_count(struct clocksource *cs) --{ -- return readl_relaxed(source_base + TIMER_COUNT_VAL); --} -- --static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) --{ -- /* -- * Shift timer count down by a constant due to unreliable lower bits -- * on some targets. -- */ -- return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; --} -- --static struct clocksource msm_clocksource = { -- .name = "dg_timer", -- .rating = 300, -- .read = msm_read_timer_count, -- .mask = CLOCKSOURCE_MASK(32), -- .flags = CLOCK_SOURCE_IS_CONTINUOUS, --}; -- --static int msm_timer_irq; --static int msm_timer_has_ppi; -- --static int msm_local_timer_setup(struct clock_event_device *evt) --{ -- int cpu = smp_processor_id(); -- int err; -- -- evt->irq = msm_timer_irq; -- evt->name = "msm_timer"; -- evt->features = CLOCK_EVT_FEAT_ONESHOT; -- evt->rating = 200; -- evt->set_mode = msm_timer_set_mode; -- evt->set_next_event = msm_timer_set_next_event; -- evt->cpumask = cpumask_of(cpu); -- -- clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); -- -- if (msm_timer_has_ppi) { -- enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); -- } else { -- err = request_irq(evt->irq, msm_timer_interrupt, -- IRQF_TIMER | IRQF_NOBALANCING | -- IRQF_TRIGGER_RISING, "gp_timer", evt); -- if (err) -- pr_err("request_irq failed\n"); -- } -- -- return 0; --} -- --static void msm_local_timer_stop(struct clock_event_device *evt) --{ -- evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); -- disable_percpu_irq(evt->irq); --} -- --static int msm_timer_cpu_notify(struct notifier_block *self, -- unsigned long action, void *hcpu) --{ -- /* -- * Grab cpu pointer in each case to avoid spurious -- * preemptible warnings -- */ -- switch (action & ~CPU_TASKS_FROZEN) { -- case CPU_STARTING: -- msm_local_timer_setup(this_cpu_ptr(msm_evt)); -- break; -- case CPU_DYING: -- msm_local_timer_stop(this_cpu_ptr(msm_evt)); -- break; -- } -- -- return NOTIFY_OK; --} -- --static struct notifier_block msm_timer_cpu_nb = { -- .notifier_call = msm_timer_cpu_notify, --}; -- --static u64 notrace msm_sched_clock_read(void) --{ -- return msm_clocksource.read(&msm_clocksource); --} -- --static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, -- bool percpu) --{ -- struct clocksource *cs = &msm_clocksource; -- int res = 0; -- -- msm_timer_irq = irq; -- msm_timer_has_ppi = percpu; -- -- msm_evt = alloc_percpu(struct clock_event_device); -- if (!msm_evt) { -- pr_err("memory allocation failed for clockevents\n"); -- goto err; -- } -- -- if (percpu) -- res = request_percpu_irq(irq, msm_timer_interrupt, -- "gp_timer", msm_evt); -- -- if (res) { -- pr_err("request_percpu_irq failed\n"); -- } else { -- res = register_cpu_notifier(&msm_timer_cpu_nb); -- if (res) { -- free_percpu_irq(irq, msm_evt); -- goto err; -- } -- -- /* Immediately configure the timer on the boot CPU */ -- msm_local_timer_setup(__this_cpu_ptr(msm_evt)); -- } -- --err: -- writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); -- res = clocksource_register_hz(cs, dgt_hz); -- if (res) -- pr_err("clocksource_register failed\n"); -- sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); --} -- --#ifdef CONFIG_OF --static void __init msm_dt_timer_init(struct device_node *np) --{ -- u32 freq; -- int irq; -- struct resource res; -- u32 percpu_offset; -- void __iomem *base; -- void __iomem *cpu0_base; -- -- base = of_iomap(np, 0); -- if (!base) { -- pr_err("Failed to map event base\n"); -- return; -- } -- -- /* We use GPT0 for the clockevent */ -- irq = irq_of_parse_and_map(np, 1); -- if (irq <= 0) { -- pr_err("Can't get irq\n"); -- return; -- } -- -- /* We use CPU0's DGT for the clocksource */ -- if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) -- percpu_offset = 0; -- -- if (of_address_to_resource(np, 0, &res)) { -- pr_err("Failed to parse DGT resource\n"); -- return; -- } -- -- cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); -- if (!cpu0_base) { -- pr_err("Failed to map source base\n"); -- return; -- } -- -- if (of_property_read_u32(np, "clock-frequency", &freq)) { -- pr_err("Unknown frequency\n"); -- return; -- } -- -- event_base = base + 0x4; -- sts_base = base + 0x88; -- source_base = cpu0_base + 0x24; -- freq /= 4; -- writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); -- -- msm_timer_init(freq, 32, irq, !!percpu_offset); --} --CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); --CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); --#endif -- --static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, -- u32 sts) --{ -- void __iomem *base; -- -- base = ioremap(addr, SZ_256); -- if (!base) { -- pr_err("Failed to map timer base\n"); -- return -ENOMEM; -- } -- event_base = base + event; -- source_base = base + source; -- if (sts) -- sts_base = base + sts; -- -- return 0; --} -- --void __init msm7x01_timer_init(void) --{ -- struct clocksource *cs = &msm_clocksource; -- -- if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0)) -- return; -- cs->read = msm_read_timer_count_shift; -- cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); -- /* 600 KHz */ -- msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7, -- false); --} -- --void __init msm7x30_timer_init(void) --{ -- if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80)) -- return; -- msm_timer_init(24576000 / 4, 32, 1, false); --} -- --void __init qsd8x50_timer_init(void) --{ -- if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34)) -- return; -- msm_timer_init(19200000 / 4, 32, 7, false); --} ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -140,3 +140,6 @@ config VF_PIT_TIMER - bool - help - Support for Period Interrupt Timer on Freescale Vybrid Family SoCs. -+ -+config CLKSRC_QCOM -+ bool ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -32,6 +32,7 @@ obj-$(CONFIG_CLKSRC_EFM32) += time-efm32 - obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o - obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o - obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o -+obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o - - obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o - obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o ---- /dev/null -+++ b/drivers/clocksource/qcom-timer.c -@@ -0,0 +1,329 @@ -+/* -+ * -+ * Copyright (C) 2007 Google, Inc. -+ * Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TIMER_MATCH_VAL 0x0000 -+#define TIMER_COUNT_VAL 0x0004 -+#define TIMER_ENABLE 0x0008 -+#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) -+#define TIMER_ENABLE_EN BIT(0) -+#define TIMER_CLEAR 0x000C -+#define DGT_CLK_CTL 0x10 -+#define DGT_CLK_CTL_DIV_4 0x3 -+#define TIMER_STS_GPT0_CLR_PEND BIT(10) -+ -+#define GPT_HZ 32768 -+ -+#define MSM_DGT_SHIFT 5 -+ -+static void __iomem *event_base; -+static void __iomem *sts_base; -+ -+static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *evt = dev_id; -+ /* Stop the timer tick */ -+ if (evt->mode == CLOCK_EVT_MODE_ONESHOT) { -+ u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -+ ctrl &= ~TIMER_ENABLE_EN; -+ writel_relaxed(ctrl, event_base + TIMER_ENABLE); -+ } -+ evt->event_handler(evt); -+ return IRQ_HANDLED; -+} -+ -+static int msm_timer_set_next_event(unsigned long cycles, -+ struct clock_event_device *evt) -+{ -+ u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); -+ -+ ctrl &= ~TIMER_ENABLE_EN; -+ writel_relaxed(ctrl, event_base + TIMER_ENABLE); -+ -+ writel_relaxed(ctrl, event_base + TIMER_CLEAR); -+ writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); -+ -+ if (sts_base) -+ while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND) -+ cpu_relax(); -+ -+ writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); -+ return 0; -+} -+ -+static void msm_timer_set_mode(enum clock_event_mode mode, -+ struct clock_event_device *evt) -+{ -+ u32 ctrl; -+ -+ ctrl = readl_relaxed(event_base + TIMER_ENABLE); -+ ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); -+ -+ switch (mode) { -+ case CLOCK_EVT_MODE_RESUME: -+ case CLOCK_EVT_MODE_PERIODIC: -+ break; -+ case CLOCK_EVT_MODE_ONESHOT: -+ /* Timer is enabled in set_next_event */ -+ break; -+ case CLOCK_EVT_MODE_UNUSED: -+ case CLOCK_EVT_MODE_SHUTDOWN: -+ break; -+ } -+ writel_relaxed(ctrl, event_base + TIMER_ENABLE); -+} -+ -+static struct clock_event_device __percpu *msm_evt; -+ -+static void __iomem *source_base; -+ -+static notrace cycle_t msm_read_timer_count(struct clocksource *cs) -+{ -+ return readl_relaxed(source_base + TIMER_COUNT_VAL); -+} -+ -+static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) -+{ -+ /* -+ * Shift timer count down by a constant due to unreliable lower bits -+ * on some targets. -+ */ -+ return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; -+} -+ -+static struct clocksource msm_clocksource = { -+ .name = "dg_timer", -+ .rating = 300, -+ .read = msm_read_timer_count, -+ .mask = CLOCKSOURCE_MASK(32), -+ .flags = CLOCK_SOURCE_IS_CONTINUOUS, -+}; -+ -+static int msm_timer_irq; -+static int msm_timer_has_ppi; -+ -+static int msm_local_timer_setup(struct clock_event_device *evt) -+{ -+ int cpu = smp_processor_id(); -+ int err; -+ -+ evt->irq = msm_timer_irq; -+ evt->name = "msm_timer"; -+ evt->features = CLOCK_EVT_FEAT_ONESHOT; -+ evt->rating = 200; -+ evt->set_mode = msm_timer_set_mode; -+ evt->set_next_event = msm_timer_set_next_event; -+ evt->cpumask = cpumask_of(cpu); -+ -+ clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff); -+ -+ if (msm_timer_has_ppi) { -+ enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING); -+ } else { -+ err = request_irq(evt->irq, msm_timer_interrupt, -+ IRQF_TIMER | IRQF_NOBALANCING | -+ IRQF_TRIGGER_RISING, "gp_timer", evt); -+ if (err) -+ pr_err("request_irq failed\n"); -+ } -+ -+ return 0; -+} -+ -+static void msm_local_timer_stop(struct clock_event_device *evt) -+{ -+ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); -+ disable_percpu_irq(evt->irq); -+} -+ -+static int msm_timer_cpu_notify(struct notifier_block *self, -+ unsigned long action, void *hcpu) -+{ -+ /* -+ * Grab cpu pointer in each case to avoid spurious -+ * preemptible warnings -+ */ -+ switch (action & ~CPU_TASKS_FROZEN) { -+ case CPU_STARTING: -+ msm_local_timer_setup(this_cpu_ptr(msm_evt)); -+ break; -+ case CPU_DYING: -+ msm_local_timer_stop(this_cpu_ptr(msm_evt)); -+ break; -+ } -+ -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block msm_timer_cpu_nb = { -+ .notifier_call = msm_timer_cpu_notify, -+}; -+ -+static u64 notrace msm_sched_clock_read(void) -+{ -+ return msm_clocksource.read(&msm_clocksource); -+} -+ -+static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq, -+ bool percpu) -+{ -+ struct clocksource *cs = &msm_clocksource; -+ int res = 0; -+ -+ msm_timer_irq = irq; -+ msm_timer_has_ppi = percpu; -+ -+ msm_evt = alloc_percpu(struct clock_event_device); -+ if (!msm_evt) { -+ pr_err("memory allocation failed for clockevents\n"); -+ goto err; -+ } -+ -+ if (percpu) -+ res = request_percpu_irq(irq, msm_timer_interrupt, -+ "gp_timer", msm_evt); -+ -+ if (res) { -+ pr_err("request_percpu_irq failed\n"); -+ } else { -+ res = register_cpu_notifier(&msm_timer_cpu_nb); -+ if (res) { -+ free_percpu_irq(irq, msm_evt); -+ goto err; -+ } -+ -+ /* Immediately configure the timer on the boot CPU */ -+ msm_local_timer_setup(__this_cpu_ptr(msm_evt)); -+ } -+ -+err: -+ writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); -+ res = clocksource_register_hz(cs, dgt_hz); -+ if (res) -+ pr_err("clocksource_register failed\n"); -+ sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); -+} -+ -+#ifdef CONFIG_OF -+static void __init msm_dt_timer_init(struct device_node *np) -+{ -+ u32 freq; -+ int irq; -+ struct resource res; -+ u32 percpu_offset; -+ void __iomem *base; -+ void __iomem *cpu0_base; -+ -+ base = of_iomap(np, 0); -+ if (!base) { -+ pr_err("Failed to map event base\n"); -+ return; -+ } -+ -+ /* We use GPT0 for the clockevent */ -+ irq = irq_of_parse_and_map(np, 1); -+ if (irq <= 0) { -+ pr_err("Can't get irq\n"); -+ return; -+ } -+ -+ /* We use CPU0's DGT for the clocksource */ -+ if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) -+ percpu_offset = 0; -+ -+ if (of_address_to_resource(np, 0, &res)) { -+ pr_err("Failed to parse DGT resource\n"); -+ return; -+ } -+ -+ cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res)); -+ if (!cpu0_base) { -+ pr_err("Failed to map source base\n"); -+ return; -+ } -+ -+ if (of_property_read_u32(np, "clock-frequency", &freq)) { -+ pr_err("Unknown frequency\n"); -+ return; -+ } -+ -+ event_base = base + 0x4; -+ sts_base = base + 0x88; -+ source_base = cpu0_base + 0x24; -+ freq /= 4; -+ writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); -+ -+ msm_timer_init(freq, 32, irq, !!percpu_offset); -+} -+CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); -+CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); -+#endif -+ -+static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, -+ u32 sts) -+{ -+ void __iomem *base; -+ -+ base = ioremap(addr, SZ_256); -+ if (!base) { -+ pr_err("Failed to map timer base\n"); -+ return -ENOMEM; -+ } -+ event_base = base + event; -+ source_base = base + source; -+ if (sts) -+ sts_base = base + sts; -+ -+ return 0; -+} -+ -+void __init msm7x01_timer_init(void) -+{ -+ struct clocksource *cs = &msm_clocksource; -+ -+ if (msm_timer_map(0xc0100000, 0x0, 0x10, 0x0)) -+ return; -+ cs->read = msm_read_timer_count_shift; -+ cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); -+ /* 600 KHz */ -+ msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7, -+ false); -+} -+ -+void __init msm7x30_timer_init(void) -+{ -+ if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80)) -+ return; -+ msm_timer_init(24576000 / 4, 32, 1, false); -+} -+ -+void __init qsd8x50_timer_init(void) -+{ -+ if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34)) -+ return; -+ msm_timer_init(19200000 / 4, 32, 7, false); -+} diff --git a/target/linux/ipq806x/patches/0005-ARM-qcom-Split-Qualcomm-support-into-legacy-and-mult.patch b/target/linux/ipq806x/patches/0005-ARM-qcom-Split-Qualcomm-support-into-legacy-and-mult.patch deleted file mode 100644 index 4cd4c4757f..0000000000 --- a/target/linux/ipq806x/patches/0005-ARM-qcom-Split-Qualcomm-support-into-legacy-and-mult.patch +++ /dev/null @@ -1,1423 +0,0 @@ -From 8c2a00c0129d6f718245f7a613c2bb28976b7973 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Tue, 21 Jan 2014 17:14:10 -0600 -Subject: [PATCH 005/182] ARM: qcom: Split Qualcomm support into legacy and - multiplatform - -Introduce a new mach-qcom that will support SoCs that intend to be -multiplatform compatible while keeping mach-msm to legacy SoC/board -support that will not transition over to multiplatform. - -As part of this, we move support for MSM8X60, MSM8960 and MSM8974 over -to mach-qcom. - -Signed-off-by: Kumar Gala ---- - MAINTAINERS | 8 ++ - arch/arm/Kconfig | 7 +- - arch/arm/Kconfig.debug | 2 +- - arch/arm/Makefile | 1 + - arch/arm/boot/dts/Makefile | 6 +- - arch/arm/mach-msm/Kconfig | 45 +------ - arch/arm/mach-msm/Makefile | 6 - - arch/arm/mach-msm/board-dt.c | 41 ------ - arch/arm/mach-msm/platsmp.c | 137 ------------------- - arch/arm/mach-msm/scm-boot.c | 39 ------ - arch/arm/mach-msm/scm-boot.h | 22 --- - arch/arm/mach-msm/scm.c | 299 ----------------------------------------- - arch/arm/mach-msm/scm.h | 25 ---- - arch/arm/mach-qcom/Kconfig | 33 +++++ - arch/arm/mach-qcom/Makefile | 5 + - arch/arm/mach-qcom/board.c | 40 ++++++ - arch/arm/mach-qcom/platsmp.c | 137 +++++++++++++++++++ - arch/arm/mach-qcom/scm-boot.c | 39 ++++++ - arch/arm/mach-qcom/scm-boot.h | 22 +++ - arch/arm/mach-qcom/scm.c | 299 +++++++++++++++++++++++++++++++++++++++++ - arch/arm/mach-qcom/scm.h | 25 ++++ - 21 files changed, 619 insertions(+), 619 deletions(-) - delete mode 100644 arch/arm/mach-msm/board-dt.c - delete mode 100644 arch/arm/mach-msm/platsmp.c - delete mode 100644 arch/arm/mach-msm/scm-boot.c - delete mode 100644 arch/arm/mach-msm/scm-boot.h - delete mode 100644 arch/arm/mach-msm/scm.c - delete mode 100644 arch/arm/mach-msm/scm.h - create mode 100644 arch/arm/mach-qcom/Kconfig - create mode 100644 arch/arm/mach-qcom/Makefile - create mode 100644 arch/arm/mach-qcom/board.c - create mode 100644 arch/arm/mach-qcom/platsmp.c - create mode 100644 arch/arm/mach-qcom/scm-boot.c - create mode 100644 arch/arm/mach-qcom/scm-boot.h - create mode 100644 arch/arm/mach-qcom/scm.c - create mode 100644 arch/arm/mach-qcom/scm.h - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1168,6 +1168,14 @@ L: linux-arm-kernel@lists.infradead.org - W: http://www.arm.linux.org.uk/ - S: Maintained - -+ARM/QUALCOMM SUPPORT -+M: Kumar Gala -+M: David Brown -+L: linux-arm-msm@vger.kernel.org -+S: Maintained -+F: arch/arm/mach-qcom/ -+T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git -+ - ARM/RADISYS ENP2611 MACHINE SUPPORT - M: Lennert Buytenhek - L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -658,9 +658,8 @@ config ARCH_PXA - help - Support for Intel/Marvell's PXA2xx/PXA3xx processor line. - --config ARCH_MSM_NODT -- bool "Qualcomm MSM" -- select ARCH_MSM -+config ARCH_MSM -+ bool "Qualcomm MSM (non-multiplatform)" - select ARCH_REQUIRE_GPIOLIB - select COMMON_CLK - select GENERIC_CLOCKEVENTS -@@ -1006,6 +1005,8 @@ source "arch/arm/plat-pxa/Kconfig" - - source "arch/arm/mach-mmp/Kconfig" - -+source "arch/arm/mach-qcom/Kconfig" -+ - source "arch/arm/mach-realview/Kconfig" - - source "arch/arm/mach-rockchip/Kconfig" ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -956,7 +956,7 @@ config DEBUG_STI_UART - - config DEBUG_MSM_UART - bool -- depends on ARCH_MSM -+ depends on ARCH_MSM || ARCH_QCOM - - config DEBUG_LL_INCLUDE - string ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -185,6 +185,7 @@ machine-$(CONFIG_ARCH_OMAP2PLUS) += omap - machine-$(CONFIG_ARCH_ORION5X) += orion5x - machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell - machine-$(CONFIG_ARCH_PXA) += pxa -+machine-$(CONFIG_ARCH_QCOM) += qcom - machine-$(CONFIG_ARCH_REALVIEW) += realview - machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip - machine-$(CONFIG_ARCH_RPC) += rpc ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -119,9 +119,6 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood- - kirkwood-ts219-6282.dtb - dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb - dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb --dtb-$(CONFIG_ARCH_MSM) += qcom-msm8660-surf.dtb \ -- qcom-msm8960-cdp.dtb \ -- qcom-apq8074-dragonboard.dtb - dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \ - armada-370-mirabox.dtb \ - armada-370-netgear-rn102.dtb \ -@@ -234,6 +231,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420 - dra7-evm.dtb - dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb - dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb -+dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \ -+ qcom-msm8960-cdp.dtb \ -+ qcom-apq8074-dragonboard.dtb - dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ - ste-hrefprev60-stuib.dtb \ - ste-hrefprev60-tvk.dtb \ ---- a/arch/arm/mach-msm/Kconfig -+++ b/arch/arm/mach-msm/Kconfig -@@ -1,50 +1,9 @@ --config ARCH_MSM -- bool -- --config ARCH_MSM_DT -- bool "Qualcomm MSM DT Support" if ARCH_MULTI_V7 -- select ARCH_MSM -- select ARCH_REQUIRE_GPIOLIB -- select CLKSRC_OF -- select GENERIC_CLOCKEVENTS -- help -- Support for Qualcomm's devicetree based MSM systems. -- - if ARCH_MSM - --menu "Qualcomm MSM SoC Selection" -- depends on ARCH_MSM_DT -- --config ARCH_MSM8X60 -- bool "Enable support for MSM8X60" -- select ARM_GIC -- select CPU_V7 -- select HAVE_SMP -- select MSM_SCM if SMP -- select CLKSRC_QCOM -- --config ARCH_MSM8960 -- bool "Enable support for MSM8960" -- select ARM_GIC -- select CPU_V7 -- select HAVE_SMP -- select MSM_SCM if SMP -- select CLKSRC_QCOM -- --config ARCH_MSM8974 -- bool "Enable support for MSM8974" -- select ARM_GIC -- select CPU_V7 -- select HAVE_ARM_ARCH_TIMER -- select HAVE_SMP -- select MSM_SCM if SMP -- --endmenu -- - choice - prompt "Qualcomm MSM SoC Type" - default ARCH_MSM7X00A -- depends on ARCH_MSM_NODT -+ depends on ARCH_MSM - - config ARCH_MSM7X00A - bool "MSM7x00A / MSM7x01A" -@@ -99,7 +58,7 @@ config MSM_VIC - bool - - menu "Qualcomm MSM Board Type" -- depends on ARCH_MSM_NODT -+ depends on ARCH_MSM - - config MACH_HALIBUT - depends on ARCH_MSM ---- a/arch/arm/mach-msm/Makefile -+++ b/arch/arm/mach-msm/Makefile -@@ -13,17 +13,11 @@ obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o - - obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o - obj-$(CONFIG_MSM_SMD) += last_radio_log.o --obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o -- --CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) -- --obj-$(CONFIG_SMP) += platsmp.o - - obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o - obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o - obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o - obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o - obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o --obj-$(CONFIG_ARCH_MSM_DT) += board-dt.o - obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o - obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o ---- a/arch/arm/mach-msm/board-dt.c -+++ /dev/null -@@ -1,41 +0,0 @@ --/* Copyright (c) 2010-2012,2013 The Linux Foundation. All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 and -- * only 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 --#include --#include -- --#include --#include -- --#include "common.h" -- --static const char * const msm_dt_match[] __initconst = { -- "qcom,msm8660-fluid", -- "qcom,msm8660-surf", -- "qcom,msm8960-cdp", -- NULL --}; -- --static const char * const apq8074_dt_match[] __initconst = { -- "qcom,apq8074-dragonboard", -- NULL --}; -- --DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)") -- .smp = smp_ops(msm_smp_ops), -- .dt_compat = msm_dt_match, --MACHINE_END -- --DT_MACHINE_START(APQ_DT, "Qualcomm MSM (Flattened Device Tree)") -- .dt_compat = apq8074_dt_match, --MACHINE_END ---- a/arch/arm/mach-msm/platsmp.c -+++ /dev/null -@@ -1,137 +0,0 @@ --/* -- * Copyright (C) 2002 ARM Ltd. -- * All Rights Reserved -- * Copyright (c) 2010, Code Aurora Forum. All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --#include --#include --#include --#include --#include --#include -- --#include --#include -- --#include "scm-boot.h" --#include "common.h" -- --#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0 --#define SCSS_CPU1CORE_RESET 0xD80 --#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 -- --extern void secondary_startup(void); -- --static DEFINE_SPINLOCK(boot_lock); -- --#ifdef CONFIG_HOTPLUG_CPU --static void __ref msm_cpu_die(unsigned int cpu) --{ -- wfi(); --} --#endif -- --static inline int get_core_count(void) --{ -- /* 1 + the PART[1:0] field of MIDR */ -- return ((read_cpuid_id() >> 4) & 3) + 1; --} -- --static void msm_secondary_init(unsigned int cpu) --{ -- /* -- * Synchronise with the boot thread. -- */ -- spin_lock(&boot_lock); -- spin_unlock(&boot_lock); --} -- --static void prepare_cold_cpu(unsigned int cpu) --{ -- int ret; -- ret = scm_set_boot_addr(virt_to_phys(secondary_startup), -- SCM_FLAG_COLDBOOT_CPU1); -- if (ret == 0) { -- void __iomem *sc1_base_ptr; -- sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2); -- if (sc1_base_ptr) { -- writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL); -- writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET); -- writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP); -- iounmap(sc1_base_ptr); -- } -- } else -- printk(KERN_DEBUG "Failed to set secondary core boot " -- "address\n"); --} -- --static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle) --{ -- static int cold_boot_done; -- -- /* Only need to bring cpu out of reset this way once */ -- if (cold_boot_done == false) { -- prepare_cold_cpu(cpu); -- cold_boot_done = true; -- } -- -- /* -- * set synchronisation state between this boot processor -- * and the secondary one -- */ -- spin_lock(&boot_lock); -- -- /* -- * Send the secondary CPU a soft interrupt, thereby causing -- * the boot monitor to read the system wide flags register, -- * and branch to the address found there. -- */ -- arch_send_wakeup_ipi_mask(cpumask_of(cpu)); -- -- /* -- * now the secondary core is starting up let it run its -- * calibrations, then wait for it to finish -- */ -- spin_unlock(&boot_lock); -- -- return 0; --} -- --/* -- * Initialise the CPU possible map early - this describes the CPUs -- * which may be present or become present in the system. The msm8x60 -- * does not support the ARM SCU, so just set the possible cpu mask to -- * NR_CPUS. -- */ --static void __init msm_smp_init_cpus(void) --{ -- unsigned int i, ncores = get_core_count(); -- -- if (ncores > nr_cpu_ids) { -- pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", -- ncores, nr_cpu_ids); -- ncores = nr_cpu_ids; -- } -- -- for (i = 0; i < ncores; i++) -- set_cpu_possible(i, true); --} -- --static void __init msm_smp_prepare_cpus(unsigned int max_cpus) --{ --} -- --struct smp_operations msm_smp_ops __initdata = { -- .smp_init_cpus = msm_smp_init_cpus, -- .smp_prepare_cpus = msm_smp_prepare_cpus, -- .smp_secondary_init = msm_secondary_init, -- .smp_boot_secondary = msm_boot_secondary, --#ifdef CONFIG_HOTPLUG_CPU -- .cpu_die = msm_cpu_die, --#endif --}; ---- a/arch/arm/mach-msm/scm-boot.c -+++ /dev/null -@@ -1,39 +0,0 @@ --/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 and -- * only 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. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- * 02110-1301, USA. -- */ -- --#include --#include -- --#include "scm.h" --#include "scm-boot.h" -- --/* -- * Set the cold/warm boot address for one of the CPU cores. -- */ --int scm_set_boot_addr(phys_addr_t addr, int flags) --{ -- struct { -- unsigned int flags; -- phys_addr_t addr; -- } cmd; -- -- cmd.addr = addr; -- cmd.flags = flags; -- return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, -- &cmd, sizeof(cmd), NULL, 0); --} --EXPORT_SYMBOL(scm_set_boot_addr); ---- a/arch/arm/mach-msm/scm-boot.h -+++ /dev/null -@@ -1,22 +0,0 @@ --/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 and -- * only 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 __MACH_SCM_BOOT_H --#define __MACH_SCM_BOOT_H -- --#define SCM_BOOT_ADDR 0x1 --#define SCM_FLAG_COLDBOOT_CPU1 0x1 --#define SCM_FLAG_WARMBOOT_CPU1 0x2 --#define SCM_FLAG_WARMBOOT_CPU0 0x4 -- --int scm_set_boot_addr(phys_addr_t addr, int flags); -- --#endif ---- a/arch/arm/mach-msm/scm.c -+++ /dev/null -@@ -1,299 +0,0 @@ --/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 and -- * only 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. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- * 02110-1301, USA. -- */ -- --#include --#include --#include --#include --#include --#include -- --#include -- --#include "scm.h" -- --/* Cache line size for msm8x60 */ --#define CACHELINESIZE 32 -- --#define SCM_ENOMEM -5 --#define SCM_EOPNOTSUPP -4 --#define SCM_EINVAL_ADDR -3 --#define SCM_EINVAL_ARG -2 --#define SCM_ERROR -1 --#define SCM_INTERRUPTED 1 -- --static DEFINE_MUTEX(scm_lock); -- --/** -- * struct scm_command - one SCM command buffer -- * @len: total available memory for command and response -- * @buf_offset: start of command buffer -- * @resp_hdr_offset: start of response buffer -- * @id: command to be executed -- * @buf: buffer returned from scm_get_command_buffer() -- * -- * An SCM command is laid out in memory as follows: -- * -- * ------------------- <--- struct scm_command -- * | command header | -- * ------------------- <--- scm_get_command_buffer() -- * | command buffer | -- * ------------------- <--- struct scm_response and -- * | response header | scm_command_to_response() -- * ------------------- <--- scm_get_response_buffer() -- * | response buffer | -- * ------------------- -- * -- * There can be arbitrary padding between the headers and buffers so -- * you should always use the appropriate scm_get_*_buffer() routines -- * to access the buffers in a safe manner. -- */ --struct scm_command { -- u32 len; -- u32 buf_offset; -- u32 resp_hdr_offset; -- u32 id; -- u32 buf[0]; --}; -- --/** -- * struct scm_response - one SCM response buffer -- * @len: total available memory for response -- * @buf_offset: start of response data relative to start of scm_response -- * @is_complete: indicates if the command has finished processing -- */ --struct scm_response { -- u32 len; -- u32 buf_offset; -- u32 is_complete; --}; -- --/** -- * alloc_scm_command() - Allocate an SCM command -- * @cmd_size: size of the command buffer -- * @resp_size: size of the response buffer -- * -- * Allocate an SCM command, including enough room for the command -- * and response headers as well as the command and response buffers. -- * -- * Returns a valid &scm_command on success or %NULL if the allocation fails. -- */ --static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size) --{ -- struct scm_command *cmd; -- size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + -- resp_size; -- -- cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); -- if (cmd) { -- cmd->len = len; -- cmd->buf_offset = offsetof(struct scm_command, buf); -- cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; -- } -- return cmd; --} -- --/** -- * free_scm_command() - Free an SCM command -- * @cmd: command to free -- * -- * Free an SCM command. -- */ --static inline void free_scm_command(struct scm_command *cmd) --{ -- kfree(cmd); --} -- --/** -- * scm_command_to_response() - Get a pointer to a scm_response -- * @cmd: command -- * -- * Returns a pointer to a response for a command. -- */ --static inline struct scm_response *scm_command_to_response( -- const struct scm_command *cmd) --{ -- return (void *)cmd + cmd->resp_hdr_offset; --} -- --/** -- * scm_get_command_buffer() - Get a pointer to a command buffer -- * @cmd: command -- * -- * Returns a pointer to the command buffer of a command. -- */ --static inline void *scm_get_command_buffer(const struct scm_command *cmd) --{ -- return (void *)cmd->buf; --} -- --/** -- * scm_get_response_buffer() - Get a pointer to a response buffer -- * @rsp: response -- * -- * Returns a pointer to a response buffer of a response. -- */ --static inline void *scm_get_response_buffer(const struct scm_response *rsp) --{ -- return (void *)rsp + rsp->buf_offset; --} -- --static int scm_remap_error(int err) --{ -- switch (err) { -- case SCM_ERROR: -- return -EIO; -- case SCM_EINVAL_ADDR: -- case SCM_EINVAL_ARG: -- return -EINVAL; -- case SCM_EOPNOTSUPP: -- return -EOPNOTSUPP; -- case SCM_ENOMEM: -- return -ENOMEM; -- } -- return -EINVAL; --} -- --static u32 smc(u32 cmd_addr) --{ -- int context_id; -- register u32 r0 asm("r0") = 1; -- register u32 r1 asm("r1") = (u32)&context_id; -- register u32 r2 asm("r2") = cmd_addr; -- do { -- asm volatile( -- __asmeq("%0", "r0") -- __asmeq("%1", "r0") -- __asmeq("%2", "r1") -- __asmeq("%3", "r2") --#ifdef REQUIRES_SEC -- ".arch_extension sec\n" --#endif -- "smc #0 @ switch to secure world\n" -- : "=r" (r0) -- : "r" (r0), "r" (r1), "r" (r2) -- : "r3"); -- } while (r0 == SCM_INTERRUPTED); -- -- return r0; --} -- --static int __scm_call(const struct scm_command *cmd) --{ -- int ret; -- u32 cmd_addr = virt_to_phys(cmd); -- -- /* -- * Flush the entire cache here so callers don't have to remember -- * to flush the cache when passing physical addresses to the secure -- * side in the buffer. -- */ -- flush_cache_all(); -- ret = smc(cmd_addr); -- if (ret < 0) -- ret = scm_remap_error(ret); -- -- return ret; --} -- --/** -- * scm_call() - Send an SCM command -- * @svc_id: service identifier -- * @cmd_id: command identifier -- * @cmd_buf: command buffer -- * @cmd_len: length of the command buffer -- * @resp_buf: response buffer -- * @resp_len: length of the response buffer -- * -- * Sends a command to the SCM and waits for the command to finish processing. -- */ --int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, -- void *resp_buf, size_t resp_len) --{ -- int ret; -- struct scm_command *cmd; -- struct scm_response *rsp; -- -- cmd = alloc_scm_command(cmd_len, resp_len); -- if (!cmd) -- return -ENOMEM; -- -- cmd->id = (svc_id << 10) | cmd_id; -- if (cmd_buf) -- memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); -- -- mutex_lock(&scm_lock); -- ret = __scm_call(cmd); -- mutex_unlock(&scm_lock); -- if (ret) -- goto out; -- -- rsp = scm_command_to_response(cmd); -- do { -- u32 start = (u32)rsp; -- u32 end = (u32)scm_get_response_buffer(rsp) + resp_len; -- start &= ~(CACHELINESIZE - 1); -- while (start < end) { -- asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) -- : "memory"); -- start += CACHELINESIZE; -- } -- } while (!rsp->is_complete); -- -- if (resp_buf) -- memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); --out: -- free_scm_command(cmd); -- return ret; --} --EXPORT_SYMBOL(scm_call); -- --u32 scm_get_version(void) --{ -- int context_id; -- static u32 version = -1; -- register u32 r0 asm("r0"); -- register u32 r1 asm("r1"); -- -- if (version != -1) -- return version; -- -- mutex_lock(&scm_lock); -- -- r0 = 0x1 << 8; -- r1 = (u32)&context_id; -- do { -- asm volatile( -- __asmeq("%0", "r0") -- __asmeq("%1", "r1") -- __asmeq("%2", "r0") -- __asmeq("%3", "r1") --#ifdef REQUIRES_SEC -- ".arch_extension sec\n" --#endif -- "smc #0 @ switch to secure world\n" -- : "=r" (r0), "=r" (r1) -- : "r" (r0), "r" (r1) -- : "r2", "r3"); -- } while (r0 == SCM_INTERRUPTED); -- -- version = r1; -- mutex_unlock(&scm_lock); -- -- return version; --} --EXPORT_SYMBOL(scm_get_version); ---- a/arch/arm/mach-msm/scm.h -+++ /dev/null -@@ -1,25 +0,0 @@ --/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 and -- * only 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 __MACH_SCM_H --#define __MACH_SCM_H -- --#define SCM_SVC_BOOT 0x1 --#define SCM_SVC_PIL 0x2 -- --extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, -- void *resp_buf, size_t resp_len); -- --#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) -- --extern u32 scm_get_version(void); -- --#endif ---- /dev/null -+++ b/arch/arm/mach-qcom/Kconfig -@@ -0,0 +1,33 @@ -+config ARCH_QCOM -+ bool "Qualcomm Support" if ARCH_MULTI_V7 -+ select ARCH_REQUIRE_GPIOLIB -+ select ARM_GIC -+ select CLKSRC_OF -+ select GENERIC_CLOCKEVENTS -+ select HAVE_SMP -+ select QCOM_SCM if SMP -+ help -+ Support for Qualcomm's devicetree based systems. -+ -+if ARCH_QCOM -+ -+menu "Qualcomm SoC Selection" -+ -+config ARCH_MSM8X60 -+ bool "Enable support for MSM8X60" -+ select CLKSRC_QCOM -+ -+config ARCH_MSM8960 -+ bool "Enable support for MSM8960" -+ select CLKSRC_QCOM -+ -+config ARCH_MSM8974 -+ bool "Enable support for MSM8974" -+ select HAVE_ARM_ARCH_TIMER -+ -+endmenu -+ -+config QCOM_SCM -+ bool -+ -+endif ---- /dev/null -+++ b/arch/arm/mach-qcom/Makefile -@@ -0,0 +1,5 @@ -+obj-y := board.o -+obj-$(CONFIG_SMP) += platsmp.o -+obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o -+ -+CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) ---- /dev/null -+++ b/arch/arm/mach-qcom/board.c -@@ -0,0 +1,40 @@ -+/* Copyright (c) 2010-2014 The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+ -+#include -+#include -+ -+extern struct smp_operations msm_smp_ops; -+ -+static const char * const qcom_dt_match[] __initconst = { -+ "qcom,msm8660-surf", -+ "qcom,msm8960-cdp", -+ NULL -+}; -+ -+static const char * const apq8074_dt_match[] __initconst = { -+ "qcom,apq8074-dragonboard", -+ NULL -+}; -+ -+DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)") -+ .smp = smp_ops(msm_smp_ops), -+ .dt_compat = qcom_dt_match, -+MACHINE_END -+ -+DT_MACHINE_START(APQ_DT, "Qualcomm (Flattened Device Tree)") -+ .dt_compat = apq8074_dt_match, -+MACHINE_END ---- /dev/null -+++ b/arch/arm/mach-qcom/platsmp.c -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (C) 2002 ARM Ltd. -+ * All Rights Reserved -+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved. -+ * Copyright (c) 2014 The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "scm-boot.h" -+ -+#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0 -+#define SCSS_CPU1CORE_RESET 0xD80 -+#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 -+ -+extern void secondary_startup(void); -+ -+static DEFINE_SPINLOCK(boot_lock); -+ -+#ifdef CONFIG_HOTPLUG_CPU -+static void __ref msm_cpu_die(unsigned int cpu) -+{ -+ wfi(); -+} -+#endif -+ -+static inline int get_core_count(void) -+{ -+ /* 1 + the PART[1:0] field of MIDR */ -+ return ((read_cpuid_id() >> 4) & 3) + 1; -+} -+ -+static void msm_secondary_init(unsigned int cpu) -+{ -+ /* -+ * Synchronise with the boot thread. -+ */ -+ spin_lock(&boot_lock); -+ spin_unlock(&boot_lock); -+} -+ -+static void prepare_cold_cpu(unsigned int cpu) -+{ -+ int ret; -+ ret = scm_set_boot_addr(virt_to_phys(secondary_startup), -+ SCM_FLAG_COLDBOOT_CPU1); -+ if (ret == 0) { -+ void __iomem *sc1_base_ptr; -+ sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2); -+ if (sc1_base_ptr) { -+ writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL); -+ writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET); -+ writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP); -+ iounmap(sc1_base_ptr); -+ } -+ } else -+ printk(KERN_DEBUG "Failed to set secondary core boot " -+ "address\n"); -+} -+ -+static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle) -+{ -+ static int cold_boot_done; -+ -+ /* Only need to bring cpu out of reset this way once */ -+ if (cold_boot_done == false) { -+ prepare_cold_cpu(cpu); -+ cold_boot_done = true; -+ } -+ -+ /* -+ * set synchronisation state between this boot processor -+ * and the secondary one -+ */ -+ spin_lock(&boot_lock); -+ -+ /* -+ * Send the secondary CPU a soft interrupt, thereby causing -+ * the boot monitor to read the system wide flags register, -+ * and branch to the address found there. -+ */ -+ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); -+ -+ /* -+ * now the secondary core is starting up let it run its -+ * calibrations, then wait for it to finish -+ */ -+ spin_unlock(&boot_lock); -+ -+ return 0; -+} -+ -+/* -+ * Initialise the CPU possible map early - this describes the CPUs -+ * which may be present or become present in the system. The msm8x60 -+ * does not support the ARM SCU, so just set the possible cpu mask to -+ * NR_CPUS. -+ */ -+static void __init msm_smp_init_cpus(void) -+{ -+ unsigned int i, ncores = get_core_count(); -+ -+ if (ncores > nr_cpu_ids) { -+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", -+ ncores, nr_cpu_ids); -+ ncores = nr_cpu_ids; -+ } -+ -+ for (i = 0; i < ncores; i++) -+ set_cpu_possible(i, true); -+} -+ -+static void __init msm_smp_prepare_cpus(unsigned int max_cpus) -+{ -+} -+ -+struct smp_operations msm_smp_ops __initdata = { -+ .smp_init_cpus = msm_smp_init_cpus, -+ .smp_prepare_cpus = msm_smp_prepare_cpus, -+ .smp_secondary_init = msm_secondary_init, -+ .smp_boot_secondary = msm_boot_secondary, -+#ifdef CONFIG_HOTPLUG_CPU -+ .cpu_die = msm_cpu_die, -+#endif -+}; ---- /dev/null -+++ b/arch/arm/mach-qcom/scm-boot.c -@@ -0,0 +1,39 @@ -+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ */ -+ -+#include -+#include -+ -+#include "scm.h" -+#include "scm-boot.h" -+ -+/* -+ * Set the cold/warm boot address for one of the CPU cores. -+ */ -+int scm_set_boot_addr(phys_addr_t addr, int flags) -+{ -+ struct { -+ unsigned int flags; -+ phys_addr_t addr; -+ } cmd; -+ -+ cmd.addr = addr; -+ cmd.flags = flags; -+ return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, -+ &cmd, sizeof(cmd), NULL, 0); -+} -+EXPORT_SYMBOL(scm_set_boot_addr); ---- /dev/null -+++ b/arch/arm/mach-qcom/scm-boot.h -@@ -0,0 +1,22 @@ -+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 __MACH_SCM_BOOT_H -+#define __MACH_SCM_BOOT_H -+ -+#define SCM_BOOT_ADDR 0x1 -+#define SCM_FLAG_COLDBOOT_CPU1 0x1 -+#define SCM_FLAG_WARMBOOT_CPU1 0x2 -+#define SCM_FLAG_WARMBOOT_CPU0 0x4 -+ -+int scm_set_boot_addr(phys_addr_t addr, int flags); -+ -+#endif ---- /dev/null -+++ b/arch/arm/mach-qcom/scm.c -@@ -0,0 +1,299 @@ -+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "scm.h" -+ -+/* Cache line size for msm8x60 */ -+#define CACHELINESIZE 32 -+ -+#define SCM_ENOMEM -5 -+#define SCM_EOPNOTSUPP -4 -+#define SCM_EINVAL_ADDR -3 -+#define SCM_EINVAL_ARG -2 -+#define SCM_ERROR -1 -+#define SCM_INTERRUPTED 1 -+ -+static DEFINE_MUTEX(scm_lock); -+ -+/** -+ * struct scm_command - one SCM command buffer -+ * @len: total available memory for command and response -+ * @buf_offset: start of command buffer -+ * @resp_hdr_offset: start of response buffer -+ * @id: command to be executed -+ * @buf: buffer returned from scm_get_command_buffer() -+ * -+ * An SCM command is laid out in memory as follows: -+ * -+ * ------------------- <--- struct scm_command -+ * | command header | -+ * ------------------- <--- scm_get_command_buffer() -+ * | command buffer | -+ * ------------------- <--- struct scm_response and -+ * | response header | scm_command_to_response() -+ * ------------------- <--- scm_get_response_buffer() -+ * | response buffer | -+ * ------------------- -+ * -+ * There can be arbitrary padding between the headers and buffers so -+ * you should always use the appropriate scm_get_*_buffer() routines -+ * to access the buffers in a safe manner. -+ */ -+struct scm_command { -+ u32 len; -+ u32 buf_offset; -+ u32 resp_hdr_offset; -+ u32 id; -+ u32 buf[0]; -+}; -+ -+/** -+ * struct scm_response - one SCM response buffer -+ * @len: total available memory for response -+ * @buf_offset: start of response data relative to start of scm_response -+ * @is_complete: indicates if the command has finished processing -+ */ -+struct scm_response { -+ u32 len; -+ u32 buf_offset; -+ u32 is_complete; -+}; -+ -+/** -+ * alloc_scm_command() - Allocate an SCM command -+ * @cmd_size: size of the command buffer -+ * @resp_size: size of the response buffer -+ * -+ * Allocate an SCM command, including enough room for the command -+ * and response headers as well as the command and response buffers. -+ * -+ * Returns a valid &scm_command on success or %NULL if the allocation fails. -+ */ -+static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size) -+{ -+ struct scm_command *cmd; -+ size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + -+ resp_size; -+ -+ cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); -+ if (cmd) { -+ cmd->len = len; -+ cmd->buf_offset = offsetof(struct scm_command, buf); -+ cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; -+ } -+ return cmd; -+} -+ -+/** -+ * free_scm_command() - Free an SCM command -+ * @cmd: command to free -+ * -+ * Free an SCM command. -+ */ -+static inline void free_scm_command(struct scm_command *cmd) -+{ -+ kfree(cmd); -+} -+ -+/** -+ * scm_command_to_response() - Get a pointer to a scm_response -+ * @cmd: command -+ * -+ * Returns a pointer to a response for a command. -+ */ -+static inline struct scm_response *scm_command_to_response( -+ const struct scm_command *cmd) -+{ -+ return (void *)cmd + cmd->resp_hdr_offset; -+} -+ -+/** -+ * scm_get_command_buffer() - Get a pointer to a command buffer -+ * @cmd: command -+ * -+ * Returns a pointer to the command buffer of a command. -+ */ -+static inline void *scm_get_command_buffer(const struct scm_command *cmd) -+{ -+ return (void *)cmd->buf; -+} -+ -+/** -+ * scm_get_response_buffer() - Get a pointer to a response buffer -+ * @rsp: response -+ * -+ * Returns a pointer to a response buffer of a response. -+ */ -+static inline void *scm_get_response_buffer(const struct scm_response *rsp) -+{ -+ return (void *)rsp + rsp->buf_offset; -+} -+ -+static int scm_remap_error(int err) -+{ -+ switch (err) { -+ case SCM_ERROR: -+ return -EIO; -+ case SCM_EINVAL_ADDR: -+ case SCM_EINVAL_ARG: -+ return -EINVAL; -+ case SCM_EOPNOTSUPP: -+ return -EOPNOTSUPP; -+ case SCM_ENOMEM: -+ return -ENOMEM; -+ } -+ return -EINVAL; -+} -+ -+static u32 smc(u32 cmd_addr) -+{ -+ int context_id; -+ register u32 r0 asm("r0") = 1; -+ register u32 r1 asm("r1") = (u32)&context_id; -+ register u32 r2 asm("r2") = cmd_addr; -+ do { -+ asm volatile( -+ __asmeq("%0", "r0") -+ __asmeq("%1", "r0") -+ __asmeq("%2", "r1") -+ __asmeq("%3", "r2") -+#ifdef REQUIRES_SEC -+ ".arch_extension sec\n" -+#endif -+ "smc #0 @ switch to secure world\n" -+ : "=r" (r0) -+ : "r" (r0), "r" (r1), "r" (r2) -+ : "r3"); -+ } while (r0 == SCM_INTERRUPTED); -+ -+ return r0; -+} -+ -+static int __scm_call(const struct scm_command *cmd) -+{ -+ int ret; -+ u32 cmd_addr = virt_to_phys(cmd); -+ -+ /* -+ * Flush the entire cache here so callers don't have to remember -+ * to flush the cache when passing physical addresses to the secure -+ * side in the buffer. -+ */ -+ flush_cache_all(); -+ ret = smc(cmd_addr); -+ if (ret < 0) -+ ret = scm_remap_error(ret); -+ -+ return ret; -+} -+ -+/** -+ * scm_call() - Send an SCM command -+ * @svc_id: service identifier -+ * @cmd_id: command identifier -+ * @cmd_buf: command buffer -+ * @cmd_len: length of the command buffer -+ * @resp_buf: response buffer -+ * @resp_len: length of the response buffer -+ * -+ * Sends a command to the SCM and waits for the command to finish processing. -+ */ -+int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, -+ void *resp_buf, size_t resp_len) -+{ -+ int ret; -+ struct scm_command *cmd; -+ struct scm_response *rsp; -+ -+ cmd = alloc_scm_command(cmd_len, resp_len); -+ if (!cmd) -+ return -ENOMEM; -+ -+ cmd->id = (svc_id << 10) | cmd_id; -+ if (cmd_buf) -+ memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); -+ -+ mutex_lock(&scm_lock); -+ ret = __scm_call(cmd); -+ mutex_unlock(&scm_lock); -+ if (ret) -+ goto out; -+ -+ rsp = scm_command_to_response(cmd); -+ do { -+ u32 start = (u32)rsp; -+ u32 end = (u32)scm_get_response_buffer(rsp) + resp_len; -+ start &= ~(CACHELINESIZE - 1); -+ while (start < end) { -+ asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) -+ : "memory"); -+ start += CACHELINESIZE; -+ } -+ } while (!rsp->is_complete); -+ -+ if (resp_buf) -+ memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); -+out: -+ free_scm_command(cmd); -+ return ret; -+} -+EXPORT_SYMBOL(scm_call); -+ -+u32 scm_get_version(void) -+{ -+ int context_id; -+ static u32 version = -1; -+ register u32 r0 asm("r0"); -+ register u32 r1 asm("r1"); -+ -+ if (version != -1) -+ return version; -+ -+ mutex_lock(&scm_lock); -+ -+ r0 = 0x1 << 8; -+ r1 = (u32)&context_id; -+ do { -+ asm volatile( -+ __asmeq("%0", "r0") -+ __asmeq("%1", "r1") -+ __asmeq("%2", "r0") -+ __asmeq("%3", "r1") -+#ifdef REQUIRES_SEC -+ ".arch_extension sec\n" -+#endif -+ "smc #0 @ switch to secure world\n" -+ : "=r" (r0), "=r" (r1) -+ : "r" (r0), "r" (r1) -+ : "r2", "r3"); -+ } while (r0 == SCM_INTERRUPTED); -+ -+ version = r1; -+ mutex_unlock(&scm_lock); -+ -+ return version; -+} -+EXPORT_SYMBOL(scm_get_version); ---- /dev/null -+++ b/arch/arm/mach-qcom/scm.h -@@ -0,0 +1,25 @@ -+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 __MACH_SCM_H -+#define __MACH_SCM_H -+ -+#define SCM_SVC_BOOT 0x1 -+#define SCM_SVC_PIL 0x2 -+ -+extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, -+ void *resp_buf, size_t resp_len); -+ -+#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) -+ -+extern u32 scm_get_version(void); -+ -+#endif diff --git a/target/linux/ipq806x/patches/0006-clocksource-qcom-split-building-of-legacy-vs-multipl.patch b/target/linux/ipq806x/patches/0006-clocksource-qcom-split-building-of-legacy-vs-multipl.patch deleted file mode 100644 index 79603f89c9..0000000000 --- a/target/linux/ipq806x/patches/0006-clocksource-qcom-split-building-of-legacy-vs-multipl.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 085d4b834dfced8580aab74707e30699b63e7c36 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Wed, 29 Jan 2014 17:01:37 -0600 -Subject: [PATCH 006/182] clocksource: qcom: split building of legacy vs - multiplatform support - -The majority of the clocksource code for the Qualcomm platform is shared -between newer (multiplatform) and older platforms. However there is a bit -of code that isn't, so only build it for the appropriate config. - -Acked-by: Olof Johansson -Signed-off-by: Kumar Gala ---- - drivers/clocksource/qcom-timer.c | 23 ++++++++++++----------- - 1 file changed, 12 insertions(+), 11 deletions(-) - ---- a/drivers/clocksource/qcom-timer.c -+++ b/drivers/clocksource/qcom-timer.c -@@ -106,15 +106,6 @@ static notrace cycle_t msm_read_timer_co - return readl_relaxed(source_base + TIMER_COUNT_VAL); - } - --static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) --{ -- /* -- * Shift timer count down by a constant due to unreliable lower bits -- * on some targets. -- */ -- return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; --} -- - static struct clocksource msm_clocksource = { - .name = "dg_timer", - .rating = 300, -@@ -228,7 +219,7 @@ err: - sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz); - } - --#ifdef CONFIG_OF -+#ifdef CONFIG_ARCH_QCOM - static void __init msm_dt_timer_init(struct device_node *np) - { - u32 freq; -@@ -281,7 +272,7 @@ static void __init msm_dt_timer_init(str - } - CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); - CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); --#endif -+#else - - static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source, - u32 sts) -@@ -301,6 +292,15 @@ static int __init msm_timer_map(phys_add - return 0; - } - -+static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) -+{ -+ /* -+ * Shift timer count down by a constant due to unreliable lower bits -+ * on some targets. -+ */ -+ return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; -+} -+ - void __init msm7x01_timer_init(void) - { - struct clocksource *cs = &msm_clocksource; -@@ -327,3 +327,4 @@ void __init qsd8x50_timer_init(void) - return; - msm_timer_init(19200000 / 4, 32, 7, false); - } -+#endif diff --git a/target/linux/ipq806x/patches/0007-ARM-qcom-Rename-various-msm-prefixed-functions-to-qc.patch b/target/linux/ipq806x/patches/0007-ARM-qcom-Rename-various-msm-prefixed-functions-to-qc.patch deleted file mode 100644 index cab5bcd203..0000000000 --- a/target/linux/ipq806x/patches/0007-ARM-qcom-Rename-various-msm-prefixed-functions-to-qc.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 35eb6f73546d3b9475652a38fa641bd1a05a1ea1 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Tue, 4 Feb 2014 15:38:45 -0600 -Subject: [PATCH 007/182] ARM: qcom: Rename various msm prefixed functions to - qcom - -As mach-qcom will support a number of different Qualcomm SoC platforms -we replace the msm prefix on function names with qcom to be a bit more -generic. - -Signed-off-by: Kumar Gala ---- - arch/arm/mach-qcom/board.c | 4 ++-- - arch/arm/mach-qcom/platsmp.c | 22 +++++++++++----------- - 2 files changed, 13 insertions(+), 13 deletions(-) - ---- a/arch/arm/mach-qcom/board.c -+++ b/arch/arm/mach-qcom/board.c -@@ -17,7 +17,7 @@ - #include - #include - --extern struct smp_operations msm_smp_ops; -+extern struct smp_operations qcom_smp_ops; - - static const char * const qcom_dt_match[] __initconst = { - "qcom,msm8660-surf", -@@ -31,7 +31,7 @@ static const char * const apq8074_dt_mat - }; - - DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)") -- .smp = smp_ops(msm_smp_ops), -+ .smp = smp_ops(qcom_smp_ops), - .dt_compat = qcom_dt_match, - MACHINE_END - ---- a/arch/arm/mach-qcom/platsmp.c -+++ b/arch/arm/mach-qcom/platsmp.c -@@ -30,7 +30,7 @@ extern void secondary_startup(void); - static DEFINE_SPINLOCK(boot_lock); - - #ifdef CONFIG_HOTPLUG_CPU --static void __ref msm_cpu_die(unsigned int cpu) -+static void __ref qcom_cpu_die(unsigned int cpu) - { - wfi(); - } -@@ -42,7 +42,7 @@ static inline int get_core_count(void) - return ((read_cpuid_id() >> 4) & 3) + 1; - } - --static void msm_secondary_init(unsigned int cpu) -+static void qcom_secondary_init(unsigned int cpu) - { - /* - * Synchronise with the boot thread. -@@ -70,7 +70,7 @@ static void prepare_cold_cpu(unsigned in - "address\n"); - } - --static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle) -+static int qcom_boot_secondary(unsigned int cpu, struct task_struct *idle) - { - static int cold_boot_done; - -@@ -108,7 +108,7 @@ static int msm_boot_secondary(unsigned i - * does not support the ARM SCU, so just set the possible cpu mask to - * NR_CPUS. - */ --static void __init msm_smp_init_cpus(void) -+static void __init qcom_smp_init_cpus(void) - { - unsigned int i, ncores = get_core_count(); - -@@ -122,16 +122,16 @@ static void __init msm_smp_init_cpus(voi - set_cpu_possible(i, true); - } - --static void __init msm_smp_prepare_cpus(unsigned int max_cpus) -+static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) - { - } - --struct smp_operations msm_smp_ops __initdata = { -- .smp_init_cpus = msm_smp_init_cpus, -- .smp_prepare_cpus = msm_smp_prepare_cpus, -- .smp_secondary_init = msm_secondary_init, -- .smp_boot_secondary = msm_boot_secondary, -+struct smp_operations qcom_smp_ops __initdata = { -+ .smp_init_cpus = qcom_smp_init_cpus, -+ .smp_prepare_cpus = qcom_smp_prepare_cpus, -+ .smp_secondary_init = qcom_secondary_init, -+ .smp_boot_secondary = qcom_boot_secondary, - #ifdef CONFIG_HOTPLUG_CPU -- .cpu_die = msm_cpu_die, -+ .cpu_die = qcom_cpu_die, - #endif - }; diff --git a/target/linux/ipq806x/patches/0008-ARM-Introduce-CPU_METHOD_OF_DECLARE-for-cpu-hotplug-.patch b/target/linux/ipq806x/patches/0008-ARM-Introduce-CPU_METHOD_OF_DECLARE-for-cpu-hotplug-.patch deleted file mode 100644 index b4a8b4b5ef..0000000000 --- a/target/linux/ipq806x/patches/0008-ARM-Introduce-CPU_METHOD_OF_DECLARE-for-cpu-hotplug-.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 48f17325fef9cbebc5cb39aa78f4c1caff5d7b16 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Wed, 30 Oct 2013 18:21:09 -0700 -Subject: [PATCH 008/182] ARM: Introduce CPU_METHOD_OF_DECLARE() for cpu - hotplug/smp - -The goal of multi-platform kernels is to remove the need for mach -directories and machine descriptors. To further that goal, -introduce CPU_METHOD_OF_DECLARE() to allow cpu hotplug/smp -support to be separated from the machine descriptors. -Implementers should specify an enable-method property in their -cpus node and then implement a matching set of smp_ops in their -hotplug/smp code, wiring it up with the CPU_METHOD_OF_DECLARE() -macro. When the kernel is compiled we'll collect all the -enable-method smp_ops into one section for use at boot. - -At boot time we'll look for an enable-method in each cpu node and -try to match that against all known CPU enable methods in the -kernel. If there are no enable-methods in the cpu nodes we -fallback to the cpus node and try to use any enable-method found -there. If that doesn't work we fall back to the old way of using -the machine descriptor. - -Acked-by: Mark Rutland -Cc: Russell King -Cc: -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/include/asm/smp.h | 9 +++++++++ - arch/arm/kernel/devtree.c | 40 +++++++++++++++++++++++++++++++++++++ - include/asm-generic/vmlinux.lds.h | 10 ++++++++++ - 3 files changed, 59 insertions(+) - ---- a/arch/arm/include/asm/smp.h -+++ b/arch/arm/include/asm/smp.h -@@ -114,6 +114,15 @@ struct smp_operations { - #endif - }; - -+struct of_cpu_method { -+ const char *method; -+ struct smp_operations *ops; -+}; -+ -+#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \ -+ static const struct of_cpu_method __cpu_method_of_table_##name \ -+ __used __section(__cpu_method_of_table) \ -+ = { .method = _method, .ops = _ops } - /* - * set platform specific SMP operations - */ ---- a/arch/arm/kernel/devtree.c -+++ b/arch/arm/kernel/devtree.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -63,6 +64,34 @@ void __init arm_dt_memblock_reserve(void - } - } - -+#ifdef CONFIG_SMP -+extern struct of_cpu_method __cpu_method_of_table_begin[]; -+extern struct of_cpu_method __cpu_method_of_table_end[]; -+ -+static int __init set_smp_ops_by_method(struct device_node *node) -+{ -+ const char *method; -+ struct of_cpu_method *m = __cpu_method_of_table_begin; -+ -+ if (of_property_read_string(node, "enable-method", &method)) -+ return 0; -+ -+ for (; m < __cpu_method_of_table_end; m++) -+ if (!strcmp(m->method, method)) { -+ smp_set_ops(m->ops); -+ return 1; -+ } -+ -+ return 0; -+} -+#else -+static inline int set_smp_ops_by_method(struct device_node *node) -+{ -+ return 1; -+} -+#endif -+ -+ - /* - * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree - * and builds the cpu logical map array containing MPIDR values related to -@@ -79,6 +108,7 @@ void __init arm_dt_init_cpu_maps(void) - * read as 0. - */ - struct device_node *cpu, *cpus; -+ int found_method = 0; - u32 i, j, cpuidx = 1; - u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0; - -@@ -150,8 +180,18 @@ void __init arm_dt_init_cpu_maps(void) - } - - tmp_map[i] = hwid; -+ -+ if (!found_method) -+ found_method = set_smp_ops_by_method(cpu); - } - -+ /* -+ * Fallback to an enable-method in the cpus node if nothing found in -+ * a cpu node. -+ */ -+ if (!found_method) -+ set_smp_ops_by_method(cpus); -+ - if (!bootcpu_valid) { - pr_warn("DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n"); - return; ---- a/include/asm-generic/vmlinux.lds.h -+++ b/include/asm-generic/vmlinux.lds.h -@@ -177,6 +177,15 @@ - #define CLK_OF_TABLES() - #endif - -+#ifdef CONFIG_SMP -+#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \ -+ VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \ -+ *(__cpu_method_of_table) \ -+ VMLINUX_SYMBOL(__cpu_method_of_table_end) = .; -+#else -+#define CPU_METHOD_OF_TABLES() -+#endif -+ - #define KERNEL_DTB() \ - STRUCT_ALIGN(); \ - VMLINUX_SYMBOL(__dtb_start) = .; \ -@@ -502,6 +511,7 @@ - MEM_DISCARD(init.rodata) \ - CLK_OF_TABLES() \ - CLKSRC_OF_TABLES() \ -+ CPU_METHOD_OF_TABLES() \ - KERNEL_DTB() \ - IRQCHIP_OF_MATCH_TABLE() - diff --git a/target/linux/ipq806x/patches/0009-ARM-qcom-Re-organize-platsmp-to-make-it-extensible.patch b/target/linux/ipq806x/patches/0009-ARM-qcom-Re-organize-platsmp-to-make-it-extensible.patch deleted file mode 100644 index 4bab4c962b..0000000000 --- a/target/linux/ipq806x/patches/0009-ARM-qcom-Re-organize-platsmp-to-make-it-extensible.patch +++ /dev/null @@ -1,241 +0,0 @@ -From 391848e75f8b0ba14816da1ac8f2d838fd0d5744 Mon Sep 17 00:00:00 2001 -From: Rohit Vaswani -Date: Tue, 21 May 2013 19:13:29 -0700 -Subject: [PATCH 009/182] ARM: qcom: Re-organize platsmp to make it extensible - -This makes it easy to add SMP support for new devices by keying -on a device node for the release sequence. We add the -enable-method property for the cpus property to specify that we -want to use the gcc-msm8660 release sequence (which is going to -look for the global clock controller device node to map some -Scorpion specific power and control registers). We also remove -the nr_cpus detection code as that is done generically in the DT -CPU detection code. - -Signed-off-by: Rohit Vaswani -[sboyd: Port to CPU_METHOD_OF_DECLARE] -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/mach-msm/common.h | 2 - - arch/arm/mach-qcom/board.c | 14 ----- - arch/arm/mach-qcom/platsmp.c | 118 +++++++++++++++++++++++------------------- - 3 files changed, 65 insertions(+), 69 deletions(-) - ---- a/arch/arm/mach-msm/common.h -+++ b/arch/arm/mach-msm/common.h -@@ -23,8 +23,6 @@ extern void msm_map_qsd8x50_io(void); - extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size, - unsigned int mtype, void *caller); - --extern struct smp_operations msm_smp_ops; -- - struct msm_mmc_platform_data; - - extern void msm_add_devices(void); ---- a/arch/arm/mach-qcom/board.c -+++ b/arch/arm/mach-qcom/board.c -@@ -11,30 +11,16 @@ - */ - - #include --#include --#include - - #include --#include -- --extern struct smp_operations qcom_smp_ops; - - static const char * const qcom_dt_match[] __initconst = { - "qcom,msm8660-surf", - "qcom,msm8960-cdp", -- NULL --}; -- --static const char * const apq8074_dt_match[] __initconst = { - "qcom,apq8074-dragonboard", - NULL - }; - - DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)") -- .smp = smp_ops(qcom_smp_ops), - .dt_compat = qcom_dt_match, - MACHINE_END -- --DT_MACHINE_START(APQ_DT, "Qualcomm (Flattened Device Tree)") -- .dt_compat = apq8074_dt_match, --MACHINE_END ---- a/arch/arm/mach-qcom/platsmp.c -+++ b/arch/arm/mach-qcom/platsmp.c -@@ -13,17 +13,18 @@ - #include - #include - #include -+#include -+#include - #include - #include - --#include - #include - - #include "scm-boot.h" - --#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0 --#define SCSS_CPU1CORE_RESET 0xD80 --#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 -+#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0 -+#define SCSS_CPU1CORE_RESET 0x2d80 -+#define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64 - - extern void secondary_startup(void); - -@@ -36,12 +37,6 @@ static void __ref qcom_cpu_die(unsigned - } - #endif - --static inline int get_core_count(void) --{ -- /* 1 + the PART[1:0] field of MIDR */ -- return ((read_cpuid_id() >> 4) & 3) + 1; --} -- - static void qcom_secondary_init(unsigned int cpu) - { - /* -@@ -51,33 +46,41 @@ static void qcom_secondary_init(unsigned - spin_unlock(&boot_lock); - } - --static void prepare_cold_cpu(unsigned int cpu) -+static int scss_release_secondary(unsigned int cpu) - { -- int ret; -- ret = scm_set_boot_addr(virt_to_phys(secondary_startup), -- SCM_FLAG_COLDBOOT_CPU1); -- if (ret == 0) { -- void __iomem *sc1_base_ptr; -- sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2); -- if (sc1_base_ptr) { -- writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL); -- writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET); -- writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP); -- iounmap(sc1_base_ptr); -- } -- } else -- printk(KERN_DEBUG "Failed to set secondary core boot " -- "address\n"); -+ struct device_node *node; -+ void __iomem *base; -+ -+ node = of_find_compatible_node(NULL, NULL, "qcom,gcc-msm8660"); -+ if (!node) { -+ pr_err("%s: can't find node\n", __func__); -+ return -ENXIO; -+ } -+ -+ base = of_iomap(node, 0); -+ of_node_put(node); -+ if (!base) -+ return -ENOMEM; -+ -+ writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL); -+ writel_relaxed(0, base + SCSS_CPU1CORE_RESET); -+ writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP); -+ mb(); -+ iounmap(base); -+ -+ return 0; - } - --static int qcom_boot_secondary(unsigned int cpu, struct task_struct *idle) -+static DEFINE_PER_CPU(int, cold_boot_done); -+ -+static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) - { -- static int cold_boot_done; -+ int ret = 0; - -- /* Only need to bring cpu out of reset this way once */ -- if (cold_boot_done == false) { -- prepare_cold_cpu(cpu); -- cold_boot_done = true; -+ if (!per_cpu(cold_boot_done, cpu)) { -+ ret = func(cpu); -+ if (!ret) -+ per_cpu(cold_boot_done, cpu) = true; - } - - /* -@@ -99,39 +102,48 @@ static int qcom_boot_secondary(unsigned - */ - spin_unlock(&boot_lock); - -- return 0; -+ return ret; - } - --/* -- * Initialise the CPU possible map early - this describes the CPUs -- * which may be present or become present in the system. The msm8x60 -- * does not support the ARM SCU, so just set the possible cpu mask to -- * NR_CPUS. -- */ --static void __init qcom_smp_init_cpus(void) --{ -- unsigned int i, ncores = get_core_count(); -- -- if (ncores > nr_cpu_ids) { -- pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", -- ncores, nr_cpu_ids); -- ncores = nr_cpu_ids; -- } -- -- for (i = 0; i < ncores; i++) -- set_cpu_possible(i, true); -+static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) -+{ -+ return qcom_boot_secondary(cpu, scss_release_secondary); - } - - static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) - { -+ int cpu, map; -+ unsigned int flags = 0; -+ static const int cold_boot_flags[] = { -+ 0, -+ SCM_FLAG_COLDBOOT_CPU1, -+ }; -+ -+ for_each_present_cpu(cpu) { -+ map = cpu_logical_map(cpu); -+ if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) { -+ set_cpu_present(cpu, false); -+ continue; -+ } -+ flags |= cold_boot_flags[map]; -+ } -+ -+ if (scm_set_boot_addr(virt_to_phys(secondary_startup), flags)) { -+ for_each_present_cpu(cpu) { -+ if (cpu == smp_processor_id()) -+ continue; -+ set_cpu_present(cpu, false); -+ } -+ pr_warn("Failed to set CPU boot address, disabling SMP\n"); -+ } - } - --struct smp_operations qcom_smp_ops __initdata = { -- .smp_init_cpus = qcom_smp_init_cpus, -+static struct smp_operations smp_msm8660_ops __initdata = { - .smp_prepare_cpus = qcom_smp_prepare_cpus, - .smp_secondary_init = qcom_secondary_init, -- .smp_boot_secondary = qcom_boot_secondary, -+ .smp_boot_secondary = msm8660_boot_secondary, - #ifdef CONFIG_HOTPLUG_CPU - .cpu_die = qcom_cpu_die, - #endif - }; -+CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops); diff --git a/target/linux/ipq806x/patches/0179-spi-qup-Add-DMA-capabilities.patch b/target/linux/ipq806x/patches/001-spi-qup-Add-DMA-capabilities.patch similarity index 81% rename from target/linux/ipq806x/patches/0179-spi-qup-Add-DMA-capabilities.patch rename to target/linux/ipq806x/patches/001-spi-qup-Add-DMA-capabilities.patch index 2f7d318aab..62badd5387 100644 --- a/target/linux/ipq806x/patches/0179-spi-qup-Add-DMA-capabilities.patch +++ b/target/linux/ipq806x/patches/001-spi-qup-Add-DMA-capabilities.patch @@ -1,17 +1,55 @@ -From 8322bafdcee1d7eaf15540ff013415bff1eacb28 Mon Sep 17 00:00:00 2001 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: spi: qup: Add DMA capabilities From: Andy Gross -Date: Thu, 26 Jun 2014 10:50:24 -0500 -Subject: [PATCH 179/182] spi: qup: Add DMA capabilities +X-Patchwork-Id: 4432401 +Message-Id: <1403816781-31008-1-git-send-email-agross@codeaurora.org> +To: Mark Brown +Cc: linux-spi@vger.kernel.org, Sagar Dharia , + Daniel Sneddon , + Bjorn Andersson , + "Ivan T. Ivanov" , + linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-arm-msm@vger.kernel.org, Andy Gross +Date: Thu, 26 Jun 2014 16:06:21 -0500 This patch adds DMA capabilities to the spi-qup driver. If DMA channels are present, the QUP will use DMA instead of block mode for transfers to/from SPI -peripherals for transactions larger greater than the length of a block. +peripherals for transactions larger than the length of a block. Signed-off-by: Andy Gross ---- - drivers/spi/spi-qup.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 340 insertions(+), 21 deletions(-) +--- +.../devicetree/bindings/spi/qcom,spi-qup.txt | 10 + + drivers/spi/spi-qup.c | 361 ++++++++++++++++++-- + 2 files changed, 350 insertions(+), 21 deletions(-) + +--- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt ++++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt +@@ -27,6 +27,11 @@ Optional properties: + - spi-max-frequency: Specifies maximum SPI clock frequency, + Units - Hz. Definition as per + Documentation/devicetree/bindings/spi/spi-bus.txt ++- dmas : Two DMA channel specifiers following the convention outlined ++ in bindings/dma/dma.txt ++- dma-names: Names for the dma channels, if present. There must be at ++ least one channel named "tx" for transmit and named "rx" for ++ receive. + - num-cs: total number of chipselects + - cs-gpios: should specify GPIOs used for chipselects. + The gpios will be referred to as reg = in the SPI child +@@ -51,6 +56,10 @@ Example: + clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; + clock-names = "core", "iface"; + ++ dmas = <&blsp2_bam 2>, ++ <&blsp2_bam 3>; ++ dma-names = "rx", "tx"; ++ + pinctrl-names = "default"; + pinctrl-0 = <&spi8_default>; + --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -22,6 +22,8 @@ @@ -32,22 +70,25 @@ Signed-off-by: Andy Gross /* high speed mode is when bus rate is greater then 26MHz */ #define SPI_HS_MIN_RATE 26000000 #define SPI_MAX_RATE 50000000 -@@ -143,6 +147,14 @@ struct spi_qup { +@@ -143,6 +147,17 @@ struct spi_qup { int tx_bytes; int rx_bytes; int qup_v1; ++ + int use_dma; + + struct dma_chan *rx_chan; + struct dma_slave_config rx_conf; + struct dma_chan *tx_chan; + struct dma_slave_config tx_conf; -+ void *dummy; ++ dma_addr_t rx_dma; ++ dma_addr_t tx_dma; ++ void *dummy; + atomic_t dma_outstanding; }; -@@ -266,6 +278,221 @@ static void spi_qup_fifo_write(struct sp +@@ -266,6 +281,221 @@ static void spi_qup_fifo_write(struct sp } } @@ -269,7 +310,7 @@ Signed-off-by: Andy Gross static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) { struct spi_qup *controller = dev_id; -@@ -315,11 +542,13 @@ static irqreturn_t spi_qup_qup_irq(int i +@@ -315,11 +545,13 @@ static irqreturn_t spi_qup_qup_irq(int i error = -EIO; } @@ -287,7 +328,7 @@ Signed-off-by: Andy Gross spin_lock_irqsave(&controller->lock, flags); controller->error = error; -@@ -339,6 +568,8 @@ static int spi_qup_io_config(struct spi_ +@@ -339,6 +571,8 @@ static int spi_qup_io_config(struct spi_ struct spi_qup *controller = spi_master_get_devdata(spi->master); u32 config, iomode, mode; int ret, n_words, w_size; @@ -296,21 +337,19 @@ Signed-off-by: Andy Gross if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { dev_err(controller->dev, "too big size for loopback %d > %d\n", -@@ -367,6 +598,13 @@ static int spi_qup_io_config(struct spi_ +@@ -367,6 +601,11 @@ static int spi_qup_io_config(struct spi_ n_words = xfer->len / w_size; controller->w_size = w_size; + if (controller->rx_chan && + IS_ALIGNED((size_t)xfer->tx_buf, dma_align) && -+ IS_ALIGNED((size_t)xfer->rx_buf, dma_align) && -+ !is_vmalloc_addr(xfer->tx_buf) && -+ !is_vmalloc_addr(xfer->rx_buf)) ++ IS_ALIGNED((size_t)xfer->rx_buf, dma_align)) + dma_available = 1; + if (n_words <= (controller->in_fifo_sz / sizeof(u32))) { mode = QUP_IO_M_MODE_FIFO; writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT); -@@ -374,19 +612,30 @@ static int spi_qup_io_config(struct spi_ +@@ -374,19 +613,31 @@ static int spi_qup_io_config(struct spi_ /* must be zero for FIFO */ writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); @@ -335,6 +374,7 @@ Signed-off-by: Andy Gross /* Set input and output transfer mode */ iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK); - iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN); ++ + if (!controller->use_dma) + iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN); + else @@ -343,7 +383,7 @@ Signed-off-by: Andy Gross iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); -@@ -419,11 +668,20 @@ static int spi_qup_io_config(struct spi_ +@@ -419,6 +670,14 @@ static int spi_qup_io_config(struct spi_ config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N); config |= xfer->bits_per_word - 1; config |= QUP_CONFIG_SPI_MODE; @@ -358,13 +398,7 @@ Signed-off-by: Andy Gross writel_relaxed(config, controller->base + QUP_CONFIG); /* only write to OPERATIONAL_MASK when register is present */ - if (!controller->qup_v1) - writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK); -+ - return 0; - } - -@@ -452,26 +710,32 @@ static int spi_qup_transfer_one(struct s +@@ -452,25 +711,29 @@ static int spi_qup_transfer_one(struct s controller->tx_bytes = 0; spin_unlock_irqrestore(&controller->lock, flags); @@ -403,16 +437,13 @@ Signed-off-by: Andy Gross - if (!wait_for_completion_timeout(&controller->done, timeout)) - ret = -ETIMEDOUT; -+ if (!ret && !wait_for_completion_timeout(&controller->done, -+ timeout)) ++ if (!wait_for_completion_timeout(&controller->done, timeout)) + ret = -ETIMEDOUT; + } exit: -+ spi_qup_set_state(controller, QUP_STATE_RESET); spin_lock_irqsave(&controller->lock, flags); - controller->xfer = NULL; -@@ -553,6 +817,7 @@ static int spi_qup_probe(struct platform +@@ -553,6 +816,7 @@ static int spi_qup_probe(struct platform master->transfer_one = spi_qup_transfer_one; master->dev.of_node = pdev->dev.of_node; master->auto_runtime_pm = true; @@ -420,9 +451,9 @@ Signed-off-by: Andy Gross platform_set_drvdata(pdev, master); -@@ -612,6 +877,55 @@ static int spi_qup_probe(struct platform - writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN, - base + SPI_ERROR_FLAGS_EN); +@@ -618,6 +882,56 @@ static int spi_qup_probe(struct platform + QUP_ERROR_INPUT_UNDER_RUN | QUP_ERROR_OUTPUT_UNDER_RUN, + base + QUP_ERROR_FLAGS_EN); + /* allocate dma resources, if available */ + controller->rx_chan = dma_request_slave_channel(&pdev->dev, "rx"); @@ -473,9 +504,10 @@ Signed-off-by: Andy Gross + } + } + - /* if earlier version of the QUP, disable INPUT_OVERRUN */ - if (controller->qup_v1) - writel_relaxed(QUP_ERROR_OUTPUT_OVER_RUN | ++ + writel_relaxed(0, base + SPI_CONFIG); + writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL); + @@ -730,6 +1044,11 @@ static int spi_qup_remove(struct platfor if (ret) return ret; diff --git a/target/linux/ipq806x/patches/0010-devicetree-bindings-Document-Krait-Scorpion-cpus-and.patch b/target/linux/ipq806x/patches/0010-devicetree-bindings-Document-Krait-Scorpion-cpus-and.patch deleted file mode 100644 index 751aa8510f..0000000000 --- a/target/linux/ipq806x/patches/0010-devicetree-bindings-Document-Krait-Scorpion-cpus-and.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 236d07c7bb0c758ea40ea0110d37306d2e7d9a4b Mon Sep 17 00:00:00 2001 -From: Rohit Vaswani -Date: Thu, 31 Oct 2013 17:26:33 -0700 -Subject: [PATCH 010/182] devicetree: bindings: Document Krait/Scorpion cpus - and enable-method - -Scorpion and Krait don't use the spin-table enable-method. -Instead they rely on mmio register accesses to enable power and -clocks to bring CPUs out of reset. Document their enable-methods. - -Cc: -Signed-off-by: Rohit Vaswani -[sboyd: Split off into separate patch, renamed methods to -match compatible nodes] -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - Documentation/devicetree/bindings/arm/cpus.txt | 25 +++++++++++++++++++++++- - 1 file changed, 24 insertions(+), 1 deletion(-) - ---- a/Documentation/devicetree/bindings/arm/cpus.txt -+++ b/Documentation/devicetree/bindings/arm/cpus.txt -@@ -180,7 +180,11 @@ nodes to be present and contain the prop - be one of: - "spin-table" - "psci" -- # On ARM 32-bit systems this property is optional. -+ # On ARM 32-bit systems this property is optional and -+ can be one of: -+ "qcom,gcc-msm8660" -+ "qcom,kpss-acc-v1" -+ "qcom,kpss-acc-v2" - - - cpu-release-addr - Usage: required for systems that have an "enable-method" -@@ -191,6 +195,21 @@ nodes to be present and contain the prop - property identifying a 64-bit zero-initialised - memory location. - -+ - qcom,saw -+ Usage: required for systems that have an "enable-method" -+ property value of "qcom,kpss-acc-v1" or -+ "qcom,kpss-acc-v2" -+ Value type: -+ Definition: Specifies the SAW[1] node associated with this CPU. -+ -+ - qcom,acc -+ Usage: required for systems that have an "enable-method" -+ property value of "qcom,kpss-acc-v1" or -+ "qcom,kpss-acc-v2" -+ Value type: -+ Definition: Specifies the ACC[2] node associated with this CPU. -+ -+ - Example 1 (dual-cluster big.LITTLE system 32-bit): - - cpus { -@@ -382,3 +401,7 @@ cpus { - cpu-release-addr = <0 0x20000000>; - }; - }; -+ -+-- -+[1] arm/msm/qcom,saw2.txt -+[2] arm/msm/qcom,kpss-acc.txt diff --git a/target/linux/ipq806x/patches/0011-devicetree-bindings-Document-qcom-kpss-acc.patch b/target/linux/ipq806x/patches/0011-devicetree-bindings-Document-qcom-kpss-acc.patch deleted file mode 100644 index dfd4c32861..0000000000 --- a/target/linux/ipq806x/patches/0011-devicetree-bindings-Document-qcom-kpss-acc.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 3a4fe9a3a4aff8b1f1c3685bc9b6adbe739d7367 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 31 Oct 2013 18:20:30 -0700 -Subject: [PATCH 011/182] devicetree: bindings: Document qcom,kpss-acc - -The kpss acc binding describes the clock, reset, and power domain -controller for a Krait CPU. - -Cc: -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - .../devicetree/bindings/arm/msm/qcom,kpss-acc.txt | 30 ++++++++++++++++++++ - 1 file changed, 30 insertions(+) - create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt -@@ -0,0 +1,30 @@ -+Krait Processor Sub-system (KPSS) Application Clock Controller (ACC) -+ -+The KPSS ACC provides clock, power domain, and reset control to a Krait CPU. -+There is one ACC register region per CPU within the KPSS remapped region as -+well as an alias register region that remaps accesses to the ACC associated -+with the CPU accessing the region. -+ -+PROPERTIES -+ -+- compatible: -+ Usage: required -+ Value type: -+ Definition: should be one of: -+ "qcom,kpss-acc-v1" -+ "qcom,kpss-acc-v2" -+ -+- reg: -+ Usage: required -+ Value type: -+ Definition: the first element specifies the base address and size of -+ the register region. An optional second element specifies -+ the base address and size of the alias register region. -+ -+Example: -+ -+ clock-controller@2088000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0x02088000 0x1000>, -+ <0x02008000 0x1000>; -+ }; diff --git a/target/linux/ipq806x/patches/0012-devicetree-bindings-Document-qcom-saw2-node.patch b/target/linux/ipq806x/patches/0012-devicetree-bindings-Document-qcom-saw2-node.patch deleted file mode 100644 index 79aaf2d898..0000000000 --- a/target/linux/ipq806x/patches/0012-devicetree-bindings-Document-qcom-saw2-node.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 17adce4d3de1fca7761607d572f4979557f0f604 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 31 Oct 2013 18:20:30 -0700 -Subject: [PATCH 012/182] devicetree: bindings: Document qcom,saw2 node - -The saw2 binding describes the SPM/AVS wrapper hardware used to -control the regulator supplying voltage to the Krait CPUs. - -Cc: -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - .../devicetree/bindings/arm/msm/qcom,saw2.txt | 35 ++++++++++++++++++++ - 1 file changed, 35 insertions(+) - create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt -@@ -0,0 +1,35 @@ -+SPM AVS Wrapper 2 (SAW2) -+ -+The SAW2 is a wrapper around the Subsystem Power Manager (SPM) and the -+Adaptive Voltage Scaling (AVS) hardware. The SPM is a programmable -+micro-controller that transitions a piece of hardware (like a processor or -+subsystem) into and out of low power modes via a direct connection to -+the PMIC. It can also be wired up to interact with other processors in the -+system, notifying them when a low power state is entered or exited. -+ -+PROPERTIES -+ -+- compatible: -+ Usage: required -+ Value type: -+ Definition: shall contain "qcom,saw2". A more specific value should be -+ one of: -+ "qcom,saw2-v1" -+ "qcom,saw2-v1.1" -+ "qcom,saw2-v2" -+ "qcom,saw2-v2.1" -+ -+- reg: -+ Usage: required -+ Value type: -+ Definition: the first element specifies the base address and size of -+ the register region. An optional second element specifies -+ the base address and size of the alias register region. -+ -+ -+Example: -+ -+ regulator@2099000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02099000 0x1000>, <0x02009000 0x1000>; -+ }; diff --git a/target/linux/ipq806x/patches/0013-ARM-qcom-Add-SMP-support-for-KPSSv1.patch b/target/linux/ipq806x/patches/0013-ARM-qcom-Add-SMP-support-for-KPSSv1.patch deleted file mode 100644 index e1d9ae1ac6..0000000000 --- a/target/linux/ipq806x/patches/0013-ARM-qcom-Add-SMP-support-for-KPSSv1.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 8e843640b3c4a43b963332fdc7b233948ad25a5b Mon Sep 17 00:00:00 2001 -From: Rohit Vaswani -Date: Tue, 21 May 2013 19:13:50 -0700 -Subject: [PATCH 013/182] ARM: qcom: Add SMP support for KPSSv1 - -Implement support for the Krait CPU release sequence when the -CPUs are part of the first version of the krait processor -subsystem. - -Signed-off-by: Rohit Vaswani -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/mach-qcom/platsmp.c | 106 +++++++++++++++++++++++++++++++++++++++++ - arch/arm/mach-qcom/scm-boot.h | 8 ++-- - 2 files changed, 111 insertions(+), 3 deletions(-) - ---- a/arch/arm/mach-qcom/platsmp.c -+++ b/arch/arm/mach-qcom/platsmp.c -@@ -26,6 +26,16 @@ - #define SCSS_CPU1CORE_RESET 0x2d80 - #define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64 - -+#define APCS_CPU_PWR_CTL 0x04 -+#define PLL_CLAMP BIT(8) -+#define CORE_PWRD_UP BIT(7) -+#define COREPOR_RST BIT(5) -+#define CORE_RST BIT(4) -+#define L2DT_SLP BIT(3) -+#define CLAMP BIT(0) -+ -+#define APCS_SAW2_VCTL 0x14 -+ - extern void secondary_startup(void); - - static DEFINE_SPINLOCK(boot_lock); -@@ -71,6 +81,85 @@ static int scss_release_secondary(unsign - return 0; - } - -+static int kpssv1_release_secondary(unsigned int cpu) -+{ -+ int ret = 0; -+ void __iomem *reg, *saw_reg; -+ struct device_node *cpu_node, *acc_node, *saw_node; -+ u32 val; -+ -+ cpu_node = of_get_cpu_node(cpu, NULL); -+ if (!cpu_node) -+ return -ENODEV; -+ -+ acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); -+ if (!acc_node) { -+ ret = -ENODEV; -+ goto out_acc; -+ } -+ -+ saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); -+ if (!saw_node) { -+ ret = -ENODEV; -+ goto out_saw; -+ } -+ -+ reg = of_iomap(acc_node, 0); -+ if (!reg) { -+ ret = -ENOMEM; -+ goto out_acc_map; -+ } -+ -+ saw_reg = of_iomap(saw_node, 0); -+ if (!saw_reg) { -+ ret = -ENOMEM; -+ goto out_saw_map; -+ } -+ -+ /* Turn on CPU rail */ -+ writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL); -+ mb(); -+ udelay(512); -+ -+ /* Krait bring-up sequence */ -+ val = PLL_CLAMP | L2DT_SLP | CLAMP; -+ writel_relaxed(val, reg + APCS_CPU_PWR_CTL); -+ val &= ~L2DT_SLP; -+ writel_relaxed(val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ ndelay(300); -+ -+ val |= COREPOR_RST; -+ writel_relaxed(val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ udelay(2); -+ -+ val &= ~CLAMP; -+ writel_relaxed(val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ udelay(2); -+ -+ val &= ~COREPOR_RST; -+ writel_relaxed(val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ udelay(100); -+ -+ val |= CORE_PWRD_UP; -+ writel_relaxed(val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ -+ iounmap(saw_reg); -+out_saw_map: -+ iounmap(reg); -+out_acc_map: -+ of_node_put(saw_node); -+out_saw: -+ of_node_put(acc_node); -+out_acc: -+ of_node_put(cpu_node); -+ return ret; -+} -+ - static DEFINE_PER_CPU(int, cold_boot_done); - - static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) -@@ -110,6 +199,11 @@ static int msm8660_boot_secondary(unsign - return qcom_boot_secondary(cpu, scss_release_secondary); - } - -+static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) -+{ -+ return qcom_boot_secondary(cpu, kpssv1_release_secondary); -+} -+ - static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) - { - int cpu, map; -@@ -117,6 +211,8 @@ static void __init qcom_smp_prepare_cpus - static const int cold_boot_flags[] = { - 0, - SCM_FLAG_COLDBOOT_CPU1, -+ SCM_FLAG_COLDBOOT_CPU2, -+ SCM_FLAG_COLDBOOT_CPU3, - }; - - for_each_present_cpu(cpu) { -@@ -147,3 +243,13 @@ static struct smp_operations smp_msm8660 - #endif - }; - CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops); -+ -+static struct smp_operations qcom_smp_kpssv1_ops __initdata = { -+ .smp_prepare_cpus = qcom_smp_prepare_cpus, -+ .smp_secondary_init = qcom_secondary_init, -+ .smp_boot_secondary = kpssv1_boot_secondary, -+#ifdef CONFIG_HOTPLUG_CPU -+ .cpu_die = qcom_cpu_die, -+#endif -+}; -+CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops); ---- a/arch/arm/mach-qcom/scm-boot.h -+++ b/arch/arm/mach-qcom/scm-boot.h -@@ -13,9 +13,11 @@ - #define __MACH_SCM_BOOT_H - - #define SCM_BOOT_ADDR 0x1 --#define SCM_FLAG_COLDBOOT_CPU1 0x1 --#define SCM_FLAG_WARMBOOT_CPU1 0x2 --#define SCM_FLAG_WARMBOOT_CPU0 0x4 -+#define SCM_FLAG_COLDBOOT_CPU1 0x01 -+#define SCM_FLAG_COLDBOOT_CPU2 0x08 -+#define SCM_FLAG_COLDBOOT_CPU3 0x20 -+#define SCM_FLAG_WARMBOOT_CPU0 0x04 -+#define SCM_FLAG_WARMBOOT_CPU1 0x02 - - int scm_set_boot_addr(phys_addr_t addr, int flags); - diff --git a/target/linux/ipq806x/patches/0014-ARM-qcom-Add-SMP-support-for-KPSSv2.patch b/target/linux/ipq806x/patches/0014-ARM-qcom-Add-SMP-support-for-KPSSv2.patch deleted file mode 100644 index 8f8ae49304..0000000000 --- a/target/linux/ipq806x/patches/0014-ARM-qcom-Add-SMP-support-for-KPSSv2.patch +++ /dev/null @@ -1,167 +0,0 @@ -From eb07c23d45ddf10fa89296e6c6c6aed553d8bbf5 Mon Sep 17 00:00:00 2001 -From: Rohit Vaswani -Date: Fri, 21 Jun 2013 17:09:13 -0700 -Subject: [PATCH 014/182] ARM: qcom: Add SMP support for KPSSv2 - -Implement support for the Krait CPU release sequence when the -CPUs are part of the second version of the Krait processor -subsystem. - -Signed-off-by: Rohit Vaswani -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/mach-qcom/platsmp.c | 123 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 123 insertions(+) - ---- a/arch/arm/mach-qcom/platsmp.c -+++ b/arch/arm/mach-qcom/platsmp.c -@@ -34,7 +34,15 @@ - #define L2DT_SLP BIT(3) - #define CLAMP BIT(0) - -+#define APC_PWR_GATE_CTL 0x14 -+#define BHS_CNT_SHIFT 24 -+#define LDO_PWR_DWN_SHIFT 16 -+#define LDO_BYP_SHIFT 8 -+#define BHS_SEG_SHIFT 1 -+#define BHS_EN BIT(0) -+ - #define APCS_SAW2_VCTL 0x14 -+#define APCS_SAW2_2_VCTL 0x1c - - extern void secondary_startup(void); - -@@ -160,6 +168,106 @@ out_acc: - return ret; - } - -+static int kpssv2_release_secondary(unsigned int cpu) -+{ -+ void __iomem *reg; -+ struct device_node *cpu_node, *l2_node, *acc_node, *saw_node; -+ void __iomem *l2_saw_base; -+ unsigned reg_val; -+ int ret; -+ -+ cpu_node = of_get_cpu_node(cpu, NULL); -+ if (!cpu_node) -+ return -ENODEV; -+ -+ acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); -+ if (!acc_node) { -+ ret = -ENODEV; -+ goto out_acc; -+ } -+ -+ l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0); -+ if (!l2_node) { -+ ret = -ENODEV; -+ goto out_l2; -+ } -+ -+ saw_node = of_parse_phandle(l2_node, "qcom,saw", 0); -+ if (!saw_node) { -+ ret = -ENODEV; -+ goto out_saw; -+ } -+ -+ reg = of_iomap(acc_node, 0); -+ if (!reg) { -+ ret = -ENOMEM; -+ goto out_map; -+ } -+ -+ l2_saw_base = of_iomap(saw_node, 0); -+ if (!l2_saw_base) { -+ ret = -ENOMEM; -+ goto out_saw_map; -+ } -+ -+ /* Turn on the BHS, turn off LDO Bypass and power down LDO */ -+ reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN; -+ writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); -+ mb(); -+ /* wait for the BHS to settle */ -+ udelay(1); -+ -+ /* Turn on BHS segments */ -+ reg_val |= 0x3f << BHS_SEG_SHIFT; -+ writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); -+ mb(); -+ /* wait for the BHS to settle */ -+ udelay(1); -+ -+ /* Finally turn on the bypass so that BHS supplies power */ -+ reg_val |= 0x3f << LDO_BYP_SHIFT; -+ writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); -+ -+ /* enable max phases */ -+ writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL); -+ mb(); -+ udelay(50); -+ -+ reg_val = COREPOR_RST | CLAMP; -+ writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ udelay(2); -+ -+ reg_val &= ~CLAMP; -+ writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ udelay(2); -+ -+ reg_val &= ~COREPOR_RST; -+ writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ -+ reg_val |= CORE_PWRD_UP; -+ writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); -+ mb(); -+ -+ ret = 0; -+ -+ iounmap(l2_saw_base); -+out_saw_map: -+ iounmap(reg); -+out_map: -+ of_node_put(saw_node); -+out_saw: -+ of_node_put(l2_node); -+out_l2: -+ of_node_put(acc_node); -+out_acc: -+ of_node_put(cpu_node); -+ -+ return ret; -+} -+ - static DEFINE_PER_CPU(int, cold_boot_done); - - static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) -@@ -204,6 +312,11 @@ static int kpssv1_boot_secondary(unsigne - return qcom_boot_secondary(cpu, kpssv1_release_secondary); - } - -+static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle) -+{ -+ return qcom_boot_secondary(cpu, kpssv2_release_secondary); -+} -+ - static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) - { - int cpu, map; -@@ -253,3 +366,13 @@ static struct smp_operations qcom_smp_kp - #endif - }; - CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops); -+ -+static struct smp_operations qcom_smp_kpssv2_ops __initdata = { -+ .smp_prepare_cpus = qcom_smp_prepare_cpus, -+ .smp_secondary_init = qcom_secondary_init, -+ .smp_boot_secondary = kpssv2_boot_secondary, -+#ifdef CONFIG_HOTPLUG_CPU -+ .cpu_die = qcom_cpu_die, -+#endif -+}; -+CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops); diff --git a/target/linux/ipq806x/patches/0015-tty-serial-msm-Enable-building-msm_serial-for-ARCH_Q.patch b/target/linux/ipq806x/patches/0015-tty-serial-msm-Enable-building-msm_serial-for-ARCH_Q.patch deleted file mode 100644 index 33870dc8fa..0000000000 --- a/target/linux/ipq806x/patches/0015-tty-serial-msm-Enable-building-msm_serial-for-ARCH_Q.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 17368813d4182894c6d58b66f9fccd339364de8f Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Wed, 29 Jan 2014 17:23:06 -0600 -Subject: [PATCH 015/182] tty: serial: msm: Enable building msm_serial for - ARCH_QCOM - -We've split Qualcomm MSM support into legacy and multiplatform. So add -the ability to build the serial driver on the newer ARCH_QCOM -multiplatform. - -Acked-by: Greg Kroah-Hartman -Signed-off-by: Kumar Gala ---- - drivers/tty/serial/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/tty/serial/Kconfig -+++ b/drivers/tty/serial/Kconfig -@@ -1024,7 +1024,7 @@ config SERIAL_SGI_IOC3 - - config SERIAL_MSM - bool "MSM on-chip serial port support" -- depends on ARCH_MSM -+ depends on ARCH_MSM || ARCH_QCOM - select SERIAL_CORE - - config SERIAL_MSM_CONSOLE diff --git a/target/linux/ipq806x/patches/0016-drm-msm-drop-ARCH_MSM-Kconfig-depend.patch b/target/linux/ipq806x/patches/0016-drm-msm-drop-ARCH_MSM-Kconfig-depend.patch deleted file mode 100644 index b80ad910f8..0000000000 --- a/target/linux/ipq806x/patches/0016-drm-msm-drop-ARCH_MSM-Kconfig-depend.patch +++ /dev/null @@ -1,28 +0,0 @@ -From aa3cf89746c43172517378224277ba961c46e28c Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 30 Jan 2014 14:45:05 -0600 -Subject: [PATCH 016/182] drm/msm: drop ARCH_MSM Kconfig depend - -The ARCH_MSM depend is redundant with ARCH_MSM8960, so we can remove it. -Additionally, we are splitting Qualcomm MSM support into legacy (ARCH_MSM) -and multiplatform (ARCH_QCOM). The MSM8960 with be ARCH_QCOM going forward -so dropping ARCH_MSM will work properly for the new ARCH_QCOM multiplatform -build. - -Acked-by: Rob Clark -Signed-off-by: Kumar Gala ---- - drivers/gpu/drm/msm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpu/drm/msm/Kconfig -+++ b/drivers/gpu/drm/msm/Kconfig -@@ -3,7 +3,7 @@ config DRM_MSM - tristate "MSM DRM" - depends on DRM - depends on MSM_IOMMU -- depends on (ARCH_MSM && ARCH_MSM8960) || (ARM && COMPILE_TEST) -+ depends on ARCH_MSM8960 || (ARM && COMPILE_TEST) - select DRM_KMS_HELPER - select SHMEM - select TMPFS diff --git a/target/linux/ipq806x/patches/0017-power-reset-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch b/target/linux/ipq806x/patches/0017-power-reset-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch deleted file mode 100644 index cf33efd9c3..0000000000 --- a/target/linux/ipq806x/patches/0017-power-reset-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 6e8707828be07397ee8ee437a6ef1b8f73f82287 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 30 Jan 2014 14:46:08 -0600 -Subject: [PATCH 017/182] power: reset: msm - switch Kconfig to ARCH_QCOM - depends - -We've split Qualcomm MSM support into legacy and multiplatform. The reset -driver is only relevant on the multiplatform supported SoCs so switch the -Kconfig depends to ARCH_QCOM. - -Acked-by: Dmitry Eremin-Solenikov -Signed-off-by: Kumar Gala ---- - drivers/power/reset/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/power/reset/Kconfig -+++ b/drivers/power/reset/Kconfig -@@ -22,7 +22,7 @@ config POWER_RESET_GPIO - - config POWER_RESET_MSM - bool "Qualcomm MSM power-off driver" -- depends on POWER_RESET && ARCH_MSM -+ depends on POWER_RESET && ARCH_QCOM - help - Power off and restart support for Qualcomm boards. - diff --git a/target/linux/ipq806x/patches/0018-hwrng-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch b/target/linux/ipq806x/patches/0018-hwrng-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch deleted file mode 100644 index 89cb8acd6d..0000000000 --- a/target/linux/ipq806x/patches/0018-hwrng-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 4aa784548190c69d946b4dfbc0592a3ed7cd18da Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 30 Jan 2014 14:43:49 -0600 -Subject: [PATCH 018/182] hwrng: msm: switch Kconfig to ARCH_QCOM depends - -We've split Qualcomm MSM support into legacy and multiplatform. The RNG -driver is only relevant on the multiplatform supported SoCs so switch the -Kconfig depends to ARCH_QCOM. - -Acked-by: Herbert Xu -CC: Stanimir Varbanov -Signed-off-by: Kumar Gala ---- - drivers/char/hw_random/Kconfig | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/char/hw_random/Kconfig -+++ b/drivers/char/hw_random/Kconfig -@@ -342,11 +342,11 @@ config HW_RANDOM_TPM - If unsure, say Y. - - config HW_RANDOM_MSM -- tristate "Qualcomm MSM Random Number Generator support" -- depends on HW_RANDOM && ARCH_MSM -+ tristate "Qualcomm SoCs Random Number Generator support" -+ depends on HW_RANDOM && ARCH_QCOM - ---help--- - This driver provides kernel-side support for the Random Number -- Generator hardware found on Qualcomm MSM SoCs. -+ Generator hardware found on Qualcomm SoCs. - - To compile this driver as a module, choose M here. the - module will be called msm-rng. diff --git a/target/linux/ipq806x/patches/0019-gpio-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch b/target/linux/ipq806x/patches/0019-gpio-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch deleted file mode 100644 index 1ead84bb4b..0000000000 --- a/target/linux/ipq806x/patches/0019-gpio-msm-switch-Kconfig-to-ARCH_QCOM-depends.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 87d52cc8a390c5b208b6f0bddd90a2d01c906616 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Tue, 11 Feb 2014 14:08:06 -0600 -Subject: [PATCH 019/182] gpio: msm: switch Kconfig to ARCH_QCOM depends - -We've split Qualcomm MSM support into legacy and multiplatform. The gpio -msm-v2 driver is only relevant on the multiplatform supported SoCs so -switch the Kconfig depends to ARCH_QCOM. - -CC: Linus Walleij -Acked-by: Alexandre Courbot -Signed-off-by: Kumar Gala ---- - drivers/gpio/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -192,7 +192,7 @@ config GPIO_MSM_V1 - - config GPIO_MSM_V2 - tristate "Qualcomm MSM GPIO v2" -- depends on GPIOLIB && OF && ARCH_MSM -+ depends on GPIOLIB && OF && ARCH_QCOM - help - Say yes here to support the GPIO interface on ARM v7 based - Qualcomm MSM chips. Most of the pins on the MSM can be diff --git a/target/linux/ipq806x/patches/002-v3-spi-qup-Fix-incorrect-block-transfers.patch b/target/linux/ipq806x/patches/002-v3-spi-qup-Fix-incorrect-block-transfers.patch new file mode 100644 index 0000000000..62ee5b4fad --- /dev/null +++ b/target/linux/ipq806x/patches/002-v3-spi-qup-Fix-incorrect-block-transfers.patch @@ -0,0 +1,376 @@ +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v3] spi: qup: Fix incorrect block transfers +From: Andy Gross +X-Patchwork-Id: 5007321 +Message-Id: <1412112088-25928-1-git-send-email-agross@codeaurora.org> +To: Mark Brown +Cc: linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, + "Ivan T. Ivanov" , + Bjorn Andersson , + Kumar Gala , Andy Gross +Date: Tue, 30 Sep 2014 16:21:28 -0500 + +This patch fixes a number of errors with the QUP block transfer mode. Errors +manifested themselves as input underruns, output overruns, and timed out +transactions. + +The block mode does not require the priming that occurs in FIFO mode. At the +moment that the QUP is placed into the RUN state, the QUP will immediately raise +an interrupt if the request is a write. Therefore, there is no need to prime +the pump. + +In addition, the block transfers require that whole blocks of data are +read/written at a time. The last block of data that completes a transaction may +contain less than a full blocks worth of data. + +Each block of data results in an input/output service interrupt accompanied with +a input/output block flag set. Additional block reads/writes require clearing +of the service flag. It is ok to check for additional blocks of data in the +ISR, but you have to ack every block you transfer. Imbalanced acks result in +early return from complete transactions with pending interrupts that still have +to be ack'd. The next transaction can be affected by these interrupts. +Transactions are deemed complete when the MAX_INPUT or MAX_OUTPUT flag are set. + +Changes from v2: +- Added in additional completion check so that transaction done is not + prematurely signaled. +- Fixed various review comments. + +Changes from v1: +- Split out read/write block function. +- Removed extraneous checks for transfer length + +Signed-off-by: Andy Gross + +--- +drivers/spi/spi-qup.c | 201 ++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 148 insertions(+), 53 deletions(-) + +--- a/drivers/spi/spi-qup.c ++++ b/drivers/spi/spi-qup.c +@@ -82,6 +82,8 @@ + #define QUP_IO_M_MODE_BAM 3 + + /* QUP_OPERATIONAL fields */ ++#define QUP_OP_IN_BLOCK_READ_REQ BIT(13) ++#define QUP_OP_OUT_BLOCK_WRITE_REQ BIT(12) + #define QUP_OP_MAX_INPUT_DONE_FLAG BIT(11) + #define QUP_OP_MAX_OUTPUT_DONE_FLAG BIT(10) + #define QUP_OP_IN_SERVICE_FLAG BIT(9) +@@ -147,6 +149,7 @@ struct spi_qup { + int tx_bytes; + int rx_bytes; + int qup_v1; ++ int mode; + + int use_dma; + +@@ -213,30 +216,14 @@ static int spi_qup_set_state(struct spi_ + return 0; + } + +- +-static void spi_qup_fifo_read(struct spi_qup *controller, +- struct spi_transfer *xfer) ++static void spi_qup_fill_read_buffer(struct spi_qup *controller, ++ struct spi_transfer *xfer, u32 data) + { + u8 *rx_buf = xfer->rx_buf; +- u32 word, state; +- int idx, shift, w_size; +- +- w_size = controller->w_size; +- +- while (controller->rx_bytes < xfer->len) { +- +- state = readl_relaxed(controller->base + QUP_OPERATIONAL); +- if (0 == (state & QUP_OP_IN_FIFO_NOT_EMPTY)) +- break; +- +- word = readl_relaxed(controller->base + QUP_INPUT_FIFO); +- +- if (!rx_buf) { +- controller->rx_bytes += w_size; +- continue; +- } ++ int idx, shift; + +- for (idx = 0; idx < w_size; idx++, controller->rx_bytes++) { ++ if (rx_buf) ++ for (idx = 0; idx < controller->w_size; idx++) { + /* + * The data format depends on bytes per SPI word: + * 4 bytes: 0x12345678 +@@ -244,41 +231,139 @@ static void spi_qup_fifo_read(struct spi + * 1 byte : 0x00000012 + */ + shift = BITS_PER_BYTE; +- shift *= (w_size - idx - 1); +- rx_buf[controller->rx_bytes] = word >> shift; ++ shift *= (controller->w_size - idx - 1); ++ rx_buf[controller->rx_bytes + idx] = data >> shift; ++ } ++ ++ controller->rx_bytes += controller->w_size; ++} ++ ++static void spi_qup_prepare_write_data(struct spi_qup *controller, ++ struct spi_transfer *xfer, u32 *data) ++{ ++ const u8 *tx_buf = xfer->tx_buf; ++ u32 val; ++ int idx; ++ ++ *data = 0; ++ ++ if (tx_buf) ++ for (idx = 0; idx < controller->w_size; idx++) { ++ val = tx_buf[controller->tx_bytes + idx]; ++ *data |= val << (BITS_PER_BYTE * (3 - idx)); + } ++ ++ controller->tx_bytes += controller->w_size; ++} ++ ++static void spi_qup_fifo_read(struct spi_qup *controller, ++ struct spi_transfer *xfer) ++{ ++ u32 data; ++ ++ /* clear service request */ ++ writel_relaxed(QUP_OP_IN_SERVICE_FLAG, ++ controller->base + QUP_OPERATIONAL); ++ ++ while (controller->rx_bytes < xfer->len) { ++ if (!(readl_relaxed(controller->base + QUP_OPERATIONAL) & ++ QUP_OP_IN_FIFO_NOT_EMPTY)) ++ break; ++ ++ data = readl_relaxed(controller->base + QUP_INPUT_FIFO); ++ ++ spi_qup_fill_read_buffer(controller, xfer, data); + } + } + + static void spi_qup_fifo_write(struct spi_qup *controller, +- struct spi_transfer *xfer) ++ struct spi_transfer *xfer) + { +- const u8 *tx_buf = xfer->tx_buf; +- u32 word, state, data; +- int idx, w_size; ++ u32 data; + +- w_size = controller->w_size; ++ /* clear service request */ ++ writel_relaxed(QUP_OP_OUT_SERVICE_FLAG, ++ controller->base + QUP_OPERATIONAL); + + while (controller->tx_bytes < xfer->len) { + +- state = readl_relaxed(controller->base + QUP_OPERATIONAL); +- if (state & QUP_OP_OUT_FIFO_FULL) ++ if (readl_relaxed(controller->base + QUP_OPERATIONAL) & ++ QUP_OP_OUT_FIFO_FULL) + break; + +- word = 0; +- for (idx = 0; idx < w_size; idx++, controller->tx_bytes++) { ++ spi_qup_prepare_write_data(controller, xfer, &data); ++ writel_relaxed(data, controller->base + QUP_OUTPUT_FIFO); + +- if (!tx_buf) { +- controller->tx_bytes += w_size; +- break; +- } ++ } ++} + +- data = tx_buf[controller->tx_bytes]; +- word |= data << (BITS_PER_BYTE * (3 - idx)); +- } ++static void spi_qup_block_read(struct spi_qup *controller, ++ struct spi_transfer *xfer) ++{ ++ u32 data; ++ u32 reads_per_blk = controller->in_blk_sz >> 2; ++ u32 num_words = (xfer->len - controller->rx_bytes) / controller->w_size; ++ int i; ++ ++ do { ++ /* ACK by clearing service flag */ ++ writel_relaxed(QUP_OP_IN_SERVICE_FLAG, ++ controller->base + QUP_OPERATIONAL); ++ ++ /* transfer up to a block size of data in a single pass */ ++ for (i = 0; num_words && i < reads_per_blk; i++, num_words--) { ++ ++ /* read data and fill up rx buffer */ ++ data = readl_relaxed(controller->base + QUP_INPUT_FIFO); ++ spi_qup_fill_read_buffer(controller, xfer, data); ++ } ++ ++ /* check to see if next block is ready */ ++ if (!(readl_relaxed(controller->base + QUP_OPERATIONAL) & ++ QUP_OP_IN_BLOCK_READ_REQ)) ++ break; + +- writel_relaxed(word, controller->base + QUP_OUTPUT_FIFO); +- } ++ } while (num_words); ++ ++ /* ++ * Due to extra stickiness of the QUP_OP_IN_SERVICE_FLAG during block ++ * reads, it has to be cleared again at the very end ++ */ ++ if (readl_relaxed(controller->base + QUP_OPERATIONAL) & ++ QUP_OP_MAX_INPUT_DONE_FLAG) ++ writel_relaxed(QUP_OP_IN_SERVICE_FLAG, ++ controller->base + QUP_OPERATIONAL); ++ ++} ++ ++static void spi_qup_block_write(struct spi_qup *controller, ++ struct spi_transfer *xfer) ++{ ++ u32 data; ++ u32 writes_per_blk = controller->out_blk_sz >> 2; ++ u32 num_words = (xfer->len - controller->tx_bytes) / controller->w_size; ++ int i; ++ ++ do { ++ /* ACK by clearing service flag */ ++ writel_relaxed(QUP_OP_OUT_SERVICE_FLAG, ++ controller->base + QUP_OPERATIONAL); ++ ++ /* transfer up to a block size of data in a single pass */ ++ for (i = 0; num_words && i < writes_per_blk; i++, num_words--) { ++ ++ /* swizzle the bytes for output and write out */ ++ spi_qup_prepare_write_data(controller, xfer, &data); ++ writel_relaxed(data, ++ controller->base + QUP_OUTPUT_FIFO); ++ } ++ ++ /* check to see if next block is ready */ ++ if (!(readl_relaxed(controller->base + QUP_OPERATIONAL) & ++ QUP_OP_OUT_BLOCK_WRITE_REQ)) ++ break; ++ ++ } while (num_words); + } + + static void qup_dma_callback(void *data) +@@ -515,9 +600,9 @@ static irqreturn_t spi_qup_qup_irq(int i + + writel_relaxed(qup_err, controller->base + QUP_ERROR_FLAGS); + writel_relaxed(spi_err, controller->base + SPI_ERROR_FLAGS); +- writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); + + if (!xfer) { ++ writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); + dev_err_ratelimited(controller->dev, "unexpected irq %08x %08x %08x\n", + qup_err, spi_err, opflags); + return IRQ_HANDLED; +@@ -546,11 +631,19 @@ static irqreturn_t spi_qup_qup_irq(int i + } + + if (!controller->use_dma) { +- if (opflags & QUP_OP_IN_SERVICE_FLAG) +- spi_qup_fifo_read(controller, xfer); ++ if (opflags & QUP_OP_IN_SERVICE_FLAG) { ++ if (opflags & QUP_OP_IN_BLOCK_READ_REQ) ++ spi_qup_block_read(controller, xfer); ++ else ++ spi_qup_fifo_read(controller, xfer); ++ } + +- if (opflags & QUP_OP_OUT_SERVICE_FLAG) +- spi_qup_fifo_write(controller, xfer); ++ if (opflags & QUP_OP_OUT_SERVICE_FLAG) { ++ if (opflags & QUP_OP_OUT_BLOCK_WRITE_REQ) ++ spi_qup_block_write(controller, xfer); ++ else ++ spi_qup_fifo_write(controller, xfer); ++ } + } + + spin_lock_irqsave(&controller->lock, flags); +@@ -558,7 +651,8 @@ static irqreturn_t spi_qup_qup_irq(int i + controller->xfer = xfer; + spin_unlock_irqrestore(&controller->lock, flags); + +- if (controller->rx_bytes == xfer->len || error) ++ if ((controller->rx_bytes == xfer->len && ++ (opflags & QUP_OP_MAX_INPUT_DONE_FLAG)) || error) + complete(&controller->done); + + return IRQ_HANDLED; +@@ -569,7 +663,7 @@ static irqreturn_t spi_qup_qup_irq(int i + static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) + { + struct spi_qup *controller = spi_master_get_devdata(spi->master); +- u32 config, iomode, mode; ++ u32 config, iomode; + int ret, n_words, w_size; + size_t dma_align = dma_get_cache_alignment(); + u32 dma_available = 0; +@@ -607,7 +701,7 @@ static int spi_qup_io_config(struct spi_ + dma_available = 1; + + if (n_words <= (controller->in_fifo_sz / sizeof(u32))) { +- mode = QUP_IO_M_MODE_FIFO; ++ controller->mode = QUP_IO_M_MODE_FIFO; + writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT); + writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT); + /* must be zero for FIFO */ +@@ -615,7 +709,7 @@ static int spi_qup_io_config(struct spi_ + writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); + controller->use_dma = 0; + } else if (!dma_available) { +- mode = QUP_IO_M_MODE_BLOCK; ++ controller->mode = QUP_IO_M_MODE_BLOCK; + writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT); + writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT); + /* must be zero for BLOCK and BAM */ +@@ -623,7 +717,7 @@ static int spi_qup_io_config(struct spi_ + writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); + controller->use_dma = 0; + } else { +- mode = QUP_IO_M_MODE_DMOV; ++ controller->mode = QUP_IO_M_MODE_DMOV; + writel_relaxed(0, controller->base + QUP_MX_READ_CNT); + writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); + controller->use_dma = 1; +@@ -638,8 +732,8 @@ static int spi_qup_io_config(struct spi_ + else + iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN; + +- iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); +- iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); ++ iomode |= (controller->mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); ++ iomode |= (controller->mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); + + writel_relaxed(iomode, controller->base + QUP_IO_M_MODES); + +@@ -724,7 +818,8 @@ static int spi_qup_transfer_one(struct s + goto exit; + } + +- spi_qup_fifo_write(controller, xfer); ++ if (controller->mode == QUP_IO_M_MODE_FIFO) ++ spi_qup_fifo_write(controller, xfer); + + if (spi_qup_set_state(controller, QUP_STATE_RUN)) { + dev_warn(controller->dev, "cannot set EXECUTE state\n"); +@@ -741,6 +836,7 @@ exit: + if (!ret) + ret = controller->error; + spin_unlock_irqrestore(&controller->lock, flags); ++ + return ret; + } + diff --git a/target/linux/ipq806x/patches/0020-ARM-qcom-Enable-basic-support-for-Qualcomm-platforms.patch b/target/linux/ipq806x/patches/0020-ARM-qcom-Enable-basic-support-for-Qualcomm-platforms.patch deleted file mode 100644 index 7c1cb29c53..0000000000 --- a/target/linux/ipq806x/patches/0020-ARM-qcom-Enable-basic-support-for-Qualcomm-platforms.patch +++ /dev/null @@ -1,49 +0,0 @@ -From a2f356a6d49f459a2dd681fe4a7c6a55aeb8893f Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Tue, 25 Feb 2014 14:34:05 -0600 -Subject: [PATCH 020/182] ARM: qcom: Enable basic support for Qualcomm - platforms in multi_v7_defconfig - -Enable support for the MSM8x60, MSM8960, and MSM8974 SoCs, clocks and -serial console as part of the standard multi_v7_defconfig. - -Signed-off-by: Kumar Gala -[khilman: removed non-qcom changes] -Signed-off-by: Kevin Hilman ---- - arch/arm/configs/multi_v7_defconfig | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/arch/arm/configs/multi_v7_defconfig -+++ b/arch/arm/configs/multi_v7_defconfig -@@ -31,6 +31,10 @@ CONFIG_SOC_OMAP5=y - CONFIG_SOC_AM33XX=y - CONFIG_SOC_DRA7XX=y - CONFIG_SOC_AM43XX=y -+CONFIG_ARCH_QCOM=y -+CONFIG_ARCH_MSM8X60=y -+CONFIG_ARCH_MSM8960=y -+CONFIG_ARCH_MSM8974=y - CONFIG_ARCH_ROCKCHIP=y - CONFIG_ARCH_SOCFPGA=y - CONFIG_PLAT_SPEAR=y -@@ -146,6 +150,8 @@ CONFIG_SERIAL_SIRFSOC_CONSOLE=y - CONFIG_SERIAL_TEGRA=y - CONFIG_SERIAL_IMX=y - CONFIG_SERIAL_IMX_CONSOLE=y -+CONFIG_SERIAL_MSM=y -+CONFIG_SERIAL_MSM_CONSOLE=y - CONFIG_SERIAL_VT8500=y - CONFIG_SERIAL_VT8500_CONSOLE=y - CONFIG_SERIAL_OF_PLATFORM=y -@@ -294,6 +300,10 @@ CONFIG_MFD_NVEC=y - CONFIG_KEYBOARD_NVEC=y - CONFIG_SERIO_NVEC_PS2=y - CONFIG_NVEC_POWER=y -+CONFIG_COMMON_CLK_QCOM=y -+CONFIG_MSM_GCC_8660=y -+CONFIG_MSM_MMCC_8960=y -+CONFIG_MSM_MMCC_8974=y - CONFIG_TEGRA_IOMMU_GART=y - CONFIG_TEGRA_IOMMU_SMMU=y - CONFIG_MEMORY=y diff --git a/target/linux/ipq806x/patches/0021-ARM-dts-qcom-Add-nodes-necessary-for-SMP-boot.patch b/target/linux/ipq806x/patches/0021-ARM-dts-qcom-Add-nodes-necessary-for-SMP-boot.patch deleted file mode 100644 index 232f2efed9..0000000000 --- a/target/linux/ipq806x/patches/0021-ARM-dts-qcom-Add-nodes-necessary-for-SMP-boot.patch +++ /dev/null @@ -1,205 +0,0 @@ -From 5a054211d9380cef5a09da7c5e815c827f330a96 Mon Sep 17 00:00:00 2001 -From: Rohit Vaswani -Date: Fri, 1 Nov 2013 10:10:40 -0700 -Subject: [PATCH 021/182] ARM: dts: qcom: Add nodes necessary for SMP boot - -Add the necessary nodes to support SMP on MSM8660, MSM8960, and -MSM8974/APQ8074. While we're here also add in the error -interrupts for the Krait cache error detection. - -Signed-off-by: Rohit Vaswani -[sboyd: Split into separate patch, add error interrupts] -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-msm8660.dtsi | 24 ++++++++++++ - arch/arm/boot/dts/qcom-msm8960.dtsi | 52 ++++++++++++++++++++++++++ - arch/arm/boot/dts/qcom-msm8974.dtsi | 69 +++++++++++++++++++++++++++++++++++ - 3 files changed, 145 insertions(+) - ---- a/arch/arm/boot/dts/qcom-msm8660.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi -@@ -9,6 +9,30 @@ - compatible = "qcom,msm8660"; - interrupt-parent = <&intc>; - -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "qcom,scorpion"; -+ enable-method = "qcom,gcc-msm8660"; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ reg = <0>; -+ next-level-cache = <&L2>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ reg = <1>; -+ next-level-cache = <&L2>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "cache"; -+ cache-level = <2>; -+ }; -+ }; -+ - intc: interrupt-controller@2080000 { - compatible = "qcom,msm-8660-qgic"; - interrupt-controller; ---- a/arch/arm/boot/dts/qcom-msm8960.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi -@@ -9,6 +9,36 @@ - compatible = "qcom,msm8960"; - interrupt-parent = <&intc>; - -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = <1 14 0x304>; -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ reg = <0>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc0>; -+ qcom,saw = <&saw0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ reg = <1>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc1>; -+ qcom,saw = <&saw1>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "cache"; -+ cache-level = <2>; -+ interrupts = <0 2 0x4>; -+ }; -+ }; -+ - intc: interrupt-controller@2000000 { - compatible = "qcom,msm-qgic2"; - interrupt-controller; -@@ -53,6 +83,28 @@ - #reset-cells = <1>; - }; - -+ acc0: clock-controller@2088000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02088000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ acc1: clock-controller@2098000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02098000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ saw0: regulator@2089000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02089000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ -+ saw1: regulator@2099000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02099000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ - serial@16440000 { - compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; - reg = <0x16440000 0x1000>, ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -9,6 +9,49 @@ - compatible = "qcom,msm8974"; - interrupt-parent = <&intc>; - -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = <1 9 0xf04>; -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v2"; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ reg = <0>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ reg = <1>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc1>; -+ }; -+ -+ cpu@2 { -+ device_type = "cpu"; -+ reg = <2>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc2>; -+ }; -+ -+ cpu@3 { -+ device_type = "cpu"; -+ reg = <3>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc3>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "cache"; -+ cache-level = <2>; -+ interrupts = <0 2 0x4>; -+ qcom,saw = <&saw_l2>; -+ }; -+ }; -+ - soc: soc { - #address-cells = <1>; - #size-cells = <1>; -@@ -91,6 +134,32 @@ - }; - }; - -+ saw_l2: regulator@f9012000 { -+ compatible = "qcom,saw2"; -+ reg = <0xf9012000 0x1000>; -+ regulator; -+ }; -+ -+ acc0: clock-controller@f9088000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf9088000 0x1000>, <0xf9008000 0x1000>; -+ }; -+ -+ acc1: clock-controller@f9098000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf9098000 0x1000>, <0xf9008000 0x1000>; -+ }; -+ -+ acc2: clock-controller@f90a8000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf90a8000 0x1000>, <0xf9008000 0x1000>; -+ }; -+ -+ acc3: clock-controller@f90b8000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf90b8000 0x1000>, <0xf9008000 0x1000>; -+ }; -+ - restart@fc4ab000 { - compatible = "qcom,pshold"; - reg = <0xfc4ab000 0x4>; diff --git a/target/linux/ipq806x/patches/0022-ARM-dts-qcom-Add-RNG-device-tree-node.patch b/target/linux/ipq806x/patches/0022-ARM-dts-qcom-Add-RNG-device-tree-node.patch deleted file mode 100644 index 76cff028ab..0000000000 --- a/target/linux/ipq806x/patches/0022-ARM-dts-qcom-Add-RNG-device-tree-node.patch +++ /dev/null @@ -1,30 +0,0 @@ -From b0f93ef8f790e77049b6149416ef0ba05cce7089 Mon Sep 17 00:00:00 2001 -From: Stanimir Varbanov -Date: Fri, 7 Feb 2014 11:23:07 +0200 -Subject: [PATCH 022/182] ARM: dts: qcom: Add RNG device tree node - -Add the necessary DT node to probe the rng driver on -msm8974 platforms. - -Signed-off-by: Stanimir Varbanov -Acked-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-msm8974.dtsi | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -186,5 +186,12 @@ - clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; - clock-names = "core", "iface"; - }; -+ -+ rng@f9bff000 { -+ compatible = "qcom,prng"; -+ reg = <0xf9bff000 0x200>; -+ clocks = <&gcc GCC_PRNG_AHB_CLK>; -+ clock-names = "core"; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0023-ARM-dts-qcom-msm8960-cdp-Add-RNG-device-tree-node.patch b/target/linux/ipq806x/patches/0023-ARM-dts-qcom-msm8960-cdp-Add-RNG-device-tree-node.patch deleted file mode 100644 index 36206d4c4b..0000000000 --- a/target/linux/ipq806x/patches/0023-ARM-dts-qcom-msm8960-cdp-Add-RNG-device-tree-node.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 82bedcd5ad0b3ac8fe78f4be25b2ffa0691d7804 Mon Sep 17 00:00:00 2001 -From: Stanimir Varbanov -Date: Wed, 19 Feb 2014 16:33:06 +0200 -Subject: [PATCH 023/182] ARM: dts: qcom-msm8960-cdp: Add RNG device tree node - -Add the necessary DT node to probe the rng driver on -msm8960-cdp platform. - -Signed-off-by: Stanimir Varbanov -Tested-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-msm8960.dtsi | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/arch/arm/boot/dts/qcom-msm8960.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi -@@ -119,4 +119,11 @@ - reg = <0x500000 0x1000>; - qcom,controller-type = "pmic-arbiter"; - }; -+ -+ rng@1a500000 { -+ compatible = "qcom,prng"; -+ reg = <0x1a500000 0x200>; -+ clocks = <&gcc PRNG_CLK>; -+ clock-names = "core"; -+ }; - }; diff --git a/target/linux/ipq806x/patches/0024-ARM-dts-msm-Add-krait-pmu-to-platforms-with-Krait-CP.patch b/target/linux/ipq806x/patches/0024-ARM-dts-msm-Add-krait-pmu-to-platforms-with-Krait-CP.patch deleted file mode 100644 index b0cefc2153..0000000000 --- a/target/linux/ipq806x/patches/0024-ARM-dts-msm-Add-krait-pmu-to-platforms-with-Krait-CP.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 02c987fb8a3607ab6e0ead0e5aaa7da753ce9537 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 21 Feb 2014 11:09:50 +0000 -Subject: [PATCH 024/182] ARM: dts: msm: Add krait-pmu to platforms with Krait - CPUs - -Allows us to probe the performance counters on Krait CPUs. - -Signed-off-by: Stephen Boyd -Signed-off-by: Will Deacon -[olof: Moved 8960 contents to the dtsi instead] -Signed-off-by: Olof Johansson ---- - arch/arm/boot/dts/qcom-msm8960.dtsi | 6 ++++++ - arch/arm/boot/dts/qcom-msm8974.dtsi | 5 +++++ - 2 files changed, 11 insertions(+) - ---- a/arch/arm/boot/dts/qcom-msm8960.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi -@@ -39,6 +39,12 @@ - }; - }; - -+ cpu-pmu { -+ compatible = "qcom,krait-pmu"; -+ interrupts = <1 10 0x304>; -+ qcom,no-pc-write; -+ }; -+ - intc: interrupt-controller@2000000 { - compatible = "qcom,msm-qgic2"; - interrupt-controller; ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -52,6 +52,11 @@ - }; - }; - -+ cpu-pmu { -+ compatible = "qcom,krait-pmu"; -+ interrupts = <1 7 0xf04>; -+ }; -+ - soc: soc { - #address-cells = <1>; - #size-cells = <1>; diff --git a/target/linux/ipq806x/patches/0025-pinctrl-msm-drop-wake_irqs-bitmap.patch b/target/linux/ipq806x/patches/0025-pinctrl-msm-drop-wake_irqs-bitmap.patch deleted file mode 100644 index d0771ff27e..0000000000 --- a/target/linux/ipq806x/patches/0025-pinctrl-msm-drop-wake_irqs-bitmap.patch +++ /dev/null @@ -1,66 +0,0 @@ -From ef8eb0991f291df12c12477648235f955cc388b0 Mon Sep 17 00:00:00 2001 -From: Josh Cartwright -Date: Wed, 5 Mar 2014 13:33:08 -0600 -Subject: [PATCH 025/182] pinctrl: msm: drop wake_irqs bitmap - -Currently, the wake_irqs bitmap is used to track whether there are any -gpio's which are configured as wake irqs, and uses this to determine -whether or not to call enable_irq_wake()/disable_irq_wake() on the -summary interrupt. - -However, the genirq core already handles this case, by maintaining a -'wake_count' per irq_desc, and only calling into the controlling -irq_chip when wake_count transitions 0 <-> 1. - -Drop this bitmap, and unconditionally call irq_set_irq_wake() on the -summary interrupt. - -Signed-off-by: Josh Cartwright -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -50,7 +50,6 @@ - * @enabled_irqs: Bitmap of currently enabled irqs. - * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge - * detection. -- * @wake_irqs: Bitmap of irqs with requested as wakeup source. - * @soc; Reference to soc_data of platform specific data. - * @regs: Base address for the TLMM register map. - */ -@@ -65,7 +64,6 @@ struct msm_pinctrl { - - DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO); - DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO); -- DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO); - - const struct msm_pinctrl_soc_data *soc; - void __iomem *regs; -@@ -783,22 +781,12 @@ static int msm_gpio_irq_set_wake(struct - { - struct msm_pinctrl *pctrl; - unsigned long flags; -- unsigned ngpio; - - pctrl = irq_data_get_irq_chip_data(d); -- ngpio = pctrl->chip.ngpio; - - spin_lock_irqsave(&pctrl->lock, flags); - -- if (on) { -- if (bitmap_empty(pctrl->wake_irqs, ngpio)) -- enable_irq_wake(pctrl->irq); -- set_bit(d->hwirq, pctrl->wake_irqs); -- } else { -- clear_bit(d->hwirq, pctrl->wake_irqs); -- if (bitmap_empty(pctrl->wake_irqs, ngpio)) -- disable_irq_wake(pctrl->irq); -- } -+ irq_set_irq_wake(pctrl->irq, on); - - spin_unlock_irqrestore(&pctrl->lock, flags); - diff --git a/target/linux/ipq806x/patches/0026-pinctrl-msm-Silence-recursive-lockdep-warning.patch b/target/linux/ipq806x/patches/0026-pinctrl-msm-Silence-recursive-lockdep-warning.patch deleted file mode 100644 index fe5008e51a..0000000000 --- a/target/linux/ipq806x/patches/0026-pinctrl-msm-Silence-recursive-lockdep-warning.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 9588c91936434166007c3a15ad7f4e2f3729c5e7 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 6 Mar 2014 22:44:40 -0800 -Subject: [PATCH 026/182] pinctrl: msm: Silence recursive lockdep warning - -If a driver calls enable_irq_wake() on a gpio turned interrupt -from the msm pinctrl driver we'll get a lockdep warning like so: - -============================================= -[ INFO: possible recursive locking detected ] -3.14.0-rc3 #2 Not tainted ---------------------------------------------- -modprobe/52 is trying to acquire lock: - (&irq_desc_lock_class){-.....}, at: [] __irq_get_desc_lock+0x48/0x88 - -but task is already holding lock: - (&irq_desc_lock_class){-.....}, at: [] __irq_get_desc_lock+0x48/0x88 - -other info that might help us debug this: - Possible unsafe locking scenario: - - CPU0 - ---- - lock(&irq_desc_lock_class); - lock(&irq_desc_lock_class); - - *** DEADLOCK *** - - May be due to missing lock nesting notation - -4 locks held by modprobe/52: - #0: (&__lockdep_no_validate__){......}, at: [] __driver_attach+0x48/0x98 - #1: (&__lockdep_no_validate__){......}, at: [] __driver_attach+0x58/0x98 - #2: (&irq_desc_lock_class){-.....}, at: [] __irq_get_desc_lock+0x48/0x88 - #3: (&(&pctrl->lock)->rlock){......}, at: [] msm_gpio_irq_set_wake+0x20/0xa8 - -Silence it by putting the gpios into their own lock class. - -Signed-off-by: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -857,6 +857,12 @@ static void msm_gpio_irq_handler(unsigne - chained_irq_exit(chip, desc); - } - -+/* -+ * This lock class tells lockdep that GPIO irqs are in a different -+ * category than their parents, so it won't report false recursion. -+ */ -+static struct lock_class_key gpio_lock_class; -+ - static int msm_gpio_init(struct msm_pinctrl *pctrl) - { - struct gpio_chip *chip; -@@ -895,6 +901,7 @@ static int msm_gpio_init(struct msm_pinc - - for (i = 0; i < chip->ngpio; i++) { - irq = irq_create_mapping(pctrl->domain, i); -+ irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, handle_edge_irq); - irq_set_chip_data(irq, pctrl); - } diff --git a/target/linux/ipq806x/patches/0027-pinctrl-msm-Check-for-ngpios-MAX_NR_GPIO.patch b/target/linux/ipq806x/patches/0027-pinctrl-msm-Check-for-ngpios-MAX_NR_GPIO.patch deleted file mode 100644 index 7cf4b14164..0000000000 --- a/target/linux/ipq806x/patches/0027-pinctrl-msm-Check-for-ngpios-MAX_NR_GPIO.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 8341db7b05b688e8e5a93acd0e80b40be409d037 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 6 Mar 2014 22:44:41 -0800 -Subject: [PATCH 027/182] pinctrl: msm: Check for ngpios > MAX_NR_GPIO - -Fail the probe and print a warning if SoC specific drivers have -more GPIOs than there can be accounted for in the static bitmaps. -This should avoid silent corruption/failures in the future. - -Signed-off-by: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -870,10 +870,14 @@ static int msm_gpio_init(struct msm_pinc - int ret; - int i; - int r; -+ unsigned ngpio = pctrl->soc->ngpios; -+ -+ if (WARN_ON(ngpio > MAX_NR_GPIO)) -+ return -EINVAL; - - chip = &pctrl->chip; - chip->base = 0; -- chip->ngpio = pctrl->soc->ngpios; -+ chip->ngpio = ngpio; - chip->label = dev_name(pctrl->dev); - chip->dev = pctrl->dev; - chip->owner = THIS_MODULE; diff --git a/target/linux/ipq806x/patches/0028-pinctrl-msm-Drop-unused-includes.patch b/target/linux/ipq806x/patches/0028-pinctrl-msm-Drop-unused-includes.patch deleted file mode 100644 index d8cd970ad3..0000000000 --- a/target/linux/ipq806x/patches/0028-pinctrl-msm-Drop-unused-includes.patch +++ /dev/null @@ -1,51 +0,0 @@ -From d2caa906f865d6919c511a956ae63ab62b240eba Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 6 Mar 2014 22:44:42 -0800 -Subject: [PATCH 028/182] pinctrl: msm: Drop unused includes - -These includes are unused or can be handled via forward -declarations. Remove them. - -Signed-off-by: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 1 - - drivers/pinctrl/pinctrl-msm.h | 5 +---- - drivers/pinctrl/pinctrl-msm8x74.c | 1 - - 3 files changed, 1 insertion(+), 6 deletions(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - - #include "core.h" ---- a/drivers/pinctrl/pinctrl-msm.h -+++ b/drivers/pinctrl/pinctrl-msm.h -@@ -13,10 +13,7 @@ - #ifndef __PINCTRL_MSM_H__ - #define __PINCTRL_MSM_H__ - --#include --#include --#include --#include -+struct pinctrl_pin_desc; - - /** - * struct msm_function - a pinmux function ---- a/drivers/pinctrl/pinctrl-msm8x74.c -+++ b/drivers/pinctrl/pinctrl-msm8x74.c -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - - #include "pinctrl-msm.h" - diff --git a/target/linux/ipq806x/patches/0029-pinctrl-msm-Drop-OF_IRQ-dependency.patch b/target/linux/ipq806x/patches/0029-pinctrl-msm-Drop-OF_IRQ-dependency.patch deleted file mode 100644 index 1357f3bb6c..0000000000 --- a/target/linux/ipq806x/patches/0029-pinctrl-msm-Drop-OF_IRQ-dependency.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2cfbd01bd994bd16dbee28a99553796f12848c4c Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 6 Mar 2014 22:44:43 -0800 -Subject: [PATCH 029/182] pinctrl: msm: Drop OF_IRQ dependency - -This driver doesn't rely on any functionality living in -drivers/of/irq.c to compile. Drop this dependency. - -Signed-off-by: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/pinctrl/Kconfig -+++ b/drivers/pinctrl/Kconfig -@@ -224,7 +224,7 @@ config PINCTRL_MSM - - config PINCTRL_MSM8X74 - tristate "Qualcomm 8x74 pin controller driver" -- depends on GPIOLIB && OF && OF_IRQ -+ depends on GPIOLIB && OF - select PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the diff --git a/target/linux/ipq806x/patches/0030-pinctrl-msm-Replace-lookup-tables-with-math.patch b/target/linux/ipq806x/patches/0030-pinctrl-msm-Replace-lookup-tables-with-math.patch deleted file mode 100644 index 6bc94affdb..0000000000 --- a/target/linux/ipq806x/patches/0030-pinctrl-msm-Replace-lookup-tables-with-math.patch +++ /dev/null @@ -1,61 +0,0 @@ -From e34d9fdac8182f6ce8933501fea6e84664060bf0 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 6 Mar 2014 22:44:44 -0800 -Subject: [PATCH 030/182] pinctrl: msm: Replace lookup tables with math - -We don't need to waste space with these lookup tables, just do -the math directly. - -Signed-off-by: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -258,8 +258,10 @@ static int msm_config_set(struct pinctrl - #define MSM_PULL_DOWN 1 - #define MSM_PULL_UP 3 - --static const unsigned msm_regval_to_drive[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; --static const unsigned msm_drive_to_regval[] = { -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1, 7 }; -+static unsigned msm_regval_to_drive(u32 val) -+{ -+ return (val + 1) * 2; -+} - - static int msm_config_group_get(struct pinctrl_dev *pctldev, - unsigned int group, -@@ -296,7 +298,7 @@ static int msm_config_group_get(struct p - arg = arg == MSM_PULL_UP; - break; - case PIN_CONFIG_DRIVE_STRENGTH: -- arg = msm_regval_to_drive[arg]; -+ arg = msm_regval_to_drive(arg); - break; - default: - dev_err(pctrl->dev, "Unsupported config parameter: %x\n", -@@ -349,10 +351,10 @@ static int msm_config_group_set(struct p - break; - case PIN_CONFIG_DRIVE_STRENGTH: - /* Check for invalid values */ -- if (arg >= ARRAY_SIZE(msm_drive_to_regval)) -+ if (arg > 16 || arg < 2 || (arg % 2) != 0) - arg = -1; - else -- arg = msm_drive_to_regval[arg]; -+ arg = (arg / 2) - 1; - break; - default: - dev_err(pctrl->dev, "Unsupported config parameter: %x\n", -@@ -531,7 +533,7 @@ static void msm_gpio_dbg_show_one(struct - pull = (ctl_reg >> g->pull_bit) & 3; - - seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func); -- seq_printf(s, " %dmA", msm_regval_to_drive[drive]); -+ seq_printf(s, " %dmA", msm_regval_to_drive(drive)); - seq_printf(s, " %s", pulls[pull]); - } - diff --git a/target/linux/ipq806x/patches/0031-pinctrl-msm-Remove-impossible-WARN_ON-s.patch b/target/linux/ipq806x/patches/0031-pinctrl-msm-Remove-impossible-WARN_ON-s.patch deleted file mode 100644 index 3356efcfea..0000000000 --- a/target/linux/ipq806x/patches/0031-pinctrl-msm-Remove-impossible-WARN_ON-s.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 286113578287b9c7619b4104864cffb91820f49d Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 6 Mar 2014 22:44:45 -0800 -Subject: [PATCH 031/182] pinctrl: msm: Remove impossible WARN_ON()s - -All these functions are limited in what they can pass as the gpio -or irq number to whatever is setup during probe. Remove the -checks. - -Signed-off-by: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 16 ---------------- - 1 file changed, 16 deletions(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -401,8 +401,6 @@ static int msm_gpio_direction_input(stru - u32 val; - - g = &pctrl->soc->groups[offset]; -- if (WARN_ON(g->io_reg < 0)) -- return -EINVAL; - - spin_lock_irqsave(&pctrl->lock, flags); - -@@ -423,8 +421,6 @@ static int msm_gpio_direction_output(str - u32 val; - - g = &pctrl->soc->groups[offset]; -- if (WARN_ON(g->io_reg < 0)) -- return -EINVAL; - - spin_lock_irqsave(&pctrl->lock, flags); - -@@ -451,8 +447,6 @@ static int msm_gpio_get(struct gpio_chip - u32 val; - - g = &pctrl->soc->groups[offset]; -- if (WARN_ON(g->io_reg < 0)) -- return -EINVAL; - - val = readl(pctrl->regs + g->io_reg); - return !!(val & BIT(g->in_bit)); -@@ -466,8 +460,6 @@ static void msm_gpio_set(struct gpio_chi - u32 val; - - g = &pctrl->soc->groups[offset]; -- if (WARN_ON(g->io_reg < 0)) -- return; - - spin_lock_irqsave(&pctrl->lock, flags); - -@@ -616,8 +608,6 @@ static void msm_gpio_irq_mask(struct irq - - pctrl = irq_data_get_irq_chip_data(d); - g = &pctrl->soc->groups[d->hwirq]; -- if (WARN_ON(g->intr_cfg_reg < 0)) -- return; - - spin_lock_irqsave(&pctrl->lock, flags); - -@@ -639,8 +629,6 @@ static void msm_gpio_irq_unmask(struct i - - pctrl = irq_data_get_irq_chip_data(d); - g = &pctrl->soc->groups[d->hwirq]; -- if (WARN_ON(g->intr_status_reg < 0)) -- return; - - spin_lock_irqsave(&pctrl->lock, flags); - -@@ -666,8 +654,6 @@ static void msm_gpio_irq_ack(struct irq_ - - pctrl = irq_data_get_irq_chip_data(d); - g = &pctrl->soc->groups[d->hwirq]; -- if (WARN_ON(g->intr_status_reg < 0)) -- return; - - spin_lock_irqsave(&pctrl->lock, flags); - -@@ -692,8 +678,6 @@ static int msm_gpio_irq_set_type(struct - - pctrl = irq_data_get_irq_chip_data(d); - g = &pctrl->soc->groups[d->hwirq]; -- if (WARN_ON(g->intr_cfg_reg < 0)) -- return -EINVAL; - - spin_lock_irqsave(&pctrl->lock, flags); - diff --git a/target/linux/ipq806x/patches/0032-pinctrl-msm-Simplify-msm_config_reg-and-callers.patch b/target/linux/ipq806x/patches/0032-pinctrl-msm-Simplify-msm_config_reg-and-callers.patch deleted file mode 100644 index f7798ae42e..0000000000 --- a/target/linux/ipq806x/patches/0032-pinctrl-msm-Simplify-msm_config_reg-and-callers.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 2d9ffb1a3f87396c3b792124870ef63fc27c568f Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 6 Mar 2014 22:44:46 -0800 -Subject: [PATCH 032/182] pinctrl: msm: Simplify msm_config_reg() and callers - -We don't need to check for a negative reg here because reg is -always the same and is always non-negative. Also, collapse the -switch statement down for the duplicate cases. - -Signed-off-by: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 29 +++++------------------------ - 1 file changed, 5 insertions(+), 24 deletions(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -200,28 +200,17 @@ static const struct pinmux_ops msm_pinmu - static int msm_config_reg(struct msm_pinctrl *pctrl, - const struct msm_pingroup *g, - unsigned param, -- s16 *reg, - unsigned *mask, - unsigned *bit) - { - switch (param) { - case PIN_CONFIG_BIAS_DISABLE: -- *reg = g->ctl_reg; -- *bit = g->pull_bit; -- *mask = 3; -- break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- *reg = g->ctl_reg; -- *bit = g->pull_bit; -- *mask = 3; -- break; - case PIN_CONFIG_BIAS_PULL_UP: -- *reg = g->ctl_reg; - *bit = g->pull_bit; - *mask = 3; - break; - case PIN_CONFIG_DRIVE_STRENGTH: -- *reg = g->ctl_reg; - *bit = g->drv_bit; - *mask = 7; - break; -@@ -230,12 +219,6 @@ static int msm_config_reg(struct msm_pin - return -ENOTSUPP; - } - -- if (*reg < 0) { -- dev_err(pctrl->dev, "Config param %04x not supported on group %s\n", -- param, g->name); -- return -ENOTSUPP; -- } -- - return 0; - } - -@@ -273,17 +256,16 @@ static int msm_config_group_get(struct p - unsigned mask; - unsigned arg; - unsigned bit; -- s16 reg; - int ret; - u32 val; - - g = &pctrl->soc->groups[group]; - -- ret = msm_config_reg(pctrl, g, param, ®, &mask, &bit); -+ ret = msm_config_reg(pctrl, g, param, &mask, &bit); - if (ret < 0) - return ret; - -- val = readl(pctrl->regs + reg); -+ val = readl(pctrl->regs + g->ctl_reg); - arg = (val >> bit) & mask; - - /* Convert register value to pinconf value */ -@@ -323,7 +305,6 @@ static int msm_config_group_set(struct p - unsigned mask; - unsigned arg; - unsigned bit; -- s16 reg; - int ret; - u32 val; - int i; -@@ -334,7 +315,7 @@ static int msm_config_group_set(struct p - param = pinconf_to_config_param(configs[i]); - arg = pinconf_to_config_argument(configs[i]); - -- ret = msm_config_reg(pctrl, g, param, ®, &mask, &bit); -+ ret = msm_config_reg(pctrl, g, param, &mask, &bit); - if (ret < 0) - return ret; - -@@ -369,10 +350,10 @@ static int msm_config_group_set(struct p - } - - spin_lock_irqsave(&pctrl->lock, flags); -- val = readl(pctrl->regs + reg); -+ val = readl(pctrl->regs + g->ctl_reg); - val &= ~(mask << bit); - val |= arg << bit; -- writel(val, pctrl->regs + reg); -+ writel(val, pctrl->regs + g->ctl_reg); - spin_unlock_irqrestore(&pctrl->lock, flags); - } - diff --git a/target/linux/ipq806x/patches/0033-pinctrl-msm-Support-output-high-low-configuration.patch b/target/linux/ipq806x/patches/0033-pinctrl-msm-Support-output-high-low-configuration.patch deleted file mode 100644 index f2f7c7d3b0..0000000000 --- a/target/linux/ipq806x/patches/0033-pinctrl-msm-Support-output-high-low-configuration.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 469f83e0ed374250be5fd6202ac535276a752fa8 Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Tue, 4 Feb 2014 19:55:31 -0800 -Subject: [PATCH 033/182] pinctrl-msm: Support output-{high,low} configuration - -Add support for configuring pins as output with value as from the -pinconf-generic interface. - -Signed-off-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -214,6 +214,11 @@ static int msm_config_reg(struct msm_pin - *bit = g->drv_bit; - *mask = 7; - break; -+ case PIN_CONFIG_OUTPUT: -+ *reg = g->ctl_reg; -+ *bit = g->oe_bit; -+ *mask = 1; -+ break; - default: - dev_err(pctrl->dev, "Invalid config param %04x\n", param); - return -ENOTSUPP; -@@ -282,6 +287,14 @@ static int msm_config_group_get(struct p - case PIN_CONFIG_DRIVE_STRENGTH: - arg = msm_regval_to_drive(arg); - break; -+ case PIN_CONFIG_OUTPUT: -+ /* Pin is not output */ -+ if (!arg) -+ return -EINVAL; -+ -+ val = readl(pctrl->regs + g->io_reg); -+ arg = !!(val & BIT(g->in_bit)); -+ break; - default: - dev_err(pctrl->dev, "Unsupported config parameter: %x\n", - param); -@@ -337,6 +350,20 @@ static int msm_config_group_set(struct p - else - arg = (arg / 2) - 1; - break; -+ case PIN_CONFIG_OUTPUT: -+ /* set output value */ -+ spin_lock_irqsave(&pctrl->lock, flags); -+ val = readl(pctrl->regs + g->io_reg); -+ if (arg) -+ val |= BIT(g->out_bit); -+ else -+ val &= ~BIT(g->out_bit); -+ writel(val, pctrl->regs + g->io_reg); -+ spin_unlock_irqrestore(&pctrl->lock, flags); -+ -+ /* enable output */ -+ arg = 1; -+ break; - default: - dev_err(pctrl->dev, "Unsupported config parameter: %x\n", - param); diff --git a/target/linux/ipq806x/patches/0034-pinctrl-msm-Add-SPI8-pin-definitions.patch b/target/linux/ipq806x/patches/0034-pinctrl-msm-Add-SPI8-pin-definitions.patch deleted file mode 100644 index a3f6d6a199..0000000000 --- a/target/linux/ipq806x/patches/0034-pinctrl-msm-Add-SPI8-pin-definitions.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 77e4b572fcc4015e235f22fd93b8df35e452baf0 Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Thu, 6 Feb 2014 17:28:48 +0200 -Subject: [PATCH 034/182] pinctrl-msm: Add SPI8 pin definitions - -Add pin, group and function definitions for SPI#8 -controller. - -Signed-off-by: Ivan T. Ivanov -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm8x74.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - ---- a/drivers/pinctrl/pinctrl-msm8x74.c -+++ b/drivers/pinctrl/pinctrl-msm8x74.c -@@ -405,6 +405,7 @@ enum msm8x74_functions { - MSM_MUX_blsp_i2c6, - MSM_MUX_blsp_i2c11, - MSM_MUX_blsp_spi1, -+ MSM_MUX_blsp_spi8, - MSM_MUX_blsp_uart2, - MSM_MUX_blsp_uart8, - MSM_MUX_slimbus, -@@ -415,6 +416,9 @@ static const char * const blsp_i2c2_grou - static const char * const blsp_i2c6_groups[] = { "gpio29", "gpio30" }; - static const char * const blsp_i2c11_groups[] = { "gpio83", "gpio84" }; - static const char * const blsp_spi1_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3" }; -+static const char * const blsp_spi8_groups[] = { -+ "gpio45", "gpio46", "gpio47", "gpio48" -+}; - static const char * const blsp_uart2_groups[] = { "gpio4", "gpio5" }; - static const char * const blsp_uart8_groups[] = { "gpio45", "gpio46" }; - static const char * const slimbus_groups[] = { "gpio70", "gpio71" }; -@@ -424,6 +428,7 @@ static const struct msm_function msm8x74 - FUNCTION(blsp_i2c6), - FUNCTION(blsp_i2c11), - FUNCTION(blsp_spi1), -+ FUNCTION(blsp_spi8), - FUNCTION(blsp_uart2), - FUNCTION(blsp_uart8), - FUNCTION(slimbus), -@@ -475,10 +480,10 @@ static const struct msm_pingroup msm8x74 - PINGROUP(42, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(43, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(44, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(45, NA, blsp_uart8, NA, NA, NA, NA, NA), -- PINGROUP(46, NA, blsp_uart8, NA, NA, NA, NA, NA), -- PINGROUP(47, NA, NA, NA, NA, NA, NA, NA), -- PINGROUP(48, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(45, blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA), -+ PINGROUP(46, blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA), -+ PINGROUP(47, blsp_spi8, NA, NA, NA, NA, NA, NA), -+ PINGROUP(48, blsp_spi8, NA, NA, NA, NA, NA, NA), - PINGROUP(49, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(50, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(51, NA, NA, NA, NA, NA, NA, NA), diff --git a/target/linux/ipq806x/patches/0035-pinctrl-msm-fix-up-out-of-order-merge-conflict.patch b/target/linux/ipq806x/patches/0035-pinctrl-msm-fix-up-out-of-order-merge-conflict.patch deleted file mode 100644 index f0bd614cfd..0000000000 --- a/target/linux/ipq806x/patches/0035-pinctrl-msm-fix-up-out-of-order-merge-conflict.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c73a138dd24049d06fe7b22518655ed9e7413cd2 Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Fri, 14 Mar 2014 07:54:20 +0100 -Subject: [PATCH 035/182] pinctrl: msm: fix up out-of-order merge conflict - -Commit 051a58b4622f0e1b732acb750097c64bc00ddb93 -"pinctrl: msm: Simplify msm_config_reg() and callers" -removed the local "reg" variable in the msm_config_reg() -function, but the earlier -commit ed118a5fd951bd2def8249ee251842c4f81fe4bd -"pinctrl-msm: Support output-{high,low} configuration" -introduced a new switchclause using it. - -Fix this up by removing the offending register assignment. - -Reported-by: Kbuild test robot -Cc: Stephen Boyd -Acked-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -215,7 +215,6 @@ static int msm_config_reg(struct msm_pin - *mask = 7; - break; - case PIN_CONFIG_OUTPUT: -- *reg = g->ctl_reg; - *bit = g->oe_bit; - *mask = 1; - break; diff --git a/target/linux/ipq806x/patches/0036-pinctrl-msm-Correct-interrupt-code-for-TLMM-v2.patch b/target/linux/ipq806x/patches/0036-pinctrl-msm-Correct-interrupt-code-for-TLMM-v2.patch deleted file mode 100644 index 384e183eb8..0000000000 --- a/target/linux/ipq806x/patches/0036-pinctrl-msm-Correct-interrupt-code-for-TLMM-v2.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 32787a9bba5a1ebeea891fd7aab954e6d344892a Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Mon, 31 Mar 2014 14:49:54 -0700 -Subject: [PATCH 036/182] pinctrl: msm: Correct interrupt code for TLMM v2 - -Acking interrupts are done differently between on v2 and v3, so add an extra -attribute to the pingroup struct to let the platform definitions control this. -Also make sure to start dual edge detection by detecting the rising edge. - -Signed-off-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 6 +++++- - drivers/pinctrl/pinctrl-msm.h | 1 + - 2 files changed, 6 insertions(+), 1 deletion(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -665,7 +665,10 @@ static void msm_gpio_irq_ack(struct irq_ - spin_lock_irqsave(&pctrl->lock, flags); - - val = readl(pctrl->regs + g->intr_status_reg); -- val &= ~BIT(g->intr_status_bit); -+ if (g->intr_ack_high) -+ val |= BIT(g->intr_status_bit); -+ else -+ val &= ~BIT(g->intr_status_bit); - writel(val, pctrl->regs + g->intr_status_reg); - - if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) -@@ -744,6 +747,7 @@ static int msm_gpio_irq_set_type(struct - break; - case IRQ_TYPE_EDGE_BOTH: - val |= BIT(g->intr_detection_bit); -+ val |= BIT(g->intr_polarity_bit); - break; - case IRQ_TYPE_LEVEL_LOW: - break; ---- a/drivers/pinctrl/pinctrl-msm.h -+++ b/drivers/pinctrl/pinctrl-msm.h -@@ -84,6 +84,7 @@ struct msm_pingroup { - - unsigned intr_enable_bit:5; - unsigned intr_status_bit:5; -+ unsigned intr_ack_high:1; - - unsigned intr_target_bit:5; - unsigned intr_raw_status_bit:5; diff --git a/target/linux/ipq806x/patches/0037-pinctrl-msm-Make-number-of-functions-variable.patch b/target/linux/ipq806x/patches/0037-pinctrl-msm-Make-number-of-functions-variable.patch deleted file mode 100644 index e36498b83d..0000000000 --- a/target/linux/ipq806x/patches/0037-pinctrl-msm-Make-number-of-functions-variable.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 1c11b14dd6d740e997919f0bf789bf921548dc0f Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Mon, 31 Mar 2014 14:49:55 -0700 -Subject: [PATCH 037/182] pinctrl: msm: Make number of functions variable - -The various pins may have different number of functions defined, so make this -number definable per pin instead of just increasing it to the largest one for -all of the platforms. - -Signed-off-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-msm.c | 4 ++-- - drivers/pinctrl/pinctrl-msm.h | 3 ++- - drivers/pinctrl/pinctrl-msm8x74.c | 3 ++- - 3 files changed, 6 insertions(+), 4 deletions(-) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -145,12 +145,12 @@ static int msm_pinmux_enable(struct pinc - if (WARN_ON(g->mux_bit < 0)) - return -EINVAL; - -- for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { -+ for (i = 0; i < g->nfuncs; i++) { - if (g->funcs[i] == function) - break; - } - -- if (WARN_ON(i == ARRAY_SIZE(g->funcs))) -+ if (WARN_ON(i == g->nfuncs)) - return -EINVAL; - - spin_lock_irqsave(&pctrl->lock, flags); ---- a/drivers/pinctrl/pinctrl-msm.h -+++ b/drivers/pinctrl/pinctrl-msm.h -@@ -65,7 +65,8 @@ struct msm_pingroup { - const unsigned *pins; - unsigned npins; - -- unsigned funcs[8]; -+ unsigned *funcs; -+ unsigned nfuncs; - - s16 ctl_reg; - s16 io_reg; ---- a/drivers/pinctrl/pinctrl-msm8x74.c -+++ b/drivers/pinctrl/pinctrl-msm8x74.c -@@ -341,7 +341,7 @@ static const unsigned int sdc2_data_pins - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ -- .funcs = { \ -+ .funcs = (int[]){ \ - MSM_MUX_NA, /* gpio mode */ \ - MSM_MUX_##f1, \ - MSM_MUX_##f2, \ -@@ -351,6 +351,7 @@ static const unsigned int sdc2_data_pins - MSM_MUX_##f6, \ - MSM_MUX_##f7 \ - }, \ -+ .nfuncs = 8, \ - .ctl_reg = 0x1000 + 0x10 * id, \ - .io_reg = 0x1004 + 0x10 * id, \ - .intr_cfg_reg = 0x1008 + 0x10 * id, \ diff --git a/target/linux/ipq806x/patches/0038-pinctrl-msm-Add-definitions-for-the-APQ8064-platform.patch b/target/linux/ipq806x/patches/0038-pinctrl-msm-Add-definitions-for-the-APQ8064-platform.patch deleted file mode 100644 index a177d35285..0000000000 --- a/target/linux/ipq806x/patches/0038-pinctrl-msm-Add-definitions-for-the-APQ8064-platform.patch +++ /dev/null @@ -1,614 +0,0 @@ -From 247288012122ccfe7d5d9af00a45814c6fdd94c5 Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Mon, 31 Mar 2014 14:49:57 -0700 -Subject: [PATCH 038/182] pinctrl: msm: Add definitions for the APQ8064 - platform - -This adds pinctrl definitions for the GPIO pins of the TLMM v2 block in the -Qualcomm APQ8064 platform. - -Signed-off-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/Kconfig | 8 + - drivers/pinctrl/Makefile | 1 + - drivers/pinctrl/pinctrl-apq8064.c | 566 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 575 insertions(+) - create mode 100644 drivers/pinctrl/pinctrl-apq8064.c - ---- a/drivers/pinctrl/Kconfig -+++ b/drivers/pinctrl/Kconfig -@@ -222,6 +222,14 @@ config PINCTRL_MSM - select PINCONF - select GENERIC_PINCONF - -+config PINCTRL_APQ8064 -+ tristate "Qualcomm APQ8064 pin controller driver" -+ depends on GPIOLIB && OF -+ select PINCTRL_MSM -+ help -+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the -+ Qualcomm TLMM block found in the Qualcomm APQ8064 platform. -+ - config PINCTRL_MSM8X74 - tristate "Qualcomm 8x74 pin controller driver" - depends on GPIOLIB && OF ---- a/drivers/pinctrl/Makefile -+++ b/drivers/pinctrl/Makefile -@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-i - obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o - obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o - obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o -+obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o - obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o - obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o - obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o ---- /dev/null -+++ b/drivers/pinctrl/pinctrl-apq8064.c -@@ -0,0 +1,566 @@ -+/* -+ * Copyright (c) 2014, Sony Mobile Communications AB. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+ -+#include "pinctrl-msm.h" -+ -+static const struct pinctrl_pin_desc apq8064_pins[] = { -+ PINCTRL_PIN(0, "GPIO_0"), -+ PINCTRL_PIN(1, "GPIO_1"), -+ PINCTRL_PIN(2, "GPIO_2"), -+ PINCTRL_PIN(3, "GPIO_3"), -+ PINCTRL_PIN(4, "GPIO_4"), -+ PINCTRL_PIN(5, "GPIO_5"), -+ PINCTRL_PIN(6, "GPIO_6"), -+ PINCTRL_PIN(7, "GPIO_7"), -+ PINCTRL_PIN(8, "GPIO_8"), -+ PINCTRL_PIN(9, "GPIO_9"), -+ PINCTRL_PIN(10, "GPIO_10"), -+ PINCTRL_PIN(11, "GPIO_11"), -+ PINCTRL_PIN(12, "GPIO_12"), -+ PINCTRL_PIN(13, "GPIO_13"), -+ PINCTRL_PIN(14, "GPIO_14"), -+ PINCTRL_PIN(15, "GPIO_15"), -+ PINCTRL_PIN(16, "GPIO_16"), -+ PINCTRL_PIN(17, "GPIO_17"), -+ PINCTRL_PIN(18, "GPIO_18"), -+ PINCTRL_PIN(19, "GPIO_19"), -+ PINCTRL_PIN(20, "GPIO_20"), -+ PINCTRL_PIN(21, "GPIO_21"), -+ PINCTRL_PIN(22, "GPIO_22"), -+ PINCTRL_PIN(23, "GPIO_23"), -+ PINCTRL_PIN(24, "GPIO_24"), -+ PINCTRL_PIN(25, "GPIO_25"), -+ PINCTRL_PIN(26, "GPIO_26"), -+ PINCTRL_PIN(27, "GPIO_27"), -+ PINCTRL_PIN(28, "GPIO_28"), -+ PINCTRL_PIN(29, "GPIO_29"), -+ PINCTRL_PIN(30, "GPIO_30"), -+ PINCTRL_PIN(31, "GPIO_31"), -+ PINCTRL_PIN(32, "GPIO_32"), -+ PINCTRL_PIN(33, "GPIO_33"), -+ PINCTRL_PIN(34, "GPIO_34"), -+ PINCTRL_PIN(35, "GPIO_35"), -+ PINCTRL_PIN(36, "GPIO_36"), -+ PINCTRL_PIN(37, "GPIO_37"), -+ PINCTRL_PIN(38, "GPIO_38"), -+ PINCTRL_PIN(39, "GPIO_39"), -+ PINCTRL_PIN(40, "GPIO_40"), -+ PINCTRL_PIN(41, "GPIO_41"), -+ PINCTRL_PIN(42, "GPIO_42"), -+ PINCTRL_PIN(43, "GPIO_43"), -+ PINCTRL_PIN(44, "GPIO_44"), -+ PINCTRL_PIN(45, "GPIO_45"), -+ PINCTRL_PIN(46, "GPIO_46"), -+ PINCTRL_PIN(47, "GPIO_47"), -+ PINCTRL_PIN(48, "GPIO_48"), -+ PINCTRL_PIN(49, "GPIO_49"), -+ PINCTRL_PIN(50, "GPIO_50"), -+ PINCTRL_PIN(51, "GPIO_51"), -+ PINCTRL_PIN(52, "GPIO_52"), -+ PINCTRL_PIN(53, "GPIO_53"), -+ PINCTRL_PIN(54, "GPIO_54"), -+ PINCTRL_PIN(55, "GPIO_55"), -+ PINCTRL_PIN(56, "GPIO_56"), -+ PINCTRL_PIN(57, "GPIO_57"), -+ PINCTRL_PIN(58, "GPIO_58"), -+ PINCTRL_PIN(59, "GPIO_59"), -+ PINCTRL_PIN(60, "GPIO_60"), -+ PINCTRL_PIN(61, "GPIO_61"), -+ PINCTRL_PIN(62, "GPIO_62"), -+ PINCTRL_PIN(63, "GPIO_63"), -+ PINCTRL_PIN(64, "GPIO_64"), -+ PINCTRL_PIN(65, "GPIO_65"), -+ PINCTRL_PIN(66, "GPIO_66"), -+ PINCTRL_PIN(67, "GPIO_67"), -+ PINCTRL_PIN(68, "GPIO_68"), -+ PINCTRL_PIN(69, "GPIO_69"), -+ PINCTRL_PIN(70, "GPIO_70"), -+ PINCTRL_PIN(71, "GPIO_71"), -+ PINCTRL_PIN(72, "GPIO_72"), -+ PINCTRL_PIN(73, "GPIO_73"), -+ PINCTRL_PIN(74, "GPIO_74"), -+ PINCTRL_PIN(75, "GPIO_75"), -+ PINCTRL_PIN(76, "GPIO_76"), -+ PINCTRL_PIN(77, "GPIO_77"), -+ PINCTRL_PIN(78, "GPIO_78"), -+ PINCTRL_PIN(79, "GPIO_79"), -+ PINCTRL_PIN(80, "GPIO_80"), -+ PINCTRL_PIN(81, "GPIO_81"), -+ PINCTRL_PIN(82, "GPIO_82"), -+ PINCTRL_PIN(83, "GPIO_83"), -+ PINCTRL_PIN(84, "GPIO_84"), -+ PINCTRL_PIN(85, "GPIO_85"), -+ PINCTRL_PIN(86, "GPIO_86"), -+ PINCTRL_PIN(87, "GPIO_87"), -+ PINCTRL_PIN(88, "GPIO_88"), -+ PINCTRL_PIN(89, "GPIO_89"), -+}; -+ -+#define DECLARE_APQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin } -+DECLARE_APQ_GPIO_PINS(0); -+DECLARE_APQ_GPIO_PINS(1); -+DECLARE_APQ_GPIO_PINS(2); -+DECLARE_APQ_GPIO_PINS(3); -+DECLARE_APQ_GPIO_PINS(4); -+DECLARE_APQ_GPIO_PINS(5); -+DECLARE_APQ_GPIO_PINS(6); -+DECLARE_APQ_GPIO_PINS(7); -+DECLARE_APQ_GPIO_PINS(8); -+DECLARE_APQ_GPIO_PINS(9); -+DECLARE_APQ_GPIO_PINS(10); -+DECLARE_APQ_GPIO_PINS(11); -+DECLARE_APQ_GPIO_PINS(12); -+DECLARE_APQ_GPIO_PINS(13); -+DECLARE_APQ_GPIO_PINS(14); -+DECLARE_APQ_GPIO_PINS(15); -+DECLARE_APQ_GPIO_PINS(16); -+DECLARE_APQ_GPIO_PINS(17); -+DECLARE_APQ_GPIO_PINS(18); -+DECLARE_APQ_GPIO_PINS(19); -+DECLARE_APQ_GPIO_PINS(20); -+DECLARE_APQ_GPIO_PINS(21); -+DECLARE_APQ_GPIO_PINS(22); -+DECLARE_APQ_GPIO_PINS(23); -+DECLARE_APQ_GPIO_PINS(24); -+DECLARE_APQ_GPIO_PINS(25); -+DECLARE_APQ_GPIO_PINS(26); -+DECLARE_APQ_GPIO_PINS(27); -+DECLARE_APQ_GPIO_PINS(28); -+DECLARE_APQ_GPIO_PINS(29); -+DECLARE_APQ_GPIO_PINS(30); -+DECLARE_APQ_GPIO_PINS(31); -+DECLARE_APQ_GPIO_PINS(32); -+DECLARE_APQ_GPIO_PINS(33); -+DECLARE_APQ_GPIO_PINS(34); -+DECLARE_APQ_GPIO_PINS(35); -+DECLARE_APQ_GPIO_PINS(36); -+DECLARE_APQ_GPIO_PINS(37); -+DECLARE_APQ_GPIO_PINS(38); -+DECLARE_APQ_GPIO_PINS(39); -+DECLARE_APQ_GPIO_PINS(40); -+DECLARE_APQ_GPIO_PINS(41); -+DECLARE_APQ_GPIO_PINS(42); -+DECLARE_APQ_GPIO_PINS(43); -+DECLARE_APQ_GPIO_PINS(44); -+DECLARE_APQ_GPIO_PINS(45); -+DECLARE_APQ_GPIO_PINS(46); -+DECLARE_APQ_GPIO_PINS(47); -+DECLARE_APQ_GPIO_PINS(48); -+DECLARE_APQ_GPIO_PINS(49); -+DECLARE_APQ_GPIO_PINS(50); -+DECLARE_APQ_GPIO_PINS(51); -+DECLARE_APQ_GPIO_PINS(52); -+DECLARE_APQ_GPIO_PINS(53); -+DECLARE_APQ_GPIO_PINS(54); -+DECLARE_APQ_GPIO_PINS(55); -+DECLARE_APQ_GPIO_PINS(56); -+DECLARE_APQ_GPIO_PINS(57); -+DECLARE_APQ_GPIO_PINS(58); -+DECLARE_APQ_GPIO_PINS(59); -+DECLARE_APQ_GPIO_PINS(60); -+DECLARE_APQ_GPIO_PINS(61); -+DECLARE_APQ_GPIO_PINS(62); -+DECLARE_APQ_GPIO_PINS(63); -+DECLARE_APQ_GPIO_PINS(64); -+DECLARE_APQ_GPIO_PINS(65); -+DECLARE_APQ_GPIO_PINS(66); -+DECLARE_APQ_GPIO_PINS(67); -+DECLARE_APQ_GPIO_PINS(68); -+DECLARE_APQ_GPIO_PINS(69); -+DECLARE_APQ_GPIO_PINS(70); -+DECLARE_APQ_GPIO_PINS(71); -+DECLARE_APQ_GPIO_PINS(72); -+DECLARE_APQ_GPIO_PINS(73); -+DECLARE_APQ_GPIO_PINS(74); -+DECLARE_APQ_GPIO_PINS(75); -+DECLARE_APQ_GPIO_PINS(76); -+DECLARE_APQ_GPIO_PINS(77); -+DECLARE_APQ_GPIO_PINS(78); -+DECLARE_APQ_GPIO_PINS(79); -+DECLARE_APQ_GPIO_PINS(80); -+DECLARE_APQ_GPIO_PINS(81); -+DECLARE_APQ_GPIO_PINS(82); -+DECLARE_APQ_GPIO_PINS(83); -+DECLARE_APQ_GPIO_PINS(84); -+DECLARE_APQ_GPIO_PINS(85); -+DECLARE_APQ_GPIO_PINS(86); -+DECLARE_APQ_GPIO_PINS(87); -+DECLARE_APQ_GPIO_PINS(88); -+DECLARE_APQ_GPIO_PINS(89); -+ -+#define FUNCTION(fname) \ -+ [APQ_MUX_##fname] = { \ -+ .name = #fname, \ -+ .groups = fname##_groups, \ -+ .ngroups = ARRAY_SIZE(fname##_groups), \ -+ } -+ -+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ -+ { \ -+ .name = "gpio" #id, \ -+ .pins = gpio##id##_pins, \ -+ .npins = ARRAY_SIZE(gpio##id##_pins), \ -+ .funcs = (int[]){ \ -+ APQ_MUX_NA, /* gpio mode */ \ -+ APQ_MUX_##f1, \ -+ APQ_MUX_##f2, \ -+ APQ_MUX_##f3, \ -+ APQ_MUX_##f4, \ -+ APQ_MUX_##f5, \ -+ APQ_MUX_##f6, \ -+ APQ_MUX_##f7, \ -+ APQ_MUX_##f8, \ -+ APQ_MUX_##f9, \ -+ APQ_MUX_##f10, \ -+ }, \ -+ .nfuncs = 11, \ -+ .ctl_reg = 0x1000 + 0x10 * id, \ -+ .io_reg = 0x1004 + 0x10 * id, \ -+ .intr_cfg_reg = 0x1008 + 0x10 * id, \ -+ .intr_status_reg = 0x100c + 0x10 * id, \ -+ .intr_target_reg = 0x400 + 0x4 * id, \ -+ .mux_bit = 2, \ -+ .pull_bit = 0, \ -+ .drv_bit = 6, \ -+ .oe_bit = 9, \ -+ .in_bit = 0, \ -+ .out_bit = 1, \ -+ .intr_enable_bit = 0, \ -+ .intr_status_bit = 0, \ -+ .intr_ack_high = 1, \ -+ .intr_target_bit = 0, \ -+ .intr_raw_status_bit = 3, \ -+ .intr_polarity_bit = 1, \ -+ .intr_detection_bit = 2, \ -+ .intr_detection_width = 1, \ -+ } -+ -+enum apq8064_functions { -+ APQ_MUX_cam_mclk, -+ APQ_MUX_codec_mic_i2s, -+ APQ_MUX_codec_spkr_i2s, -+ APQ_MUX_gsbi1, -+ APQ_MUX_gsbi2, -+ APQ_MUX_gsbi3, -+ APQ_MUX_gsbi4, -+ APQ_MUX_gsbi4_cam_i2c, -+ APQ_MUX_gsbi5, -+ APQ_MUX_gsbi5_spi_cs1, -+ APQ_MUX_gsbi5_spi_cs2, -+ APQ_MUX_gsbi5_spi_cs3, -+ APQ_MUX_gsbi6, -+ APQ_MUX_gsbi6_spi_cs1, -+ APQ_MUX_gsbi6_spi_cs2, -+ APQ_MUX_gsbi6_spi_cs3, -+ APQ_MUX_gsbi7, -+ APQ_MUX_gsbi7_spi_cs1, -+ APQ_MUX_gsbi7_spi_cs2, -+ APQ_MUX_gsbi7_spi_cs3, -+ APQ_MUX_gsbi_cam_i2c, -+ APQ_MUX_hdmi, -+ APQ_MUX_mi2s, -+ APQ_MUX_riva_bt, -+ APQ_MUX_riva_fm, -+ APQ_MUX_riva_wlan, -+ APQ_MUX_sdc2, -+ APQ_MUX_sdc4, -+ APQ_MUX_slimbus, -+ APQ_MUX_spkr_i2s, -+ APQ_MUX_tsif1, -+ APQ_MUX_tsif2, -+ APQ_MUX_usb2_hsic, -+ APQ_MUX_NA, -+}; -+ -+static const char * const cam_mclk_groups[] = { -+ "gpio4" "gpio5" -+}; -+static const char * const codec_mic_i2s_groups[] = { -+ "gpio34", "gpio35", "gpio36", "gpio37", "gpio38" -+}; -+static const char * const codec_spkr_i2s_groups[] = { -+ "gpio39", "gpio40", "gpio41", "gpio42" -+}; -+static const char * const gsbi1_groups[] = { -+ "gpio18", "gpio19", "gpio20", "gpio21" -+}; -+static const char * const gsbi2_groups[] = { -+ "gpio22", "gpio23", "gpio24", "gpio25" -+}; -+static const char * const gsbi3_groups[] = { -+ "gpio6", "gpio7", "gpio8", "gpio9" -+}; -+static const char * const gsbi4_groups[] = { -+ "gpio10", "gpio11", "gpio12", "gpio13" -+}; -+static const char * const gsbi4_cam_i2c_groups[] = { -+ "gpio10", "gpio11", "gpio12", "gpio13" -+}; -+static const char * const gsbi5_groups[] = { -+ "gpio51", "gpio52", "gpio53", "gpio54" -+}; -+static const char * const gsbi5_spi_cs1_groups[] = { -+ "gpio47" -+}; -+static const char * const gsbi5_spi_cs2_groups[] = { -+ "gpio31" -+}; -+static const char * const gsbi5_spi_cs3_groups[] = { -+ "gpio32" -+}; -+static const char * const gsbi6_groups[] = { -+ "gpio14", "gpio15", "gpio16", "gpio17" -+}; -+static const char * const gsbi6_spi_cs1_groups[] = { -+ "gpio47" -+}; -+static const char * const gsbi6_spi_cs2_groups[] = { -+ "gpio31" -+}; -+static const char * const gsbi6_spi_cs3_groups[] = { -+ "gpio32" -+}; -+static const char * const gsbi7_groups[] = { -+ "gpio82", "gpio83", "gpio84", "gpio85" -+}; -+static const char * const gsbi7_spi_cs1_groups[] = { -+ "gpio47" -+}; -+static const char * const gsbi7_spi_cs2_groups[] = { -+ "gpio31" -+}; -+static const char * const gsbi7_spi_cs3_groups[] = { -+ "gpio32" -+}; -+static const char * const gsbi_cam_i2c_groups[] = { -+ "gpio10", "gpio11", "gpio12", "gpio13" -+}; -+static const char * const hdmi_groups[] = { -+ "gpio69", "gpio70", "gpio71", "gpio72" -+}; -+static const char * const mi2s_groups[] = { -+ "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33" -+}; -+static const char * const riva_bt_groups[] = { -+ "gpio16", "gpio17" -+}; -+static const char * const riva_fm_groups[] = { -+ "gpio14", "gpio15" -+}; -+static const char * const riva_wlan_groups[] = { -+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68" -+}; -+static const char * const sdc2_groups[] = { -+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62" -+}; -+static const char * const sdc4_groups[] = { -+ "gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68" -+}; -+static const char * const slimbus_groups[] = { -+ "gpio40", "gpio41" -+}; -+static const char * const spkr_i2s_groups[] = { -+ "gpio47", "gpio48", "gpio49", "gpio50" -+}; -+static const char * const tsif1_groups[] = { -+ "gpio55", "gpio56", "gpio57" -+}; -+static const char * const tsif2_groups[] = { -+ "gpio58", "gpio59", "gpio60" -+}; -+static const char * const usb2_hsic_groups[] = { -+ "gpio88", "gpio89" -+}; -+ -+static const struct msm_function apq8064_functions[] = { -+ FUNCTION(cam_mclk), -+ FUNCTION(codec_mic_i2s), -+ FUNCTION(codec_spkr_i2s), -+ FUNCTION(gsbi1), -+ FUNCTION(gsbi2), -+ FUNCTION(gsbi3), -+ FUNCTION(gsbi4), -+ FUNCTION(gsbi4_cam_i2c), -+ FUNCTION(gsbi5), -+ FUNCTION(gsbi5_spi_cs1), -+ FUNCTION(gsbi5_spi_cs2), -+ FUNCTION(gsbi5_spi_cs3), -+ FUNCTION(gsbi6), -+ FUNCTION(gsbi6_spi_cs1), -+ FUNCTION(gsbi6_spi_cs2), -+ FUNCTION(gsbi6_spi_cs3), -+ FUNCTION(gsbi7), -+ FUNCTION(gsbi7_spi_cs1), -+ FUNCTION(gsbi7_spi_cs2), -+ FUNCTION(gsbi7_spi_cs3), -+ FUNCTION(gsbi_cam_i2c), -+ FUNCTION(hdmi), -+ FUNCTION(mi2s), -+ FUNCTION(riva_bt), -+ FUNCTION(riva_fm), -+ FUNCTION(riva_wlan), -+ FUNCTION(sdc2), -+ FUNCTION(sdc4), -+ FUNCTION(slimbus), -+ FUNCTION(spkr_i2s), -+ FUNCTION(tsif1), -+ FUNCTION(tsif2), -+ FUNCTION(usb2_hsic), -+}; -+ -+static const struct msm_pingroup apq8064_groups[] = { -+ PINGROUP(0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(4, NA, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(5, NA, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(6, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(7, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(8, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(9, gsbi3, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(10, gsbi4, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c, NA), -+ PINGROUP(11, gsbi4, NA, NA, NA, NA, NA, NA, NA, NA, gsbi4_cam_i2c), -+ PINGROUP(12, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA), -+ PINGROUP(13, gsbi4, NA, NA, NA, NA, gsbi4_cam_i2c, NA, NA, NA, NA), -+ PINGROUP(14, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(15, riva_fm, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(16, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(17, riva_bt, gsbi6, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(18, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(19, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(20, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(21, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(22, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(23, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(24, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(25, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(27, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(28, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(29, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(30, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(31, mi2s, NA, gsbi5_spi_cs2, gsbi6_spi_cs2, gsbi7_spi_cs2, NA, NA, NA, NA, NA), -+ PINGROUP(32, mi2s, NA, NA, NA, NA, gsbi5_spi_cs3, gsbi6_spi_cs3, gsbi7_spi_cs3, NA, NA), -+ PINGROUP(33, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(34, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(35, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(36, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(37, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(38, codec_mic_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(39, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(40, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(41, slimbus, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(42, codec_spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(46, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(47, spkr_i2s, gsbi5_spi_cs1, gsbi6_spi_cs1, gsbi7_spi_cs1, NA, NA, NA, NA, NA, NA), -+ PINGROUP(48, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(49, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(50, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(51, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(52, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(53, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(54, NA, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(55, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(56, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(57, tsif1, sdc2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(58, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(59, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(60, tsif2, sdc2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(61, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(62, NA, sdc2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(63, NA, sdc4, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(64, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(65, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(66, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(67, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(68, riva_wlan, sdc4, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(69, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(70, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(71, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(72, hdmi, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(73, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(74, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(75, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(76, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(77, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(79, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(81, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(82, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(83, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(84, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(85, NA, NA, gsbi7, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(88, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(89, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+}; -+ -+#define NUM_GPIO_PINGROUPS 90 -+ -+static const struct msm_pinctrl_soc_data apq8064_pinctrl = { -+ .pins = apq8064_pins, -+ .npins = ARRAY_SIZE(apq8064_pins), -+ .functions = apq8064_functions, -+ .nfunctions = ARRAY_SIZE(apq8064_functions), -+ .groups = apq8064_groups, -+ .ngroups = ARRAY_SIZE(apq8064_groups), -+ .ngpios = NUM_GPIO_PINGROUPS, -+}; -+ -+static int apq8064_pinctrl_probe(struct platform_device *pdev) -+{ -+ return msm_pinctrl_probe(pdev, &apq8064_pinctrl); -+} -+ -+static const struct of_device_id apq8064_pinctrl_of_match[] = { -+ { .compatible = "qcom,apq8064-pinctrl", }, -+ { }, -+}; -+ -+static struct platform_driver apq8064_pinctrl_driver = { -+ .driver = { -+ .name = "apq8064-pinctrl", -+ .owner = THIS_MODULE, -+ .of_match_table = apq8064_pinctrl_of_match, -+ }, -+ .probe = apq8064_pinctrl_probe, -+ .remove = msm_pinctrl_remove, -+}; -+ -+static int __init apq8064_pinctrl_init(void) -+{ -+ return platform_driver_register(&apq8064_pinctrl_driver); -+} -+arch_initcall(apq8064_pinctrl_init); -+ -+static void __exit apq8064_pinctrl_exit(void) -+{ -+ platform_driver_unregister(&apq8064_pinctrl_driver); -+} -+module_exit(apq8064_pinctrl_exit); -+ -+MODULE_AUTHOR("Bjorn Andersson "); -+MODULE_DESCRIPTION("Qualcomm APQ8064 pinctrl driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_DEVICE_TABLE(of, apq8064_pinctrl_of_match); diff --git a/target/linux/ipq806x/patches/0039-pinctrl-msm8x74-make-Kconfig-dependency-more-strict.patch b/target/linux/ipq806x/patches/0039-pinctrl-msm8x74-make-Kconfig-dependency-more-strict.patch deleted file mode 100644 index 7c56af6537..0000000000 --- a/target/linux/ipq806x/patches/0039-pinctrl-msm8x74-make-Kconfig-dependency-more-strict.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 8605197c200786888415bf2e30d1fbde6ba8ba03 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= -Date: Tue, 1 Apr 2014 22:25:59 +0200 -Subject: [PATCH 039/182] pinctrl: msm8x74: make Kconfig dependency more - strict -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This driver is only useful on MSM8x74, so let the driver depend on -ARCH_QCOM but allow compile coverage testing. -The main benefit is that the driver isn't available to be selected for -machines that don't have the matching hardware. - -Signed-off-by: Uwe Kleine-König -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/pinctrl/Kconfig -+++ b/drivers/pinctrl/Kconfig -@@ -232,7 +232,7 @@ config PINCTRL_APQ8064 - - config PINCTRL_MSM8X74 - tristate "Qualcomm 8x74 pin controller driver" -- depends on GPIOLIB && OF -+ depends on GPIOLIB && OF && (ARCH_QCOM || COMPILE_TEST) - select PINCTRL_MSM - help - This is the pinctrl, pinmux, pinconf and gpiolib driver for the diff --git a/target/linux/ipq806x/patches/0040-pinctrl-qcom-Add-definitions-for-IPQ8064.patch b/target/linux/ipq806x/patches/0040-pinctrl-qcom-Add-definitions-for-IPQ8064.patch deleted file mode 100644 index a54604a775..0000000000 --- a/target/linux/ipq806x/patches/0040-pinctrl-qcom-Add-definitions-for-IPQ8064.patch +++ /dev/null @@ -1,701 +0,0 @@ -From 9bbd9d7e40944ca95e07f363b68700225beb9bef Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 14 Apr 2014 22:10:35 -0500 -Subject: [PATCH 040/182] pinctrl: qcom: Add definitions for IPQ8064 - -This adds pinctrl definitions for the GPIO pins of the TLMM v2 block in the -Qualcomm IPQ8064 platform. - -Signed-off-by: Andy Gross -Reviewed-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/Kconfig | 8 + - drivers/pinctrl/Makefile | 1 + - drivers/pinctrl/pinctrl-ipq8064.c | 653 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 662 insertions(+) - create mode 100644 drivers/pinctrl/pinctrl-ipq8064.c - ---- a/drivers/pinctrl/Kconfig -+++ b/drivers/pinctrl/Kconfig -@@ -230,6 +230,14 @@ config PINCTRL_APQ8064 - This is the pinctrl, pinmux, pinconf and gpiolib driver for the - Qualcomm TLMM block found in the Qualcomm APQ8064 platform. - -+config PINCTRL_IPQ8064 -+ tristate "Qualcomm IPQ8064 pin controller driver" -+ depends on GPIOLIB && OF -+ select PINCTRL_MSM -+ help -+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the -+ Qualcomm TLMM block found in the Qualcomm IPQ8064 platform. -+ - config PINCTRL_MSM8X74 - tristate "Qualcomm 8x74 pin controller driver" - depends on GPIOLIB && OF && (ARCH_QCOM || COMPILE_TEST) ---- a/drivers/pinctrl/Makefile -+++ b/drivers/pinctrl/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-i - obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o - obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o - obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o -+obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o - obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o - obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o - obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o ---- /dev/null -+++ b/drivers/pinctrl/pinctrl-ipq8064.c -@@ -0,0 +1,653 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+ -+#include "pinctrl-msm.h" -+ -+static const struct pinctrl_pin_desc ipq8064_pins[] = { -+ PINCTRL_PIN(0, "GPIO_1"), -+ PINCTRL_PIN(1, "GPIO_1"), -+ PINCTRL_PIN(2, "GPIO_2"), -+ PINCTRL_PIN(3, "GPIO_3"), -+ PINCTRL_PIN(4, "GPIO_4"), -+ PINCTRL_PIN(5, "GPIO_5"), -+ PINCTRL_PIN(6, "GPIO_6"), -+ PINCTRL_PIN(7, "GPIO_7"), -+ PINCTRL_PIN(8, "GPIO_8"), -+ PINCTRL_PIN(9, "GPIO_9"), -+ PINCTRL_PIN(10, "GPIO_10"), -+ PINCTRL_PIN(11, "GPIO_11"), -+ PINCTRL_PIN(12, "GPIO_12"), -+ PINCTRL_PIN(13, "GPIO_13"), -+ PINCTRL_PIN(14, "GPIO_14"), -+ PINCTRL_PIN(15, "GPIO_15"), -+ PINCTRL_PIN(16, "GPIO_16"), -+ PINCTRL_PIN(17, "GPIO_17"), -+ PINCTRL_PIN(18, "GPIO_18"), -+ PINCTRL_PIN(19, "GPIO_19"), -+ PINCTRL_PIN(20, "GPIO_20"), -+ PINCTRL_PIN(21, "GPIO_21"), -+ PINCTRL_PIN(22, "GPIO_22"), -+ PINCTRL_PIN(23, "GPIO_23"), -+ PINCTRL_PIN(24, "GPIO_24"), -+ PINCTRL_PIN(25, "GPIO_25"), -+ PINCTRL_PIN(26, "GPIO_26"), -+ PINCTRL_PIN(27, "GPIO_27"), -+ PINCTRL_PIN(28, "GPIO_28"), -+ PINCTRL_PIN(29, "GPIO_29"), -+ PINCTRL_PIN(30, "GPIO_30"), -+ PINCTRL_PIN(31, "GPIO_31"), -+ PINCTRL_PIN(32, "GPIO_32"), -+ PINCTRL_PIN(33, "GPIO_33"), -+ PINCTRL_PIN(34, "GPIO_34"), -+ PINCTRL_PIN(35, "GPIO_35"), -+ PINCTRL_PIN(36, "GPIO_36"), -+ PINCTRL_PIN(37, "GPIO_37"), -+ PINCTRL_PIN(38, "GPIO_38"), -+ PINCTRL_PIN(39, "GPIO_39"), -+ PINCTRL_PIN(40, "GPIO_40"), -+ PINCTRL_PIN(41, "GPIO_41"), -+ PINCTRL_PIN(42, "GPIO_42"), -+ PINCTRL_PIN(43, "GPIO_43"), -+ PINCTRL_PIN(44, "GPIO_44"), -+ PINCTRL_PIN(45, "GPIO_45"), -+ PINCTRL_PIN(46, "GPIO_46"), -+ PINCTRL_PIN(47, "GPIO_47"), -+ PINCTRL_PIN(48, "GPIO_48"), -+ PINCTRL_PIN(49, "GPIO_49"), -+ PINCTRL_PIN(50, "GPIO_50"), -+ PINCTRL_PIN(51, "GPIO_51"), -+ PINCTRL_PIN(52, "GPIO_52"), -+ PINCTRL_PIN(53, "GPIO_53"), -+ PINCTRL_PIN(54, "GPIO_54"), -+ PINCTRL_PIN(55, "GPIO_55"), -+ PINCTRL_PIN(56, "GPIO_56"), -+ PINCTRL_PIN(57, "GPIO_57"), -+ PINCTRL_PIN(58, "GPIO_58"), -+ PINCTRL_PIN(59, "GPIO_59"), -+ PINCTRL_PIN(60, "GPIO_60"), -+ PINCTRL_PIN(61, "GPIO_61"), -+ PINCTRL_PIN(62, "GPIO_62"), -+ PINCTRL_PIN(63, "GPIO_63"), -+ PINCTRL_PIN(64, "GPIO_64"), -+ PINCTRL_PIN(65, "GPIO_65"), -+ PINCTRL_PIN(66, "GPIO_66"), -+ PINCTRL_PIN(67, "GPIO_67"), -+ PINCTRL_PIN(68, "GPIO_68"), -+ -+ PINCTRL_PIN(69, "SDC3_CLK"), -+ PINCTRL_PIN(70, "SDC3_CMD"), -+ PINCTRL_PIN(71, "SDC3_DATA"), -+}; -+ -+#define DECLARE_IPQ_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin } -+DECLARE_IPQ_GPIO_PINS(0); -+DECLARE_IPQ_GPIO_PINS(1); -+DECLARE_IPQ_GPIO_PINS(2); -+DECLARE_IPQ_GPIO_PINS(3); -+DECLARE_IPQ_GPIO_PINS(4); -+DECLARE_IPQ_GPIO_PINS(5); -+DECLARE_IPQ_GPIO_PINS(6); -+DECLARE_IPQ_GPIO_PINS(7); -+DECLARE_IPQ_GPIO_PINS(8); -+DECLARE_IPQ_GPIO_PINS(9); -+DECLARE_IPQ_GPIO_PINS(10); -+DECLARE_IPQ_GPIO_PINS(11); -+DECLARE_IPQ_GPIO_PINS(12); -+DECLARE_IPQ_GPIO_PINS(13); -+DECLARE_IPQ_GPIO_PINS(14); -+DECLARE_IPQ_GPIO_PINS(15); -+DECLARE_IPQ_GPIO_PINS(16); -+DECLARE_IPQ_GPIO_PINS(17); -+DECLARE_IPQ_GPIO_PINS(18); -+DECLARE_IPQ_GPIO_PINS(19); -+DECLARE_IPQ_GPIO_PINS(20); -+DECLARE_IPQ_GPIO_PINS(21); -+DECLARE_IPQ_GPIO_PINS(22); -+DECLARE_IPQ_GPIO_PINS(23); -+DECLARE_IPQ_GPIO_PINS(24); -+DECLARE_IPQ_GPIO_PINS(25); -+DECLARE_IPQ_GPIO_PINS(26); -+DECLARE_IPQ_GPIO_PINS(27); -+DECLARE_IPQ_GPIO_PINS(28); -+DECLARE_IPQ_GPIO_PINS(29); -+DECLARE_IPQ_GPIO_PINS(30); -+DECLARE_IPQ_GPIO_PINS(31); -+DECLARE_IPQ_GPIO_PINS(32); -+DECLARE_IPQ_GPIO_PINS(33); -+DECLARE_IPQ_GPIO_PINS(34); -+DECLARE_IPQ_GPIO_PINS(35); -+DECLARE_IPQ_GPIO_PINS(36); -+DECLARE_IPQ_GPIO_PINS(37); -+DECLARE_IPQ_GPIO_PINS(38); -+DECLARE_IPQ_GPIO_PINS(39); -+DECLARE_IPQ_GPIO_PINS(40); -+DECLARE_IPQ_GPIO_PINS(41); -+DECLARE_IPQ_GPIO_PINS(42); -+DECLARE_IPQ_GPIO_PINS(43); -+DECLARE_IPQ_GPIO_PINS(44); -+DECLARE_IPQ_GPIO_PINS(45); -+DECLARE_IPQ_GPIO_PINS(46); -+DECLARE_IPQ_GPIO_PINS(47); -+DECLARE_IPQ_GPIO_PINS(48); -+DECLARE_IPQ_GPIO_PINS(49); -+DECLARE_IPQ_GPIO_PINS(50); -+DECLARE_IPQ_GPIO_PINS(51); -+DECLARE_IPQ_GPIO_PINS(52); -+DECLARE_IPQ_GPIO_PINS(53); -+DECLARE_IPQ_GPIO_PINS(54); -+DECLARE_IPQ_GPIO_PINS(55); -+DECLARE_IPQ_GPIO_PINS(56); -+DECLARE_IPQ_GPIO_PINS(57); -+DECLARE_IPQ_GPIO_PINS(58); -+DECLARE_IPQ_GPIO_PINS(59); -+DECLARE_IPQ_GPIO_PINS(60); -+DECLARE_IPQ_GPIO_PINS(61); -+DECLARE_IPQ_GPIO_PINS(62); -+DECLARE_IPQ_GPIO_PINS(63); -+DECLARE_IPQ_GPIO_PINS(64); -+DECLARE_IPQ_GPIO_PINS(65); -+DECLARE_IPQ_GPIO_PINS(66); -+DECLARE_IPQ_GPIO_PINS(67); -+DECLARE_IPQ_GPIO_PINS(68); -+ -+static const unsigned int sdc3_clk_pins[] = { 69 }; -+static const unsigned int sdc3_cmd_pins[] = { 70 }; -+static const unsigned int sdc3_data_pins[] = { 71 }; -+ -+#define FUNCTION(fname) \ -+ [IPQ_MUX_##fname] = { \ -+ .name = #fname, \ -+ .groups = fname##_groups, \ -+ .ngroups = ARRAY_SIZE(fname##_groups), \ -+ } -+ -+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10) \ -+ { \ -+ .name = "gpio" #id, \ -+ .pins = gpio##id##_pins, \ -+ .npins = ARRAY_SIZE(gpio##id##_pins), \ -+ .funcs = (int[]){ \ -+ IPQ_MUX_NA, /* gpio mode */ \ -+ IPQ_MUX_##f1, \ -+ IPQ_MUX_##f2, \ -+ IPQ_MUX_##f3, \ -+ IPQ_MUX_##f4, \ -+ IPQ_MUX_##f5, \ -+ IPQ_MUX_##f6, \ -+ IPQ_MUX_##f7, \ -+ IPQ_MUX_##f8, \ -+ IPQ_MUX_##f9, \ -+ IPQ_MUX_##f10, \ -+ }, \ -+ .nfuncs = 11, \ -+ .ctl_reg = 0x1000 + 0x10 * id, \ -+ .io_reg = 0x1004 + 0x10 * id, \ -+ .intr_cfg_reg = 0x1008 + 0x10 * id, \ -+ .intr_status_reg = 0x100c + 0x10 * id, \ -+ .intr_target_reg = 0x400 + 0x4 * id, \ -+ .mux_bit = 2, \ -+ .pull_bit = 0, \ -+ .drv_bit = 6, \ -+ .oe_bit = 9, \ -+ .in_bit = 0, \ -+ .out_bit = 1, \ -+ .intr_enable_bit = 0, \ -+ .intr_status_bit = 0, \ -+ .intr_ack_high = 1, \ -+ .intr_target_bit = 0, \ -+ .intr_raw_status_bit = 3, \ -+ .intr_polarity_bit = 1, \ -+ .intr_detection_bit = 2, \ -+ .intr_detection_width = 1, \ -+ } -+ -+#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ -+ { \ -+ .name = #pg_name, \ -+ .pins = pg_name##_pins, \ -+ .npins = ARRAY_SIZE(pg_name##_pins), \ -+ .ctl_reg = ctl, \ -+ .io_reg = 0, \ -+ .intr_cfg_reg = 0, \ -+ .intr_status_reg = 0, \ -+ .intr_target_reg = 0, \ -+ .mux_bit = -1, \ -+ .pull_bit = pull, \ -+ .drv_bit = drv, \ -+ .oe_bit = -1, \ -+ .in_bit = -1, \ -+ .out_bit = -1, \ -+ .intr_enable_bit = -1, \ -+ .intr_status_bit = -1, \ -+ .intr_target_bit = -1, \ -+ .intr_raw_status_bit = -1, \ -+ .intr_polarity_bit = -1, \ -+ .intr_detection_bit = -1, \ -+ .intr_detection_width = -1, \ -+ } -+ -+enum ipq8064_functions { -+ IPQ_MUX_mdio, -+ IPQ_MUX_mi2s, -+ IPQ_MUX_pdm, -+ IPQ_MUX_ssbi, -+ IPQ_MUX_spmi, -+ IPQ_MUX_audio_pcm, -+ IPQ_MUX_gsbi1, -+ IPQ_MUX_gsbi2, -+ IPQ_MUX_gsbi4, -+ IPQ_MUX_gsbi5, -+ IPQ_MUX_gsbi5_spi_cs1, -+ IPQ_MUX_gsbi5_spi_cs2, -+ IPQ_MUX_gsbi5_spi_cs3, -+ IPQ_MUX_gsbi6, -+ IPQ_MUX_gsbi7, -+ IPQ_MUX_nss_spi, -+ IPQ_MUX_sdc1, -+ IPQ_MUX_spdif, -+ IPQ_MUX_nand, -+ IPQ_MUX_tsif1, -+ IPQ_MUX_tsif2, -+ IPQ_MUX_usb_fs_n, -+ IPQ_MUX_usb_fs, -+ IPQ_MUX_usb2_hsic, -+ IPQ_MUX_rgmii2, -+ IPQ_MUX_sata, -+ IPQ_MUX_pcie1_rst, -+ IPQ_MUX_pcie1_prsnt, -+ IPQ_MUX_pcie1_pwrflt, -+ IPQ_MUX_pcie1_pwren_n, -+ IPQ_MUX_pcie1_pwren, -+ IPQ_MUX_pcie1_clk_req, -+ IPQ_MUX_pcie2_rst, -+ IPQ_MUX_pcie2_prsnt, -+ IPQ_MUX_pcie2_pwrflt, -+ IPQ_MUX_pcie2_pwren_n, -+ IPQ_MUX_pcie2_pwren, -+ IPQ_MUX_pcie2_clk_req, -+ IPQ_MUX_pcie3_rst, -+ IPQ_MUX_pcie3_prsnt, -+ IPQ_MUX_pcie3_pwrflt, -+ IPQ_MUX_pcie3_pwren_n, -+ IPQ_MUX_pcie3_pwren, -+ IPQ_MUX_pcie3_clk_req, -+ IPQ_MUX_ps_hold, -+ IPQ_MUX_NA, -+}; -+ -+static const char * const mdio_groups[] = { -+ "gpio0", "gpio1", "gpio10", "gpio11", -+}; -+ -+static const char * const mi2s_groups[] = { -+ "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", -+ "gpio33", "gpio55", "gpio56", "gpio57", "gpio58", -+}; -+ -+static const char * const pdm_groups[] = { -+ "gpio3", "gpio16", "gpio17", "gpio22", "gpio30", "gpio31", -+ "gpio34", "gpio35", "gpio52", "gpio55", "gpio56", "gpio58", -+ "gpio59", -+}; -+ -+static const char * const ssbi_groups[] = { -+ "gpio10", "gpio11", -+}; -+ -+static const char * const spmi_groups[] = { -+ "gpio10", "gpio11", -+}; -+ -+static const char * const audio_pcm_groups[] = { -+ "gpio14", "gpio15", "gpio16", "gpio17", -+}; -+ -+static const char * const gsbi1_groups[] = { -+ "gpio51", "gpio52", "gpio53", "gpio54", -+}; -+ -+static const char * const gsbi2_groups[] = { -+ "gpio22", "gpio23", "gpio24", "gpio25", -+}; -+ -+static const char * const gsbi4_groups[] = { -+ "gpio10", "gpio11", "gpio12", "gpio13", -+}; -+ -+static const char * const gsbi5_groups[] = { -+ "gpio18", "gpio19", "gpio20", "gpio21", -+}; -+ -+static const char * const gsbi5_spi_cs1_groups[] = { -+ "gpio6", "gpio61", -+}; -+ -+static const char * const gsbi5_spi_cs2_groups[] = { -+ "gpio7", "gpio62", -+}; -+ -+static const char * const gsbi5_spi_cs3_groups[] = { -+ "gpio2", -+}; -+ -+static const char * const gsbi6_groups[] = { -+ "gpio27", "gpio28", "gpio29", "gpio30", "gpio55", "gpio56", -+ "gpio57", "gpio58", -+}; -+ -+static const char * const gsbi7_groups[] = { -+ "gpio6", "gpio7", "gpio8", "gpio9", -+}; -+ -+static const char * const nss_spi_groups[] = { -+ "gpio14", "gpio15", "gpio16", "gpio17", "gpio55", "gpio56", -+ "gpio57", "gpio58", -+}; -+ -+static const char * const sdc1_groups[] = { -+ "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", -+ "gpio44", "gpio45", "gpio46", "gpio47", -+}; -+ -+static const char * const spdif_groups[] = { -+ "gpio_10", "gpio_48", -+}; -+ -+static const char * const nand_groups[] = { -+ "gpio34", "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", -+ "gpio40", "gpio41", "gpio42", "gpio43", "gpio44", "gpio45", -+ "gpio46", "gpio47", -+}; -+ -+static const char * const tsif1_groups[] = { -+ "gpio55", "gpio56", "gpio57", "gpio58", -+}; -+ -+static const char * const tsif2_groups[] = { -+ "gpio59", "gpio60", "gpio61", "gpio62", -+}; -+ -+static const char * const usb_fs_n_groups[] = { -+ "gpio6", -+}; -+ -+static const char * const usb_fs_groups[] = { -+ "gpio6", "gpio7", "gpio8", -+}; -+ -+static const char * const usb2_hsic_groups[] = { -+ "gpio67", "gpio68", -+}; -+ -+static const char * const rgmii2_groups[] = { -+ "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", -+ "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62", -+}; -+ -+static const char * const sata_groups[] = { -+ "gpio10", -+}; -+ -+static const char * const pcie1_rst_groups[] = { -+ "gpio3", -+}; -+ -+static const char * const pcie1_prsnt_groups[] = { -+ "gpio3", "gpio11", -+}; -+ -+static const char * const pcie1_pwren_n_groups[] = { -+ "gpio4", "gpio12", -+}; -+ -+static const char * const pcie1_pwren_groups[] = { -+ "gpio4", "gpio12", -+}; -+ -+static const char * const pcie1_pwrflt_groups[] = { -+ "gpio5", "gpio13", -+}; -+ -+static const char * const pcie1_clk_req_groups[] = { -+ "gpio5", -+}; -+ -+static const char * const pcie2_rst_groups[] = { -+ "gpio48", -+}; -+ -+static const char * const pcie2_prsnt_groups[] = { -+ "gpio11", "gpio48", -+}; -+ -+static const char * const pcie2_pwren_n_groups[] = { -+ "gpio12", "gpio49", -+}; -+ -+static const char * const pcie2_pwren_groups[] = { -+ "gpio12", "gpio49", -+}; -+ -+static const char * const pcie2_pwrflt_groups[] = { -+ "gpio13", "gpio50", -+}; -+ -+static const char * const pcie2_clk_req_groups[] = { -+ "gpio50", -+}; -+ -+static const char * const pcie3_rst_groups[] = { -+ "gpio63", -+}; -+ -+static const char * const pcie3_prsnt_groups[] = { -+ "gpio11", -+}; -+ -+static const char * const pcie3_pwren_n_groups[] = { -+ "gpio12", -+}; -+ -+static const char * const pcie3_pwren_groups[] = { -+ "gpio12", -+}; -+ -+static const char * const pcie3_pwrflt_groups[] = { -+ "gpio13", -+}; -+ -+static const char * const pcie3_clk_req_groups[] = { -+ "gpio65", -+}; -+ -+static const char * const ps_hold_groups[] = { -+ "gpio26", -+}; -+ -+static const struct msm_function ipq8064_functions[] = { -+ FUNCTION(mdio), -+ FUNCTION(ssbi), -+ FUNCTION(spmi), -+ FUNCTION(mi2s), -+ FUNCTION(pdm), -+ FUNCTION(audio_pcm), -+ FUNCTION(gsbi1), -+ FUNCTION(gsbi2), -+ FUNCTION(gsbi4), -+ FUNCTION(gsbi5), -+ FUNCTION(gsbi5_spi_cs1), -+ FUNCTION(gsbi5_spi_cs2), -+ FUNCTION(gsbi5_spi_cs3), -+ FUNCTION(gsbi6), -+ FUNCTION(gsbi7), -+ FUNCTION(nss_spi), -+ FUNCTION(sdc1), -+ FUNCTION(spdif), -+ FUNCTION(nand), -+ FUNCTION(tsif1), -+ FUNCTION(tsif2), -+ FUNCTION(usb_fs_n), -+ FUNCTION(usb_fs), -+ FUNCTION(usb2_hsic), -+ FUNCTION(rgmii2), -+ FUNCTION(sata), -+ FUNCTION(pcie1_rst), -+ FUNCTION(pcie1_prsnt), -+ FUNCTION(pcie1_pwren_n), -+ FUNCTION(pcie1_pwren), -+ FUNCTION(pcie1_pwrflt), -+ FUNCTION(pcie1_clk_req), -+ FUNCTION(pcie2_rst), -+ FUNCTION(pcie2_prsnt), -+ FUNCTION(pcie2_pwren_n), -+ FUNCTION(pcie2_pwren), -+ FUNCTION(pcie2_pwrflt), -+ FUNCTION(pcie2_clk_req), -+ FUNCTION(pcie3_rst), -+ FUNCTION(pcie3_prsnt), -+ FUNCTION(pcie3_pwren_n), -+ FUNCTION(pcie3_pwren), -+ FUNCTION(pcie3_pwrflt), -+ FUNCTION(pcie3_clk_req), -+ FUNCTION(ps_hold), -+}; -+ -+static const struct msm_pingroup ipq8064_groups[] = { -+ PINGROUP(0, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(1, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(2, gsbi5_spi_cs3, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(3, pcie1_rst, pcie1_prsnt, pdm, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(4, pcie1_pwren_n, pcie1_pwren, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(5, pcie1_clk_req, pcie1_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(6, gsbi7, usb_fs, gsbi5_spi_cs1, usb_fs_n, NA, NA, NA, NA, NA, NA), -+ PINGROUP(7, gsbi7, usb_fs, gsbi5_spi_cs2, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(8, gsbi7, usb_fs, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(9, gsbi7, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(10, gsbi4, spdif, sata, ssbi, mdio, spmi, NA, NA, NA, NA), -+ PINGROUP(11, gsbi4, pcie2_prsnt, pcie1_prsnt, pcie3_prsnt, ssbi, mdio, spmi, NA, NA, NA), -+ PINGROUP(12, gsbi4, pcie2_pwren_n, pcie1_pwren_n, pcie3_pwren_n, pcie2_pwren, pcie1_pwren, pcie3_pwren, NA, NA, NA), -+ PINGROUP(13, gsbi4, pcie2_pwrflt, pcie1_pwrflt, pcie3_pwrflt, NA, NA, NA, NA, NA, NA), -+ PINGROUP(14, audio_pcm, nss_spi, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(15, audio_pcm, nss_spi, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(16, audio_pcm, nss_spi, pdm, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(17, audio_pcm, nss_spi, pdm, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(18, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(19, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(20, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(21, gsbi5, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(22, gsbi2, pdm, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(23, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(24, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(25, gsbi2, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(26, ps_hold, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(27, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(28, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(29, mi2s, rgmii2, gsbi6, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(30, mi2s, rgmii2, gsbi6, pdm, NA, NA, NA, NA, NA, NA), -+ PINGROUP(31, mi2s, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(32, mi2s, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(33, mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(34, nand, pdm, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(35, nand, pdm, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(36, nand, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(37, nand, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(38, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(39, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(40, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(41, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(42, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(43, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(44, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(45, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(46, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(47, nand, sdc1, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(48, pcie2_rst, spdif, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(49, pcie2_pwren_n, pcie2_pwren, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(50, pcie2_clk_req, pcie2_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(51, gsbi1, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(52, gsbi1, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(53, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(54, gsbi1, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(55, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA), -+ PINGROUP(56, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA), -+ PINGROUP(57, tsif1, mi2s, gsbi6, nss_spi, NA, NA, NA, NA, NA, NA), -+ PINGROUP(58, tsif1, mi2s, gsbi6, pdm, nss_spi, NA, NA, NA, NA, NA), -+ PINGROUP(59, tsif2, rgmii2, pdm, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(60, tsif2, rgmii2, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(61, tsif2, rgmii2, gsbi5_spi_cs1, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(62, tsif2, rgmii2, gsbi5_spi_cs2, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(63, pcie3_rst, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(65, pcie3_clk_req, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(67, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ PINGROUP(68, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), -+ SDC_PINGROUP(sdc3_clk, 0x204a, 14, 6), -+ SDC_PINGROUP(sdc3_cmd, 0x204a, 11, 3), -+ SDC_PINGROUP(sdc3_data, 0x204a, 9, 0), -+}; -+ -+#define NUM_GPIO_PINGROUPS 69 -+ -+static const struct msm_pinctrl_soc_data ipq8064_pinctrl = { -+ .pins = ipq8064_pins, -+ .npins = ARRAY_SIZE(ipq8064_pins), -+ .functions = ipq8064_functions, -+ .nfunctions = ARRAY_SIZE(ipq8064_functions), -+ .groups = ipq8064_groups, -+ .ngroups = ARRAY_SIZE(ipq8064_groups), -+ .ngpios = NUM_GPIO_PINGROUPS, -+}; -+ -+static int ipq8064_pinctrl_probe(struct platform_device *pdev) -+{ -+ return msm_pinctrl_probe(pdev, &ipq8064_pinctrl); -+} -+ -+static const struct of_device_id ipq8064_pinctrl_of_match[] = { -+ { .compatible = "qcom,ipq8064-pinctrl", }, -+ { }, -+}; -+ -+static struct platform_driver ipq8064_pinctrl_driver = { -+ .driver = { -+ .name = "ipq8064-pinctrl", -+ .owner = THIS_MODULE, -+ .of_match_table = ipq8064_pinctrl_of_match, -+ }, -+ .probe = ipq8064_pinctrl_probe, -+ .remove = msm_pinctrl_remove, -+}; -+ -+static int __init ipq8064_pinctrl_init(void) -+{ -+ return platform_driver_register(&ipq8064_pinctrl_driver); -+} -+arch_initcall(ipq8064_pinctrl_init); -+ -+static void __exit ipq8064_pinctrl_exit(void) -+{ -+ platform_driver_unregister(&ipq8064_pinctrl_driver); -+} -+module_exit(ipq8064_pinctrl_exit); -+ -+MODULE_AUTHOR("Andy Gross "); -+MODULE_DESCRIPTION("Qualcomm IPQ8064 pinctrl driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_DEVICE_TABLE(of, ipq8064_pinctrl_of_match); diff --git a/target/linux/ipq806x/patches/0041-dt-Document-Qualcomm-IPQ8064-pinctrl-binding.patch b/target/linux/ipq806x/patches/0041-dt-Document-Qualcomm-IPQ8064-pinctrl-binding.patch deleted file mode 100644 index c1adc991d8..0000000000 --- a/target/linux/ipq806x/patches/0041-dt-Document-Qualcomm-IPQ8064-pinctrl-binding.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 425015979d3b1600d14403be7d6d64ba1238e58d Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 14 Apr 2014 22:10:36 -0500 -Subject: [PATCH 041/182] dt: Document Qualcomm IPQ8064 pinctrl binding - -Define a new binding for the Qualcomm TLMMv2 based pin controller inside the -IPQ8064. - -Signed-off-by: Andy Gross -Reviewed-by: Bjorn Andersson -Signed-off-by: Linus Walleij ---- - .../bindings/pinctrl/qcom,ipq8064-pinctrl.txt | 95 ++++++++++++++++++++ - 1 file changed, 95 insertions(+) - create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt -@@ -0,0 +1,95 @@ -+Qualcomm IPQ8064 TLMM block -+ -+Required properties: -+- compatible: "qcom,ipq8064-pinctrl" -+- reg: Should be the base address and length of the TLMM block. -+- interrupts: Should be the parent IRQ of the TLMM block. -+- interrupt-controller: Marks the device node as an interrupt controller. -+- #interrupt-cells: Should be two. -+- gpio-controller: Marks the device node as a GPIO controller. -+- #gpio-cells : Should be two. -+ The first cell is the gpio pin number and the -+ second cell is used for optional parameters. -+ -+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for -+a general description of GPIO and interrupt bindings. -+ -+Please refer to pinctrl-bindings.txt in this directory for details of the -+common pinctrl bindings used by client devices, including the meaning of the -+phrase "pin configuration node". -+ -+Qualcomm's pin configuration nodes act as a container for an abitrary number of -+subnodes. Each of these subnodes represents some desired configuration for a -+pin, a group, or a list of pins or groups. This configuration can include the -+mux function to select on those pin(s)/group(s), and various pin configuration -+parameters, such as pull-up, drive strength, etc. -+ -+The name of each subnode is not important; all subnodes should be enumerated -+and processed purely based on their content. -+ -+Each subnode only affects those parameters that are explicitly listed. In -+other words, a subnode that lists a mux function but no pin configuration -+parameters implies no information about any pin configuration parameters. -+Similarly, a pin subnode that describes a pullup parameter implies no -+information about e.g. the mux function. -+ -+ -+The following generic properties as defined in pinctrl-bindings.txt are valid -+to specify in a pin configuration subnode: -+ -+ pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength, -+ output-low, output-high. -+ -+Non-empty subnodes must specify the 'pins' property. -+ -+Valid values for qcom,pins are: -+ gpio0-gpio68 -+ Supports mux, bias, and drive-strength -+ -+ sdc3_clk, sdc3_cmd, sdc3_data -+ Supports bias and drive-strength -+ -+ -+Valid values for function are: -+ mdio, mi2s, pdm, ssbi, spmi, audio_pcm, gsbi1, gsbi2, gsbi4, gsbi5, -+ gsbi5_spi_cs1, gsbi5_spi_cs2, gsbi5_spi_cs3, gsbi6, gsbi7, nss_spi, sdc1, -+ spdif, nand, tsif1, tsif2, usb_fs_n, usb_fs, usb2_hsic, rgmii2, sata, -+ pcie1_rst, pcie1_prsnt, pcie1_pwren_n, pcie1_pwren, pcie1_pwrflt, -+ pcie1_clk_req, pcie2_rst, pcie2_prsnt, pcie2_pwren_n, pcie2_pwren, -+ pcie2_pwrflt, pcie2_clk_req, pcie3_rst, pcie3_prsnt, pcie3_pwren_n, -+ pcie3_pwren, pcie3_pwrflt, pcie3_clk_req, ps_hold -+ -+Example: -+ -+ pinmux: pinctrl@800000 { -+ compatible = "qcom,ipq8064-pinctrl"; -+ reg = <0x800000 0x4000>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupts = <0 32 0x4>; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&gsbi5_uart_default>; -+ -+ gsbi5_uart_default: gsbi5_uart_default { -+ mux { -+ pins = "gpio18", "gpio19"; -+ function = "gsbi5"; -+ }; -+ -+ tx { -+ pins = "gpio18"; -+ drive-strength = <4>; -+ bias-disable; -+ }; -+ -+ rx { -+ pins = "gpio19"; -+ drive-strength = <2>; -+ bias-pull-up; -+ }; -+ }; -+ }; diff --git a/target/linux/ipq806x/patches/0042-ARM-qcom-Select-PINCTRL-by-default-for-ARCH_QCOM.patch b/target/linux/ipq806x/patches/0042-ARM-qcom-Select-PINCTRL-by-default-for-ARCH_QCOM.patch deleted file mode 100644 index cbccbc2d80..0000000000 --- a/target/linux/ipq806x/patches/0042-ARM-qcom-Select-PINCTRL-by-default-for-ARCH_QCOM.patch +++ /dev/null @@ -1,24 +0,0 @@ -From add2c1451495ccc4e67ced3dd12d4286500f1672 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 14 Apr 2014 22:10:37 -0500 -Subject: [PATCH 042/182] ARM: qcom: Select PINCTRL by default for ARCH_QCOM - -Add missing PINCTRL selection. This enables selection of pinctrollers for -Qualcomm processors. - -Signed-off-by: Andy Gross -Acked-by: Linus Walleij ---- - arch/arm/mach-qcom/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/mach-qcom/Kconfig -+++ b/arch/arm/mach-qcom/Kconfig -@@ -5,6 +5,7 @@ config ARCH_QCOM - select CLKSRC_OF - select GENERIC_CLOCKEVENTS - select HAVE_SMP -+ select PINCTRL - select QCOM_SCM if SMP - help - Support for Qualcomm's devicetree based systems. diff --git a/target/linux/ipq806x/patches/0043-pinctrl-qcom-Correct-name-for-pin-0.patch b/target/linux/ipq806x/patches/0043-pinctrl-qcom-Correct-name-for-pin-0.patch deleted file mode 100644 index 03896ec85c..0000000000 --- a/target/linux/ipq806x/patches/0043-pinctrl-qcom-Correct-name-for-pin-0.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 4cf6d61dc3441f50d1d56bfd72280dbcd2b584a6 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Fri, 25 Apr 2014 15:41:55 -0500 -Subject: [PATCH 043/182] pinctrl: qcom: Correct name for pin 0 - -Fix copy/paste error in pinctrl_pin_desc for pin 0. - -Signed-off-by: Andy Gross ---- - drivers/pinctrl/pinctrl-ipq8064.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/pinctrl/pinctrl-ipq8064.c -+++ b/drivers/pinctrl/pinctrl-ipq8064.c -@@ -20,7 +20,7 @@ - #include "pinctrl-msm.h" - - static const struct pinctrl_pin_desc ipq8064_pins[] = { -- PINCTRL_PIN(0, "GPIO_1"), -+ PINCTRL_PIN(0, "GPIO_0"), - PINCTRL_PIN(1, "GPIO_1"), - PINCTRL_PIN(2, "GPIO_2"), - PINCTRL_PIN(3, "GPIO_3"), diff --git a/target/linux/ipq806x/patches/0044-dmaengine-qcom_bam_dma-Add-device-tree-binding.patch b/target/linux/ipq806x/patches/0044-dmaengine-qcom_bam_dma-Add-device-tree-binding.patch deleted file mode 100644 index e77d05f279..0000000000 --- a/target/linux/ipq806x/patches/0044-dmaengine-qcom_bam_dma-Add-device-tree-binding.patch +++ /dev/null @@ -1,59 +0,0 @@ -From b5e19b657e352d565c5ddeae5f6dfd542de9d7e5 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 10 Mar 2014 16:40:19 -0500 -Subject: [PATCH 044/182] dmaengine: qcom_bam_dma: Add device tree binding - -Add device tree binding support for the QCOM BAM DMA driver. - -Acked-by: Kumar Gala -Signed-off-by: Andy Gross -Signed-off-by: Vinod Koul ---- - .../devicetree/bindings/dma/qcom_bam_dma.txt | 41 ++++++++++++++++++++ - 1 file changed, 41 insertions(+) - create mode 100644 Documentation/devicetree/bindings/dma/qcom_bam_dma.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt -@@ -0,0 +1,41 @@ -+QCOM BAM DMA controller -+ -+Required properties: -+- compatible: must contain "qcom,bam-v1.4.0" for MSM8974 -+- reg: Address range for DMA registers -+- interrupts: Should contain the one interrupt shared by all channels -+- #dma-cells: must be <1>, the cell in the dmas property of the client device -+ represents the channel number -+- clocks: required clock -+- clock-names: must contain "bam_clk" entry -+- qcom,ee : indicates the active Execution Environment identifier (0-7) used in -+ the secure world. -+ -+Example: -+ -+ uart-bam: dma@f9984000 = { -+ compatible = "qcom,bam-v1.4.0"; -+ reg = <0xf9984000 0x15000>; -+ interrupts = <0 94 0>; -+ clocks = <&gcc GCC_BAM_DMA_AHB_CLK>; -+ clock-names = "bam_clk"; -+ #dma-cells = <1>; -+ qcom,ee = <0>; -+ }; -+ -+DMA clients must use the format described in the dma.txt file, using a two cell -+specifier for each channel. -+ -+Example: -+ serial@f991e000 { -+ compatible = "qcom,msm-uart"; -+ reg = <0xf991e000 0x1000> -+ <0xf9944000 0x19000>; -+ interrupts = <0 108 0>; -+ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, -+ <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; -+ -+ dmas = <&uart-bam 0>, <&uart-bam 1>; -+ dma-names = "rx", "tx"; -+ }; diff --git a/target/linux/ipq806x/patches/0045-dmaengine-add-Qualcomm-BAM-dma-driver.patch b/target/linux/ipq806x/patches/0045-dmaengine-add-Qualcomm-BAM-dma-driver.patch deleted file mode 100644 index 98c71db5ab..0000000000 --- a/target/linux/ipq806x/patches/0045-dmaengine-add-Qualcomm-BAM-dma-driver.patch +++ /dev/null @@ -1,1164 +0,0 @@ -From 23dd43da9c885789b3d5aceed3e401345f8e8106 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Sat, 29 Mar 2014 18:53:16 +0530 -Subject: [PATCH 045/182] dmaengine: add Qualcomm BAM dma driver - -Add the DMA engine driver for the QCOM Bus Access Manager (BAM) DMA controller -found in the MSM 8x74 platforms. - -Each BAM DMA device is associated with a specific on-chip peripheral. Each -channel provides a uni-directional data transfer engine that is capable of -transferring data between the peripheral and system memory (System mode), or -between two peripherals (BAM2BAM). - -The initial release of this driver only supports slave transfers between -peripherals and system memory. - -Signed-off-by: Andy Gross -Tested-by: Stanimir Varbanov -Signed-off-by: Vinod Koul ---- - drivers/dma/Kconfig | 9 + - drivers/dma/Makefile | 2 + - drivers/dma/qcom_bam_dma.c | 1111 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 1122 insertions(+) - create mode 100644 drivers/dma/qcom_bam_dma.c - ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -401,4 +401,13 @@ config DMATEST - config DMA_ENGINE_RAID - bool - -+config QCOM_BAM_DMA -+ tristate "QCOM BAM DMA support" -+ depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM) -+ select DMA_ENGINE -+ select DMA_VIRTUAL_CHANNELS -+ ---help--- -+ Enable support for the QCOM BAM DMA controller. This controller -+ provides DMA capabilities for a variety of on-chip devices. -+ - endif ---- a/drivers/dma/Makefile -+++ b/drivers/dma/Makefile -@@ -44,3 +44,5 @@ obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o - obj-$(CONFIG_TI_CPPI41) += cppi41.o - obj-$(CONFIG_K3_DMA) += k3dma.o - obj-$(CONFIG_MOXART_DMA) += moxart-dma.o -+obj-$(CONFIG_FSL_EDMA) += fsl-edma.o -+obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o ---- /dev/null -+++ b/drivers/dma/qcom_bam_dma.c -@@ -0,0 +1,1111 @@ -+/* -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ * -+ */ -+/* -+ * QCOM BAM DMA engine driver -+ * -+ * QCOM BAM DMA blocks are distributed amongst a number of the on-chip -+ * peripherals on the MSM 8x74. The configuration of the channels are dependent -+ * on the way they are hard wired to that specific peripheral. The peripheral -+ * device tree entries specify the configuration of each channel. -+ * -+ * The DMA controller requires the use of external memory for storage of the -+ * hardware descriptors for each channel. The descriptor FIFO is accessed as a -+ * circular buffer and operations are managed according to the offset within the -+ * FIFO. After pipe/channel reset, all of the pipe registers and internal state -+ * are back to defaults. -+ * -+ * During DMA operations, we write descriptors to the FIFO, being careful to -+ * handle wrapping and then write the last FIFO offset to that channel's -+ * P_EVNT_REG register to kick off the transaction. The P_SW_OFSTS register -+ * indicates the current FIFO offset that is being processed, so there is some -+ * indication of where the hardware is currently working. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dmaengine.h" -+#include "virt-dma.h" -+ -+struct bam_desc_hw { -+ u32 addr; /* Buffer physical address */ -+ u16 size; /* Buffer size in bytes */ -+ u16 flags; -+}; -+ -+#define DESC_FLAG_INT BIT(15) -+#define DESC_FLAG_EOT BIT(14) -+#define DESC_FLAG_EOB BIT(13) -+ -+struct bam_async_desc { -+ struct virt_dma_desc vd; -+ -+ u32 num_desc; -+ u32 xfer_len; -+ struct bam_desc_hw *curr_desc; -+ -+ enum dma_transfer_direction dir; -+ size_t length; -+ struct bam_desc_hw desc[0]; -+}; -+ -+#define BAM_CTRL 0x0000 -+#define BAM_REVISION 0x0004 -+#define BAM_SW_REVISION 0x0080 -+#define BAM_NUM_PIPES 0x003C -+#define BAM_TIMER 0x0040 -+#define BAM_TIMER_CTRL 0x0044 -+#define BAM_DESC_CNT_TRSHLD 0x0008 -+#define BAM_IRQ_SRCS 0x000C -+#define BAM_IRQ_SRCS_MSK 0x0010 -+#define BAM_IRQ_SRCS_UNMASKED 0x0030 -+#define BAM_IRQ_STTS 0x0014 -+#define BAM_IRQ_CLR 0x0018 -+#define BAM_IRQ_EN 0x001C -+#define BAM_CNFG_BITS 0x007C -+#define BAM_IRQ_SRCS_EE(ee) (0x0800 + ((ee) * 0x80)) -+#define BAM_IRQ_SRCS_MSK_EE(ee) (0x0804 + ((ee) * 0x80)) -+#define BAM_P_CTRL(pipe) (0x1000 + ((pipe) * 0x1000)) -+#define BAM_P_RST(pipe) (0x1004 + ((pipe) * 0x1000)) -+#define BAM_P_HALT(pipe) (0x1008 + ((pipe) * 0x1000)) -+#define BAM_P_IRQ_STTS(pipe) (0x1010 + ((pipe) * 0x1000)) -+#define BAM_P_IRQ_CLR(pipe) (0x1014 + ((pipe) * 0x1000)) -+#define BAM_P_IRQ_EN(pipe) (0x1018 + ((pipe) * 0x1000)) -+#define BAM_P_EVNT_DEST_ADDR(pipe) (0x182C + ((pipe) * 0x1000)) -+#define BAM_P_EVNT_REG(pipe) (0x1818 + ((pipe) * 0x1000)) -+#define BAM_P_SW_OFSTS(pipe) (0x1800 + ((pipe) * 0x1000)) -+#define BAM_P_DATA_FIFO_ADDR(pipe) (0x1824 + ((pipe) * 0x1000)) -+#define BAM_P_DESC_FIFO_ADDR(pipe) (0x181C + ((pipe) * 0x1000)) -+#define BAM_P_EVNT_TRSHLD(pipe) (0x1828 + ((pipe) * 0x1000)) -+#define BAM_P_FIFO_SIZES(pipe) (0x1820 + ((pipe) * 0x1000)) -+ -+/* BAM CTRL */ -+#define BAM_SW_RST BIT(0) -+#define BAM_EN BIT(1) -+#define BAM_EN_ACCUM BIT(4) -+#define BAM_TESTBUS_SEL_SHIFT 5 -+#define BAM_TESTBUS_SEL_MASK 0x3F -+#define BAM_DESC_CACHE_SEL_SHIFT 13 -+#define BAM_DESC_CACHE_SEL_MASK 0x3 -+#define BAM_CACHED_DESC_STORE BIT(15) -+#define IBC_DISABLE BIT(16) -+ -+/* BAM REVISION */ -+#define REVISION_SHIFT 0 -+#define REVISION_MASK 0xFF -+#define NUM_EES_SHIFT 8 -+#define NUM_EES_MASK 0xF -+#define CE_BUFFER_SIZE BIT(13) -+#define AXI_ACTIVE BIT(14) -+#define USE_VMIDMT BIT(15) -+#define SECURED BIT(16) -+#define BAM_HAS_NO_BYPASS BIT(17) -+#define HIGH_FREQUENCY_BAM BIT(18) -+#define INACTIV_TMRS_EXST BIT(19) -+#define NUM_INACTIV_TMRS BIT(20) -+#define DESC_CACHE_DEPTH_SHIFT 21 -+#define DESC_CACHE_DEPTH_1 (0 << DESC_CACHE_DEPTH_SHIFT) -+#define DESC_CACHE_DEPTH_2 (1 << DESC_CACHE_DEPTH_SHIFT) -+#define DESC_CACHE_DEPTH_3 (2 << DESC_CACHE_DEPTH_SHIFT) -+#define DESC_CACHE_DEPTH_4 (3 << DESC_CACHE_DEPTH_SHIFT) -+#define CMD_DESC_EN BIT(23) -+#define INACTIV_TMR_BASE_SHIFT 24 -+#define INACTIV_TMR_BASE_MASK 0xFF -+ -+/* BAM NUM PIPES */ -+#define BAM_NUM_PIPES_SHIFT 0 -+#define BAM_NUM_PIPES_MASK 0xFF -+#define PERIPH_NON_PIPE_GRP_SHIFT 16 -+#define PERIPH_NON_PIP_GRP_MASK 0xFF -+#define BAM_NON_PIPE_GRP_SHIFT 24 -+#define BAM_NON_PIPE_GRP_MASK 0xFF -+ -+/* BAM CNFG BITS */ -+#define BAM_PIPE_CNFG BIT(2) -+#define BAM_FULL_PIPE BIT(11) -+#define BAM_NO_EXT_P_RST BIT(12) -+#define BAM_IBC_DISABLE BIT(13) -+#define BAM_SB_CLK_REQ BIT(14) -+#define BAM_PSM_CSW_REQ BIT(15) -+#define BAM_PSM_P_RES BIT(16) -+#define BAM_AU_P_RES BIT(17) -+#define BAM_SI_P_RES BIT(18) -+#define BAM_WB_P_RES BIT(19) -+#define BAM_WB_BLK_CSW BIT(20) -+#define BAM_WB_CSW_ACK_IDL BIT(21) -+#define BAM_WB_RETR_SVPNT BIT(22) -+#define BAM_WB_DSC_AVL_P_RST BIT(23) -+#define BAM_REG_P_EN BIT(24) -+#define BAM_PSM_P_HD_DATA BIT(25) -+#define BAM_AU_ACCUMED BIT(26) -+#define BAM_CMD_ENABLE BIT(27) -+ -+#define BAM_CNFG_BITS_DEFAULT (BAM_PIPE_CNFG | \ -+ BAM_NO_EXT_P_RST | \ -+ BAM_IBC_DISABLE | \ -+ BAM_SB_CLK_REQ | \ -+ BAM_PSM_CSW_REQ | \ -+ BAM_PSM_P_RES | \ -+ BAM_AU_P_RES | \ -+ BAM_SI_P_RES | \ -+ BAM_WB_P_RES | \ -+ BAM_WB_BLK_CSW | \ -+ BAM_WB_CSW_ACK_IDL | \ -+ BAM_WB_RETR_SVPNT | \ -+ BAM_WB_DSC_AVL_P_RST | \ -+ BAM_REG_P_EN | \ -+ BAM_PSM_P_HD_DATA | \ -+ BAM_AU_ACCUMED | \ -+ BAM_CMD_ENABLE) -+ -+/* PIPE CTRL */ -+#define P_EN BIT(1) -+#define P_DIRECTION BIT(3) -+#define P_SYS_STRM BIT(4) -+#define P_SYS_MODE BIT(5) -+#define P_AUTO_EOB BIT(6) -+#define P_AUTO_EOB_SEL_SHIFT 7 -+#define P_AUTO_EOB_SEL_512 (0 << P_AUTO_EOB_SEL_SHIFT) -+#define P_AUTO_EOB_SEL_256 (1 << P_AUTO_EOB_SEL_SHIFT) -+#define P_AUTO_EOB_SEL_128 (2 << P_AUTO_EOB_SEL_SHIFT) -+#define P_AUTO_EOB_SEL_64 (3 << P_AUTO_EOB_SEL_SHIFT) -+#define P_PREFETCH_LIMIT_SHIFT 9 -+#define P_PREFETCH_LIMIT_32 (0 << P_PREFETCH_LIMIT_SHIFT) -+#define P_PREFETCH_LIMIT_16 (1 << P_PREFETCH_LIMIT_SHIFT) -+#define P_PREFETCH_LIMIT_4 (2 << P_PREFETCH_LIMIT_SHIFT) -+#define P_WRITE_NWD BIT(11) -+#define P_LOCK_GROUP_SHIFT 16 -+#define P_LOCK_GROUP_MASK 0x1F -+ -+/* BAM_DESC_CNT_TRSHLD */ -+#define CNT_TRSHLD 0xffff -+#define DEFAULT_CNT_THRSHLD 0x4 -+ -+/* BAM_IRQ_SRCS */ -+#define BAM_IRQ BIT(31) -+#define P_IRQ 0x7fffffff -+ -+/* BAM_IRQ_SRCS_MSK */ -+#define BAM_IRQ_MSK BAM_IRQ -+#define P_IRQ_MSK P_IRQ -+ -+/* BAM_IRQ_STTS */ -+#define BAM_TIMER_IRQ BIT(4) -+#define BAM_EMPTY_IRQ BIT(3) -+#define BAM_ERROR_IRQ BIT(2) -+#define BAM_HRESP_ERR_IRQ BIT(1) -+ -+/* BAM_IRQ_CLR */ -+#define BAM_TIMER_CLR BIT(4) -+#define BAM_EMPTY_CLR BIT(3) -+#define BAM_ERROR_CLR BIT(2) -+#define BAM_HRESP_ERR_CLR BIT(1) -+ -+/* BAM_IRQ_EN */ -+#define BAM_TIMER_EN BIT(4) -+#define BAM_EMPTY_EN BIT(3) -+#define BAM_ERROR_EN BIT(2) -+#define BAM_HRESP_ERR_EN BIT(1) -+ -+/* BAM_P_IRQ_EN */ -+#define P_PRCSD_DESC_EN BIT(0) -+#define P_TIMER_EN BIT(1) -+#define P_WAKE_EN BIT(2) -+#define P_OUT_OF_DESC_EN BIT(3) -+#define P_ERR_EN BIT(4) -+#define P_TRNSFR_END_EN BIT(5) -+#define P_DEFAULT_IRQS_EN (P_PRCSD_DESC_EN | P_ERR_EN | P_TRNSFR_END_EN) -+ -+/* BAM_P_SW_OFSTS */ -+#define P_SW_OFSTS_MASK 0xffff -+ -+#define BAM_DESC_FIFO_SIZE SZ_32K -+#define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1) -+#define BAM_MAX_DATA_SIZE (SZ_32K - 8) -+ -+struct bam_chan { -+ struct virt_dma_chan vc; -+ -+ struct bam_device *bdev; -+ -+ /* configuration from device tree */ -+ u32 id; -+ -+ struct bam_async_desc *curr_txd; /* current running dma */ -+ -+ /* runtime configuration */ -+ struct dma_slave_config slave; -+ -+ /* fifo storage */ -+ struct bam_desc_hw *fifo_virt; -+ dma_addr_t fifo_phys; -+ -+ /* fifo markers */ -+ unsigned short head; /* start of active descriptor entries */ -+ unsigned short tail; /* end of active descriptor entries */ -+ -+ unsigned int initialized; /* is the channel hw initialized? */ -+ unsigned int paused; /* is the channel paused? */ -+ unsigned int reconfigure; /* new slave config? */ -+ -+ struct list_head node; -+}; -+ -+static inline struct bam_chan *to_bam_chan(struct dma_chan *common) -+{ -+ return container_of(common, struct bam_chan, vc.chan); -+} -+ -+struct bam_device { -+ void __iomem *regs; -+ struct device *dev; -+ struct dma_device common; -+ struct device_dma_parameters dma_parms; -+ struct bam_chan *channels; -+ u32 num_channels; -+ -+ /* execution environment ID, from DT */ -+ u32 ee; -+ -+ struct clk *bamclk; -+ int irq; -+ -+ /* dma start transaction tasklet */ -+ struct tasklet_struct task; -+}; -+ -+/** -+ * bam_reset_channel - Reset individual BAM DMA channel -+ * @bchan: bam channel -+ * -+ * This function resets a specific BAM channel -+ */ -+static void bam_reset_channel(struct bam_chan *bchan) -+{ -+ struct bam_device *bdev = bchan->bdev; -+ -+ lockdep_assert_held(&bchan->vc.lock); -+ -+ /* reset channel */ -+ writel_relaxed(1, bdev->regs + BAM_P_RST(bchan->id)); -+ writel_relaxed(0, bdev->regs + BAM_P_RST(bchan->id)); -+ -+ /* don't allow cpu to reorder BAM register accesses done after this */ -+ wmb(); -+ -+ /* make sure hw is initialized when channel is used the first time */ -+ bchan->initialized = 0; -+} -+ -+/** -+ * bam_chan_init_hw - Initialize channel hardware -+ * @bchan: bam channel -+ * -+ * This function resets and initializes the BAM channel -+ */ -+static void bam_chan_init_hw(struct bam_chan *bchan, -+ enum dma_transfer_direction dir) -+{ -+ struct bam_device *bdev = bchan->bdev; -+ u32 val; -+ -+ /* Reset the channel to clear internal state of the FIFO */ -+ bam_reset_channel(bchan); -+ -+ /* -+ * write out 8 byte aligned address. We have enough space for this -+ * because we allocated 1 more descriptor (8 bytes) than we can use -+ */ -+ writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)), -+ bdev->regs + BAM_P_DESC_FIFO_ADDR(bchan->id)); -+ writel_relaxed(BAM_DESC_FIFO_SIZE, bdev->regs + -+ BAM_P_FIFO_SIZES(bchan->id)); -+ -+ /* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */ -+ writel_relaxed(P_DEFAULT_IRQS_EN, bdev->regs + BAM_P_IRQ_EN(bchan->id)); -+ -+ /* unmask the specific pipe and EE combo */ -+ val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee)); -+ val |= BIT(bchan->id); -+ writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee)); -+ -+ /* don't allow cpu to reorder the channel enable done below */ -+ wmb(); -+ -+ /* set fixed direction and mode, then enable channel */ -+ val = P_EN | P_SYS_MODE; -+ if (dir == DMA_DEV_TO_MEM) -+ val |= P_DIRECTION; -+ -+ writel_relaxed(val, bdev->regs + BAM_P_CTRL(bchan->id)); -+ -+ bchan->initialized = 1; -+ -+ /* init FIFO pointers */ -+ bchan->head = 0; -+ bchan->tail = 0; -+} -+ -+/** -+ * bam_alloc_chan - Allocate channel resources for DMA channel. -+ * @chan: specified channel -+ * -+ * This function allocates the FIFO descriptor memory -+ */ -+static int bam_alloc_chan(struct dma_chan *chan) -+{ -+ struct bam_chan *bchan = to_bam_chan(chan); -+ struct bam_device *bdev = bchan->bdev; -+ -+ if (bchan->fifo_virt) -+ return 0; -+ -+ /* allocate FIFO descriptor space, but only if necessary */ -+ bchan->fifo_virt = dma_alloc_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE, -+ &bchan->fifo_phys, GFP_KERNEL); -+ -+ if (!bchan->fifo_virt) { -+ dev_err(bdev->dev, "Failed to allocate desc fifo\n"); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+/** -+ * bam_free_chan - Frees dma resources associated with specific channel -+ * @chan: specified channel -+ * -+ * Free the allocated fifo descriptor memory and channel resources -+ * -+ */ -+static void bam_free_chan(struct dma_chan *chan) -+{ -+ struct bam_chan *bchan = to_bam_chan(chan); -+ struct bam_device *bdev = bchan->bdev; -+ u32 val; -+ unsigned long flags; -+ -+ vchan_free_chan_resources(to_virt_chan(chan)); -+ -+ if (bchan->curr_txd) { -+ dev_err(bchan->bdev->dev, "Cannot free busy channel\n"); -+ return; -+ } -+ -+ spin_lock_irqsave(&bchan->vc.lock, flags); -+ bam_reset_channel(bchan); -+ spin_unlock_irqrestore(&bchan->vc.lock, flags); -+ -+ dma_free_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt, -+ bchan->fifo_phys); -+ bchan->fifo_virt = NULL; -+ -+ /* mask irq for pipe/channel */ -+ val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee)); -+ val &= ~BIT(bchan->id); -+ writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee)); -+ -+ /* disable irq */ -+ writel_relaxed(0, bdev->regs + BAM_P_IRQ_EN(bchan->id)); -+} -+ -+/** -+ * bam_slave_config - set slave configuration for channel -+ * @chan: dma channel -+ * @cfg: slave configuration -+ * -+ * Sets slave configuration for channel -+ * -+ */ -+static void bam_slave_config(struct bam_chan *bchan, -+ struct dma_slave_config *cfg) -+{ -+ memcpy(&bchan->slave, cfg, sizeof(*cfg)); -+ bchan->reconfigure = 1; -+} -+ -+/** -+ * bam_prep_slave_sg - Prep slave sg transaction -+ * -+ * @chan: dma channel -+ * @sgl: scatter gather list -+ * @sg_len: length of sg -+ * @direction: DMA transfer direction -+ * @flags: DMA flags -+ * @context: transfer context (unused) -+ */ -+static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, -+ struct scatterlist *sgl, unsigned int sg_len, -+ enum dma_transfer_direction direction, unsigned long flags, -+ void *context) -+{ -+ struct bam_chan *bchan = to_bam_chan(chan); -+ struct bam_device *bdev = bchan->bdev; -+ struct bam_async_desc *async_desc; -+ struct scatterlist *sg; -+ u32 i; -+ struct bam_desc_hw *desc; -+ unsigned int num_alloc = 0; -+ -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(bdev->dev, "invalid dma direction\n"); -+ return NULL; -+ } -+ -+ /* calculate number of required entries */ -+ for_each_sg(sgl, sg, sg_len, i) -+ num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_MAX_DATA_SIZE); -+ -+ /* allocate enough room to accomodate the number of entries */ -+ async_desc = kzalloc(sizeof(*async_desc) + -+ (num_alloc * sizeof(struct bam_desc_hw)), GFP_NOWAIT); -+ -+ if (!async_desc) -+ goto err_out; -+ -+ async_desc->num_desc = num_alloc; -+ async_desc->curr_desc = async_desc->desc; -+ async_desc->dir = direction; -+ -+ /* fill in temporary descriptors */ -+ desc = async_desc->desc; -+ for_each_sg(sgl, sg, sg_len, i) { -+ unsigned int remainder = sg_dma_len(sg); -+ unsigned int curr_offset = 0; -+ -+ do { -+ desc->addr = sg_dma_address(sg) + curr_offset; -+ -+ if (remainder > BAM_MAX_DATA_SIZE) { -+ desc->size = BAM_MAX_DATA_SIZE; -+ remainder -= BAM_MAX_DATA_SIZE; -+ curr_offset += BAM_MAX_DATA_SIZE; -+ } else { -+ desc->size = remainder; -+ remainder = 0; -+ } -+ -+ async_desc->length += desc->size; -+ desc++; -+ } while (remainder > 0); -+ } -+ -+ return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); -+ -+err_out: -+ kfree(async_desc); -+ return NULL; -+} -+ -+/** -+ * bam_dma_terminate_all - terminate all transactions on a channel -+ * @bchan: bam dma channel -+ * -+ * Dequeues and frees all transactions -+ * No callbacks are done -+ * -+ */ -+static void bam_dma_terminate_all(struct bam_chan *bchan) -+{ -+ unsigned long flag; -+ LIST_HEAD(head); -+ -+ /* remove all transactions, including active transaction */ -+ spin_lock_irqsave(&bchan->vc.lock, flag); -+ if (bchan->curr_txd) { -+ list_add(&bchan->curr_txd->vd.node, &bchan->vc.desc_issued); -+ bchan->curr_txd = NULL; -+ } -+ -+ vchan_get_all_descriptors(&bchan->vc, &head); -+ spin_unlock_irqrestore(&bchan->vc.lock, flag); -+ -+ vchan_dma_desc_free_list(&bchan->vc, &head); -+} -+ -+/** -+ * bam_control - DMA device control -+ * @chan: dma channel -+ * @cmd: control cmd -+ * @arg: cmd argument -+ * -+ * Perform DMA control command -+ * -+ */ -+static int bam_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, -+ unsigned long arg) -+{ -+ struct bam_chan *bchan = to_bam_chan(chan); -+ struct bam_device *bdev = bchan->bdev; -+ int ret = 0; -+ unsigned long flag; -+ -+ switch (cmd) { -+ case DMA_PAUSE: -+ spin_lock_irqsave(&bchan->vc.lock, flag); -+ writel_relaxed(1, bdev->regs + BAM_P_HALT(bchan->id)); -+ bchan->paused = 1; -+ spin_unlock_irqrestore(&bchan->vc.lock, flag); -+ break; -+ -+ case DMA_RESUME: -+ spin_lock_irqsave(&bchan->vc.lock, flag); -+ writel_relaxed(0, bdev->regs + BAM_P_HALT(bchan->id)); -+ bchan->paused = 0; -+ spin_unlock_irqrestore(&bchan->vc.lock, flag); -+ break; -+ -+ case DMA_TERMINATE_ALL: -+ bam_dma_terminate_all(bchan); -+ break; -+ -+ case DMA_SLAVE_CONFIG: -+ spin_lock_irqsave(&bchan->vc.lock, flag); -+ bam_slave_config(bchan, (struct dma_slave_config *)arg); -+ spin_unlock_irqrestore(&bchan->vc.lock, flag); -+ break; -+ -+ default: -+ ret = -ENXIO; -+ break; -+ } -+ -+ return ret; -+} -+ -+/** -+ * process_channel_irqs - processes the channel interrupts -+ * @bdev: bam controller -+ * -+ * This function processes the channel interrupts -+ * -+ */ -+static u32 process_channel_irqs(struct bam_device *bdev) -+{ -+ u32 i, srcs, pipe_stts; -+ unsigned long flags; -+ struct bam_async_desc *async_desc; -+ -+ srcs = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_EE(bdev->ee)); -+ -+ /* return early if no pipe/channel interrupts are present */ -+ if (!(srcs & P_IRQ)) -+ return srcs; -+ -+ for (i = 0; i < bdev->num_channels; i++) { -+ struct bam_chan *bchan = &bdev->channels[i]; -+ -+ if (!(srcs & BIT(i))) -+ continue; -+ -+ /* clear pipe irq */ -+ pipe_stts = readl_relaxed(bdev->regs + -+ BAM_P_IRQ_STTS(i)); -+ -+ writel_relaxed(pipe_stts, bdev->regs + -+ BAM_P_IRQ_CLR(i)); -+ -+ spin_lock_irqsave(&bchan->vc.lock, flags); -+ async_desc = bchan->curr_txd; -+ -+ if (async_desc) { -+ async_desc->num_desc -= async_desc->xfer_len; -+ async_desc->curr_desc += async_desc->xfer_len; -+ bchan->curr_txd = NULL; -+ -+ /* manage FIFO */ -+ bchan->head += async_desc->xfer_len; -+ bchan->head %= MAX_DESCRIPTORS; -+ -+ /* -+ * if complete, process cookie. Otherwise -+ * push back to front of desc_issued so that -+ * it gets restarted by the tasklet -+ */ -+ if (!async_desc->num_desc) -+ vchan_cookie_complete(&async_desc->vd); -+ else -+ list_add(&async_desc->vd.node, -+ &bchan->vc.desc_issued); -+ } -+ -+ spin_unlock_irqrestore(&bchan->vc.lock, flags); -+ } -+ -+ return srcs; -+} -+ -+/** -+ * bam_dma_irq - irq handler for bam controller -+ * @irq: IRQ of interrupt -+ * @data: callback data -+ * -+ * IRQ handler for the bam controller -+ */ -+static irqreturn_t bam_dma_irq(int irq, void *data) -+{ -+ struct bam_device *bdev = data; -+ u32 clr_mask = 0, srcs = 0; -+ -+ srcs |= process_channel_irqs(bdev); -+ -+ /* kick off tasklet to start next dma transfer */ -+ if (srcs & P_IRQ) -+ tasklet_schedule(&bdev->task); -+ -+ if (srcs & BAM_IRQ) -+ clr_mask = readl_relaxed(bdev->regs + BAM_IRQ_STTS); -+ -+ /* don't allow reorder of the various accesses to the BAM registers */ -+ mb(); -+ -+ writel_relaxed(clr_mask, bdev->regs + BAM_IRQ_CLR); -+ -+ return IRQ_HANDLED; -+} -+ -+/** -+ * bam_tx_status - returns status of transaction -+ * @chan: dma channel -+ * @cookie: transaction cookie -+ * @txstate: DMA transaction state -+ * -+ * Return status of dma transaction -+ */ -+static enum dma_status bam_tx_status(struct dma_chan *chan, dma_cookie_t cookie, -+ struct dma_tx_state *txstate) -+{ -+ struct bam_chan *bchan = to_bam_chan(chan); -+ struct virt_dma_desc *vd; -+ int ret; -+ size_t residue = 0; -+ unsigned int i; -+ unsigned long flags; -+ -+ ret = dma_cookie_status(chan, cookie, txstate); -+ if (ret == DMA_COMPLETE) -+ return ret; -+ -+ if (!txstate) -+ return bchan->paused ? DMA_PAUSED : ret; -+ -+ spin_lock_irqsave(&bchan->vc.lock, flags); -+ vd = vchan_find_desc(&bchan->vc, cookie); -+ if (vd) -+ residue = container_of(vd, struct bam_async_desc, vd)->length; -+ else if (bchan->curr_txd && bchan->curr_txd->vd.tx.cookie == cookie) -+ for (i = 0; i < bchan->curr_txd->num_desc; i++) -+ residue += bchan->curr_txd->curr_desc[i].size; -+ -+ spin_unlock_irqrestore(&bchan->vc.lock, flags); -+ -+ dma_set_residue(txstate, residue); -+ -+ if (ret == DMA_IN_PROGRESS && bchan->paused) -+ ret = DMA_PAUSED; -+ -+ return ret; -+} -+ -+/** -+ * bam_apply_new_config -+ * @bchan: bam dma channel -+ * @dir: DMA direction -+ */ -+static void bam_apply_new_config(struct bam_chan *bchan, -+ enum dma_transfer_direction dir) -+{ -+ struct bam_device *bdev = bchan->bdev; -+ u32 maxburst; -+ -+ if (dir == DMA_DEV_TO_MEM) -+ maxburst = bchan->slave.src_maxburst; -+ else -+ maxburst = bchan->slave.dst_maxburst; -+ -+ writel_relaxed(maxburst, bdev->regs + BAM_DESC_CNT_TRSHLD); -+ -+ bchan->reconfigure = 0; -+} -+ -+/** -+ * bam_start_dma - start next transaction -+ * @bchan - bam dma channel -+ */ -+static void bam_start_dma(struct bam_chan *bchan) -+{ -+ struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc); -+ struct bam_device *bdev = bchan->bdev; -+ struct bam_async_desc *async_desc; -+ struct bam_desc_hw *desc; -+ struct bam_desc_hw *fifo = PTR_ALIGN(bchan->fifo_virt, -+ sizeof(struct bam_desc_hw)); -+ -+ lockdep_assert_held(&bchan->vc.lock); -+ -+ if (!vd) -+ return; -+ -+ list_del(&vd->node); -+ -+ async_desc = container_of(vd, struct bam_async_desc, vd); -+ bchan->curr_txd = async_desc; -+ -+ /* on first use, initialize the channel hardware */ -+ if (!bchan->initialized) -+ bam_chan_init_hw(bchan, async_desc->dir); -+ -+ /* apply new slave config changes, if necessary */ -+ if (bchan->reconfigure) -+ bam_apply_new_config(bchan, async_desc->dir); -+ -+ desc = bchan->curr_txd->curr_desc; -+ -+ if (async_desc->num_desc > MAX_DESCRIPTORS) -+ async_desc->xfer_len = MAX_DESCRIPTORS; -+ else -+ async_desc->xfer_len = async_desc->num_desc; -+ -+ /* set INT on last descriptor */ -+ desc[async_desc->xfer_len - 1].flags |= DESC_FLAG_INT; -+ -+ if (bchan->tail + async_desc->xfer_len > MAX_DESCRIPTORS) { -+ u32 partial = MAX_DESCRIPTORS - bchan->tail; -+ -+ memcpy(&fifo[bchan->tail], desc, -+ partial * sizeof(struct bam_desc_hw)); -+ memcpy(fifo, &desc[partial], (async_desc->xfer_len - partial) * -+ sizeof(struct bam_desc_hw)); -+ } else { -+ memcpy(&fifo[bchan->tail], desc, -+ async_desc->xfer_len * sizeof(struct bam_desc_hw)); -+ } -+ -+ bchan->tail += async_desc->xfer_len; -+ bchan->tail %= MAX_DESCRIPTORS; -+ -+ /* ensure descriptor writes and dma start not reordered */ -+ wmb(); -+ writel_relaxed(bchan->tail * sizeof(struct bam_desc_hw), -+ bdev->regs + BAM_P_EVNT_REG(bchan->id)); -+} -+ -+/** -+ * dma_tasklet - DMA IRQ tasklet -+ * @data: tasklet argument (bam controller structure) -+ * -+ * Sets up next DMA operation and then processes all completed transactions -+ */ -+static void dma_tasklet(unsigned long data) -+{ -+ struct bam_device *bdev = (struct bam_device *)data; -+ struct bam_chan *bchan; -+ unsigned long flags; -+ unsigned int i; -+ -+ /* go through the channels and kick off transactions */ -+ for (i = 0; i < bdev->num_channels; i++) { -+ bchan = &bdev->channels[i]; -+ spin_lock_irqsave(&bchan->vc.lock, flags); -+ -+ if (!list_empty(&bchan->vc.desc_issued) && !bchan->curr_txd) -+ bam_start_dma(bchan); -+ spin_unlock_irqrestore(&bchan->vc.lock, flags); -+ } -+} -+ -+/** -+ * bam_issue_pending - starts pending transactions -+ * @chan: dma channel -+ * -+ * Calls tasklet directly which in turn starts any pending transactions -+ */ -+static void bam_issue_pending(struct dma_chan *chan) -+{ -+ struct bam_chan *bchan = to_bam_chan(chan); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&bchan->vc.lock, flags); -+ -+ /* if work pending and idle, start a transaction */ -+ if (vchan_issue_pending(&bchan->vc) && !bchan->curr_txd) -+ bam_start_dma(bchan); -+ -+ spin_unlock_irqrestore(&bchan->vc.lock, flags); -+} -+ -+/** -+ * bam_dma_free_desc - free descriptor memory -+ * @vd: virtual descriptor -+ * -+ */ -+static void bam_dma_free_desc(struct virt_dma_desc *vd) -+{ -+ struct bam_async_desc *async_desc = container_of(vd, -+ struct bam_async_desc, vd); -+ -+ kfree(async_desc); -+} -+ -+static struct dma_chan *bam_dma_xlate(struct of_phandle_args *dma_spec, -+ struct of_dma *of) -+{ -+ struct bam_device *bdev = container_of(of->of_dma_data, -+ struct bam_device, common); -+ unsigned int request; -+ -+ if (dma_spec->args_count != 1) -+ return NULL; -+ -+ request = dma_spec->args[0]; -+ if (request >= bdev->num_channels) -+ return NULL; -+ -+ return dma_get_slave_channel(&(bdev->channels[request].vc.chan)); -+} -+ -+/** -+ * bam_init -+ * @bdev: bam device -+ * -+ * Initialization helper for global bam registers -+ */ -+static int bam_init(struct bam_device *bdev) -+{ -+ u32 val; -+ -+ /* read revision and configuration information */ -+ val = readl_relaxed(bdev->regs + BAM_REVISION) >> NUM_EES_SHIFT; -+ val &= NUM_EES_MASK; -+ -+ /* check that configured EE is within range */ -+ if (bdev->ee >= val) -+ return -EINVAL; -+ -+ val = readl_relaxed(bdev->regs + BAM_NUM_PIPES); -+ bdev->num_channels = val & BAM_NUM_PIPES_MASK; -+ -+ /* s/w reset bam */ -+ /* after reset all pipes are disabled and idle */ -+ val = readl_relaxed(bdev->regs + BAM_CTRL); -+ val |= BAM_SW_RST; -+ writel_relaxed(val, bdev->regs + BAM_CTRL); -+ val &= ~BAM_SW_RST; -+ writel_relaxed(val, bdev->regs + BAM_CTRL); -+ -+ /* make sure previous stores are visible before enabling BAM */ -+ wmb(); -+ -+ /* enable bam */ -+ val |= BAM_EN; -+ writel_relaxed(val, bdev->regs + BAM_CTRL); -+ -+ /* set descriptor threshhold, start with 4 bytes */ -+ writel_relaxed(DEFAULT_CNT_THRSHLD, bdev->regs + BAM_DESC_CNT_TRSHLD); -+ -+ /* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */ -+ writel_relaxed(BAM_CNFG_BITS_DEFAULT, bdev->regs + BAM_CNFG_BITS); -+ -+ /* enable irqs for errors */ -+ writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN, -+ bdev->regs + BAM_IRQ_EN); -+ -+ /* unmask global bam interrupt */ -+ writel_relaxed(BAM_IRQ_MSK, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee)); -+ -+ return 0; -+} -+ -+static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan, -+ u32 index) -+{ -+ bchan->id = index; -+ bchan->bdev = bdev; -+ -+ vchan_init(&bchan->vc, &bdev->common); -+ bchan->vc.desc_free = bam_dma_free_desc; -+} -+ -+static int bam_dma_probe(struct platform_device *pdev) -+{ -+ struct bam_device *bdev; -+ struct resource *iores; -+ int ret, i; -+ -+ bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL); -+ if (!bdev) -+ return -ENOMEM; -+ -+ bdev->dev = &pdev->dev; -+ -+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ bdev->regs = devm_ioremap_resource(&pdev->dev, iores); -+ if (IS_ERR(bdev->regs)) -+ return PTR_ERR(bdev->regs); -+ -+ bdev->irq = platform_get_irq(pdev, 0); -+ if (bdev->irq < 0) -+ return bdev->irq; -+ -+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &bdev->ee); -+ if (ret) { -+ dev_err(bdev->dev, "Execution environment unspecified\n"); -+ return ret; -+ } -+ -+ bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); -+ if (IS_ERR(bdev->bamclk)) -+ return PTR_ERR(bdev->bamclk); -+ -+ ret = clk_prepare_enable(bdev->bamclk); -+ if (ret) { -+ dev_err(bdev->dev, "failed to prepare/enable clock\n"); -+ return ret; -+ } -+ -+ ret = bam_init(bdev); -+ if (ret) -+ goto err_disable_clk; -+ -+ tasklet_init(&bdev->task, dma_tasklet, (unsigned long)bdev); -+ -+ bdev->channels = devm_kcalloc(bdev->dev, bdev->num_channels, -+ sizeof(*bdev->channels), GFP_KERNEL); -+ -+ if (!bdev->channels) { -+ ret = -ENOMEM; -+ goto err_disable_clk; -+ } -+ -+ /* allocate and initialize channels */ -+ INIT_LIST_HEAD(&bdev->common.channels); -+ -+ for (i = 0; i < bdev->num_channels; i++) -+ bam_channel_init(bdev, &bdev->channels[i], i); -+ -+ ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq, -+ IRQF_TRIGGER_HIGH, "bam_dma", bdev); -+ if (ret) -+ goto err_disable_clk; -+ -+ /* set max dma segment size */ -+ bdev->common.dev = bdev->dev; -+ bdev->common.dev->dma_parms = &bdev->dma_parms; -+ ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE); -+ if (ret) { -+ dev_err(bdev->dev, "cannot set maximum segment size\n"); -+ goto err_disable_clk; -+ } -+ -+ platform_set_drvdata(pdev, bdev); -+ -+ /* set capabilities */ -+ dma_cap_zero(bdev->common.cap_mask); -+ dma_cap_set(DMA_SLAVE, bdev->common.cap_mask); -+ -+ /* initialize dmaengine apis */ -+ bdev->common.device_alloc_chan_resources = bam_alloc_chan; -+ bdev->common.device_free_chan_resources = bam_free_chan; -+ bdev->common.device_prep_slave_sg = bam_prep_slave_sg; -+ bdev->common.device_control = bam_control; -+ bdev->common.device_issue_pending = bam_issue_pending; -+ bdev->common.device_tx_status = bam_tx_status; -+ bdev->common.dev = bdev->dev; -+ -+ ret = dma_async_device_register(&bdev->common); -+ if (ret) { -+ dev_err(bdev->dev, "failed to register dma async device\n"); -+ goto err_disable_clk; -+ } -+ -+ ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate, -+ &bdev->common); -+ if (ret) -+ goto err_unregister_dma; -+ -+ return 0; -+ -+err_unregister_dma: -+ dma_async_device_unregister(&bdev->common); -+err_disable_clk: -+ clk_disable_unprepare(bdev->bamclk); -+ return ret; -+} -+ -+static int bam_dma_remove(struct platform_device *pdev) -+{ -+ struct bam_device *bdev = platform_get_drvdata(pdev); -+ u32 i; -+ -+ of_dma_controller_free(pdev->dev.of_node); -+ dma_async_device_unregister(&bdev->common); -+ -+ /* mask all interrupts for this execution environment */ -+ writel_relaxed(0, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee)); -+ -+ devm_free_irq(bdev->dev, bdev->irq, bdev); -+ -+ for (i = 0; i < bdev->num_channels; i++) { -+ bam_dma_terminate_all(&bdev->channels[i]); -+ tasklet_kill(&bdev->channels[i].vc.task); -+ -+ dma_free_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE, -+ bdev->channels[i].fifo_virt, -+ bdev->channels[i].fifo_phys); -+ } -+ -+ tasklet_kill(&bdev->task); -+ -+ clk_disable_unprepare(bdev->bamclk); -+ -+ return 0; -+} -+ -+static const struct of_device_id bam_of_match[] = { -+ { .compatible = "qcom,bam-v1.4.0", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, bam_of_match); -+ -+static struct platform_driver bam_dma_driver = { -+ .probe = bam_dma_probe, -+ .remove = bam_dma_remove, -+ .driver = { -+ .name = "bam-dma-engine", -+ .owner = THIS_MODULE, -+ .of_match_table = bam_of_match, -+ }, -+}; -+ -+module_platform_driver(bam_dma_driver); -+ -+MODULE_AUTHOR("Andy Gross "); -+MODULE_DESCRIPTION("QCOM BAM DMA engine driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0046-mmc-sdhci-msm-Qualcomm-SDHCI-binding-documentation.patch b/target/linux/ipq806x/patches/0046-mmc-sdhci-msm-Qualcomm-SDHCI-binding-documentation.patch deleted file mode 100644 index 65c5347fd5..0000000000 --- a/target/linux/ipq806x/patches/0046-mmc-sdhci-msm-Qualcomm-SDHCI-binding-documentation.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 8a70c89b2fbb635a8d4fec302165343827aeed9f Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Mon, 10 Mar 2014 17:37:11 +0200 -Subject: [PATCH 046/182] mmc: sdhci-msm: Qualcomm SDHCI binding documentation - -This patch adds the device-tree binding documentation for Qualcomm -SDHCI driver. It contains the differences between the core properties -in mmc.txt and the properties used by the sdhci-msm driver. - -Signed-off-by: Georgi Djakov -Acked-by: Ulf Hansson -Signed-off-by: Chris Ball ---- - .../devicetree/bindings/mmc/sdhci-msm.txt | 55 ++++++++++++++++++++ - 1 file changed, 55 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-msm.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt -@@ -0,0 +1,55 @@ -+* Qualcomm SDHCI controller (sdhci-msm) -+ -+This file documents differences between the core properties in mmc.txt -+and the properties used by the sdhci-msm driver. -+ -+Required properties: -+- compatible: Should contain "qcom,sdhci-msm-v4". -+- reg: Base address and length of the register in the following order: -+ - Host controller register map (required) -+ - SD Core register map (required) -+- interrupts: Should contain an interrupt-specifiers for the interrupts: -+ - Host controller interrupt (required) -+- pinctrl-names: Should contain only one value - "default". -+- pinctrl-0: Should specify pin control groups used for this controller. -+- clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock-names. -+- clock-names: Should contain the following: -+ "iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required) -+ "core" - SDC MMC clock (MCLK) (required) -+ "bus" - SDCC bus voter clock (optional) -+ -+Example: -+ -+ sdhc_1: sdhci@f9824900 { -+ compatible = "qcom,sdhci-msm-v4"; -+ reg = <0xf9824900 0x11c>, <0xf9824000 0x800>; -+ interrupts = <0 123 0>; -+ bus-width = <8>; -+ non-removable; -+ -+ vmmc = <&pm8941_l20>; -+ vqmmc = <&pm8941_s3>; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdc1_clk &sdc1_cmd &sdc1_data>; -+ -+ clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>; -+ clock-names = "core", "iface"; -+ }; -+ -+ sdhc_2: sdhci@f98a4900 { -+ compatible = "qcom,sdhci-msm-v4"; -+ reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>; -+ interrupts = <0 125 0>; -+ bus-width = <4>; -+ cd-gpios = <&msmgpio 62 0x1>; -+ -+ vmmc = <&pm8941_l21>; -+ vqmmc = <&pm8941_l13>; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdc2_clk &sdc2_cmd &sdc2_data>; -+ -+ clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>; -+ clock-names = "core", "iface"; -+ }; diff --git a/target/linux/ipq806x/patches/0047-mmc-sdhci-msm-Initial-support-for-Qualcomm-chipsets.patch b/target/linux/ipq806x/patches/0047-mmc-sdhci-msm-Initial-support-for-Qualcomm-chipsets.patch deleted file mode 100644 index 9417e1d593..0000000000 --- a/target/linux/ipq806x/patches/0047-mmc-sdhci-msm-Initial-support-for-Qualcomm-chipsets.patch +++ /dev/null @@ -1,265 +0,0 @@ -From 5a8f026acb4a7a6c6d0c868cc1790363640b9b8f Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Mon, 10 Mar 2014 17:37:12 +0200 -Subject: [PATCH 047/182] mmc: sdhci-msm: Initial support for Qualcomm - chipsets - -This platform driver adds the initial support of Secure Digital Host -Controller Interface compliant controller found in Qualcomm chipsets. - -Signed-off-by: Asutosh Das -Signed-off-by: Venkat Gopalakrishnan -Tested-by: Ivan T. Ivanov -Signed-off-by: Georgi Djakov -Acked-by: Ulf Hansson -Signed-off-by: Chris Ball ---- - drivers/mmc/host/Kconfig | 13 +++ - drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/sdhci-msm.c | 208 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 222 insertions(+) - create mode 100644 drivers/mmc/host/sdhci-msm.c - ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -334,6 +334,19 @@ config MMC_ATMELMCI - - If unsure, say N. - -+config MMC_SDHCI_MSM -+ tristate "Qualcomm SDHCI Controller Support" -+ depends on ARCH_QCOM -+ depends on MMC_SDHCI_PLTFM -+ help -+ This selects the Secure Digital Host Controller Interface (SDHCI) -+ support present in Qualcomm SOCs. The controller supports -+ SD/MMC/SDIO devices. -+ -+ If you have a controller with this interface, say Y or M here. -+ -+ If unsure, say N. -+ - config MMC_MSM - tristate "Qualcomm SDCC Controller Support" - depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50) ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -65,6 +65,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhc - obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o - obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o - obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o -+obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o - - ifeq ($(CONFIG_CB710_DEBUG),y) - CFLAGS-cb710-mmc += -DDEBUG ---- /dev/null -+++ b/drivers/mmc/host/sdhci-msm.c -@@ -0,0 +1,208 @@ -+/* -+ * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver -+ * -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+ -+#include "sdhci-pltfm.h" -+ -+#define CORE_HC_MODE 0x78 -+#define HC_MODE_EN 0x1 -+#define CORE_POWER 0x0 -+#define CORE_SW_RST BIT(7) -+ -+ -+struct sdhci_msm_host { -+ struct platform_device *pdev; -+ void __iomem *core_mem; /* MSM SDCC mapped address */ -+ struct clk *clk; /* main SD/MMC bus clock */ -+ struct clk *pclk; /* SDHC peripheral bus clock */ -+ struct clk *bus_clk; /* SDHC bus voter clock */ -+ struct mmc_host *mmc; -+ struct sdhci_pltfm_data sdhci_msm_pdata; -+}; -+ -+/* Platform specific tuning */ -+static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode) -+{ -+ /* -+ * Tuning is required for SDR104, HS200 and HS400 cards and if the clock -+ * frequency greater than 100MHz in those modes. The standard tuning -+ * procedure should not be executed, but a custom implementation will be -+ * added here instead. -+ */ -+ return 0; -+} -+ -+static const struct of_device_id sdhci_msm_dt_match[] = { -+ { .compatible = "qcom,sdhci-msm-v4" }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match); -+ -+static struct sdhci_ops sdhci_msm_ops = { -+ .platform_execute_tuning = sdhci_msm_execute_tuning, -+}; -+ -+static int sdhci_msm_probe(struct platform_device *pdev) -+{ -+ struct sdhci_host *host; -+ struct sdhci_pltfm_host *pltfm_host; -+ struct sdhci_msm_host *msm_host; -+ struct resource *core_memres; -+ int ret; -+ u16 host_version; -+ -+ msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); -+ if (!msm_host) -+ return -ENOMEM; -+ -+ msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops; -+ host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0); -+ if (IS_ERR(host)) -+ return PTR_ERR(host); -+ -+ pltfm_host = sdhci_priv(host); -+ pltfm_host->priv = msm_host; -+ msm_host->mmc = host->mmc; -+ msm_host->pdev = pdev; -+ -+ ret = mmc_of_parse(host->mmc); -+ if (ret) -+ goto pltfm_free; -+ -+ sdhci_get_of_property(pdev); -+ -+ /* Setup SDCC bus voter clock. */ -+ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); -+ if (!IS_ERR(msm_host->bus_clk)) { -+ /* Vote for max. clk rate for max. performance */ -+ ret = clk_set_rate(msm_host->bus_clk, INT_MAX); -+ if (ret) -+ goto pltfm_free; -+ ret = clk_prepare_enable(msm_host->bus_clk); -+ if (ret) -+ goto pltfm_free; -+ } -+ -+ /* Setup main peripheral bus clock */ -+ msm_host->pclk = devm_clk_get(&pdev->dev, "iface"); -+ if (IS_ERR(msm_host->pclk)) { -+ ret = PTR_ERR(msm_host->pclk); -+ dev_err(&pdev->dev, "Perpheral clk setup failed (%d)\n", ret); -+ goto bus_clk_disable; -+ } -+ -+ ret = clk_prepare_enable(msm_host->pclk); -+ if (ret) -+ goto bus_clk_disable; -+ -+ /* Setup SDC MMC clock */ -+ msm_host->clk = devm_clk_get(&pdev->dev, "core"); -+ if (IS_ERR(msm_host->clk)) { -+ ret = PTR_ERR(msm_host->clk); -+ dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret); -+ goto pclk_disable; -+ } -+ -+ ret = clk_prepare_enable(msm_host->clk); -+ if (ret) -+ goto pclk_disable; -+ -+ core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres); -+ -+ if (IS_ERR(msm_host->core_mem)) { -+ dev_err(&pdev->dev, "Failed to remap registers\n"); -+ ret = PTR_ERR(msm_host->core_mem); -+ goto clk_disable; -+ } -+ -+ /* Reset the core and Enable SDHC mode */ -+ writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) | -+ CORE_SW_RST, msm_host->core_mem + CORE_POWER); -+ -+ /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */ -+ usleep_range(1000, 5000); -+ if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) { -+ dev_err(&pdev->dev, "Stuck in reset\n"); -+ ret = -ETIMEDOUT; -+ goto clk_disable; -+ } -+ -+ /* Set HC_MODE_EN bit in HC_MODE register */ -+ writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE)); -+ -+ host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; -+ host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE; -+ -+ host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); -+ dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", -+ host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> -+ SDHCI_VENDOR_VER_SHIFT)); -+ -+ ret = sdhci_add_host(host); -+ if (ret) -+ goto clk_disable; -+ -+ return 0; -+ -+clk_disable: -+ clk_disable_unprepare(msm_host->clk); -+pclk_disable: -+ clk_disable_unprepare(msm_host->pclk); -+bus_clk_disable: -+ if (!IS_ERR(msm_host->bus_clk)) -+ clk_disable_unprepare(msm_host->bus_clk); -+pltfm_free: -+ sdhci_pltfm_free(pdev); -+ return ret; -+} -+ -+static int sdhci_msm_remove(struct platform_device *pdev) -+{ -+ struct sdhci_host *host = platform_get_drvdata(pdev); -+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); -+ struct sdhci_msm_host *msm_host = pltfm_host->priv; -+ int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == -+ 0xffffffff); -+ -+ sdhci_remove_host(host, dead); -+ sdhci_pltfm_free(pdev); -+ clk_disable_unprepare(msm_host->clk); -+ clk_disable_unprepare(msm_host->pclk); -+ if (!IS_ERR(msm_host->bus_clk)) -+ clk_disable_unprepare(msm_host->bus_clk); -+ return 0; -+} -+ -+static struct platform_driver sdhci_msm_driver = { -+ .probe = sdhci_msm_probe, -+ .remove = sdhci_msm_remove, -+ .driver = { -+ .name = "sdhci_msm", -+ .owner = THIS_MODULE, -+ .of_match_table = sdhci_msm_dt_match, -+ }, -+}; -+ -+module_platform_driver(sdhci_msm_driver); -+ -+MODULE_DESCRIPTION("Qualcomm Secure Digital Host Controller Interface driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0048-mmc-sdhci-msm-Add-platform_execute_tuning-implementa.patch b/target/linux/ipq806x/patches/0048-mmc-sdhci-msm-Add-platform_execute_tuning-implementa.patch deleted file mode 100644 index e2c34bfc12..0000000000 --- a/target/linux/ipq806x/patches/0048-mmc-sdhci-msm-Add-platform_execute_tuning-implementa.patch +++ /dev/null @@ -1,467 +0,0 @@ -From c2a237b3e467c8bb349c4624b71ec400abaf8ad1 Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Mon, 10 Mar 2014 17:37:13 +0200 -Subject: [PATCH 048/182] mmc: sdhci-msm: Add platform_execute_tuning - implementation - -This patch adds implementation for platform specific tuning in order -to support HS200 bus speed mode on Qualcomm SDHCI controller. - -Signed-off-by: Asutosh Das -Signed-off-by: Venkat Gopalakrishnan -Signed-off-by: Georgi Djakov -Acked-by: Ulf Hansson -Signed-off-by: Chris Ball ---- - drivers/mmc/host/sdhci-msm.c | 420 +++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 415 insertions(+), 5 deletions(-) - ---- a/drivers/mmc/host/sdhci-msm.c -+++ b/drivers/mmc/host/sdhci-msm.c -@@ -18,6 +18,8 @@ - #include - #include - #include -+#include -+#include - - #include "sdhci-pltfm.h" - -@@ -26,6 +28,42 @@ - #define CORE_POWER 0x0 - #define CORE_SW_RST BIT(7) - -+#define MAX_PHASES 16 -+#define CORE_DLL_LOCK BIT(7) -+#define CORE_DLL_EN BIT(16) -+#define CORE_CDR_EN BIT(17) -+#define CORE_CK_OUT_EN BIT(18) -+#define CORE_CDR_EXT_EN BIT(19) -+#define CORE_DLL_PDN BIT(29) -+#define CORE_DLL_RST BIT(30) -+#define CORE_DLL_CONFIG 0x100 -+#define CORE_DLL_STATUS 0x108 -+ -+#define CORE_VENDOR_SPEC 0x10c -+#define CORE_CLK_PWRSAVE BIT(1) -+ -+#define CDR_SELEXT_SHIFT 20 -+#define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT) -+#define CMUX_SHIFT_PHASE_SHIFT 24 -+#define CMUX_SHIFT_PHASE_MASK (7 << CMUX_SHIFT_PHASE_SHIFT) -+ -+static const u32 tuning_block_64[] = { -+ 0x00ff0fff, 0xccc3ccff, 0xffcc3cc3, 0xeffefffe, -+ 0xddffdfff, 0xfbfffbff, 0xff7fffbf, 0xefbdf777, -+ 0xf0fff0ff, 0x3cccfc0f, 0xcfcc33cc, 0xeeffefff, -+ 0xfdfffdff, 0xffbfffdf, 0xfff7ffbb, 0xde7b7ff7 -+}; -+ -+static const u32 tuning_block_128[] = { -+ 0xff00ffff, 0x0000ffff, 0xccccffff, 0xcccc33cc, -+ 0xcc3333cc, 0xffffcccc, 0xffffeeff, 0xffeeeeff, -+ 0xffddffff, 0xddddffff, 0xbbffffff, 0xbbffffff, -+ 0xffffffbb, 0xffffff77, 0x77ff7777, 0xffeeddbb, -+ 0x00ffffff, 0x00ffffff, 0xccffff00, 0xcc33cccc, -+ 0x3333cccc, 0xffcccccc, 0xffeeffff, 0xeeeeffff, -+ 0xddffffff, 0xddffffff, 0xffffffdd, 0xffffffbb, -+ 0xffffbbbb, 0xffff77ff, 0xff7777ff, 0xeeddbb77 -+}; - - struct sdhci_msm_host { - struct platform_device *pdev; -@@ -38,17 +76,389 @@ struct sdhci_msm_host { - }; - - /* Platform specific tuning */ --static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode) -+static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll) -+{ -+ u32 wait_cnt = 50; -+ u8 ck_out_en; -+ struct mmc_host *mmc = host->mmc; -+ -+ /* Poll for CK_OUT_EN bit. max. poll time = 50us */ -+ ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & -+ CORE_CK_OUT_EN); -+ -+ while (ck_out_en != poll) { -+ if (--wait_cnt == 0) { -+ dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n", -+ mmc_hostname(mmc), poll); -+ return -ETIMEDOUT; -+ } -+ udelay(1); -+ -+ ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & -+ CORE_CK_OUT_EN); -+ } -+ -+ return 0; -+} -+ -+static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase) -+{ -+ int rc; -+ static const u8 grey_coded_phase_table[] = { -+ 0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4, -+ 0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8 -+ }; -+ unsigned long flags; -+ u32 config; -+ struct mmc_host *mmc = host->mmc; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ -+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); -+ config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN); -+ config |= (CORE_CDR_EXT_EN | CORE_DLL_EN); -+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */ -+ rc = msm_dll_poll_ck_out_en(host, 0); -+ if (rc) -+ goto err_out; -+ -+ /* -+ * Write the selected DLL clock output phase (0 ... 15) -+ * to CDR_SELEXT bit field of DLL_CONFIG register. -+ */ -+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); -+ config &= ~CDR_SELEXT_MASK; -+ config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT; -+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) -+ | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */ -+ rc = msm_dll_poll_ck_out_en(host, 1); -+ if (rc) -+ goto err_out; -+ -+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); -+ config |= CORE_CDR_EN; -+ config &= ~CORE_CDR_EXT_EN; -+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); -+ goto out; -+ -+err_out: -+ dev_err(mmc_dev(mmc), "%s: Failed to set DLL phase: %d\n", -+ mmc_hostname(mmc), phase); -+out: -+ spin_unlock_irqrestore(&host->lock, flags); -+ return rc; -+} -+ -+/* -+ * Find out the greatest range of consecuitive selected -+ * DLL clock output phases that can be used as sampling -+ * setting for SD3.0 UHS-I card read operation (in SDR104 -+ * timing mode) or for eMMC4.5 card read operation (in HS200 -+ * timing mode). -+ * Select the 3/4 of the range and configure the DLL with the -+ * selected DLL clock output phase. -+ */ -+ -+static int msm_find_most_appropriate_phase(struct sdhci_host *host, -+ u8 *phase_table, u8 total_phases) -+{ -+ int ret; -+ u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} }; -+ u8 phases_per_row[MAX_PHASES] = { 0 }; -+ int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0; -+ int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0; -+ bool phase_0_found = false, phase_15_found = false; -+ struct mmc_host *mmc = host->mmc; -+ -+ if (!total_phases || (total_phases > MAX_PHASES)) { -+ dev_err(mmc_dev(mmc), "%s: Invalid argument: total_phases=%d\n", -+ mmc_hostname(mmc), total_phases); -+ return -EINVAL; -+ } -+ -+ for (cnt = 0; cnt < total_phases; cnt++) { -+ ranges[row_index][col_index] = phase_table[cnt]; -+ phases_per_row[row_index] += 1; -+ col_index++; -+ -+ if ((cnt + 1) == total_phases) { -+ continue; -+ /* check if next phase in phase_table is consecutive or not */ -+ } else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) { -+ row_index++; -+ col_index = 0; -+ } -+ } -+ -+ if (row_index >= MAX_PHASES) -+ return -EINVAL; -+ -+ /* Check if phase-0 is present in first valid window? */ -+ if (!ranges[0][0]) { -+ phase_0_found = true; -+ phase_0_raw_index = 0; -+ /* Check if cycle exist between 2 valid windows */ -+ for (cnt = 1; cnt <= row_index; cnt++) { -+ if (phases_per_row[cnt]) { -+ for (i = 0; i < phases_per_row[cnt]; i++) { -+ if (ranges[cnt][i] == 15) { -+ phase_15_found = true; -+ phase_15_raw_index = cnt; -+ break; -+ } -+ } -+ } -+ } -+ } -+ -+ /* If 2 valid windows form cycle then merge them as single window */ -+ if (phase_0_found && phase_15_found) { -+ /* number of phases in raw where phase 0 is present */ -+ u8 phases_0 = phases_per_row[phase_0_raw_index]; -+ /* number of phases in raw where phase 15 is present */ -+ u8 phases_15 = phases_per_row[phase_15_raw_index]; -+ -+ if (phases_0 + phases_15 >= MAX_PHASES) -+ /* -+ * If there are more than 1 phase windows then total -+ * number of phases in both the windows should not be -+ * more than or equal to MAX_PHASES. -+ */ -+ return -EINVAL; -+ -+ /* Merge 2 cyclic windows */ -+ i = phases_15; -+ for (cnt = 0; cnt < phases_0; cnt++) { -+ ranges[phase_15_raw_index][i] = -+ ranges[phase_0_raw_index][cnt]; -+ if (++i >= MAX_PHASES) -+ break; -+ } -+ -+ phases_per_row[phase_0_raw_index] = 0; -+ phases_per_row[phase_15_raw_index] = phases_15 + phases_0; -+ } -+ -+ for (cnt = 0; cnt <= row_index; cnt++) { -+ if (phases_per_row[cnt] > curr_max) { -+ curr_max = phases_per_row[cnt]; -+ selected_row_index = cnt; -+ } -+ } -+ -+ i = (curr_max * 3) / 4; -+ if (i) -+ i--; -+ -+ ret = ranges[selected_row_index][i]; -+ -+ if (ret >= MAX_PHASES) { -+ ret = -EINVAL; -+ dev_err(mmc_dev(mmc), "%s: Invalid phase selected=%d\n", -+ mmc_hostname(mmc), ret); -+ } -+ -+ return ret; -+} -+ -+static inline void msm_cm_dll_set_freq(struct sdhci_host *host) -+{ -+ u32 mclk_freq = 0, config; -+ -+ /* Program the MCLK value to MCLK_FREQ bit field */ -+ if (host->clock <= 112000000) -+ mclk_freq = 0; -+ else if (host->clock <= 125000000) -+ mclk_freq = 1; -+ else if (host->clock <= 137000000) -+ mclk_freq = 2; -+ else if (host->clock <= 150000000) -+ mclk_freq = 3; -+ else if (host->clock <= 162000000) -+ mclk_freq = 4; -+ else if (host->clock <= 175000000) -+ mclk_freq = 5; -+ else if (host->clock <= 187000000) -+ mclk_freq = 6; -+ else if (host->clock <= 200000000) -+ mclk_freq = 7; -+ -+ config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); -+ config &= ~CMUX_SHIFT_PHASE_MASK; -+ config |= mclk_freq << CMUX_SHIFT_PHASE_SHIFT; -+ writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); -+} -+ -+/* Initialize the DLL (Programmable Delay Line) */ -+static int msm_init_cm_dll(struct sdhci_host *host) - { -+ struct mmc_host *mmc = host->mmc; -+ int wait_cnt = 50; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&host->lock, flags); -+ - /* -- * Tuning is required for SDR104, HS200 and HS400 cards and if the clock -- * frequency greater than 100MHz in those modes. The standard tuning -- * procedure should not be executed, but a custom implementation will be -- * added here instead. -+ * Make sure that clock is always enabled when DLL -+ * tuning is in progress. Keeping PWRSAVE ON may -+ * turn off the clock. - */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) -+ & ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC); -+ -+ /* Write 1 to DLL_RST bit of DLL_CONFIG register */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) -+ | CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Write 1 to DLL_PDN bit of DLL_CONFIG register */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) -+ | CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); -+ msm_cm_dll_set_freq(host); -+ -+ /* Write 0 to DLL_RST bit of DLL_CONFIG register */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) -+ & ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Write 0 to DLL_PDN bit of DLL_CONFIG register */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) -+ & ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Set DLL_EN bit to 1. */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) -+ | CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Set CK_OUT_EN bit to 1. */ -+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) -+ | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG); -+ -+ /* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */ -+ while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) & -+ CORE_DLL_LOCK)) { -+ /* max. wait for 50us sec for LOCK bit to be set */ -+ if (--wait_cnt == 0) { -+ dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n", -+ mmc_hostname(mmc)); -+ spin_unlock_irqrestore(&host->lock, flags); -+ return -ETIMEDOUT; -+ } -+ udelay(1); -+ } -+ -+ spin_unlock_irqrestore(&host->lock, flags); - return 0; - } - -+static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode) -+{ -+ int tuning_seq_cnt = 3; -+ u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0; -+ const u32 *tuning_block_pattern = tuning_block_64; -+ int size = sizeof(tuning_block_64); /* Pattern size in bytes */ -+ int rc; -+ struct mmc_host *mmc = host->mmc; -+ struct mmc_ios ios = host->mmc->ios; -+ -+ /* -+ * Tuning is required for SDR104, HS200 and HS400 cards and -+ * if clock frequency is greater than 100MHz in these modes. -+ */ -+ if (host->clock <= 100 * 1000 * 1000 || -+ !((ios.timing == MMC_TIMING_MMC_HS200) || -+ (ios.timing == MMC_TIMING_UHS_SDR104))) -+ return 0; -+ -+ if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) && -+ (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) { -+ tuning_block_pattern = tuning_block_128; -+ size = sizeof(tuning_block_128); -+ } -+ -+ data_buf = kmalloc(size, GFP_KERNEL); -+ if (!data_buf) -+ return -ENOMEM; -+ -+retry: -+ /* First of all reset the tuning block */ -+ rc = msm_init_cm_dll(host); -+ if (rc) -+ goto out; -+ -+ phase = 0; -+ do { -+ struct mmc_command cmd = { 0 }; -+ struct mmc_data data = { 0 }; -+ struct mmc_request mrq = { -+ .cmd = &cmd, -+ .data = &data -+ }; -+ struct scatterlist sg; -+ -+ /* Set the phase in delay line hw block */ -+ rc = msm_config_cm_dll_phase(host, phase); -+ if (rc) -+ goto out; -+ -+ cmd.opcode = opcode; -+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; -+ -+ data.blksz = size; -+ data.blocks = 1; -+ data.flags = MMC_DATA_READ; -+ data.timeout_ns = NSEC_PER_SEC; /* 1 second */ -+ -+ data.sg = &sg; -+ data.sg_len = 1; -+ sg_init_one(&sg, data_buf, size); -+ memset(data_buf, 0, size); -+ mmc_wait_for_req(mmc, &mrq); -+ -+ if (!cmd.error && !data.error && -+ !memcmp(data_buf, tuning_block_pattern, size)) { -+ /* Tuning is successful at this tuning point */ -+ tuned_phases[tuned_phase_cnt++] = phase; -+ dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n", -+ mmc_hostname(mmc), phase); -+ } -+ } while (++phase < ARRAY_SIZE(tuned_phases)); -+ -+ if (tuned_phase_cnt) { -+ rc = msm_find_most_appropriate_phase(host, tuned_phases, -+ tuned_phase_cnt); -+ if (rc < 0) -+ goto out; -+ else -+ phase = rc; -+ -+ /* -+ * Finally set the selected phase in delay -+ * line hw block. -+ */ -+ rc = msm_config_cm_dll_phase(host, phase); -+ if (rc) -+ goto out; -+ dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", -+ mmc_hostname(mmc), phase); -+ } else { -+ if (--tuning_seq_cnt) -+ goto retry; -+ /* Tuning failed */ -+ dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n", -+ mmc_hostname(mmc)); -+ rc = -EIO; -+ } -+ -+out: -+ kfree(data_buf); -+ return rc; -+} -+ - static const struct of_device_id sdhci_msm_dt_match[] = { - { .compatible = "qcom,sdhci-msm-v4" }, - {}, diff --git a/target/linux/ipq806x/patches/0049-drivers-of-add-initialization-code-for-static-reserv.patch b/target/linux/ipq806x/patches/0049-drivers-of-add-initialization-code-for-static-reserv.patch deleted file mode 100644 index 1e304dddb0..0000000000 --- a/target/linux/ipq806x/patches/0049-drivers-of-add-initialization-code-for-static-reserv.patch +++ /dev/null @@ -1,209 +0,0 @@ -From 60ee5b21ce14a7d5c269115b0751b904d0e005ed Mon Sep 17 00:00:00 2001 -From: Marek Szyprowski -Date: Fri, 28 Feb 2014 14:42:47 +0100 -Subject: [PATCH 049/182] drivers: of: add initialization code for static - reserved memory - -This patch adds support for static (defined by 'reg' property) reserved -memory regions declared in device tree. - -Memory blocks can be reliably reserved only during early boot. This must -happen before the whole memory management subsystem is initialized, -because we need to ensure that the given contiguous blocks are not yet -allocated by kernel. Also it must happen before kernel mappings for the -whole low memory are created, to ensure that there will be no mappings -(for reserved blocks). Typically, all this happens before device tree -structures are unflattened, so we need to get reserved memory layout -directly from fdt. - -Based on previous code provided by Josh Cartwright - -Signed-off-by: Marek Szyprowski -Signed-off-by: Grant Likely ---- - drivers/of/fdt.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/of_fdt.h | 4 ++ - 2 files changed, 135 insertions(+) - ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -440,6 +441,118 @@ struct boot_param_header *initial_boot_p - #ifdef CONFIG_OF_EARLY_FLATTREE - - /** -+ * res_mem_reserve_reg() - reserve all memory described in 'reg' property -+ */ -+static int __init __reserved_mem_reserve_reg(unsigned long node, -+ const char *uname) -+{ -+ int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); -+ phys_addr_t base, size; -+ unsigned long len; -+ __be32 *prop; -+ int nomap; -+ -+ prop = of_get_flat_dt_prop(node, "reg", &len); -+ if (!prop) -+ return -ENOENT; -+ -+ if (len && len % t_len != 0) { -+ pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n", -+ uname); -+ return -EINVAL; -+ } -+ -+ nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; -+ -+ while (len >= t_len) { -+ base = dt_mem_next_cell(dt_root_addr_cells, &prop); -+ size = dt_mem_next_cell(dt_root_size_cells, &prop); -+ -+ if (base && size && -+ early_init_dt_reserve_memory_arch(base, size, nomap) == 0) -+ pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", -+ uname, &base, (unsigned long)size / SZ_1M); -+ else -+ pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", -+ uname, &base, (unsigned long)size / SZ_1M); -+ -+ len -= t_len; -+ } -+ return 0; -+} -+ -+/** -+ * __reserved_mem_check_root() - check if #size-cells, #address-cells provided -+ * in /reserved-memory matches the values supported by the current implementation, -+ * also check if ranges property has been provided -+ */ -+static int __reserved_mem_check_root(unsigned long node) -+{ -+ __be32 *prop; -+ -+ prop = of_get_flat_dt_prop(node, "#size-cells", NULL); -+ if (!prop || be32_to_cpup(prop) != dt_root_size_cells) -+ return -EINVAL; -+ -+ prop = of_get_flat_dt_prop(node, "#address-cells", NULL); -+ if (!prop || be32_to_cpup(prop) != dt_root_addr_cells) -+ return -EINVAL; -+ -+ prop = of_get_flat_dt_prop(node, "ranges", NULL); -+ if (!prop) -+ return -EINVAL; -+ return 0; -+} -+ -+/** -+ * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory -+ */ -+static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, -+ int depth, void *data) -+{ -+ static int found; -+ const char *status; -+ -+ if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { -+ if (__reserved_mem_check_root(node) != 0) { -+ pr_err("Reserved memory: unsupported node format, ignoring\n"); -+ /* break scan */ -+ return 1; -+ } -+ found = 1; -+ /* scan next node */ -+ return 0; -+ } else if (!found) { -+ /* scan next node */ -+ return 0; -+ } else if (found && depth < 2) { -+ /* scanning of /reserved-memory has been finished */ -+ return 1; -+ } -+ -+ status = of_get_flat_dt_prop(node, "status", NULL); -+ if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) -+ return 0; -+ -+ __reserved_mem_reserve_reg(node, uname); -+ -+ /* scan next node */ -+ return 0; -+} -+ -+/** -+ * early_init_fdt_scan_reserved_mem() - create reserved memory regions -+ * -+ * This function grabs memory from early allocator for device exclusive use -+ * defined in device tree structures. It should be called by arch specific code -+ * once the early allocator (i.e. memblock) has been fully activated. -+ */ -+void __init early_init_fdt_scan_reserved_mem(void) -+{ -+ of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); -+} -+ -+/** - * of_scan_flat_dt - scan flattened tree blob and call callback on each. - * @it: callback function - * @data: context data pointer -@@ -859,6 +972,16 @@ void __init __weak early_init_dt_add_mem - memblock_add(base, size); - } - -+int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, -+ phys_addr_t size, bool nomap) -+{ -+ if (memblock_is_region_reserved(base, size)) -+ return -EBUSY; -+ if (nomap) -+ return memblock_remove(base, size); -+ return memblock_reserve(base, size); -+} -+ - /* - * called from unflatten_device_tree() to bootstrap devicetree itself - * Architectures can override this definition if memblock isn't used -@@ -867,6 +990,14 @@ void * __init __weak early_init_dt_alloc - { - return __va(memblock_alloc(size, align)); - } -+#else -+int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, -+ phys_addr_t size, bool nomap) -+{ -+ pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", -+ base, size, nomap ? " (nomap)" : ""); -+ return -ENOSYS; -+} - #endif - - bool __init early_init_dt_scan(void *params) ---- a/include/linux/of_fdt.h -+++ b/include/linux/of_fdt.h -@@ -98,7 +98,10 @@ extern int early_init_dt_scan_chosen(uns - int depth, void *data); - extern int early_init_dt_scan_memory(unsigned long node, const char *uname, - int depth, void *data); -+extern void early_init_fdt_scan_reserved_mem(void); - extern void early_init_dt_add_memory_arch(u64 base, u64 size); -+extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, -+ bool no_map); - extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); - extern u64 dt_mem_next_cell(int s, __be32 **cellp); - -@@ -118,6 +121,7 @@ extern void unflatten_and_copy_device_tr - extern void early_init_devtree(void *); - extern void early_get_first_memblock_info(void *, phys_addr_t *); - #else /* CONFIG_OF_FLATTREE */ -+static inline void early_init_fdt_scan_reserved_mem(void) {} - static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } - static inline void unflatten_device_tree(void) {} - static inline void unflatten_and_copy_device_tree(void) {} diff --git a/target/linux/ipq806x/patches/0050-drivers-of-add-initialization-code-for-dynamic-reser.patch b/target/linux/ipq806x/patches/0050-drivers-of-add-initialization-code-for-dynamic-reser.patch deleted file mode 100644 index 4b633b599f..0000000000 --- a/target/linux/ipq806x/patches/0050-drivers-of-add-initialization-code-for-dynamic-reser.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 968b497e1027ec78e986370976c76e1652aa0459 Mon Sep 17 00:00:00 2001 -From: Marek Szyprowski -Date: Fri, 28 Feb 2014 14:42:48 +0100 -Subject: [PATCH 050/182] drivers: of: add initialization code for dynamic - reserved memory - -This patch adds support for dynamically allocated reserved memory regions -declared in device tree. Such regions are defined by 'size', 'alignment' -and 'alloc-ranges' properties. - -Based on previous code provided by Josh Cartwright - -Signed-off-by: Marek Szyprowski -Signed-off-by: Grant Likely ---- - drivers/of/Kconfig | 6 ++ - drivers/of/Makefile | 1 + - drivers/of/fdt.c | 13 ++- - drivers/of/of_reserved_mem.c | 188 +++++++++++++++++++++++++++++++++++++++ - include/linux/of_reserved_mem.h | 21 +++++ - 5 files changed, 227 insertions(+), 2 deletions(-) - create mode 100644 drivers/of/of_reserved_mem.c - create mode 100644 include/linux/of_reserved_mem.h - ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -75,4 +75,10 @@ config OF_MTD - depends on MTD - def_bool y - -+config OF_RESERVED_MEM -+ depends on OF_EARLY_FLATTREE -+ bool -+ help -+ Helpers to allow for reservation of memory regions -+ - endmenu # OF ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -9,3 +9,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o - obj-$(CONFIG_OF_PCI) += of_pci.o - obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o - obj-$(CONFIG_OF_MTD) += of_mtd.o -+obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -450,7 +451,7 @@ static int __init __reserved_mem_reserve - phys_addr_t base, size; - unsigned long len; - __be32 *prop; -- int nomap; -+ int nomap, first = 1; - - prop = of_get_flat_dt_prop(node, "reg", &len); - if (!prop) -@@ -477,6 +478,10 @@ static int __init __reserved_mem_reserve - uname, &base, (unsigned long)size / SZ_1M); - - len -= t_len; -+ if (first) { -+ fdt_reserved_mem_save_node(node, uname, base, size); -+ first = 0; -+ } - } - return 0; - } -@@ -512,6 +517,7 @@ static int __init __fdt_scan_reserved_me - { - static int found; - const char *status; -+ int err; - - if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { - if (__reserved_mem_check_root(node) != 0) { -@@ -534,7 +540,9 @@ static int __init __fdt_scan_reserved_me - if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) - return 0; - -- __reserved_mem_reserve_reg(node, uname); -+ err = __reserved_mem_reserve_reg(node, uname); -+ if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL)) -+ fdt_reserved_mem_save_node(node, uname, 0, 0); - - /* scan next node */ - return 0; -@@ -550,6 +558,7 @@ static int __init __fdt_scan_reserved_me - void __init early_init_fdt_scan_reserved_mem(void) - { - of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); -+ fdt_init_reserved_mem(); - } - - /** ---- /dev/null -+++ b/drivers/of/of_reserved_mem.c -@@ -0,0 +1,188 @@ -+/* -+ * Device tree based initialization code for reserved memory. -+ * -+ * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. -+ * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. -+ * http://www.samsung.com -+ * Author: Marek Szyprowski -+ * Author: Josh Cartwright -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License or (at your optional) any later version of the license. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_RESERVED_REGIONS 16 -+static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; -+static int reserved_mem_count; -+ -+#if defined(CONFIG_HAVE_MEMBLOCK) -+#include -+int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, -+ phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, -+ phys_addr_t *res_base) -+{ -+ /* -+ * We use __memblock_alloc_base() because memblock_alloc_base() -+ * panic()s on allocation failure. -+ */ -+ phys_addr_t base = __memblock_alloc_base(size, align, end); -+ if (!base) -+ return -ENOMEM; -+ -+ /* -+ * Check if the allocated region fits in to start..end window -+ */ -+ if (base < start) { -+ memblock_free(base, size); -+ return -ENOMEM; -+ } -+ -+ *res_base = base; -+ if (nomap) -+ return memblock_remove(base, size); -+ return 0; -+} -+#else -+int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, -+ phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, -+ phys_addr_t *res_base) -+{ -+ pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n", -+ size, nomap ? " (nomap)" : ""); -+ return -ENOSYS; -+} -+#endif -+ -+/** -+ * res_mem_save_node() - save fdt node for second pass initialization -+ */ -+void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, -+ phys_addr_t base, phys_addr_t size) -+{ -+ struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; -+ -+ if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { -+ pr_err("Reserved memory: not enough space all defined regions.\n"); -+ return; -+ } -+ -+ rmem->fdt_node = node; -+ rmem->name = uname; -+ rmem->base = base; -+ rmem->size = size; -+ -+ reserved_mem_count++; -+ return; -+} -+ -+/** -+ * res_mem_alloc_size() - allocate reserved memory described by 'size', 'align' -+ * and 'alloc-ranges' properties -+ */ -+static int __init __reserved_mem_alloc_size(unsigned long node, -+ const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) -+{ -+ int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); -+ phys_addr_t start = 0, end = 0; -+ phys_addr_t base = 0, align = 0, size; -+ unsigned long len; -+ __be32 *prop; -+ int nomap; -+ int ret; -+ -+ prop = of_get_flat_dt_prop(node, "size", &len); -+ if (!prop) -+ return -EINVAL; -+ -+ if (len != dt_root_size_cells * sizeof(__be32)) { -+ pr_err("Reserved memory: invalid size property in '%s' node.\n", -+ uname); -+ return -EINVAL; -+ } -+ size = dt_mem_next_cell(dt_root_size_cells, &prop); -+ -+ nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; -+ -+ prop = of_get_flat_dt_prop(node, "alignment", &len); -+ if (prop) { -+ if (len != dt_root_addr_cells * sizeof(__be32)) { -+ pr_err("Reserved memory: invalid alignment property in '%s' node.\n", -+ uname); -+ return -EINVAL; -+ } -+ align = dt_mem_next_cell(dt_root_addr_cells, &prop); -+ } -+ -+ prop = of_get_flat_dt_prop(node, "alloc-ranges", &len); -+ if (prop) { -+ -+ if (len % t_len != 0) { -+ pr_err("Reserved memory: invalid alloc-ranges property in '%s', skipping node.\n", -+ uname); -+ return -EINVAL; -+ } -+ -+ base = 0; -+ -+ while (len > 0) { -+ start = dt_mem_next_cell(dt_root_addr_cells, &prop); -+ end = start + dt_mem_next_cell(dt_root_size_cells, -+ &prop); -+ -+ ret = early_init_dt_alloc_reserved_memory_arch(size, -+ align, start, end, nomap, &base); -+ if (ret == 0) { -+ pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", -+ uname, &base, -+ (unsigned long)size / SZ_1M); -+ break; -+ } -+ len -= t_len; -+ } -+ -+ } else { -+ ret = early_init_dt_alloc_reserved_memory_arch(size, align, -+ 0, 0, nomap, &base); -+ if (ret == 0) -+ pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", -+ uname, &base, (unsigned long)size / SZ_1M); -+ } -+ -+ if (base == 0) { -+ pr_info("Reserved memory: failed to allocate memory for node '%s'\n", -+ uname); -+ return -ENOMEM; -+ } -+ -+ *res_base = base; -+ *res_size = size; -+ -+ return 0; -+} -+ -+/** -+ * fdt_init_reserved_mem - allocate and init all saved reserved memory regions -+ */ -+void __init fdt_init_reserved_mem(void) -+{ -+ int i; -+ for (i = 0; i < reserved_mem_count; i++) { -+ struct reserved_mem *rmem = &reserved_mem[i]; -+ unsigned long node = rmem->fdt_node; -+ int err = 0; -+ -+ if (rmem->size == 0) -+ err = __reserved_mem_alloc_size(node, rmem->name, -+ &rmem->base, &rmem->size); -+ } -+} ---- /dev/null -+++ b/include/linux/of_reserved_mem.h -@@ -0,0 +1,21 @@ -+#ifndef __OF_RESERVED_MEM_H -+#define __OF_RESERVED_MEM_H -+ -+struct reserved_mem { -+ const char *name; -+ unsigned long fdt_node; -+ phys_addr_t base; -+ phys_addr_t size; -+}; -+ -+#ifdef CONFIG_OF_RESERVED_MEM -+void fdt_init_reserved_mem(void); -+void fdt_reserved_mem_save_node(unsigned long node, const char *uname, -+ phys_addr_t base, phys_addr_t size); -+#else -+static inline void fdt_init_reserved_mem(void) { } -+static inline void fdt_reserved_mem_save_node(unsigned long node, -+ const char *uname, phys_addr_t base, phys_addr_t size) { } -+#endif -+ -+#endif /* __OF_RESERVED_MEM_H */ diff --git a/target/linux/ipq806x/patches/0051-drivers-of-add-support-for-custom-reserved-memory-dr.patch b/target/linux/ipq806x/patches/0051-drivers-of-add-support-for-custom-reserved-memory-dr.patch deleted file mode 100644 index 48ad8ac835..0000000000 --- a/target/linux/ipq806x/patches/0051-drivers-of-add-support-for-custom-reserved-memory-dr.patch +++ /dev/null @@ -1,147 +0,0 @@ -From fc9e25ed9db2fcfbf16a9cbbf5a1f449da78f1d9 Mon Sep 17 00:00:00 2001 -From: Marek Szyprowski -Date: Fri, 28 Feb 2014 14:42:49 +0100 -Subject: [PATCH 051/182] drivers: of: add support for custom reserved memory - drivers - -Add support for custom reserved memory drivers. Call their init() function -for each reserved region and prepare for using operations provided by them -with by the reserved_mem->ops array. - -Based on previous code provided by Josh Cartwright - -Signed-off-by: Marek Szyprowski -Signed-off-by: Grant Likely ---- - drivers/of/of_reserved_mem.c | 29 +++++++++++++++++++++++++++++ - include/asm-generic/vmlinux.lds.h | 11 +++++++++++ - include/linux/of_reserved_mem.h | 32 ++++++++++++++++++++++++++++++++ - 3 files changed, 72 insertions(+) - ---- a/drivers/of/of_reserved_mem.c -+++ b/drivers/of/of_reserved_mem.c -@@ -170,6 +170,33 @@ static int __init __reserved_mem_alloc_s - return 0; - } - -+static const struct of_device_id __rmem_of_table_sentinel -+ __used __section(__reservedmem_of_table_end); -+ -+/** -+ * res_mem_init_node() - call region specific reserved memory init code -+ */ -+static int __init __reserved_mem_init_node(struct reserved_mem *rmem) -+{ -+ extern const struct of_device_id __reservedmem_of_table[]; -+ const struct of_device_id *i; -+ -+ for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { -+ reservedmem_of_init_fn initfn = i->data; -+ const char *compat = i->compatible; -+ -+ if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) -+ continue; -+ -+ if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) { -+ pr_info("Reserved memory: initialized node %s, compatible id %s\n", -+ rmem->name, compat); -+ return 0; -+ } -+ } -+ return -ENOENT; -+} -+ - /** - * fdt_init_reserved_mem - allocate and init all saved reserved memory regions - */ -@@ -184,5 +211,7 @@ void __init fdt_init_reserved_mem(void) - if (rmem->size == 0) - err = __reserved_mem_alloc_size(node, rmem->name, - &rmem->base, &rmem->size); -+ if (err == 0) -+ __reserved_mem_init_node(rmem); - } - } ---- a/include/asm-generic/vmlinux.lds.h -+++ b/include/asm-generic/vmlinux.lds.h -@@ -177,6 +177,16 @@ - #define CLK_OF_TABLES() - #endif - -+#ifdef CONFIG_OF_RESERVED_MEM -+#define RESERVEDMEM_OF_TABLES() \ -+ . = ALIGN(8); \ -+ VMLINUX_SYMBOL(__reservedmem_of_table) = .; \ -+ *(__reservedmem_of_table) \ -+ *(__reservedmem_of_table_end) -+#else -+#define RESERVEDMEM_OF_TABLES() -+#endif -+ - #ifdef CONFIG_SMP - #define CPU_METHOD_OF_TABLES() . = ALIGN(8); \ - VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \ -@@ -510,6 +520,7 @@ - TRACE_SYSCALLS() \ - MEM_DISCARD(init.rodata) \ - CLK_OF_TABLES() \ -+ RESERVEDMEM_OF_TABLES() \ - CLKSRC_OF_TABLES() \ - CPU_METHOD_OF_TABLES() \ - KERNEL_DTB() \ ---- a/include/linux/of_reserved_mem.h -+++ b/include/linux/of_reserved_mem.h -@@ -1,21 +1,53 @@ - #ifndef __OF_RESERVED_MEM_H - #define __OF_RESERVED_MEM_H - -+struct device; -+struct of_phandle_args; -+struct reserved_mem_ops; -+ - struct reserved_mem { - const char *name; - unsigned long fdt_node; -+ const struct reserved_mem_ops *ops; - phys_addr_t base; - phys_addr_t size; -+ void *priv; -+}; -+ -+struct reserved_mem_ops { -+ void (*device_init)(struct reserved_mem *rmem, -+ struct device *dev); -+ void (*device_release)(struct reserved_mem *rmem, -+ struct device *dev); - }; - -+typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem, -+ unsigned long node, const char *uname); -+ - #ifdef CONFIG_OF_RESERVED_MEM - void fdt_init_reserved_mem(void); - void fdt_reserved_mem_save_node(unsigned long node, const char *uname, - phys_addr_t base, phys_addr_t size); -+ -+#define RESERVEDMEM_OF_DECLARE(name, compat, init) \ -+ static const struct of_device_id __reservedmem_of_table_##name \ -+ __used __section(__reservedmem_of_table) \ -+ = { .compatible = compat, \ -+ .data = (init == (reservedmem_of_init_fn)NULL) ? \ -+ init : init } -+ - #else - static inline void fdt_init_reserved_mem(void) { } - static inline void fdt_reserved_mem_save_node(unsigned long node, - const char *uname, phys_addr_t base, phys_addr_t size) { } -+ -+#define RESERVEDMEM_OF_DECLARE(name, compat, init) \ -+ static const struct of_device_id __reservedmem_of_table_##name \ -+ __attribute__((unused)) \ -+ = { .compatible = compat, \ -+ .data = (init == (reservedmem_of_init_fn)NULL) ? \ -+ init : init } -+ - #endif - - #endif /* __OF_RESERVED_MEM_H */ diff --git a/target/linux/ipq806x/patches/0052-arm-add-support-for-reserved-memory-defined-by-devic.patch b/target/linux/ipq806x/patches/0052-arm-add-support-for-reserved-memory-defined-by-devic.patch deleted file mode 100644 index 7e90e2d88a..0000000000 --- a/target/linux/ipq806x/patches/0052-arm-add-support-for-reserved-memory-defined-by-devic.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 95c831bca9181df62230171fd66286d08ea886a8 Mon Sep 17 00:00:00 2001 -From: Marek Szyprowski -Date: Fri, 28 Feb 2014 14:42:54 +0100 -Subject: [PATCH 052/182] arm: add support for reserved memory defined by - device tree - -Enable reserved memory initialization from device tree. - -Signed-off-by: Marek Szyprowski -Signed-off-by: Grant Likely ---- - arch/arm/Kconfig | 1 + - arch/arm/mm/init.c | 2 ++ - 2 files changed, 3 insertions(+) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -1923,6 +1923,7 @@ config USE_OF - select IRQ_DOMAIN - select OF - select OF_EARLY_FLATTREE -+ select OF_RESERVED_MEM - help - Include support for flattened device tree machine descriptions. - ---- a/arch/arm/mm/init.c -+++ b/arch/arm/mm/init.c -@@ -323,6 +323,8 @@ void __init arm_memblock_init(struct mem - if (mdesc->reserve) - mdesc->reserve(); - -+ early_init_fdt_scan_reserved_mem(); -+ - /* - * reserve memory for DMA contigouos allocations, - * must come from DMA area inside low memory diff --git a/target/linux/ipq806x/patches/0053-of-document-bindings-for-reserved-memory-nodes.patch b/target/linux/ipq806x/patches/0053-of-document-bindings-for-reserved-memory-nodes.patch deleted file mode 100644 index 5363b706c2..0000000000 --- a/target/linux/ipq806x/patches/0053-of-document-bindings-for-reserved-memory-nodes.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 060a8e3db75ef98fb296b03b8fb0cdfcbcc76c6e Mon Sep 17 00:00:00 2001 -From: Grant Likely -Date: Fri, 28 Feb 2014 14:42:46 +0100 -Subject: [PATCH 053/182] of: document bindings for reserved-memory nodes - -Reserved memory nodes allow for the reservation of static (fixed -address) regions, or dynamically allocated regions for a specific -purpose. - -[joshc: Based on binding document proposed (in non-patch form) here: - http://lkml.kernel.org/g/20131030134702.19B57C402A0@trevor.secretlab.ca - adapted to support #memory-region-cells] -Signed-off-by: Josh Cartwright -[mszyprow: removed #memory-region-cells property] -Signed-off-by: Marek Szyprowski -[grant.likely: removed residual #memory-region-cells example] -Signed-off-by: Grant Likely ---- - .../bindings/reserved-memory/reserved-memory.txt | 133 ++++++++++++++++++++ - 1 file changed, 133 insertions(+) - create mode 100644 Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt -@@ -0,0 +1,133 @@ -+*** Reserved memory regions *** -+ -+Reserved memory is specified as a node under the /reserved-memory node. -+The operating system shall exclude reserved memory from normal usage -+one can create child nodes describing particular reserved (excluded from -+normal use) memory regions. Such memory regions are usually designed for -+the special usage by various device drivers. -+ -+Parameters for each memory region can be encoded into the device tree -+with the following nodes: -+ -+/reserved-memory node -+--------------------- -+#address-cells, #size-cells (required) - standard definition -+ - Should use the same values as the root node -+ranges (required) - standard definition -+ - Should be empty -+ -+/reserved-memory/ child nodes -+----------------------------- -+Each child of the reserved-memory node specifies one or more regions of -+reserved memory. Each child node may either use a 'reg' property to -+specify a specific range of reserved memory, or a 'size' property with -+optional constraints to request a dynamically allocated block of memory. -+ -+Following the generic-names recommended practice, node names should -+reflect the purpose of the node (ie. "framebuffer" or "dma-pool"). Unit -+address (@
) should be appended to the name if the node is a -+static allocation. -+ -+Properties: -+Requires either a) or b) below. -+a) static allocation -+ reg (required) - standard definition -+b) dynamic allocation -+ size (required) - length based on parent's #size-cells -+ - Size in bytes of memory to reserve. -+ alignment (optional) - length based on parent's #size-cells -+ - Address boundary for alignment of allocation. -+ alloc-ranges (optional) - prop-encoded-array (address, length pairs). -+ - Specifies regions of memory that are -+ acceptable to allocate from. -+ -+If both reg and size are present, then the reg property takes precedence -+and size is ignored. -+ -+Additional properties: -+compatible (optional) - standard definition -+ - may contain the following strings: -+ - shared-dma-pool: This indicates a region of memory meant to be -+ used as a shared pool of DMA buffers for a set of devices. It can -+ be used by an operating system to instanciate the necessary pool -+ management subsystem if necessary. -+ - vendor specific string in the form ,[-] -+no-map (optional) - empty property -+ - Indicates the operating system must not create a virtual mapping -+ of the region as part of its standard mapping of system memory, -+ nor permit speculative access to it under any circumstances other -+ than under the control of the device driver using the region. -+reusable (optional) - empty property -+ - The operating system can use the memory in this region with the -+ limitation that the device driver(s) owning the region need to be -+ able to reclaim it back. Typically that means that the operating -+ system can use that region to store volatile or cached data that -+ can be otherwise regenerated or migrated elsewhere. -+ -+Linux implementation note: -+- If a "linux,cma-default" property is present, then Linux will use the -+ region for the default pool of the contiguous memory allocator. -+ -+Device node references to reserved memory -+----------------------------------------- -+Regions in the /reserved-memory node may be referenced by other device -+nodes by adding a memory-region property to the device node. -+ -+memory-region (optional) - phandle, specifier pairs to children of /reserved-memory -+ -+Example -+------- -+This example defines 3 contiguous regions are defined for Linux kernel: -+one default of all device drivers (named linux,cma@72000000 and 64MiB in size), -+one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and -+one for multimedia processing (named multimedia-memory@77000000, 64MiB). -+ -+/ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ memory { -+ reg = <0x40000000 0x40000000>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ /* global autoconfigured region for contiguous allocations */ -+ linux,cma { -+ compatible = "shared-dma-pool"; -+ reusable; -+ size = <0x4000000>; -+ alignment = <0x2000>; -+ linux,cma-default; -+ }; -+ -+ display_reserved: framebuffer@78000000 { -+ reg = <0x78000000 0x800000>; -+ }; -+ -+ multimedia_reserved: multimedia@77000000 { -+ compatible = "acme,multimedia-memory"; -+ reg = <0x77000000 0x4000000>; -+ }; -+ }; -+ -+ /* ... */ -+ -+ fb0: video@12300000 { -+ memory-region = <&display_reserved>; -+ /* ... */ -+ }; -+ -+ scaler: scaler@12500000 { -+ memory-region = <&multimedia_reserved>; -+ /* ... */ -+ }; -+ -+ codec: codec@12600000 { -+ memory-region = <&multimedia_reserved>; -+ /* ... */ -+ }; -+}; diff --git a/target/linux/ipq806x/patches/0054-of-only-scan-for-reserved-mem-when-fdt-present.patch b/target/linux/ipq806x/patches/0054-of-only-scan-for-reserved-mem-when-fdt-present.patch deleted file mode 100644 index 6efcf38205..0000000000 --- a/target/linux/ipq806x/patches/0054-of-only-scan-for-reserved-mem-when-fdt-present.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 884ab569aec3a0847702dff0dad133bfb67e234c Mon Sep 17 00:00:00 2001 -From: Josh Cartwright -Date: Thu, 13 Mar 2014 16:36:36 -0500 -Subject: [PATCH 054/182] of: only scan for reserved mem when fdt present - -When the reserved memory patches hit -next, several legacy (non-DT) boot -failures were detected and bisected down to that commit. There needs to -be some sanity checking whether a DT is even present before parsing the -reserved ranges. - -Reported-by: Kevin Hilman -Signed-off-by: Josh Cartwright -Tested-by: Kevin Hilman -Signed-off-by: Grant Likely ---- - drivers/of/fdt.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -557,6 +557,9 @@ static int __init __fdt_scan_reserved_me - */ - void __init early_init_fdt_scan_reserved_mem(void) - { -+ if (!initial_boot_params) -+ return; -+ - of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); - fdt_init_reserved_mem(); - } diff --git a/target/linux/ipq806x/patches/0055-spmi-Linux-driver-framework-for-SPMI.patch b/target/linux/ipq806x/patches/0055-spmi-Linux-driver-framework-for-SPMI.patch deleted file mode 100644 index 80d3b6c05c..0000000000 --- a/target/linux/ipq806x/patches/0055-spmi-Linux-driver-framework-for-SPMI.patch +++ /dev/null @@ -1,919 +0,0 @@ -From 1b0018dfd6295cbcc87738601b84bf49f3004419 Mon Sep 17 00:00:00 2001 -From: Kenneth Heitke -Date: Wed, 12 Feb 2014 13:44:22 -0600 -Subject: [PATCH 055/182] spmi: Linux driver framework for SPMI - -System Power Management Interface (SPMI) is a specification -developed by the MIPI (Mobile Industry Process Interface) Alliance -optimized for the real time control of Power Management ICs (PMIC). - -SPMI is a two-wire serial interface that supports up to 4 master -devices and up to 16 logical slaves. - -The framework supports message APIs, multiple busses (1 controller -per bus) and multiple clients/slave devices per controller. - -Signed-off-by: Kenneth Heitke -Signed-off-by: Michael Bohan -Signed-off-by: Josh Cartwright -Signed-off-by: Greg Kroah-Hartman ---- - drivers/Kconfig | 2 + - drivers/Makefile | 1 + - drivers/spmi/Kconfig | 9 + - drivers/spmi/Makefile | 4 + - drivers/spmi/spmi.c | 609 +++++++++++++++++++++++++++++++++++++++ - include/dt-bindings/spmi/spmi.h | 18 ++ - include/linux/mod_devicetable.h | 8 + - include/linux/spmi.h | 191 ++++++++++++ - 8 files changed, 842 insertions(+) - create mode 100644 drivers/spmi/Kconfig - create mode 100644 drivers/spmi/Makefile - create mode 100644 drivers/spmi/spmi.c - create mode 100644 include/dt-bindings/spmi/spmi.h - create mode 100644 include/linux/spmi.h - ---- a/drivers/Kconfig -+++ b/drivers/Kconfig -@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig" - - source "drivers/spi/Kconfig" - -+source "drivers/spmi/Kconfig" -+ - source "drivers/hsi/Kconfig" - - source "drivers/pps/Kconfig" ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -66,6 +66,7 @@ obj-$(CONFIG_ATA) += ata/ - obj-$(CONFIG_TARGET_CORE) += target/ - obj-$(CONFIG_MTD) += mtd/ - obj-$(CONFIG_SPI) += spi/ -+obj-$(CONFIG_SPMI) += spmi/ - obj-y += hsi/ - obj-y += net/ - obj-$(CONFIG_ATM) += atm/ ---- /dev/null -+++ b/drivers/spmi/Kconfig -@@ -0,0 +1,9 @@ -+# -+# SPMI driver configuration -+# -+menuconfig SPMI -+ tristate "SPMI support" -+ help -+ SPMI (System Power Management Interface) is a two-wire -+ serial interface between baseband and application processors -+ and Power Management Integrated Circuits (PMIC). ---- /dev/null -+++ b/drivers/spmi/Makefile -@@ -0,0 +1,4 @@ -+# -+# Makefile for kernel SPMI framework. -+# -+obj-$(CONFIG_SPMI) += spmi.o ---- /dev/null -+++ b/drivers/spmi/spmi.c -@@ -0,0 +1,609 @@ -+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+static DEFINE_IDA(ctrl_ida); -+ -+static void spmi_dev_release(struct device *dev) -+{ -+ struct spmi_device *sdev = to_spmi_device(dev); -+ kfree(sdev); -+} -+ -+static const struct device_type spmi_dev_type = { -+ .release = spmi_dev_release, -+}; -+ -+static void spmi_ctrl_release(struct device *dev) -+{ -+ struct spmi_controller *ctrl = to_spmi_controller(dev); -+ ida_simple_remove(&ctrl_ida, ctrl->nr); -+ kfree(ctrl); -+} -+ -+static const struct device_type spmi_ctrl_type = { -+ .release = spmi_ctrl_release, -+}; -+ -+#ifdef CONFIG_PM_RUNTIME -+static int spmi_runtime_suspend(struct device *dev) -+{ -+ struct spmi_device *sdev = to_spmi_device(dev); -+ int err; -+ -+ err = pm_generic_runtime_suspend(dev); -+ if (err) -+ return err; -+ -+ return spmi_command_sleep(sdev); -+} -+ -+static int spmi_runtime_resume(struct device *dev) -+{ -+ struct spmi_device *sdev = to_spmi_device(dev); -+ int err; -+ -+ err = spmi_command_wakeup(sdev); -+ if (err) -+ return err; -+ -+ return pm_generic_runtime_resume(dev); -+} -+#endif -+ -+static const struct dev_pm_ops spmi_pm_ops = { -+ SET_RUNTIME_PM_OPS( -+ spmi_runtime_suspend, -+ spmi_runtime_resume, -+ NULL -+ ) -+}; -+ -+static int spmi_device_match(struct device *dev, struct device_driver *drv) -+{ -+ if (of_driver_match_device(dev, drv)) -+ return 1; -+ -+ if (drv->name) -+ return strncmp(dev_name(dev), drv->name, -+ SPMI_NAME_SIZE) == 0; -+ -+ return 0; -+} -+ -+/** -+ * spmi_device_add() - add a device previously constructed via spmi_device_alloc() -+ * @sdev: spmi_device to be added -+ */ -+int spmi_device_add(struct spmi_device *sdev) -+{ -+ struct spmi_controller *ctrl = sdev->ctrl; -+ int err; -+ -+ dev_set_name(&sdev->dev, "%d-%02x", ctrl->nr, sdev->usid); -+ -+ err = device_add(&sdev->dev); -+ if (err < 0) { -+ dev_err(&sdev->dev, "Can't add %s, status %d\n", -+ dev_name(&sdev->dev), err); -+ goto err_device_add; -+ } -+ -+ dev_dbg(&sdev->dev, "device %s registered\n", dev_name(&sdev->dev)); -+ -+err_device_add: -+ return err; -+} -+EXPORT_SYMBOL_GPL(spmi_device_add); -+ -+/** -+ * spmi_device_remove(): remove an SPMI device -+ * @sdev: spmi_device to be removed -+ */ -+void spmi_device_remove(struct spmi_device *sdev) -+{ -+ device_unregister(&sdev->dev); -+} -+EXPORT_SYMBOL_GPL(spmi_device_remove); -+ -+static inline int -+spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid) -+{ -+ if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type) -+ return -EINVAL; -+ -+ return ctrl->cmd(ctrl, opcode, sid); -+} -+ -+static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode, -+ u8 sid, u16 addr, u8 *buf, size_t len) -+{ -+ if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type) -+ return -EINVAL; -+ -+ return ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len); -+} -+ -+static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode, -+ u8 sid, u16 addr, const u8 *buf, size_t len) -+{ -+ if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type) -+ return -EINVAL; -+ -+ return ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len); -+} -+ -+/** -+ * spmi_register_read() - register read -+ * @sdev: SPMI device. -+ * @addr: slave register address (5-bit address). -+ * @buf: buffer to be populated with data from the Slave. -+ * -+ * Reads 1 byte of data from a Slave device register. -+ */ -+int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf) -+{ -+ /* 5-bit register address */ -+ if (addr > 0x1F) -+ return -EINVAL; -+ -+ return spmi_read_cmd(sdev->ctrl, SPMI_CMD_READ, sdev->usid, addr, -+ buf, 1); -+} -+EXPORT_SYMBOL_GPL(spmi_register_read); -+ -+/** -+ * spmi_ext_register_read() - extended register read -+ * @sdev: SPMI device. -+ * @addr: slave register address (8-bit address). -+ * @buf: buffer to be populated with data from the Slave. -+ * @len: the request number of bytes to read (up to 16 bytes). -+ * -+ * Reads up to 16 bytes of data from the extended register space on a -+ * Slave device. -+ */ -+int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf, -+ size_t len) -+{ -+ /* 8-bit register address, up to 16 bytes */ -+ if (len == 0 || len > 16) -+ return -EINVAL; -+ -+ return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READ, sdev->usid, addr, -+ buf, len); -+} -+EXPORT_SYMBOL_GPL(spmi_ext_register_read); -+ -+/** -+ * spmi_ext_register_readl() - extended register read long -+ * @sdev: SPMI device. -+ * @addr: slave register address (16-bit address). -+ * @buf: buffer to be populated with data from the Slave. -+ * @len: the request number of bytes to read (up to 8 bytes). -+ * -+ * Reads up to 8 bytes of data from the extended register space on a -+ * Slave device using 16-bit address. -+ */ -+int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf, -+ size_t len) -+{ -+ /* 16-bit register address, up to 8 bytes */ -+ if (len == 0 || len > 8) -+ return -EINVAL; -+ -+ return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READL, sdev->usid, addr, -+ buf, len); -+} -+EXPORT_SYMBOL_GPL(spmi_ext_register_readl); -+ -+/** -+ * spmi_register_write() - register write -+ * @sdev: SPMI device -+ * @addr: slave register address (5-bit address). -+ * @data: buffer containing the data to be transferred to the Slave. -+ * -+ * Writes 1 byte of data to a Slave device register. -+ */ -+int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data) -+{ -+ /* 5-bit register address */ -+ if (addr > 0x1F) -+ return -EINVAL; -+ -+ return spmi_write_cmd(sdev->ctrl, SPMI_CMD_WRITE, sdev->usid, addr, -+ &data, 1); -+} -+EXPORT_SYMBOL_GPL(spmi_register_write); -+ -+/** -+ * spmi_register_zero_write() - register zero write -+ * @sdev: SPMI device. -+ * @data: the data to be written to register 0 (7-bits). -+ * -+ * Writes data to register 0 of the Slave device. -+ */ -+int spmi_register_zero_write(struct spmi_device *sdev, u8 data) -+{ -+ return spmi_write_cmd(sdev->ctrl, SPMI_CMD_ZERO_WRITE, sdev->usid, 0, -+ &data, 1); -+} -+EXPORT_SYMBOL_GPL(spmi_register_zero_write); -+ -+/** -+ * spmi_ext_register_write() - extended register write -+ * @sdev: SPMI device. -+ * @addr: slave register address (8-bit address). -+ * @buf: buffer containing the data to be transferred to the Slave. -+ * @len: the request number of bytes to read (up to 16 bytes). -+ * -+ * Writes up to 16 bytes of data to the extended register space of a -+ * Slave device. -+ */ -+int spmi_ext_register_write(struct spmi_device *sdev, u8 addr, const u8 *buf, -+ size_t len) -+{ -+ /* 8-bit register address, up to 16 bytes */ -+ if (len == 0 || len > 16) -+ return -EINVAL; -+ -+ return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITE, sdev->usid, addr, -+ buf, len); -+} -+EXPORT_SYMBOL_GPL(spmi_ext_register_write); -+ -+/** -+ * spmi_ext_register_writel() - extended register write long -+ * @sdev: SPMI device. -+ * @addr: slave register address (16-bit address). -+ * @buf: buffer containing the data to be transferred to the Slave. -+ * @len: the request number of bytes to read (up to 8 bytes). -+ * -+ * Writes up to 8 bytes of data to the extended register space of a -+ * Slave device using 16-bit address. -+ */ -+int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr, const u8 *buf, -+ size_t len) -+{ -+ /* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */ -+ if (len == 0 || len > 8) -+ return -EINVAL; -+ -+ return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITEL, sdev->usid, -+ addr, buf, len); -+} -+EXPORT_SYMBOL_GPL(spmi_ext_register_writel); -+ -+/** -+ * spmi_command_reset() - sends RESET command to the specified slave -+ * @sdev: SPMI device. -+ * -+ * The Reset command initializes the Slave and forces all registers to -+ * their reset values. The Slave shall enter the STARTUP state after -+ * receiving a Reset command. -+ */ -+int spmi_command_reset(struct spmi_device *sdev) -+{ -+ return spmi_cmd(sdev->ctrl, SPMI_CMD_RESET, sdev->usid); -+} -+EXPORT_SYMBOL_GPL(spmi_command_reset); -+ -+/** -+ * spmi_command_sleep() - sends SLEEP command to the specified SPMI device -+ * @sdev: SPMI device. -+ * -+ * The Sleep command causes the Slave to enter the user defined SLEEP state. -+ */ -+int spmi_command_sleep(struct spmi_device *sdev) -+{ -+ return spmi_cmd(sdev->ctrl, SPMI_CMD_SLEEP, sdev->usid); -+} -+EXPORT_SYMBOL_GPL(spmi_command_sleep); -+ -+/** -+ * spmi_command_wakeup() - sends WAKEUP command to the specified SPMI device -+ * @sdev: SPMI device. -+ * -+ * The Wakeup command causes the Slave to move from the SLEEP state to -+ * the ACTIVE state. -+ */ -+int spmi_command_wakeup(struct spmi_device *sdev) -+{ -+ return spmi_cmd(sdev->ctrl, SPMI_CMD_WAKEUP, sdev->usid); -+} -+EXPORT_SYMBOL_GPL(spmi_command_wakeup); -+ -+/** -+ * spmi_command_shutdown() - sends SHUTDOWN command to the specified SPMI device -+ * @sdev: SPMI device. -+ * -+ * The Shutdown command causes the Slave to enter the SHUTDOWN state. -+ */ -+int spmi_command_shutdown(struct spmi_device *sdev) -+{ -+ return spmi_cmd(sdev->ctrl, SPMI_CMD_SHUTDOWN, sdev->usid); -+} -+EXPORT_SYMBOL_GPL(spmi_command_shutdown); -+ -+static int spmi_drv_probe(struct device *dev) -+{ -+ const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); -+ struct spmi_device *sdev = to_spmi_device(dev); -+ int err; -+ -+ /* Ensure the slave is in ACTIVE state */ -+ err = spmi_command_wakeup(sdev); -+ if (err) -+ goto fail_wakeup; -+ -+ pm_runtime_get_noresume(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ -+ err = sdrv->probe(sdev); -+ if (err) -+ goto fail_probe; -+ -+ return 0; -+ -+fail_probe: -+ pm_runtime_disable(dev); -+ pm_runtime_set_suspended(dev); -+ pm_runtime_put_noidle(dev); -+fail_wakeup: -+ return err; -+} -+ -+static int spmi_drv_remove(struct device *dev) -+{ -+ const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); -+ -+ pm_runtime_get_sync(dev); -+ sdrv->remove(to_spmi_device(dev)); -+ pm_runtime_put_noidle(dev); -+ -+ pm_runtime_disable(dev); -+ pm_runtime_set_suspended(dev); -+ pm_runtime_put_noidle(dev); -+ return 0; -+} -+ -+static struct bus_type spmi_bus_type = { -+ .name = "spmi", -+ .match = spmi_device_match, -+ .pm = &spmi_pm_ops, -+ .probe = spmi_drv_probe, -+ .remove = spmi_drv_remove, -+}; -+ -+/** -+ * spmi_controller_alloc() - Allocate a new SPMI device -+ * @ctrl: associated controller -+ * -+ * Caller is responsible for either calling spmi_device_add() to add the -+ * newly allocated controller, or calling spmi_device_put() to discard it. -+ */ -+struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl) -+{ -+ struct spmi_device *sdev; -+ -+ sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); -+ if (!sdev) -+ return NULL; -+ -+ sdev->ctrl = ctrl; -+ device_initialize(&sdev->dev); -+ sdev->dev.parent = &ctrl->dev; -+ sdev->dev.bus = &spmi_bus_type; -+ sdev->dev.type = &spmi_dev_type; -+ return sdev; -+} -+EXPORT_SYMBOL_GPL(spmi_device_alloc); -+ -+/** -+ * spmi_controller_alloc() - Allocate a new SPMI controller -+ * @parent: parent device -+ * @size: size of private data -+ * -+ * Caller is responsible for either calling spmi_controller_add() to add the -+ * newly allocated controller, or calling spmi_controller_put() to discard it. -+ * The allocated private data region may be accessed via -+ * spmi_controller_get_drvdata() -+ */ -+struct spmi_controller *spmi_controller_alloc(struct device *parent, -+ size_t size) -+{ -+ struct spmi_controller *ctrl; -+ int id; -+ -+ if (WARN_ON(!parent)) -+ return NULL; -+ -+ ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL); -+ if (!ctrl) -+ return NULL; -+ -+ device_initialize(&ctrl->dev); -+ ctrl->dev.type = &spmi_ctrl_type; -+ ctrl->dev.bus = &spmi_bus_type; -+ ctrl->dev.parent = parent; -+ ctrl->dev.of_node = parent->of_node; -+ spmi_controller_set_drvdata(ctrl, &ctrl[1]); -+ -+ id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); -+ if (id < 0) { -+ dev_err(parent, -+ "unable to allocate SPMI controller identifier.\n"); -+ spmi_controller_put(ctrl); -+ return NULL; -+ } -+ -+ ctrl->nr = id; -+ dev_set_name(&ctrl->dev, "spmi-%d", id); -+ -+ dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id); -+ return ctrl; -+} -+EXPORT_SYMBOL_GPL(spmi_controller_alloc); -+ -+static void of_spmi_register_devices(struct spmi_controller *ctrl) -+{ -+ struct device_node *node; -+ int err; -+ -+ if (!ctrl->dev.of_node) -+ return; -+ -+ for_each_available_child_of_node(ctrl->dev.of_node, node) { -+ struct spmi_device *sdev; -+ u32 reg[2]; -+ -+ dev_dbg(&ctrl->dev, "adding child %s\n", node->full_name); -+ -+ err = of_property_read_u32_array(node, "reg", reg, 2); -+ if (err) { -+ dev_err(&ctrl->dev, -+ "node %s err (%d) does not have 'reg' property\n", -+ node->full_name, err); -+ continue; -+ } -+ -+ if (reg[1] != SPMI_USID) { -+ dev_err(&ctrl->dev, -+ "node %s contains unsupported 'reg' entry\n", -+ node->full_name); -+ continue; -+ } -+ -+ if (reg[0] >= SPMI_MAX_SLAVE_ID) { -+ dev_err(&ctrl->dev, -+ "invalid usid on node %s\n", -+ node->full_name); -+ continue; -+ } -+ -+ dev_dbg(&ctrl->dev, "read usid %02x\n", reg[0]); -+ -+ sdev = spmi_device_alloc(ctrl); -+ if (!sdev) -+ continue; -+ -+ sdev->dev.of_node = node; -+ sdev->usid = (u8) reg[0]; -+ -+ err = spmi_device_add(sdev); -+ if (err) { -+ dev_err(&sdev->dev, -+ "failure adding device. status %d\n", err); -+ spmi_device_put(sdev); -+ } -+ } -+} -+ -+/** -+ * spmi_controller_add() - Add an SPMI controller -+ * @ctrl: controller to be registered. -+ * -+ * Register a controller previously allocated via spmi_controller_alloc() with -+ * the SPMI core. -+ */ -+int spmi_controller_add(struct spmi_controller *ctrl) -+{ -+ int ret; -+ -+ /* Can't register until after driver model init */ -+ if (WARN_ON(!spmi_bus_type.p)) -+ return -EAGAIN; -+ -+ ret = device_add(&ctrl->dev); -+ if (ret) -+ return ret; -+ -+ if (IS_ENABLED(CONFIG_OF)) -+ of_spmi_register_devices(ctrl); -+ -+ dev_dbg(&ctrl->dev, "spmi-%d registered: dev:%p\n", -+ ctrl->nr, &ctrl->dev); -+ -+ return 0; -+}; -+EXPORT_SYMBOL_GPL(spmi_controller_add); -+ -+/* Remove a device associated with a controller */ -+static int spmi_ctrl_remove_device(struct device *dev, void *data) -+{ -+ struct spmi_device *spmidev = to_spmi_device(dev); -+ if (dev->type == &spmi_dev_type) -+ spmi_device_remove(spmidev); -+ return 0; -+} -+ -+/** -+ * spmi_controller_remove(): remove an SPMI controller -+ * @ctrl: controller to remove -+ * -+ * Remove a SPMI controller. Caller is responsible for calling -+ * spmi_controller_put() to discard the allocated controller. -+ */ -+void spmi_controller_remove(struct spmi_controller *ctrl) -+{ -+ int dummy; -+ -+ if (!ctrl) -+ return; -+ -+ dummy = device_for_each_child(&ctrl->dev, NULL, -+ spmi_ctrl_remove_device); -+ device_del(&ctrl->dev); -+} -+EXPORT_SYMBOL_GPL(spmi_controller_remove); -+ -+/** -+ * spmi_driver_register() - Register client driver with SPMI core -+ * @sdrv: client driver to be associated with client-device. -+ * -+ * This API will register the client driver with the SPMI framework. -+ * It is typically called from the driver's module-init function. -+ */ -+int spmi_driver_register(struct spmi_driver *sdrv) -+{ -+ sdrv->driver.bus = &spmi_bus_type; -+ return driver_register(&sdrv->driver); -+} -+EXPORT_SYMBOL_GPL(spmi_driver_register); -+ -+static void __exit spmi_exit(void) -+{ -+ bus_unregister(&spmi_bus_type); -+} -+module_exit(spmi_exit); -+ -+static int __init spmi_init(void) -+{ -+ return bus_register(&spmi_bus_type); -+} -+postcore_initcall(spmi_init); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("SPMI module"); -+MODULE_ALIAS("platform:spmi"); ---- /dev/null -+++ b/include/dt-bindings/spmi/spmi.h -@@ -0,0 +1,18 @@ -+/* Copyright (c) 2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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_SPMI_H -+#define __DT_BINDINGS_SPMI_H -+ -+#define SPMI_USID 0 -+#define SPMI_GSID 1 -+ -+#endif ---- a/include/linux/mod_devicetable.h -+++ b/include/linux/mod_devicetable.h -@@ -432,6 +432,14 @@ struct spi_device_id { - kernel_ulong_t driver_data; /* Data private to the driver */ - }; - -+#define SPMI_NAME_SIZE 32 -+#define SPMI_MODULE_PREFIX "spmi:" -+ -+struct spmi_device_id { -+ char name[SPMI_NAME_SIZE]; -+ kernel_ulong_t driver_data; /* Data private to the driver */ -+}; -+ - /* dmi */ - enum dmi_field { - DMI_NONE, ---- /dev/null -+++ b/include/linux/spmi.h -@@ -0,0 +1,191 @@ -+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#ifndef _LINUX_SPMI_H -+#define _LINUX_SPMI_H -+ -+#include -+#include -+#include -+ -+/* Maximum slave identifier */ -+#define SPMI_MAX_SLAVE_ID 16 -+ -+/* SPMI Commands */ -+#define SPMI_CMD_EXT_WRITE 0x00 -+#define SPMI_CMD_RESET 0x10 -+#define SPMI_CMD_SLEEP 0x11 -+#define SPMI_CMD_SHUTDOWN 0x12 -+#define SPMI_CMD_WAKEUP 0x13 -+#define SPMI_CMD_AUTHENTICATE 0x14 -+#define SPMI_CMD_MSTR_READ 0x15 -+#define SPMI_CMD_MSTR_WRITE 0x16 -+#define SPMI_CMD_TRANSFER_BUS_OWNERSHIP 0x1A -+#define SPMI_CMD_DDB_MASTER_READ 0x1B -+#define SPMI_CMD_DDB_SLAVE_READ 0x1C -+#define SPMI_CMD_EXT_READ 0x20 -+#define SPMI_CMD_EXT_WRITEL 0x30 -+#define SPMI_CMD_EXT_READL 0x38 -+#define SPMI_CMD_WRITE 0x40 -+#define SPMI_CMD_READ 0x60 -+#define SPMI_CMD_ZERO_WRITE 0x80 -+ -+/** -+ * struct spmi_device - Basic representation of an SPMI device -+ * @dev: Driver model representation of the device. -+ * @ctrl: SPMI controller managing the bus hosting this device. -+ * @usid: This devices' Unique Slave IDentifier. -+ */ -+struct spmi_device { -+ struct device dev; -+ struct spmi_controller *ctrl; -+ u8 usid; -+}; -+ -+static inline struct spmi_device *to_spmi_device(struct device *d) -+{ -+ return container_of(d, struct spmi_device, dev); -+} -+ -+static inline void *spmi_device_get_drvdata(const struct spmi_device *sdev) -+{ -+ return dev_get_drvdata(&sdev->dev); -+} -+ -+static inline void spmi_device_set_drvdata(struct spmi_device *sdev, void *data) -+{ -+ dev_set_drvdata(&sdev->dev, data); -+} -+ -+struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl); -+ -+static inline void spmi_device_put(struct spmi_device *sdev) -+{ -+ if (sdev) -+ put_device(&sdev->dev); -+} -+ -+int spmi_device_add(struct spmi_device *sdev); -+ -+void spmi_device_remove(struct spmi_device *sdev); -+ -+/** -+ * struct spmi_controller - interface to the SPMI master controller -+ * @dev: Driver model representation of the device. -+ * @nr: board-specific number identifier for this controller/bus -+ * @cmd: sends a non-data command sequence on the SPMI bus. -+ * @read_cmd: sends a register read command sequence on the SPMI bus. -+ * @write_cmd: sends a register write command sequence on the SPMI bus. -+ */ -+struct spmi_controller { -+ struct device dev; -+ unsigned int nr; -+ int (*cmd)(struct spmi_controller *ctrl, u8 opcode, u8 sid); -+ int (*read_cmd)(struct spmi_controller *ctrl, u8 opcode, -+ u8 sid, u16 addr, u8 *buf, size_t len); -+ int (*write_cmd)(struct spmi_controller *ctrl, u8 opcode, -+ u8 sid, u16 addr, const u8 *buf, size_t len); -+}; -+ -+static inline struct spmi_controller *to_spmi_controller(struct device *d) -+{ -+ return container_of(d, struct spmi_controller, dev); -+} -+ -+static inline -+void *spmi_controller_get_drvdata(const struct spmi_controller *ctrl) -+{ -+ return dev_get_drvdata(&ctrl->dev); -+} -+ -+static inline void spmi_controller_set_drvdata(struct spmi_controller *ctrl, -+ void *data) -+{ -+ dev_set_drvdata(&ctrl->dev, data); -+} -+ -+struct spmi_controller *spmi_controller_alloc(struct device *parent, -+ size_t size); -+ -+/** -+ * spmi_controller_put() - decrement controller refcount -+ * @ctrl SPMI controller. -+ */ -+static inline void spmi_controller_put(struct spmi_controller *ctrl) -+{ -+ if (ctrl) -+ put_device(&ctrl->dev); -+} -+ -+int spmi_controller_add(struct spmi_controller *ctrl); -+void spmi_controller_remove(struct spmi_controller *ctrl); -+ -+/** -+ * struct spmi_driver - SPMI slave device driver -+ * @driver: SPMI device drivers should initialize name and owner field of -+ * this structure. -+ * @probe: binds this driver to a SPMI device. -+ * @remove: unbinds this driver from the SPMI device. -+ * @shutdown: standard shutdown callback used during powerdown/halt. -+ * @suspend: standard suspend callback used during system suspend. -+ * @resume: standard resume callback used during system resume. -+ * -+ * If PM runtime support is desired for a slave, a device driver can call -+ * pm_runtime_put() from their probe() routine (and a balancing -+ * pm_runtime_get() in remove()). PM runtime support for a slave is -+ * implemented by issuing a SLEEP command to the slave on runtime_suspend(), -+ * transitioning the slave into the SLEEP state. On runtime_resume(), a WAKEUP -+ * command is sent to the slave to bring it back to ACTIVE. -+ */ -+struct spmi_driver { -+ struct device_driver driver; -+ int (*probe)(struct spmi_device *sdev); -+ void (*remove)(struct spmi_device *sdev); -+}; -+ -+static inline struct spmi_driver *to_spmi_driver(struct device_driver *d) -+{ -+ return container_of(d, struct spmi_driver, driver); -+} -+ -+int spmi_driver_register(struct spmi_driver *sdrv); -+ -+/** -+ * spmi_driver_unregister() - unregister an SPMI client driver -+ * @sdrv: the driver to unregister -+ */ -+static inline void spmi_driver_unregister(struct spmi_driver *sdrv) -+{ -+ if (sdrv) -+ driver_unregister(&sdrv->driver); -+} -+ -+#define module_spmi_driver(__spmi_driver) \ -+ module_driver(__spmi_driver, spmi_driver_register, \ -+ spmi_driver_unregister) -+ -+int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf); -+int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf, -+ size_t len); -+int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf, -+ size_t len); -+int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data); -+int spmi_register_zero_write(struct spmi_device *sdev, u8 data); -+int spmi_ext_register_write(struct spmi_device *sdev, u8 addr, -+ const u8 *buf, size_t len); -+int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr, -+ const u8 *buf, size_t len); -+int spmi_command_reset(struct spmi_device *sdev); -+int spmi_command_sleep(struct spmi_device *sdev); -+int spmi_command_wakeup(struct spmi_device *sdev); -+int spmi_command_shutdown(struct spmi_device *sdev); -+ -+#endif diff --git a/target/linux/ipq806x/patches/0056-spmi-Add-MSM-PMIC-Arbiter-SPMI-controller.patch b/target/linux/ipq806x/patches/0056-spmi-Add-MSM-PMIC-Arbiter-SPMI-controller.patch deleted file mode 100644 index e2fde2d788..0000000000 --- a/target/linux/ipq806x/patches/0056-spmi-Add-MSM-PMIC-Arbiter-SPMI-controller.patch +++ /dev/null @@ -1,467 +0,0 @@ -From 1e1f53fbc2848b23af572c16d19e8004f6a7c9c1 Mon Sep 17 00:00:00 2001 -From: Kenneth Heitke -Date: Wed, 12 Feb 2014 13:44:24 -0600 -Subject: [PATCH 056/182] spmi: Add MSM PMIC Arbiter SPMI controller - -Qualcomm's PMIC Arbiter SPMI controller functions as a bus master and -is used to communication with one or more PMIC (slave) devices on the -SPMI bus. The PMIC Arbiter is actually a hardware wrapper around the -SPMI controller that provides concurrent and autonomous PMIC access -to various entities that need to communicate with the PMIC. - -The SPMI controller hardware handles all of the SPMI bus activity (bus -arbitration, sequence start condition, transmission of frames, etc). -This software driver uses the PMIC Arbiter register interface to -initiate command sequences on the SPMI bus. The status register is -read to determine when the command sequence has completed and whether -or not it completed successfully. - -Signed-off-by: Kenneth Heitke -Signed-off-by: Josh Cartwright -Signed-off-by: Greg Kroah-Hartman ---- - drivers/spmi/Kconfig | 17 ++ - drivers/spmi/Makefile | 2 + - drivers/spmi/spmi-pmic-arb.c | 405 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 424 insertions(+) - create mode 100644 drivers/spmi/spmi-pmic-arb.c - ---- a/drivers/spmi/Kconfig -+++ b/drivers/spmi/Kconfig -@@ -7,3 +7,20 @@ menuconfig SPMI - SPMI (System Power Management Interface) is a two-wire - serial interface between baseband and application processors - and Power Management Integrated Circuits (PMIC). -+ -+if SPMI -+ -+config SPMI_MSM_PMIC_ARB -+ tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" -+ depends on ARM -+ depends on ARCH_MSM || COMPILE_TEST -+ default ARCH_MSM -+ help -+ If you say yes to this option, support will be included for the -+ built-in SPMI PMIC Arbiter interface on Qualcomm MSM family -+ processors. -+ -+ This is required for communicating with Qualcomm PMICs and -+ other devices that have the SPMI interface. -+ -+endif ---- a/drivers/spmi/Makefile -+++ b/drivers/spmi/Makefile -@@ -2,3 +2,5 @@ - # Makefile for kernel SPMI framework. - # - obj-$(CONFIG_SPMI) += spmi.o -+ -+obj-$(CONFIG_SPMI_MSM_PMIC_ARB) += spmi-pmic-arb.o ---- /dev/null -+++ b/drivers/spmi/spmi-pmic-arb.c -@@ -0,0 +1,405 @@ -+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* PMIC Arbiter configuration registers */ -+#define PMIC_ARB_VERSION 0x0000 -+#define PMIC_ARB_INT_EN 0x0004 -+ -+/* PMIC Arbiter channel registers */ -+#define PMIC_ARB_CMD(N) (0x0800 + (0x80 * (N))) -+#define PMIC_ARB_CONFIG(N) (0x0804 + (0x80 * (N))) -+#define PMIC_ARB_STATUS(N) (0x0808 + (0x80 * (N))) -+#define PMIC_ARB_WDATA0(N) (0x0810 + (0x80 * (N))) -+#define PMIC_ARB_WDATA1(N) (0x0814 + (0x80 * (N))) -+#define PMIC_ARB_RDATA0(N) (0x0818 + (0x80 * (N))) -+#define PMIC_ARB_RDATA1(N) (0x081C + (0x80 * (N))) -+ -+/* Interrupt Controller */ -+#define SPMI_PIC_OWNER_ACC_STATUS(M, N) (0x0000 + ((32 * (M)) + (4 * (N)))) -+#define SPMI_PIC_ACC_ENABLE(N) (0x0200 + (4 * (N))) -+#define SPMI_PIC_IRQ_STATUS(N) (0x0600 + (4 * (N))) -+#define SPMI_PIC_IRQ_CLEAR(N) (0x0A00 + (4 * (N))) -+ -+/* Mapping Table */ -+#define SPMI_MAPPING_TABLE_REG(N) (0x0B00 + (4 * (N))) -+#define SPMI_MAPPING_BIT_INDEX(X) (((X) >> 18) & 0xF) -+#define SPMI_MAPPING_BIT_IS_0_FLAG(X) (((X) >> 17) & 0x1) -+#define SPMI_MAPPING_BIT_IS_0_RESULT(X) (((X) >> 9) & 0xFF) -+#define SPMI_MAPPING_BIT_IS_1_FLAG(X) (((X) >> 8) & 0x1) -+#define SPMI_MAPPING_BIT_IS_1_RESULT(X) (((X) >> 0) & 0xFF) -+ -+#define SPMI_MAPPING_TABLE_LEN 255 -+#define SPMI_MAPPING_TABLE_TREE_DEPTH 16 /* Maximum of 16-bits */ -+ -+/* Ownership Table */ -+#define SPMI_OWNERSHIP_TABLE_REG(N) (0x0700 + (4 * (N))) -+#define SPMI_OWNERSHIP_PERIPH2OWNER(X) ((X) & 0x7) -+ -+/* Channel Status fields */ -+enum pmic_arb_chnl_status { -+ PMIC_ARB_STATUS_DONE = (1 << 0), -+ PMIC_ARB_STATUS_FAILURE = (1 << 1), -+ PMIC_ARB_STATUS_DENIED = (1 << 2), -+ PMIC_ARB_STATUS_DROPPED = (1 << 3), -+}; -+ -+/* Command register fields */ -+#define PMIC_ARB_CMD_MAX_BYTE_COUNT 8 -+ -+/* Command Opcodes */ -+enum pmic_arb_cmd_op_code { -+ PMIC_ARB_OP_EXT_WRITEL = 0, -+ PMIC_ARB_OP_EXT_READL = 1, -+ PMIC_ARB_OP_EXT_WRITE = 2, -+ PMIC_ARB_OP_RESET = 3, -+ PMIC_ARB_OP_SLEEP = 4, -+ PMIC_ARB_OP_SHUTDOWN = 5, -+ PMIC_ARB_OP_WAKEUP = 6, -+ PMIC_ARB_OP_AUTHENTICATE = 7, -+ PMIC_ARB_OP_MSTR_READ = 8, -+ PMIC_ARB_OP_MSTR_WRITE = 9, -+ PMIC_ARB_OP_EXT_READ = 13, -+ PMIC_ARB_OP_WRITE = 14, -+ PMIC_ARB_OP_READ = 15, -+ PMIC_ARB_OP_ZERO_WRITE = 16, -+}; -+ -+/* Maximum number of support PMIC peripherals */ -+#define PMIC_ARB_MAX_PERIPHS 256 -+#define PMIC_ARB_PERIPH_ID_VALID (1 << 15) -+#define PMIC_ARB_TIMEOUT_US 100 -+#define PMIC_ARB_MAX_TRANS_BYTES (8) -+ -+#define PMIC_ARB_APID_MASK 0xFF -+#define PMIC_ARB_PPID_MASK 0xFFF -+ -+/* interrupt enable bit */ -+#define SPMI_PIC_ACC_ENABLE_BIT BIT(0) -+ -+/** -+ * spmi_pmic_arb_dev - SPMI PMIC Arbiter object -+ * -+ * @base: address of the PMIC Arbiter core registers. -+ * @intr: address of the SPMI interrupt control registers. -+ * @cnfg: address of the PMIC Arbiter configuration registers. -+ * @lock: lock to synchronize accesses. -+ * @channel: which channel to use for accesses. -+ */ -+struct spmi_pmic_arb_dev { -+ void __iomem *base; -+ void __iomem *intr; -+ void __iomem *cnfg; -+ raw_spinlock_t lock; -+ u8 channel; -+}; -+ -+static inline u32 pmic_arb_base_read(struct spmi_pmic_arb_dev *dev, u32 offset) -+{ -+ return readl_relaxed(dev->base + offset); -+} -+ -+static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev, -+ u32 offset, u32 val) -+{ -+ writel_relaxed(val, dev->base + offset); -+} -+ -+/** -+ * pa_read_data: reads pmic-arb's register and copy 1..4 bytes to buf -+ * @bc: byte count -1. range: 0..3 -+ * @reg: register's address -+ * @buf: output parameter, length must be bc + 1 -+ */ -+static void pa_read_data(struct spmi_pmic_arb_dev *dev, u8 *buf, u32 reg, u8 bc) -+{ -+ u32 data = pmic_arb_base_read(dev, reg); -+ memcpy(buf, &data, (bc & 3) + 1); -+} -+ -+/** -+ * pa_write_data: write 1..4 bytes from buf to pmic-arb's register -+ * @bc: byte-count -1. range: 0..3. -+ * @reg: register's address. -+ * @buf: buffer to write. length must be bc + 1. -+ */ -+static void -+pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, u8 bc) -+{ -+ u32 data = 0; -+ memcpy(&data, buf, (bc & 3) + 1); -+ pmic_arb_base_write(dev, reg, data); -+} -+ -+static int pmic_arb_wait_for_done(struct spmi_controller *ctrl) -+{ -+ struct spmi_pmic_arb_dev *dev = spmi_controller_get_drvdata(ctrl); -+ u32 status = 0; -+ u32 timeout = PMIC_ARB_TIMEOUT_US; -+ u32 offset = PMIC_ARB_STATUS(dev->channel); -+ -+ while (timeout--) { -+ status = pmic_arb_base_read(dev, offset); -+ -+ if (status & PMIC_ARB_STATUS_DONE) { -+ if (status & PMIC_ARB_STATUS_DENIED) { -+ dev_err(&ctrl->dev, -+ "%s: transaction denied (0x%x)\n", -+ __func__, status); -+ return -EPERM; -+ } -+ -+ if (status & PMIC_ARB_STATUS_FAILURE) { -+ dev_err(&ctrl->dev, -+ "%s: transaction failed (0x%x)\n", -+ __func__, status); -+ return -EIO; -+ } -+ -+ if (status & PMIC_ARB_STATUS_DROPPED) { -+ dev_err(&ctrl->dev, -+ "%s: transaction dropped (0x%x)\n", -+ __func__, status); -+ return -EIO; -+ } -+ -+ return 0; -+ } -+ udelay(1); -+ } -+ -+ dev_err(&ctrl->dev, -+ "%s: timeout, status 0x%x\n", -+ __func__, status); -+ return -ETIMEDOUT; -+} -+ -+/* Non-data command */ -+static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid) -+{ -+ struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl); -+ unsigned long flags; -+ u32 cmd; -+ int rc; -+ -+ /* Check for valid non-data command */ -+ if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP) -+ return -EINVAL; -+ -+ cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20); -+ -+ raw_spin_lock_irqsave(&pmic_arb->lock, flags); -+ pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd); -+ rc = pmic_arb_wait_for_done(ctrl); -+ raw_spin_unlock_irqrestore(&pmic_arb->lock, flags); -+ -+ return rc; -+} -+ -+static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, -+ u16 addr, u8 *buf, size_t len) -+{ -+ struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl); -+ unsigned long flags; -+ u8 bc = len - 1; -+ u32 cmd; -+ int rc; -+ -+ if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { -+ dev_err(&ctrl->dev, -+ "pmic-arb supports 1..%d bytes per trans, but %d requested", -+ PMIC_ARB_MAX_TRANS_BYTES, len); -+ return -EINVAL; -+ } -+ -+ /* Check the opcode */ -+ if (opc >= 0x60 && opc <= 0x7F) -+ opc = PMIC_ARB_OP_READ; -+ else if (opc >= 0x20 && opc <= 0x2F) -+ opc = PMIC_ARB_OP_EXT_READ; -+ else if (opc >= 0x38 && opc <= 0x3F) -+ opc = PMIC_ARB_OP_EXT_READL; -+ else -+ return -EINVAL; -+ -+ cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7); -+ -+ raw_spin_lock_irqsave(&pmic_arb->lock, flags); -+ pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd); -+ rc = pmic_arb_wait_for_done(ctrl); -+ if (rc) -+ goto done; -+ -+ pa_read_data(pmic_arb, buf, PMIC_ARB_RDATA0(pmic_arb->channel), -+ min_t(u8, bc, 3)); -+ -+ if (bc > 3) -+ pa_read_data(pmic_arb, buf + 4, -+ PMIC_ARB_RDATA1(pmic_arb->channel), bc - 4); -+ -+done: -+ raw_spin_unlock_irqrestore(&pmic_arb->lock, flags); -+ return rc; -+} -+ -+static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, -+ u16 addr, const u8 *buf, size_t len) -+{ -+ struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl); -+ unsigned long flags; -+ u8 bc = len - 1; -+ u32 cmd; -+ int rc; -+ -+ if (bc >= PMIC_ARB_MAX_TRANS_BYTES) { -+ dev_err(&ctrl->dev, -+ "pmic-arb supports 1..%d bytes per trans, but:%d requested", -+ PMIC_ARB_MAX_TRANS_BYTES, len); -+ return -EINVAL; -+ } -+ -+ /* Check the opcode */ -+ if (opc >= 0x40 && opc <= 0x5F) -+ opc = PMIC_ARB_OP_WRITE; -+ else if (opc >= 0x00 && opc <= 0x0F) -+ opc = PMIC_ARB_OP_EXT_WRITE; -+ else if (opc >= 0x30 && opc <= 0x37) -+ opc = PMIC_ARB_OP_EXT_WRITEL; -+ else if (opc >= 0x80 && opc <= 0xFF) -+ opc = PMIC_ARB_OP_ZERO_WRITE; -+ else -+ return -EINVAL; -+ -+ cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7); -+ -+ /* Write data to FIFOs */ -+ raw_spin_lock_irqsave(&pmic_arb->lock, flags); -+ pa_write_data(pmic_arb, buf, PMIC_ARB_WDATA0(pmic_arb->channel) -+ , min_t(u8, bc, 3)); -+ if (bc > 3) -+ pa_write_data(pmic_arb, buf + 4, -+ PMIC_ARB_WDATA1(pmic_arb->channel), bc - 4); -+ -+ /* Start the transaction */ -+ pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd); -+ rc = pmic_arb_wait_for_done(ctrl); -+ raw_spin_unlock_irqrestore(&pmic_arb->lock, flags); -+ -+ return rc; -+} -+ -+static int spmi_pmic_arb_probe(struct platform_device *pdev) -+{ -+ struct spmi_pmic_arb_dev *pa; -+ struct spmi_controller *ctrl; -+ struct resource *res; -+ u32 channel; -+ int err, i; -+ -+ ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pa)); -+ if (!ctrl) -+ return -ENOMEM; -+ -+ pa = spmi_controller_get_drvdata(ctrl); -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); -+ pa->base = devm_ioremap_resource(&ctrl->dev, res); -+ if (IS_ERR(pa->base)) { -+ err = PTR_ERR(pa->base); -+ goto err_put_ctrl; -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr"); -+ pa->intr = devm_ioremap_resource(&ctrl->dev, res); -+ if (IS_ERR(pa->intr)) { -+ err = PTR_ERR(pa->intr); -+ goto err_put_ctrl; -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cnfg"); -+ pa->cnfg = devm_ioremap_resource(&ctrl->dev, res); -+ if (IS_ERR(pa->cnfg)) { -+ err = PTR_ERR(pa->cnfg); -+ goto err_put_ctrl; -+ } -+ -+ err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel); -+ if (err) { -+ dev_err(&pdev->dev, "channel unspecified.\n"); -+ goto err_put_ctrl; -+ } -+ -+ if (channel > 5) { -+ dev_err(&pdev->dev, "invalid channel (%u) specified.\n", -+ channel); -+ goto err_put_ctrl; -+ } -+ -+ pa->channel = channel; -+ -+ platform_set_drvdata(pdev, ctrl); -+ raw_spin_lock_init(&pa->lock); -+ -+ ctrl->cmd = pmic_arb_cmd; -+ ctrl->read_cmd = pmic_arb_read_cmd; -+ ctrl->write_cmd = pmic_arb_write_cmd; -+ -+ err = spmi_controller_add(ctrl); -+ if (err) -+ goto err_put_ctrl; -+ -+ dev_dbg(&ctrl->dev, "PMIC Arb Version 0x%x\n", -+ pmic_arb_base_read(pa, PMIC_ARB_VERSION)); -+ -+ return 0; -+ -+err_put_ctrl: -+ spmi_controller_put(ctrl); -+ return err; -+} -+ -+static int spmi_pmic_arb_remove(struct platform_device *pdev) -+{ -+ struct spmi_controller *ctrl = platform_get_drvdata(pdev); -+ spmi_controller_remove(ctrl); -+ spmi_controller_put(ctrl); -+ return 0; -+} -+ -+static const struct of_device_id spmi_pmic_arb_match_table[] = { -+ { .compatible = "qcom,spmi-pmic-arb", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table); -+ -+static struct platform_driver spmi_pmic_arb_driver = { -+ .probe = spmi_pmic_arb_probe, -+ .remove = spmi_pmic_arb_remove, -+ .driver = { -+ .name = "spmi_pmic_arb", -+ .owner = THIS_MODULE, -+ .of_match_table = spmi_pmic_arb_match_table, -+ }, -+}; -+module_platform_driver(spmi_pmic_arb_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:spmi_pmic_arb"); diff --git a/target/linux/ipq806x/patches/0057-spmi-pmic_arb-add-support-for-interrupt-handling.patch b/target/linux/ipq806x/patches/0057-spmi-pmic_arb-add-support-for-interrupt-handling.patch deleted file mode 100644 index b1420b4050..0000000000 --- a/target/linux/ipq806x/patches/0057-spmi-pmic_arb-add-support-for-interrupt-handling.patch +++ /dev/null @@ -1,487 +0,0 @@ -From b5bc51d44485c7ce0ca180a8c5de11a206f686e8 Mon Sep 17 00:00:00 2001 -From: Josh Cartwright -Date: Wed, 12 Feb 2014 13:44:25 -0600 -Subject: [PATCH 057/182] spmi: pmic_arb: add support for interrupt handling - -The Qualcomm PMIC Arbiter, in addition to being a basic SPMI controller, -also implements interrupt handling for slave devices. Note, this is -outside the scope of SPMI, as SPMI leaves interrupt handling completely -unspecified. - -Extend the driver to provide a irq_chip implementation and chained irq -handling which allows for these interrupts to be used. - -Cc: Thomas Gleixner -Signed-off-by: Josh Cartwright -Signed-off-by: Greg Kroah-Hartman ---- - drivers/spmi/Kconfig | 1 + - drivers/spmi/spmi-pmic-arb.c | 377 +++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 376 insertions(+), 2 deletions(-) - ---- a/drivers/spmi/Kconfig -+++ b/drivers/spmi/Kconfig -@@ -13,6 +13,7 @@ if SPMI - config SPMI_MSM_PMIC_ARB - tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" - depends on ARM -+ depends on IRQ_DOMAIN - depends on ARCH_MSM || COMPILE_TEST - default ARCH_MSM - help ---- a/drivers/spmi/spmi-pmic-arb.c -+++ b/drivers/spmi/spmi-pmic-arb.c -@@ -13,6 +13,9 @@ - #include - #include - #include -+#include -+#include -+#include - #include - #include - #include -@@ -103,6 +106,14 @@ enum pmic_arb_cmd_op_code { - * @cnfg: address of the PMIC Arbiter configuration registers. - * @lock: lock to synchronize accesses. - * @channel: which channel to use for accesses. -+ * @irq: PMIC ARB interrupt. -+ * @ee: the current Execution Environment -+ * @min_apid: minimum APID (used for bounding IRQ search) -+ * @max_apid: maximum APID -+ * @mapping_table: in-memory copy of PPID -> APID mapping table. -+ * @domain: irq domain object for PMIC IRQ domain -+ * @spmic: SPMI controller object -+ * @apid_to_ppid: cached mapping from APID to PPID - */ - struct spmi_pmic_arb_dev { - void __iomem *base; -@@ -110,6 +121,14 @@ struct spmi_pmic_arb_dev { - void __iomem *cnfg; - raw_spinlock_t lock; - u8 channel; -+ int irq; -+ u8 ee; -+ u8 min_apid; -+ u8 max_apid; -+ u32 mapping_table[SPMI_MAPPING_TABLE_LEN]; -+ struct irq_domain *domain; -+ struct spmi_controller *spmic; -+ u16 apid_to_ppid[256]; - }; - - static inline u32 pmic_arb_base_read(struct spmi_pmic_arb_dev *dev, u32 offset) -@@ -306,12 +325,316 @@ static int pmic_arb_write_cmd(struct spm - return rc; - } - -+enum qpnpint_regs { -+ QPNPINT_REG_RT_STS = 0x10, -+ QPNPINT_REG_SET_TYPE = 0x11, -+ QPNPINT_REG_POLARITY_HIGH = 0x12, -+ QPNPINT_REG_POLARITY_LOW = 0x13, -+ QPNPINT_REG_LATCHED_CLR = 0x14, -+ QPNPINT_REG_EN_SET = 0x15, -+ QPNPINT_REG_EN_CLR = 0x16, -+ QPNPINT_REG_LATCHED_STS = 0x18, -+}; -+ -+struct spmi_pmic_arb_qpnpint_type { -+ u8 type; /* 1 -> edge */ -+ u8 polarity_high; -+ u8 polarity_low; -+} __packed; -+ -+/* Simplified accessor functions for irqchip callbacks */ -+static void qpnpint_spmi_write(struct irq_data *d, u8 reg, void *buf, -+ size_t len) -+{ -+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d); -+ u8 sid = d->hwirq >> 24; -+ u8 per = d->hwirq >> 16; -+ -+ if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid, -+ (per << 8) + reg, buf, len)) -+ dev_err_ratelimited(&pa->spmic->dev, -+ "failed irqchip transaction on %x\n", -+ d->irq); -+} -+ -+static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len) -+{ -+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d); -+ u8 sid = d->hwirq >> 24; -+ u8 per = d->hwirq >> 16; -+ -+ if (pmic_arb_read_cmd(pa->spmic, SPMI_CMD_EXT_READL, sid, -+ (per << 8) + reg, buf, len)) -+ dev_err_ratelimited(&pa->spmic->dev, -+ "failed irqchip transaction on %x\n", -+ d->irq); -+} -+ -+static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid) -+{ -+ unsigned int irq; -+ u32 status; -+ int id; -+ -+ status = readl_relaxed(pa->intr + SPMI_PIC_IRQ_STATUS(apid)); -+ while (status) { -+ id = ffs(status) - 1; -+ status &= ~(1 << id); -+ irq = irq_find_mapping(pa->domain, -+ pa->apid_to_ppid[apid] << 16 -+ | id << 8 -+ | apid); -+ generic_handle_irq(irq); -+ } -+} -+ -+static void pmic_arb_chained_irq(unsigned int irq, struct irq_desc *desc) -+{ -+ struct spmi_pmic_arb_dev *pa = irq_get_handler_data(irq); -+ struct irq_chip *chip = irq_get_chip(irq); -+ void __iomem *intr = pa->intr; -+ int first = pa->min_apid >> 5; -+ int last = pa->max_apid >> 5; -+ u32 status; -+ int i, id; -+ -+ chained_irq_enter(chip, desc); -+ -+ for (i = first; i <= last; ++i) { -+ status = readl_relaxed(intr + -+ SPMI_PIC_OWNER_ACC_STATUS(pa->ee, i)); -+ while (status) { -+ id = ffs(status) - 1; -+ status &= ~(1 << id); -+ periph_interrupt(pa, id + i * 32); -+ } -+ } -+ -+ chained_irq_exit(chip, desc); -+} -+ -+static void qpnpint_irq_ack(struct irq_data *d) -+{ -+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d); -+ u8 irq = d->hwirq >> 8; -+ u8 apid = d->hwirq; -+ unsigned long flags; -+ u8 data; -+ -+ raw_spin_lock_irqsave(&pa->lock, flags); -+ writel_relaxed(1 << irq, pa->intr + SPMI_PIC_IRQ_CLEAR(apid)); -+ raw_spin_unlock_irqrestore(&pa->lock, flags); -+ -+ data = 1 << irq; -+ qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1); -+} -+ -+static void qpnpint_irq_mask(struct irq_data *d) -+{ -+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d); -+ u8 irq = d->hwirq >> 8; -+ u8 apid = d->hwirq; -+ unsigned long flags; -+ u32 status; -+ u8 data; -+ -+ raw_spin_lock_irqsave(&pa->lock, flags); -+ status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid)); -+ if (status & SPMI_PIC_ACC_ENABLE_BIT) { -+ status = status & ~SPMI_PIC_ACC_ENABLE_BIT; -+ writel_relaxed(status, pa->intr + SPMI_PIC_ACC_ENABLE(apid)); -+ } -+ raw_spin_unlock_irqrestore(&pa->lock, flags); -+ -+ data = 1 << irq; -+ qpnpint_spmi_write(d, QPNPINT_REG_EN_CLR, &data, 1); -+} -+ -+static void qpnpint_irq_unmask(struct irq_data *d) -+{ -+ struct spmi_pmic_arb_dev *pa = irq_data_get_irq_chip_data(d); -+ u8 irq = d->hwirq >> 8; -+ u8 apid = d->hwirq; -+ unsigned long flags; -+ u32 status; -+ u8 data; -+ -+ raw_spin_lock_irqsave(&pa->lock, flags); -+ status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid)); -+ if (!(status & SPMI_PIC_ACC_ENABLE_BIT)) { -+ writel_relaxed(status | SPMI_PIC_ACC_ENABLE_BIT, -+ pa->intr + SPMI_PIC_ACC_ENABLE(apid)); -+ } -+ raw_spin_unlock_irqrestore(&pa->lock, flags); -+ -+ data = 1 << irq; -+ qpnpint_spmi_write(d, QPNPINT_REG_EN_SET, &data, 1); -+} -+ -+static void qpnpint_irq_enable(struct irq_data *d) -+{ -+ u8 irq = d->hwirq >> 8; -+ u8 data; -+ -+ qpnpint_irq_unmask(d); -+ -+ data = 1 << irq; -+ qpnpint_spmi_write(d, QPNPINT_REG_LATCHED_CLR, &data, 1); -+} -+ -+static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type) -+{ -+ struct spmi_pmic_arb_qpnpint_type type; -+ u8 irq = d->hwirq >> 8; -+ -+ qpnpint_spmi_read(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type)); -+ -+ if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { -+ type.type |= 1 << irq; -+ if (flow_type & IRQF_TRIGGER_RISING) -+ type.polarity_high |= 1 << irq; -+ if (flow_type & IRQF_TRIGGER_FALLING) -+ type.polarity_low |= 1 << irq; -+ } else { -+ if ((flow_type & (IRQF_TRIGGER_HIGH)) && -+ (flow_type & (IRQF_TRIGGER_LOW))) -+ return -EINVAL; -+ -+ type.type &= ~(1 << irq); /* level trig */ -+ if (flow_type & IRQF_TRIGGER_HIGH) -+ type.polarity_high |= 1 << irq; -+ else -+ type.polarity_low |= 1 << irq; -+ } -+ -+ qpnpint_spmi_write(d, QPNPINT_REG_SET_TYPE, &type, sizeof(type)); -+ return 0; -+} -+ -+static struct irq_chip pmic_arb_irqchip = { -+ .name = "pmic_arb", -+ .irq_enable = qpnpint_irq_enable, -+ .irq_ack = qpnpint_irq_ack, -+ .irq_mask = qpnpint_irq_mask, -+ .irq_unmask = qpnpint_irq_unmask, -+ .irq_set_type = qpnpint_irq_set_type, -+ .flags = IRQCHIP_MASK_ON_SUSPEND -+ | IRQCHIP_SKIP_SET_WAKE, -+}; -+ -+struct spmi_pmic_arb_irq_spec { -+ unsigned slave:4; -+ unsigned per:8; -+ unsigned irq:3; -+}; -+ -+static int search_mapping_table(struct spmi_pmic_arb_dev *pa, -+ struct spmi_pmic_arb_irq_spec *spec, -+ u8 *apid) -+{ -+ u16 ppid = spec->slave << 8 | spec->per; -+ u32 *mapping_table = pa->mapping_table; -+ int index = 0, i; -+ u32 data; -+ -+ for (i = 0; i < SPMI_MAPPING_TABLE_TREE_DEPTH; ++i) { -+ data = mapping_table[index]; -+ -+ if (ppid & (1 << SPMI_MAPPING_BIT_INDEX(data))) { -+ if (SPMI_MAPPING_BIT_IS_1_FLAG(data)) { -+ index = SPMI_MAPPING_BIT_IS_1_RESULT(data); -+ } else { -+ *apid = SPMI_MAPPING_BIT_IS_1_RESULT(data); -+ return 0; -+ } -+ } else { -+ if (SPMI_MAPPING_BIT_IS_0_FLAG(data)) { -+ index = SPMI_MAPPING_BIT_IS_0_RESULT(data); -+ } else { -+ *apid = SPMI_MAPPING_BIT_IS_0_RESULT(data); -+ return 0; -+ } -+ } -+ } -+ -+ return -ENODEV; -+} -+ -+static int qpnpint_irq_domain_dt_translate(struct irq_domain *d, -+ struct device_node *controller, -+ const u32 *intspec, -+ unsigned int intsize, -+ unsigned long *out_hwirq, -+ unsigned int *out_type) -+{ -+ struct spmi_pmic_arb_dev *pa = d->host_data; -+ struct spmi_pmic_arb_irq_spec spec; -+ int err; -+ u8 apid; -+ -+ dev_dbg(&pa->spmic->dev, -+ "intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x\n", -+ intspec[0], intspec[1], intspec[2]); -+ -+ if (d->of_node != controller) -+ return -EINVAL; -+ if (intsize != 4) -+ return -EINVAL; -+ if (intspec[0] > 0xF || intspec[1] > 0xFF || intspec[2] > 0x7) -+ return -EINVAL; -+ -+ spec.slave = intspec[0]; -+ spec.per = intspec[1]; -+ spec.irq = intspec[2]; -+ -+ err = search_mapping_table(pa, &spec, &apid); -+ if (err) -+ return err; -+ -+ pa->apid_to_ppid[apid] = spec.slave << 8 | spec.per; -+ -+ /* Keep track of {max,min}_apid for bounding search during interrupt */ -+ if (apid > pa->max_apid) -+ pa->max_apid = apid; -+ if (apid < pa->min_apid) -+ pa->min_apid = apid; -+ -+ *out_hwirq = spec.slave << 24 -+ | spec.per << 16 -+ | spec.irq << 8 -+ | apid; -+ *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK; -+ -+ dev_dbg(&pa->spmic->dev, "out_hwirq = %lu\n", *out_hwirq); -+ -+ return 0; -+} -+ -+static int qpnpint_irq_domain_map(struct irq_domain *d, -+ unsigned int virq, -+ irq_hw_number_t hwirq) -+{ -+ struct spmi_pmic_arb_dev *pa = d->host_data; -+ -+ dev_dbg(&pa->spmic->dev, "virq = %u, hwirq = %lu\n", virq, hwirq); -+ -+ irq_set_chip_and_handler(virq, &pmic_arb_irqchip, handle_level_irq); -+ irq_set_chip_data(virq, d->host_data); -+ irq_set_noprobe(virq); -+ return 0; -+} -+ -+static const struct irq_domain_ops pmic_arb_irq_domain_ops = { -+ .map = qpnpint_irq_domain_map, -+ .xlate = qpnpint_irq_domain_dt_translate, -+}; -+ - static int spmi_pmic_arb_probe(struct platform_device *pdev) - { - struct spmi_pmic_arb_dev *pa; - struct spmi_controller *ctrl; - struct resource *res; -- u32 channel; -+ u32 channel, ee; - int err, i; - - ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pa)); -@@ -319,6 +642,7 @@ static int spmi_pmic_arb_probe(struct pl - return -ENOMEM; - - pa = spmi_controller_get_drvdata(ctrl); -+ pa->spmic = ctrl; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); - pa->base = devm_ioremap_resource(&ctrl->dev, res); -@@ -341,6 +665,12 @@ static int spmi_pmic_arb_probe(struct pl - goto err_put_ctrl; - } - -+ pa->irq = platform_get_irq_byname(pdev, "periph_irq"); -+ if (pa->irq < 0) { -+ err = pa->irq; -+ goto err_put_ctrl; -+ } -+ - err = of_property_read_u32(pdev->dev.of_node, "qcom,channel", &channel); - if (err) { - dev_err(&pdev->dev, "channel unspecified.\n"); -@@ -355,6 +685,29 @@ static int spmi_pmic_arb_probe(struct pl - - pa->channel = channel; - -+ err = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &ee); -+ if (err) { -+ dev_err(&pdev->dev, "EE unspecified.\n"); -+ goto err_put_ctrl; -+ } -+ -+ if (ee > 5) { -+ dev_err(&pdev->dev, "invalid EE (%u) specified\n", ee); -+ err = -EINVAL; -+ goto err_put_ctrl; -+ } -+ -+ pa->ee = ee; -+ -+ for (i = 0; i < ARRAY_SIZE(pa->mapping_table); ++i) -+ pa->mapping_table[i] = readl_relaxed( -+ pa->cnfg + SPMI_MAPPING_TABLE_REG(i)); -+ -+ /* Initialize max_apid/min_apid to the opposite bounds, during -+ * the irq domain translation, we are sure to update these */ -+ pa->max_apid = 0; -+ pa->min_apid = PMIC_ARB_MAX_PERIPHS - 1; -+ - platform_set_drvdata(pdev, ctrl); - raw_spin_lock_init(&pa->lock); - -@@ -362,15 +715,31 @@ static int spmi_pmic_arb_probe(struct pl - ctrl->read_cmd = pmic_arb_read_cmd; - ctrl->write_cmd = pmic_arb_write_cmd; - -+ dev_dbg(&pdev->dev, "adding irq domain\n"); -+ pa->domain = irq_domain_add_tree(pdev->dev.of_node, -+ &pmic_arb_irq_domain_ops, pa); -+ if (!pa->domain) { -+ dev_err(&pdev->dev, "unable to create irq_domain\n"); -+ err = -ENOMEM; -+ goto err_put_ctrl; -+ } -+ -+ irq_set_handler_data(pa->irq, pa); -+ irq_set_chained_handler(pa->irq, pmic_arb_chained_irq); -+ - err = spmi_controller_add(ctrl); - if (err) -- goto err_put_ctrl; -+ goto err_domain_remove; - - dev_dbg(&ctrl->dev, "PMIC Arb Version 0x%x\n", - pmic_arb_base_read(pa, PMIC_ARB_VERSION)); - - return 0; - -+err_domain_remove: -+ irq_set_chained_handler(pa->irq, NULL); -+ irq_set_handler_data(pa->irq, NULL); -+ irq_domain_remove(pa->domain); - err_put_ctrl: - spmi_controller_put(ctrl); - return err; -@@ -379,7 +748,11 @@ err_put_ctrl: - static int spmi_pmic_arb_remove(struct platform_device *pdev) - { - struct spmi_controller *ctrl = platform_get_drvdata(pdev); -+ struct spmi_pmic_arb_dev *pa = spmi_controller_get_drvdata(ctrl); - spmi_controller_remove(ctrl); -+ irq_set_chained_handler(pa->irq, NULL); -+ irq_set_handler_data(pa->irq, NULL); -+ irq_domain_remove(pa->domain); - spmi_controller_put(ctrl); - return 0; - } diff --git a/target/linux/ipq806x/patches/0058-spmi-pmic_arb-make-selectable-on-ARCH_QCOM.patch b/target/linux/ipq806x/patches/0058-spmi-pmic_arb-make-selectable-on-ARCH_QCOM.patch deleted file mode 100644 index 0df3780fa0..0000000000 --- a/target/linux/ipq806x/patches/0058-spmi-pmic_arb-make-selectable-on-ARCH_QCOM.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 840fe915072597b5ba9599c4579f014f47b9638e Mon Sep 17 00:00:00 2001 -From: Josh Cartwright -Date: Mon, 3 Mar 2014 10:49:43 -0600 -Subject: [PATCH 058/182] spmi: pmic_arb: make selectable on ARCH_QCOM - -With the split of Qualcomm MSM support into legacy and multiplatform, -the SPMI PMIC arb driver is only relevant on the multiplatform supported -SoCs. Switch the Kconfig depends to ARCH_QCOM. - -Acked-by: Kumar Gala -Signed-off-by: Josh Cartwright -Signed-off-by: Greg Kroah-Hartman ---- - drivers/spmi/Kconfig | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/spmi/Kconfig -+++ b/drivers/spmi/Kconfig -@@ -14,8 +14,8 @@ config SPMI_MSM_PMIC_ARB - tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)" - depends on ARM - depends on IRQ_DOMAIN -- depends on ARCH_MSM || COMPILE_TEST -- default ARCH_MSM -+ depends on ARCH_QCOM || COMPILE_TEST -+ default ARCH_QCOM - help - If you say yes to this option, support will be included for the - built-in SPMI PMIC Arbiter interface on Qualcomm MSM family diff --git a/target/linux/ipq806x/patches/0059-spmi-pm-drop-bus-level-PM-suspend-resume-routines.patch b/target/linux/ipq806x/patches/0059-spmi-pm-drop-bus-level-PM-suspend-resume-routines.patch deleted file mode 100644 index b8bb48cb4e..0000000000 --- a/target/linux/ipq806x/patches/0059-spmi-pm-drop-bus-level-PM-suspend-resume-routines.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 9d13f01e2ec45253adaae1a330cdc4eb881c7377 Mon Sep 17 00:00:00 2001 -From: Josh Cartwright -Date: Mon, 3 Mar 2014 10:49:44 -0600 -Subject: [PATCH 059/182] spmi: pm: drop bus-level PM suspend/resume routines - -SPMI defines the behavior of a device in the "SLEEP" state as being -"user-defined or specified by the device manufacturer". Without -clearly-defined bus-level semantics for low-power states, push the -responsibility of transitioning a device into/out of "SLEEP" into SPMI -device drivers. - -Cc: Felipe Balbi -Signed-off-by: Josh Cartwright -Signed-off-by: Greg Kroah-Hartman ---- - drivers/spmi/spmi.c | 35 ----------------------------------- - 1 file changed, 35 deletions(-) - ---- a/drivers/spmi/spmi.c -+++ b/drivers/spmi/spmi.c -@@ -46,40 +46,6 @@ static const struct device_type spmi_ctr - .release = spmi_ctrl_release, - }; - --#ifdef CONFIG_PM_RUNTIME --static int spmi_runtime_suspend(struct device *dev) --{ -- struct spmi_device *sdev = to_spmi_device(dev); -- int err; -- -- err = pm_generic_runtime_suspend(dev); -- if (err) -- return err; -- -- return spmi_command_sleep(sdev); --} -- --static int spmi_runtime_resume(struct device *dev) --{ -- struct spmi_device *sdev = to_spmi_device(dev); -- int err; -- -- err = spmi_command_wakeup(sdev); -- if (err) -- return err; -- -- return pm_generic_runtime_resume(dev); --} --#endif -- --static const struct dev_pm_ops spmi_pm_ops = { -- SET_RUNTIME_PM_OPS( -- spmi_runtime_suspend, -- spmi_runtime_resume, -- NULL -- ) --}; -- - static int spmi_device_match(struct device *dev, struct device_driver *drv) - { - if (of_driver_match_device(dev, drv)) -@@ -391,7 +357,6 @@ static int spmi_drv_remove(struct device - static struct bus_type spmi_bus_type = { - .name = "spmi", - .match = spmi_device_match, -- .pm = &spmi_pm_ops, - .probe = spmi_drv_probe, - .remove = spmi_drv_remove, - }; diff --git a/target/linux/ipq806x/patches/0060-i2c-qup-New-bus-driver-for-the-Qualcomm-QUP-I2C-cont.patch b/target/linux/ipq806x/patches/0060-i2c-qup-New-bus-driver-for-the-Qualcomm-QUP-I2C-cont.patch deleted file mode 100644 index c96fc154e1..0000000000 --- a/target/linux/ipq806x/patches/0060-i2c-qup-New-bus-driver-for-the-Qualcomm-QUP-I2C-cont.patch +++ /dev/null @@ -1,825 +0,0 @@ -From 226eff10dc11af5d6b1bc31e5cedc079aa564fb3 Mon Sep 17 00:00:00 2001 -From: Bjorn Andersson -Date: Thu, 13 Mar 2014 19:07:43 -0700 -Subject: [PATCH 060/182] i2c: qup: New bus driver for the Qualcomm QUP I2C - controller - -This bus driver supports the QUP i2c hardware controller in the Qualcomm SOCs. -The Qualcomm Universal Peripheral Engine (QUP) is a general purpose data path -engine with input/output FIFOs and an embedded i2c mini-core. The driver -supports FIFO mode (for low bandwidth applications) and block mode (interrupt -generated for each block-size data transfer). - -Signed-off-by: Ivan T. Ivanov -Signed-off-by: Bjorn Andersson -Reviewed-by: Andy Gross -Tested-by: Philip Elcan -[wsa: removed needless IS_ERR_VALUE] -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/Kconfig | 10 + - drivers/i2c/busses/Makefile | 1 + - drivers/i2c/busses/i2c-qup.c | 768 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 779 insertions(+) - create mode 100644 drivers/i2c/busses/i2c-qup.c - ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -649,6 +649,16 @@ config I2C_PXA_SLAVE - is necessary for systems where the PXA may be a target on the - I2C bus. - -+config I2C_QUP -+ tristate "Qualcomm QUP based I2C controller" -+ depends on ARCH_QCOM -+ help -+ If you say yes to this option, support will be included for the -+ built-in I2C interface on the Qualcomm SoCs. -+ -+ This driver can also be built as a module. If so, the module -+ will be called i2c-qup. -+ - config I2C_RIIC - tristate "Renesas RIIC adapter" - depends on ARCH_SHMOBILE || COMPILE_TEST ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -63,6 +63,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o - obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o - obj-$(CONFIG_I2C_PXA) += i2c-pxa.o - obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o -+obj-$(CONFIG_I2C_QUP) += i2c-qup.o - obj-$(CONFIG_I2C_RIIC) += i2c-riic.o - obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o - obj-$(CONFIG_I2C_S6000) += i2c-s6000.o ---- /dev/null -+++ b/drivers/i2c/busses/i2c-qup.c -@@ -0,0 +1,768 @@ -+/* -+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2014, Sony Mobile Communications AB. -+ * -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* QUP Registers */ -+#define QUP_CONFIG 0x000 -+#define QUP_STATE 0x004 -+#define QUP_IO_MODE 0x008 -+#define QUP_SW_RESET 0x00c -+#define QUP_OPERATIONAL 0x018 -+#define QUP_ERROR_FLAGS 0x01c -+#define QUP_ERROR_FLAGS_EN 0x020 -+#define QUP_HW_VERSION 0x030 -+#define QUP_MX_OUTPUT_CNT 0x100 -+#define QUP_OUT_FIFO_BASE 0x110 -+#define QUP_MX_WRITE_CNT 0x150 -+#define QUP_MX_INPUT_CNT 0x200 -+#define QUP_MX_READ_CNT 0x208 -+#define QUP_IN_FIFO_BASE 0x218 -+#define QUP_I2C_CLK_CTL 0x400 -+#define QUP_I2C_STATUS 0x404 -+ -+/* QUP States and reset values */ -+#define QUP_RESET_STATE 0 -+#define QUP_RUN_STATE 1 -+#define QUP_PAUSE_STATE 3 -+#define QUP_STATE_MASK 3 -+ -+#define QUP_STATE_VALID BIT(2) -+#define QUP_I2C_MAST_GEN BIT(4) -+ -+#define QUP_OPERATIONAL_RESET 0x000ff0 -+#define QUP_I2C_STATUS_RESET 0xfffffc -+ -+/* QUP OPERATIONAL FLAGS */ -+#define QUP_I2C_NACK_FLAG BIT(3) -+#define QUP_OUT_NOT_EMPTY BIT(4) -+#define QUP_IN_NOT_EMPTY BIT(5) -+#define QUP_OUT_FULL BIT(6) -+#define QUP_OUT_SVC_FLAG BIT(8) -+#define QUP_IN_SVC_FLAG BIT(9) -+#define QUP_MX_OUTPUT_DONE BIT(10) -+#define QUP_MX_INPUT_DONE BIT(11) -+ -+/* I2C mini core related values */ -+#define QUP_CLOCK_AUTO_GATE BIT(13) -+#define I2C_MINI_CORE (2 << 8) -+#define I2C_N_VAL 15 -+/* Most significant word offset in FIFO port */ -+#define QUP_MSW_SHIFT (I2C_N_VAL + 1) -+ -+/* Packing/Unpacking words in FIFOs, and IO modes */ -+#define QUP_OUTPUT_BLK_MODE (1 << 10) -+#define QUP_INPUT_BLK_MODE (1 << 12) -+#define QUP_UNPACK_EN BIT(14) -+#define QUP_PACK_EN BIT(15) -+ -+#define QUP_REPACK_EN (QUP_UNPACK_EN | QUP_PACK_EN) -+ -+#define QUP_OUTPUT_BLOCK_SIZE(x)(((x) >> 0) & 0x03) -+#define QUP_OUTPUT_FIFO_SIZE(x) (((x) >> 2) & 0x07) -+#define QUP_INPUT_BLOCK_SIZE(x) (((x) >> 5) & 0x03) -+#define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07) -+ -+/* QUP tags */ -+#define QUP_TAG_START (1 << 8) -+#define QUP_TAG_DATA (2 << 8) -+#define QUP_TAG_STOP (3 << 8) -+#define QUP_TAG_REC (4 << 8) -+ -+/* Status, Error flags */ -+#define I2C_STATUS_WR_BUFFER_FULL BIT(0) -+#define I2C_STATUS_BUS_ACTIVE BIT(8) -+#define I2C_STATUS_ERROR_MASK 0x38000fc -+#define QUP_STATUS_ERROR_FLAGS 0x7c -+ -+#define QUP_READ_LIMIT 256 -+ -+struct qup_i2c_dev { -+ struct device *dev; -+ void __iomem *base; -+ int irq; -+ struct clk *clk; -+ struct clk *pclk; -+ struct i2c_adapter adap; -+ -+ int clk_ctl; -+ int out_fifo_sz; -+ int in_fifo_sz; -+ int out_blk_sz; -+ int in_blk_sz; -+ -+ unsigned long one_byte_t; -+ -+ struct i2c_msg *msg; -+ /* Current posion in user message buffer */ -+ int pos; -+ /* I2C protocol errors */ -+ u32 bus_err; -+ /* QUP core errors */ -+ u32 qup_err; -+ -+ struct completion xfer; -+}; -+ -+static irqreturn_t qup_i2c_interrupt(int irq, void *dev) -+{ -+ struct qup_i2c_dev *qup = dev; -+ u32 bus_err; -+ u32 qup_err; -+ u32 opflags; -+ -+ bus_err = readl(qup->base + QUP_I2C_STATUS); -+ qup_err = readl(qup->base + QUP_ERROR_FLAGS); -+ opflags = readl(qup->base + QUP_OPERATIONAL); -+ -+ if (!qup->msg) { -+ /* Clear Error interrupt */ -+ writel(QUP_RESET_STATE, qup->base + QUP_STATE); -+ return IRQ_HANDLED; -+ } -+ -+ bus_err &= I2C_STATUS_ERROR_MASK; -+ qup_err &= QUP_STATUS_ERROR_FLAGS; -+ -+ if (qup_err) { -+ /* Clear Error interrupt */ -+ writel(qup_err, qup->base + QUP_ERROR_FLAGS); -+ goto done; -+ } -+ -+ if (bus_err) { -+ /* Clear Error interrupt */ -+ writel(QUP_RESET_STATE, qup->base + QUP_STATE); -+ goto done; -+ } -+ -+ if (opflags & QUP_IN_SVC_FLAG) -+ writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL); -+ -+ if (opflags & QUP_OUT_SVC_FLAG) -+ writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL); -+ -+done: -+ qup->qup_err = qup_err; -+ qup->bus_err = bus_err; -+ complete(&qup->xfer); -+ return IRQ_HANDLED; -+} -+ -+static int qup_i2c_poll_state_mask(struct qup_i2c_dev *qup, -+ u32 req_state, u32 req_mask) -+{ -+ int retries = 1; -+ u32 state; -+ -+ /* -+ * State transition takes 3 AHB clocks cycles + 3 I2C master clock -+ * cycles. So retry once after a 1uS delay. -+ */ -+ do { -+ state = readl(qup->base + QUP_STATE); -+ -+ if (state & QUP_STATE_VALID && -+ (state & req_mask) == req_state) -+ return 0; -+ -+ udelay(1); -+ } while (retries--); -+ -+ return -ETIMEDOUT; -+} -+ -+static int qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state) -+{ -+ return qup_i2c_poll_state_mask(qup, req_state, QUP_STATE_MASK); -+} -+ -+static int qup_i2c_poll_state_valid(struct qup_i2c_dev *qup) -+{ -+ return qup_i2c_poll_state_mask(qup, 0, 0); -+} -+ -+static int qup_i2c_poll_state_i2c_master(struct qup_i2c_dev *qup) -+{ -+ return qup_i2c_poll_state_mask(qup, QUP_I2C_MAST_GEN, QUP_I2C_MAST_GEN); -+} -+ -+static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state) -+{ -+ if (qup_i2c_poll_state_valid(qup) != 0) -+ return -EIO; -+ -+ writel(state, qup->base + QUP_STATE); -+ -+ if (qup_i2c_poll_state(qup, state) != 0) -+ return -EIO; -+ return 0; -+} -+ -+static int qup_i2c_wait_writeready(struct qup_i2c_dev *qup) -+{ -+ unsigned long timeout; -+ u32 opflags; -+ u32 status; -+ -+ timeout = jiffies + HZ; -+ -+ for (;;) { -+ opflags = readl(qup->base + QUP_OPERATIONAL); -+ status = readl(qup->base + QUP_I2C_STATUS); -+ -+ if (!(opflags & QUP_OUT_NOT_EMPTY) && -+ !(status & I2C_STATUS_BUS_ACTIVE)) -+ return 0; -+ -+ if (time_after(jiffies, timeout)) -+ return -ETIMEDOUT; -+ -+ usleep_range(qup->one_byte_t, qup->one_byte_t * 2); -+ } -+} -+ -+static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg) -+{ -+ /* Number of entries to shift out, including the start */ -+ int total = msg->len + 1; -+ -+ if (total < qup->out_fifo_sz) { -+ /* FIFO mode */ -+ writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); -+ writel(total, qup->base + QUP_MX_WRITE_CNT); -+ } else { -+ /* BLOCK mode (transfer data on chunks) */ -+ writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN, -+ qup->base + QUP_IO_MODE); -+ writel(total, qup->base + QUP_MX_OUTPUT_CNT); -+ } -+} -+ -+static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg) -+{ -+ u32 addr = msg->addr << 1; -+ u32 qup_tag; -+ u32 opflags; -+ int idx; -+ u32 val; -+ -+ if (qup->pos == 0) { -+ val = QUP_TAG_START | addr; -+ idx = 1; -+ } else { -+ val = 0; -+ idx = 0; -+ } -+ -+ while (qup->pos < msg->len) { -+ /* Check that there's space in the FIFO for our pair */ -+ opflags = readl(qup->base + QUP_OPERATIONAL); -+ if (opflags & QUP_OUT_FULL) -+ break; -+ -+ if (qup->pos == msg->len - 1) -+ qup_tag = QUP_TAG_STOP; -+ else -+ qup_tag = QUP_TAG_DATA; -+ -+ if (idx & 1) -+ val |= (qup_tag | msg->buf[qup->pos]) << QUP_MSW_SHIFT; -+ else -+ val = qup_tag | msg->buf[qup->pos]; -+ -+ /* Write out the pair and the last odd value */ -+ if (idx & 1 || qup->pos == msg->len - 1) -+ writel(val, qup->base + QUP_OUT_FIFO_BASE); -+ -+ qup->pos++; -+ idx++; -+ } -+} -+ -+static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) -+{ -+ unsigned long left; -+ int ret; -+ -+ qup->msg = msg; -+ qup->pos = 0; -+ -+ enable_irq(qup->irq); -+ -+ qup_i2c_set_write_mode(qup, msg); -+ -+ ret = qup_i2c_change_state(qup, QUP_RUN_STATE); -+ if (ret) -+ goto err; -+ -+ writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); -+ -+ do { -+ ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); -+ if (ret) -+ goto err; -+ -+ qup_i2c_issue_write(qup, msg); -+ -+ ret = qup_i2c_change_state(qup, QUP_RUN_STATE); -+ if (ret) -+ goto err; -+ -+ left = wait_for_completion_timeout(&qup->xfer, HZ); -+ if (!left) { -+ writel(1, qup->base + QUP_SW_RESET); -+ ret = -ETIMEDOUT; -+ goto err; -+ } -+ -+ if (qup->bus_err || qup->qup_err) { -+ if (qup->bus_err & QUP_I2C_NACK_FLAG) -+ dev_err(qup->dev, "NACK from %x\n", msg->addr); -+ ret = -EIO; -+ goto err; -+ } -+ } while (qup->pos < msg->len); -+ -+ /* Wait for the outstanding data in the fifo to drain */ -+ ret = qup_i2c_wait_writeready(qup); -+ -+err: -+ disable_irq(qup->irq); -+ qup->msg = NULL; -+ -+ return ret; -+} -+ -+static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len) -+{ -+ if (len < qup->in_fifo_sz) { -+ /* FIFO mode */ -+ writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); -+ writel(len, qup->base + QUP_MX_READ_CNT); -+ } else { -+ /* BLOCK mode (transfer data on chunks) */ -+ writel(QUP_INPUT_BLK_MODE | QUP_REPACK_EN, -+ qup->base + QUP_IO_MODE); -+ writel(len, qup->base + QUP_MX_INPUT_CNT); -+ } -+} -+ -+static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg) -+{ -+ u32 addr, len, val; -+ -+ addr = (msg->addr << 1) | 1; -+ -+ /* 0 is used to specify a length 256 (QUP_READ_LIMIT) */ -+ len = (msg->len == QUP_READ_LIMIT) ? 0 : msg->len; -+ -+ val = ((QUP_TAG_REC | len) << QUP_MSW_SHIFT) | QUP_TAG_START | addr; -+ writel(val, qup->base + QUP_OUT_FIFO_BASE); -+} -+ -+ -+static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg) -+{ -+ u32 opflags; -+ u32 val = 0; -+ int idx; -+ -+ for (idx = 0; qup->pos < msg->len; idx++) { -+ if ((idx & 1) == 0) { -+ /* Check that FIFO have data */ -+ opflags = readl(qup->base + QUP_OPERATIONAL); -+ if (!(opflags & QUP_IN_NOT_EMPTY)) -+ break; -+ -+ /* Reading 2 words at time */ -+ val = readl(qup->base + QUP_IN_FIFO_BASE); -+ -+ msg->buf[qup->pos++] = val & 0xFF; -+ } else { -+ msg->buf[qup->pos++] = val >> QUP_MSW_SHIFT; -+ } -+ } -+} -+ -+static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) -+{ -+ unsigned long left; -+ int ret; -+ -+ /* -+ * The QUP block will issue a NACK and STOP on the bus when reaching -+ * the end of the read, the length of the read is specified as one byte -+ * which limits the possible read to 256 (QUP_READ_LIMIT) bytes. -+ */ -+ if (msg->len > QUP_READ_LIMIT) { -+ dev_err(qup->dev, "HW not capable of reads over %d bytes\n", -+ QUP_READ_LIMIT); -+ return -EINVAL; -+ } -+ -+ qup->msg = msg; -+ qup->pos = 0; -+ -+ enable_irq(qup->irq); -+ -+ qup_i2c_set_read_mode(qup, msg->len); -+ -+ ret = qup_i2c_change_state(qup, QUP_RUN_STATE); -+ if (ret) -+ goto err; -+ -+ writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); -+ -+ ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); -+ if (ret) -+ goto err; -+ -+ qup_i2c_issue_read(qup, msg); -+ -+ ret = qup_i2c_change_state(qup, QUP_RUN_STATE); -+ if (ret) -+ goto err; -+ -+ do { -+ left = wait_for_completion_timeout(&qup->xfer, HZ); -+ if (!left) { -+ writel(1, qup->base + QUP_SW_RESET); -+ ret = -ETIMEDOUT; -+ goto err; -+ } -+ -+ if (qup->bus_err || qup->qup_err) { -+ if (qup->bus_err & QUP_I2C_NACK_FLAG) -+ dev_err(qup->dev, "NACK from %x\n", msg->addr); -+ ret = -EIO; -+ goto err; -+ } -+ -+ qup_i2c_read_fifo(qup, msg); -+ } while (qup->pos < msg->len); -+ -+err: -+ disable_irq(qup->irq); -+ qup->msg = NULL; -+ -+ return ret; -+} -+ -+static int qup_i2c_xfer(struct i2c_adapter *adap, -+ struct i2c_msg msgs[], -+ int num) -+{ -+ struct qup_i2c_dev *qup = i2c_get_adapdata(adap); -+ int ret, idx; -+ -+ ret = pm_runtime_get_sync(qup->dev); -+ if (ret) -+ goto out; -+ -+ writel(1, qup->base + QUP_SW_RESET); -+ ret = qup_i2c_poll_state(qup, QUP_RESET_STATE); -+ if (ret) -+ goto out; -+ -+ /* Configure QUP as I2C mini core */ -+ writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG); -+ -+ for (idx = 0; idx < num; idx++) { -+ if (msgs[idx].len == 0) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (qup_i2c_poll_state_i2c_master(qup)) { -+ ret = -EIO; -+ goto out; -+ } -+ -+ if (msgs[idx].flags & I2C_M_RD) -+ ret = qup_i2c_read_one(qup, &msgs[idx]); -+ else -+ ret = qup_i2c_write_one(qup, &msgs[idx]); -+ -+ if (ret) -+ break; -+ -+ ret = qup_i2c_change_state(qup, QUP_RESET_STATE); -+ if (ret) -+ break; -+ } -+ -+ if (ret == 0) -+ ret = num; -+out: -+ -+ pm_runtime_mark_last_busy(qup->dev); -+ pm_runtime_put_autosuspend(qup->dev); -+ -+ return ret; -+} -+ -+static u32 qup_i2c_func(struct i2c_adapter *adap) -+{ -+ return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); -+} -+ -+static const struct i2c_algorithm qup_i2c_algo = { -+ .master_xfer = qup_i2c_xfer, -+ .functionality = qup_i2c_func, -+}; -+ -+static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup) -+{ -+ clk_prepare_enable(qup->clk); -+ clk_prepare_enable(qup->pclk); -+} -+ -+static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) -+{ -+ u32 config; -+ -+ qup_i2c_change_state(qup, QUP_RESET_STATE); -+ clk_disable_unprepare(qup->clk); -+ config = readl(qup->base + QUP_CONFIG); -+ config |= QUP_CLOCK_AUTO_GATE; -+ writel(config, qup->base + QUP_CONFIG); -+ clk_disable_unprepare(qup->pclk); -+} -+ -+static int qup_i2c_probe(struct platform_device *pdev) -+{ -+ static const int blk_sizes[] = {4, 16, 32}; -+ struct device_node *node = pdev->dev.of_node; -+ struct qup_i2c_dev *qup; -+ unsigned long one_bit_t; -+ struct resource *res; -+ u32 io_mode, hw_ver, size; -+ int ret, fs_div, hs_div; -+ int src_clk_freq; -+ int clk_freq = 100000; -+ -+ qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL); -+ if (!qup) -+ return -ENOMEM; -+ -+ qup->dev = &pdev->dev; -+ init_completion(&qup->xfer); -+ platform_set_drvdata(pdev, qup); -+ -+ of_property_read_u32(node, "clock-frequency", &clk_freq); -+ -+ /* We support frequencies up to FAST Mode (400KHz) */ -+ if (!clk_freq || clk_freq > 400000) { -+ dev_err(qup->dev, "clock frequency not supported %d\n", -+ clk_freq); -+ return -EINVAL; -+ } -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ qup->base = devm_ioremap_resource(qup->dev, res); -+ if (IS_ERR(qup->base)) -+ return PTR_ERR(qup->base); -+ -+ qup->irq = platform_get_irq(pdev, 0); -+ if (qup->irq < 0) { -+ dev_err(qup->dev, "No IRQ defined\n"); -+ return qup->irq; -+ } -+ -+ qup->clk = devm_clk_get(qup->dev, "core"); -+ if (IS_ERR(qup->clk)) { -+ dev_err(qup->dev, "Could not get core clock\n"); -+ return PTR_ERR(qup->clk); -+ } -+ -+ qup->pclk = devm_clk_get(qup->dev, "iface"); -+ if (IS_ERR(qup->pclk)) { -+ dev_err(qup->dev, "Could not get iface clock\n"); -+ return PTR_ERR(qup->pclk); -+ } -+ -+ qup_i2c_enable_clocks(qup); -+ -+ /* -+ * Bootloaders might leave a pending interrupt on certain QUP's, -+ * so we reset the core before registering for interrupts. -+ */ -+ writel(1, qup->base + QUP_SW_RESET); -+ ret = qup_i2c_poll_state_valid(qup); -+ if (ret) -+ goto fail; -+ -+ ret = devm_request_irq(qup->dev, qup->irq, qup_i2c_interrupt, -+ IRQF_TRIGGER_HIGH, "i2c_qup", qup); -+ if (ret) { -+ dev_err(qup->dev, "Request %d IRQ failed\n", qup->irq); -+ goto fail; -+ } -+ disable_irq(qup->irq); -+ -+ hw_ver = readl(qup->base + QUP_HW_VERSION); -+ dev_dbg(qup->dev, "Revision %x\n", hw_ver); -+ -+ io_mode = readl(qup->base + QUP_IO_MODE); -+ -+ /* -+ * The block/fifo size w.r.t. 'actual data' is 1/2 due to 'tag' -+ * associated with each byte written/received -+ */ -+ size = QUP_OUTPUT_BLOCK_SIZE(io_mode); -+ if (size > ARRAY_SIZE(blk_sizes)) -+ return -EIO; -+ qup->out_blk_sz = blk_sizes[size] / 2; -+ -+ size = QUP_INPUT_BLOCK_SIZE(io_mode); -+ if (size > ARRAY_SIZE(blk_sizes)) -+ return -EIO; -+ qup->in_blk_sz = blk_sizes[size] / 2; -+ -+ size = QUP_OUTPUT_FIFO_SIZE(io_mode); -+ qup->out_fifo_sz = qup->out_blk_sz * (2 << size); -+ -+ size = QUP_INPUT_FIFO_SIZE(io_mode); -+ qup->in_fifo_sz = qup->in_blk_sz * (2 << size); -+ -+ src_clk_freq = clk_get_rate(qup->clk); -+ fs_div = ((src_clk_freq / clk_freq) / 2) - 3; -+ hs_div = 3; -+ qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff); -+ -+ /* -+ * Time it takes for a byte to be clocked out on the bus. -+ * Each byte takes 9 clock cycles (8 bits + 1 ack). -+ */ -+ one_bit_t = (USEC_PER_SEC / clk_freq) + 1; -+ qup->one_byte_t = one_bit_t * 9; -+ -+ dev_dbg(qup->dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", -+ qup->in_blk_sz, qup->in_fifo_sz, -+ qup->out_blk_sz, qup->out_fifo_sz); -+ -+ i2c_set_adapdata(&qup->adap, qup); -+ qup->adap.algo = &qup_i2c_algo; -+ qup->adap.dev.parent = qup->dev; -+ qup->adap.dev.of_node = pdev->dev.of_node; -+ strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name)); -+ -+ ret = i2c_add_adapter(&qup->adap); -+ if (ret) -+ goto fail; -+ -+ pm_runtime_set_autosuspend_delay(qup->dev, MSEC_PER_SEC); -+ pm_runtime_use_autosuspend(qup->dev); -+ pm_runtime_set_active(qup->dev); -+ pm_runtime_enable(qup->dev); -+ return 0; -+ -+fail: -+ qup_i2c_disable_clocks(qup); -+ return ret; -+} -+ -+static int qup_i2c_remove(struct platform_device *pdev) -+{ -+ struct qup_i2c_dev *qup = platform_get_drvdata(pdev); -+ -+ disable_irq(qup->irq); -+ qup_i2c_disable_clocks(qup); -+ i2c_del_adapter(&qup->adap); -+ pm_runtime_disable(qup->dev); -+ pm_runtime_set_suspended(qup->dev); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int qup_i2c_pm_suspend_runtime(struct device *device) -+{ -+ struct qup_i2c_dev *qup = dev_get_drvdata(device); -+ -+ dev_dbg(device, "pm_runtime: suspending...\n"); -+ qup_i2c_disable_clocks(qup); -+ return 0; -+} -+ -+static int qup_i2c_pm_resume_runtime(struct device *device) -+{ -+ struct qup_i2c_dev *qup = dev_get_drvdata(device); -+ -+ dev_dbg(device, "pm_runtime: resuming...\n"); -+ qup_i2c_enable_clocks(qup); -+ return 0; -+} -+#endif -+ -+#ifdef CONFIG_PM_SLEEP -+static int qup_i2c_suspend(struct device *device) -+{ -+ qup_i2c_pm_suspend_runtime(device); -+ return 0; -+} -+ -+static int qup_i2c_resume(struct device *device) -+{ -+ qup_i2c_pm_resume_runtime(device); -+ pm_runtime_mark_last_busy(device); -+ pm_request_autosuspend(device); -+ return 0; -+} -+#endif -+ -+static const struct dev_pm_ops qup_i2c_qup_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS( -+ qup_i2c_suspend, -+ qup_i2c_resume) -+ SET_RUNTIME_PM_OPS( -+ qup_i2c_pm_suspend_runtime, -+ qup_i2c_pm_resume_runtime, -+ NULL) -+}; -+ -+static const struct of_device_id qup_i2c_dt_match[] = { -+ { .compatible = "qcom,i2c-qup-v1.1.1" }, -+ { .compatible = "qcom,i2c-qup-v2.1.1" }, -+ { .compatible = "qcom,i2c-qup-v2.2.1" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, qup_i2c_dt_match); -+ -+static struct platform_driver qup_i2c_driver = { -+ .probe = qup_i2c_probe, -+ .remove = qup_i2c_remove, -+ .driver = { -+ .name = "i2c_qup", -+ .owner = THIS_MODULE, -+ .pm = &qup_i2c_qup_pm_ops, -+ .of_match_table = qup_i2c_dt_match, -+ }, -+}; -+ -+module_platform_driver(qup_i2c_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:i2c_qup"); diff --git a/target/linux/ipq806x/patches/0061-i2c-qup-Add-device-tree-bindings-information.patch b/target/linux/ipq806x/patches/0061-i2c-qup-Add-device-tree-bindings-information.patch deleted file mode 100644 index 2f9ee58f35..0000000000 --- a/target/linux/ipq806x/patches/0061-i2c-qup-Add-device-tree-bindings-information.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 81480a89c72d811376e9e040729721705b2a984d Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Thu, 13 Mar 2014 19:07:42 -0700 -Subject: [PATCH 061/182] i2c: qup: Add device tree bindings information - -The Qualcomm Universal Peripherial (QUP) wraps I2C mini-core and -provide input and output FIFO's for it. I2C controller can operate -as master with supported bus speeds of 100Kbps and 400Kbps. - -Signed-off-by: Ivan T. Ivanov -[bjorn: reformulated part of binding description - added version to compatible - cleaned up example] -Signed-off-by: Bjorn Andersson -Acked-by: Rob Herring -[wsa: removed the dummy child node which was a confusing example] -Signed-off-by: Wolfram Sang ---- - .../devicetree/bindings/i2c/qcom,i2c-qup.txt | 40 ++++++++++++++++++++ - 1 file changed, 40 insertions(+) - create mode 100644 Documentation/devicetree/bindings/i2c/qcom,i2c-qup.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-qup.txt -@@ -0,0 +1,40 @@ -+Qualcomm Universal Peripheral (QUP) I2C controller -+ -+Required properties: -+ - compatible: Should be: -+ * "qcom,i2c-qup-v1.1.1" for 8660, 8960 and 8064. -+ * "qcom,i2c-qup-v2.1.1" for 8974 v1. -+ * "qcom,i2c-qup-v2.2.1" for 8974 v2 and later. -+ - reg: Should contain QUP register address and length. -+ - interrupts: Should contain I2C interrupt. -+ -+ - clocks: A list of phandles + clock-specifiers, one for each entry in -+ clock-names. -+ - clock-names: Should contain: -+ * "core" for the core clock -+ * "iface" for the AHB clock -+ -+ - #address-cells: Should be <1> Address cells for i2c device address -+ - #size-cells: Should be <0> as i2c addresses have no size component -+ -+Optional properties: -+ - clock-frequency: Should specify the desired i2c bus clock frequency in Hz, -+ defaults to 100kHz if omitted. -+ -+Child nodes should conform to i2c bus binding. -+ -+Example: -+ -+ i2c@f9924000 { -+ compatible = "qcom,i2c-qup-v2.2.1"; -+ reg = <0xf9924000 0x1000>; -+ interrupts = <0 96 0>; -+ -+ clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; -+ clock-names = "core", "iface"; -+ -+ clock-frequency = <355000>; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; diff --git a/target/linux/ipq806x/patches/0062-i2c-qup-off-by-ones-in-qup_i2c_probe.patch b/target/linux/ipq806x/patches/0062-i2c-qup-off-by-ones-in-qup_i2c_probe.patch deleted file mode 100644 index 3feef669cf..0000000000 --- a/target/linux/ipq806x/patches/0062-i2c-qup-off-by-ones-in-qup_i2c_probe.patch +++ /dev/null @@ -1,31 +0,0 @@ -From aa50d1b0d81e4a9509f15894ec64013aa5190b59 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Thu, 3 Apr 2014 10:22:54 +0300 -Subject: [PATCH 062/182] i2c: qup: off by ones in qup_i2c_probe() - -These should ">= ARRAY_SIZE()" instead of "> ARRAY_SIZE()". - -Fixes: 10c5a8425968 ('i2c: qup: New bus driver for the Qualcomm QUP I2C controller') -Signed-off-by: Dan Carpenter -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-qup.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/i2c/busses/i2c-qup.c -+++ b/drivers/i2c/busses/i2c-qup.c -@@ -633,12 +633,12 @@ static int qup_i2c_probe(struct platform - * associated with each byte written/received - */ - size = QUP_OUTPUT_BLOCK_SIZE(io_mode); -- if (size > ARRAY_SIZE(blk_sizes)) -+ if (size >= ARRAY_SIZE(blk_sizes)) - return -EIO; - qup->out_blk_sz = blk_sizes[size] / 2; - - size = QUP_INPUT_BLOCK_SIZE(io_mode); -- if (size > ARRAY_SIZE(blk_sizes)) -+ if (size >= ARRAY_SIZE(blk_sizes)) - return -EIO; - qup->in_blk_sz = blk_sizes[size] / 2; - diff --git a/target/linux/ipq806x/patches/0063-i2c-qup-use-proper-type-fro-clk_freq.patch b/target/linux/ipq806x/patches/0063-i2c-qup-use-proper-type-fro-clk_freq.patch deleted file mode 100644 index 13ffab4c0c..0000000000 --- a/target/linux/ipq806x/patches/0063-i2c-qup-use-proper-type-fro-clk_freq.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 62bdf6c11c9120543ba4831f0226bf51db1d1fc0 Mon Sep 17 00:00:00 2001 -From: Wolfram Sang -Date: Thu, 3 Apr 2014 11:30:33 +0200 -Subject: [PATCH 063/182] i2c: qup: use proper type fro clk_freq - -It is used with of_property_read_u32(), so it should be u32. - -Signed-off-by: Wolfram Sang -Acked-by: Bjorn Andersson -Fixes: 10c5a8425968 ('i2c: qup: New bus driver for the Qualcomm QUP I2C controller') ---- - drivers/i2c/busses/i2c-qup.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/i2c/busses/i2c-qup.c -+++ b/drivers/i2c/busses/i2c-qup.c -@@ -562,7 +562,7 @@ static int qup_i2c_probe(struct platform - u32 io_mode, hw_ver, size; - int ret, fs_div, hs_div; - int src_clk_freq; -- int clk_freq = 100000; -+ u32 clk_freq = 100000; - - qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL); - if (!qup) diff --git a/target/linux/ipq806x/patches/0064-i2c-qup-Fix-pm_runtime_get_sync-usage.patch b/target/linux/ipq806x/patches/0064-i2c-qup-Fix-pm_runtime_get_sync-usage.patch deleted file mode 100644 index 497b57e623..0000000000 --- a/target/linux/ipq806x/patches/0064-i2c-qup-Fix-pm_runtime_get_sync-usage.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 82f2e53f207019c0d364d92515410be8dffd7524 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Fri, 2 May 2014 20:54:29 -0500 -Subject: [PATCH 064/182] i2c: qup: Fix pm_runtime_get_sync usage - -This patch corrects the error check on the call to pm_runtime_get_sync. - -Signed-off-by: Andy Gross -Reviewed-by: Ivan T. Ivanov -Acked-by: Bjorn Andersson -Signed-off-by: Wolfram Sang ---- - drivers/i2c/busses/i2c-qup.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/i2c/busses/i2c-qup.c -+++ b/drivers/i2c/busses/i2c-qup.c -@@ -479,7 +479,7 @@ static int qup_i2c_xfer(struct i2c_adapt - int ret, idx; - - ret = pm_runtime_get_sync(qup->dev); -- if (ret) -+ if (ret < 0) - goto out; - - writel(1, qup->base + QUP_SW_RESET); diff --git a/target/linux/ipq806x/patches/0065-spi-Add-Qualcomm-QUP-SPI-controller-support.patch b/target/linux/ipq806x/patches/0065-spi-Add-Qualcomm-QUP-SPI-controller-support.patch deleted file mode 100644 index 3c52f24674..0000000000 --- a/target/linux/ipq806x/patches/0065-spi-Add-Qualcomm-QUP-SPI-controller-support.patch +++ /dev/null @@ -1,897 +0,0 @@ -From 24884115a6029995dba2561b1ee810f28a34271a Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Thu, 13 Feb 2014 18:21:38 +0200 -Subject: [PATCH 065/182] spi: Add Qualcomm QUP SPI controller support - -Qualcomm Universal Peripheral (QUP) core is an AHB slave that -provides a common data path (an output FIFO and an input FIFO) -for serial peripheral interface (SPI) mini-core. SPI in master -mode supports up to 50MHz, up to four chip selects, programmable -data path from 4 bits to 32 bits and numerous protocol variants. - -Cc: Alok Chauhan -Cc: Gilad Avidov -Cc: Kiran Gunda -Cc: Sagar Dharia -Cc: dsneddon@codeaurora.org -Signed-off-by: Ivan T. Ivanov -Signed-off-by: Mark Brown ---- - drivers/spi/Kconfig | 13 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-qup.c | 837 +++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 851 insertions(+) - create mode 100644 drivers/spi/spi-qup.c - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -390,6 +390,19 @@ config SPI_RSPI - help - SPI driver for Renesas RSPI and QSPI blocks. - -+config SPI_QUP -+ tristate "Qualcomm SPI controller with QUP interface" -+ depends on ARCH_MSM_DT -+ help -+ Qualcomm Universal Peripheral (QUP) core is an AHB slave that -+ provides a common data path (an output FIFO and an input FIFO) -+ for serial peripheral interface (SPI) mini-core. SPI in master -+ mode supports up to 50MHz, up to four chip selects, programmable -+ data path from 4 bits to 32 bits and numerous protocol variants. -+ -+ This driver can also be built as a module. If so, the module -+ will be called spi_qup. -+ - config SPI_S3C24XX - tristate "Samsung S3C24XX series SPI" - depends on ARCH_S3C24XX ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -60,6 +60,7 @@ spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_ - spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o - obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o - obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o -+obj-$(CONFIG_SPI_QUP) += spi-qup.o - obj-$(CONFIG_SPI_RSPI) += spi-rspi.o - obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o - spi-s3c24xx-hw-y := spi-s3c24xx.o ---- /dev/null -+++ b/drivers/spi/spi-qup.c -@@ -0,0 +1,837 @@ -+/* -+ * Copyright (c) 2008-2014, The Linux foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License rev 2 and -+ * only rev 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define QUP_CONFIG 0x0000 -+#define QUP_STATE 0x0004 -+#define QUP_IO_M_MODES 0x0008 -+#define QUP_SW_RESET 0x000c -+#define QUP_OPERATIONAL 0x0018 -+#define QUP_ERROR_FLAGS 0x001c -+#define QUP_ERROR_FLAGS_EN 0x0020 -+#define QUP_OPERATIONAL_MASK 0x0028 -+#define QUP_HW_VERSION 0x0030 -+#define QUP_MX_OUTPUT_CNT 0x0100 -+#define QUP_OUTPUT_FIFO 0x0110 -+#define QUP_MX_WRITE_CNT 0x0150 -+#define QUP_MX_INPUT_CNT 0x0200 -+#define QUP_MX_READ_CNT 0x0208 -+#define QUP_INPUT_FIFO 0x0218 -+ -+#define SPI_CONFIG 0x0300 -+#define SPI_IO_CONTROL 0x0304 -+#define SPI_ERROR_FLAGS 0x0308 -+#define SPI_ERROR_FLAGS_EN 0x030c -+ -+/* QUP_CONFIG fields */ -+#define QUP_CONFIG_SPI_MODE (1 << 8) -+#define QUP_CONFIG_CLOCK_AUTO_GATE BIT(13) -+#define QUP_CONFIG_NO_INPUT BIT(7) -+#define QUP_CONFIG_NO_OUTPUT BIT(6) -+#define QUP_CONFIG_N 0x001f -+ -+/* QUP_STATE fields */ -+#define QUP_STATE_VALID BIT(2) -+#define QUP_STATE_RESET 0 -+#define QUP_STATE_RUN 1 -+#define QUP_STATE_PAUSE 3 -+#define QUP_STATE_MASK 3 -+#define QUP_STATE_CLEAR 2 -+ -+#define QUP_HW_VERSION_2_1_1 0x20010001 -+ -+/* QUP_IO_M_MODES fields */ -+#define QUP_IO_M_PACK_EN BIT(15) -+#define QUP_IO_M_UNPACK_EN BIT(14) -+#define QUP_IO_M_INPUT_MODE_MASK_SHIFT 12 -+#define QUP_IO_M_OUTPUT_MODE_MASK_SHIFT 10 -+#define QUP_IO_M_INPUT_MODE_MASK (3 << QUP_IO_M_INPUT_MODE_MASK_SHIFT) -+#define QUP_IO_M_OUTPUT_MODE_MASK (3 << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT) -+ -+#define QUP_IO_M_OUTPUT_BLOCK_SIZE(x) (((x) & (0x03 << 0)) >> 0) -+#define QUP_IO_M_OUTPUT_FIFO_SIZE(x) (((x) & (0x07 << 2)) >> 2) -+#define QUP_IO_M_INPUT_BLOCK_SIZE(x) (((x) & (0x03 << 5)) >> 5) -+#define QUP_IO_M_INPUT_FIFO_SIZE(x) (((x) & (0x07 << 7)) >> 7) -+ -+#define QUP_IO_M_MODE_FIFO 0 -+#define QUP_IO_M_MODE_BLOCK 1 -+#define QUP_IO_M_MODE_DMOV 2 -+#define QUP_IO_M_MODE_BAM 3 -+ -+/* QUP_OPERATIONAL fields */ -+#define QUP_OP_MAX_INPUT_DONE_FLAG BIT(11) -+#define QUP_OP_MAX_OUTPUT_DONE_FLAG BIT(10) -+#define QUP_OP_IN_SERVICE_FLAG BIT(9) -+#define QUP_OP_OUT_SERVICE_FLAG BIT(8) -+#define QUP_OP_IN_FIFO_FULL BIT(7) -+#define QUP_OP_OUT_FIFO_FULL BIT(6) -+#define QUP_OP_IN_FIFO_NOT_EMPTY BIT(5) -+#define QUP_OP_OUT_FIFO_NOT_EMPTY BIT(4) -+ -+/* QUP_ERROR_FLAGS and QUP_ERROR_FLAGS_EN fields */ -+#define QUP_ERROR_OUTPUT_OVER_RUN BIT(5) -+#define QUP_ERROR_INPUT_UNDER_RUN BIT(4) -+#define QUP_ERROR_OUTPUT_UNDER_RUN BIT(3) -+#define QUP_ERROR_INPUT_OVER_RUN BIT(2) -+ -+/* SPI_CONFIG fields */ -+#define SPI_CONFIG_HS_MODE BIT(10) -+#define SPI_CONFIG_INPUT_FIRST BIT(9) -+#define SPI_CONFIG_LOOPBACK BIT(8) -+ -+/* SPI_IO_CONTROL fields */ -+#define SPI_IO_C_FORCE_CS BIT(11) -+#define SPI_IO_C_CLK_IDLE_HIGH BIT(10) -+#define SPI_IO_C_MX_CS_MODE BIT(8) -+#define SPI_IO_C_CS_N_POLARITY_0 BIT(4) -+#define SPI_IO_C_CS_SELECT(x) (((x) & 3) << 2) -+#define SPI_IO_C_CS_SELECT_MASK 0x000c -+#define SPI_IO_C_TRISTATE_CS BIT(1) -+#define SPI_IO_C_NO_TRI_STATE BIT(0) -+ -+/* SPI_ERROR_FLAGS and SPI_ERROR_FLAGS_EN fields */ -+#define SPI_ERROR_CLK_OVER_RUN BIT(1) -+#define SPI_ERROR_CLK_UNDER_RUN BIT(0) -+ -+#define SPI_NUM_CHIPSELECTS 4 -+ -+/* high speed mode is when bus rate is greater then 26MHz */ -+#define SPI_HS_MIN_RATE 26000000 -+#define SPI_MAX_RATE 50000000 -+ -+#define SPI_DELAY_THRESHOLD 1 -+#define SPI_DELAY_RETRY 10 -+ -+struct spi_qup_device { -+ int select; -+ u16 mode; -+}; -+ -+struct spi_qup { -+ void __iomem *base; -+ struct device *dev; -+ struct clk *cclk; /* core clock */ -+ struct clk *iclk; /* interface clock */ -+ int irq; -+ u32 max_speed_hz; -+ spinlock_t lock; -+ -+ int in_fifo_sz; -+ int out_fifo_sz; -+ int in_blk_sz; -+ int out_blk_sz; -+ -+ struct spi_transfer *xfer; -+ struct completion done; -+ int error; -+ int w_size; /* bytes per SPI word */ -+ int tx_bytes; -+ int rx_bytes; -+}; -+ -+ -+static inline bool spi_qup_is_valid_state(struct spi_qup *controller) -+{ -+ u32 opstate = readl_relaxed(controller->base + QUP_STATE); -+ -+ return opstate & QUP_STATE_VALID; -+} -+ -+static int spi_qup_set_state(struct spi_qup *controller, u32 state) -+{ -+ unsigned long loop; -+ u32 cur_state; -+ -+ loop = 0; -+ while (!spi_qup_is_valid_state(controller)) { -+ -+ usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2); -+ -+ if (++loop > SPI_DELAY_RETRY) -+ return -EIO; -+ } -+ -+ if (loop) -+ dev_dbg(controller->dev, "invalid state for %ld,us %d\n", -+ loop, state); -+ -+ cur_state = readl_relaxed(controller->base + QUP_STATE); -+ /* -+ * Per spec: for PAUSE_STATE to RESET_STATE, two writes -+ * of (b10) are required -+ */ -+ if (((cur_state & QUP_STATE_MASK) == QUP_STATE_PAUSE) && -+ (state == QUP_STATE_RESET)) { -+ writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE); -+ writel_relaxed(QUP_STATE_CLEAR, controller->base + QUP_STATE); -+ } else { -+ cur_state &= ~QUP_STATE_MASK; -+ cur_state |= state; -+ writel_relaxed(cur_state, controller->base + QUP_STATE); -+ } -+ -+ loop = 0; -+ while (!spi_qup_is_valid_state(controller)) { -+ -+ usleep_range(SPI_DELAY_THRESHOLD, SPI_DELAY_THRESHOLD * 2); -+ -+ if (++loop > SPI_DELAY_RETRY) -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+ -+static void spi_qup_fifo_read(struct spi_qup *controller, -+ struct spi_transfer *xfer) -+{ -+ u8 *rx_buf = xfer->rx_buf; -+ u32 word, state; -+ int idx, shift, w_size; -+ -+ w_size = controller->w_size; -+ -+ while (controller->rx_bytes < xfer->len) { -+ -+ state = readl_relaxed(controller->base + QUP_OPERATIONAL); -+ if (0 == (state & QUP_OP_IN_FIFO_NOT_EMPTY)) -+ break; -+ -+ word = readl_relaxed(controller->base + QUP_INPUT_FIFO); -+ -+ if (!rx_buf) { -+ controller->rx_bytes += w_size; -+ continue; -+ } -+ -+ for (idx = 0; idx < w_size; idx++, controller->rx_bytes++) { -+ /* -+ * The data format depends on bytes per SPI word: -+ * 4 bytes: 0x12345678 -+ * 2 bytes: 0x00001234 -+ * 1 byte : 0x00000012 -+ */ -+ shift = BITS_PER_BYTE; -+ shift *= (w_size - idx - 1); -+ rx_buf[controller->rx_bytes] = word >> shift; -+ } -+ } -+} -+ -+static void spi_qup_fifo_write(struct spi_qup *controller, -+ struct spi_transfer *xfer) -+{ -+ const u8 *tx_buf = xfer->tx_buf; -+ u32 word, state, data; -+ int idx, w_size; -+ -+ w_size = controller->w_size; -+ -+ while (controller->tx_bytes < xfer->len) { -+ -+ state = readl_relaxed(controller->base + QUP_OPERATIONAL); -+ if (state & QUP_OP_OUT_FIFO_FULL) -+ break; -+ -+ word = 0; -+ for (idx = 0; idx < w_size; idx++, controller->tx_bytes++) { -+ -+ if (!tx_buf) { -+ controller->tx_bytes += w_size; -+ break; -+ } -+ -+ data = tx_buf[controller->tx_bytes]; -+ word |= data << (BITS_PER_BYTE * (3 - idx)); -+ } -+ -+ writel_relaxed(word, controller->base + QUP_OUTPUT_FIFO); -+ } -+} -+ -+static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) -+{ -+ struct spi_qup *controller = dev_id; -+ struct spi_transfer *xfer; -+ u32 opflags, qup_err, spi_err; -+ unsigned long flags; -+ int error = 0; -+ -+ spin_lock_irqsave(&controller->lock, flags); -+ xfer = controller->xfer; -+ controller->xfer = NULL; -+ spin_unlock_irqrestore(&controller->lock, flags); -+ -+ qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS); -+ spi_err = readl_relaxed(controller->base + SPI_ERROR_FLAGS); -+ opflags = readl_relaxed(controller->base + QUP_OPERATIONAL); -+ -+ writel_relaxed(qup_err, controller->base + QUP_ERROR_FLAGS); -+ writel_relaxed(spi_err, controller->base + SPI_ERROR_FLAGS); -+ writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); -+ -+ if (!xfer) { -+ dev_err_ratelimited(controller->dev, "unexpected irq %x08 %x08 %x08\n", -+ qup_err, spi_err, opflags); -+ return IRQ_HANDLED; -+ } -+ -+ if (qup_err) { -+ if (qup_err & QUP_ERROR_OUTPUT_OVER_RUN) -+ dev_warn(controller->dev, "OUTPUT_OVER_RUN\n"); -+ if (qup_err & QUP_ERROR_INPUT_UNDER_RUN) -+ dev_warn(controller->dev, "INPUT_UNDER_RUN\n"); -+ if (qup_err & QUP_ERROR_OUTPUT_UNDER_RUN) -+ dev_warn(controller->dev, "OUTPUT_UNDER_RUN\n"); -+ if (qup_err & QUP_ERROR_INPUT_OVER_RUN) -+ dev_warn(controller->dev, "INPUT_OVER_RUN\n"); -+ -+ error = -EIO; -+ } -+ -+ if (spi_err) { -+ if (spi_err & SPI_ERROR_CLK_OVER_RUN) -+ dev_warn(controller->dev, "CLK_OVER_RUN\n"); -+ if (spi_err & SPI_ERROR_CLK_UNDER_RUN) -+ dev_warn(controller->dev, "CLK_UNDER_RUN\n"); -+ -+ error = -EIO; -+ } -+ -+ if (opflags & QUP_OP_IN_SERVICE_FLAG) -+ spi_qup_fifo_read(controller, xfer); -+ -+ if (opflags & QUP_OP_OUT_SERVICE_FLAG) -+ spi_qup_fifo_write(controller, xfer); -+ -+ spin_lock_irqsave(&controller->lock, flags); -+ controller->error = error; -+ controller->xfer = xfer; -+ spin_unlock_irqrestore(&controller->lock, flags); -+ -+ if (controller->rx_bytes == xfer->len || error) -+ complete(&controller->done); -+ -+ return IRQ_HANDLED; -+} -+ -+ -+/* set clock freq ... bits per word */ -+static int spi_qup_io_config(struct spi_qup *controller, -+ struct spi_qup_device *chip, -+ struct spi_transfer *xfer) -+{ -+ u32 config, iomode, mode; -+ int ret, n_words, w_size; -+ -+ if (chip->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { -+ dev_err(controller->dev, "too big size for loopback %d > %d\n", -+ xfer->len, controller->in_fifo_sz); -+ return -EIO; -+ } -+ -+ ret = clk_set_rate(controller->cclk, xfer->speed_hz); -+ if (ret) { -+ dev_err(controller->dev, "fail to set frequency %d", -+ xfer->speed_hz); -+ return -EIO; -+ } -+ -+ if (spi_qup_set_state(controller, QUP_STATE_RESET)) { -+ dev_err(controller->dev, "cannot set RESET state\n"); -+ return -EIO; -+ } -+ -+ w_size = 4; -+ if (xfer->bits_per_word <= 8) -+ w_size = 1; -+ else if (xfer->bits_per_word <= 16) -+ w_size = 2; -+ -+ n_words = xfer->len / w_size; -+ controller->w_size = w_size; -+ -+ if (n_words <= controller->in_fifo_sz) { -+ mode = QUP_IO_M_MODE_FIFO; -+ writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT); -+ writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT); -+ /* must be zero for FIFO */ -+ writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT); -+ writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT); -+ } else { -+ mode = QUP_IO_M_MODE_BLOCK; -+ writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT); -+ writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT); -+ /* must be zero for BLOCK and BAM */ -+ writel_relaxed(0, controller->base + QUP_MX_READ_CNT); -+ writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT); -+ } -+ -+ iomode = readl_relaxed(controller->base + QUP_IO_M_MODES); -+ /* Set input and output transfer mode */ -+ iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK); -+ iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN); -+ iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT); -+ iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT); -+ -+ writel_relaxed(iomode, controller->base + QUP_IO_M_MODES); -+ -+ config = readl_relaxed(controller->base + SPI_CONFIG); -+ -+ if (chip->mode & SPI_LOOP) -+ config |= SPI_CONFIG_LOOPBACK; -+ else -+ config &= ~SPI_CONFIG_LOOPBACK; -+ -+ if (chip->mode & SPI_CPHA) -+ config &= ~SPI_CONFIG_INPUT_FIRST; -+ else -+ config |= SPI_CONFIG_INPUT_FIRST; -+ -+ /* -+ * HS_MODE improves signal stability for spi-clk high rates, -+ * but is invalid in loop back mode. -+ */ -+ if ((xfer->speed_hz >= SPI_HS_MIN_RATE) && !(chip->mode & SPI_LOOP)) -+ config |= SPI_CONFIG_HS_MODE; -+ else -+ config &= ~SPI_CONFIG_HS_MODE; -+ -+ writel_relaxed(config, controller->base + SPI_CONFIG); -+ -+ config = readl_relaxed(controller->base + QUP_CONFIG); -+ config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N); -+ config |= xfer->bits_per_word - 1; -+ config |= QUP_CONFIG_SPI_MODE; -+ writel_relaxed(config, controller->base + QUP_CONFIG); -+ -+ writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK); -+ return 0; -+} -+ -+static void spi_qup_set_cs(struct spi_device *spi, bool enable) -+{ -+ struct spi_qup *controller = spi_master_get_devdata(spi->master); -+ struct spi_qup_device *chip = spi_get_ctldata(spi); -+ -+ u32 iocontol, mask; -+ -+ iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL); -+ -+ /* Disable auto CS toggle and use manual */ -+ iocontol &= ~SPI_IO_C_MX_CS_MODE; -+ iocontol |= SPI_IO_C_FORCE_CS; -+ -+ iocontol &= ~SPI_IO_C_CS_SELECT_MASK; -+ iocontol |= SPI_IO_C_CS_SELECT(chip->select); -+ -+ mask = SPI_IO_C_CS_N_POLARITY_0 << chip->select; -+ -+ if (enable) -+ iocontol |= mask; -+ else -+ iocontol &= ~mask; -+ -+ writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL); -+} -+ -+static int spi_qup_transfer_one(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *xfer) -+{ -+ struct spi_qup *controller = spi_master_get_devdata(master); -+ struct spi_qup_device *chip = spi_get_ctldata(spi); -+ unsigned long timeout, flags; -+ int ret = -EIO; -+ -+ ret = spi_qup_io_config(controller, chip, xfer); -+ if (ret) -+ return ret; -+ -+ timeout = DIV_ROUND_UP(xfer->speed_hz, MSEC_PER_SEC); -+ timeout = DIV_ROUND_UP(xfer->len * 8, timeout); -+ timeout = 100 * msecs_to_jiffies(timeout); -+ -+ reinit_completion(&controller->done); -+ -+ spin_lock_irqsave(&controller->lock, flags); -+ controller->xfer = xfer; -+ controller->error = 0; -+ controller->rx_bytes = 0; -+ controller->tx_bytes = 0; -+ spin_unlock_irqrestore(&controller->lock, flags); -+ -+ if (spi_qup_set_state(controller, QUP_STATE_RUN)) { -+ dev_warn(controller->dev, "cannot set RUN state\n"); -+ goto exit; -+ } -+ -+ if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) { -+ dev_warn(controller->dev, "cannot set PAUSE state\n"); -+ goto exit; -+ } -+ -+ spi_qup_fifo_write(controller, xfer); -+ -+ if (spi_qup_set_state(controller, QUP_STATE_RUN)) { -+ dev_warn(controller->dev, "cannot set EXECUTE state\n"); -+ goto exit; -+ } -+ -+ if (!wait_for_completion_timeout(&controller->done, timeout)) -+ ret = -ETIMEDOUT; -+exit: -+ spi_qup_set_state(controller, QUP_STATE_RESET); -+ spin_lock_irqsave(&controller->lock, flags); -+ controller->xfer = NULL; -+ if (!ret) -+ ret = controller->error; -+ spin_unlock_irqrestore(&controller->lock, flags); -+ return ret; -+} -+ -+static int spi_qup_setup(struct spi_device *spi) -+{ -+ struct spi_qup *controller = spi_master_get_devdata(spi->master); -+ struct spi_qup_device *chip = spi_get_ctldata(spi); -+ -+ if (spi->chip_select >= spi->master->num_chipselect) { -+ dev_err(controller->dev, "invalid chip_select %d\n", -+ spi->chip_select); -+ return -EINVAL; -+ } -+ -+ if (spi->max_speed_hz > controller->max_speed_hz) { -+ dev_err(controller->dev, "invalid max_speed_hz %d\n", -+ spi->max_speed_hz); -+ return -EINVAL; -+ } -+ -+ if (!chip) { -+ /* First setup */ -+ chip = kzalloc(sizeof(*chip), GFP_KERNEL); -+ if (!chip) { -+ dev_err(controller->dev, "no memory for chip data\n"); -+ return -ENOMEM; -+ } -+ -+ chip->mode = spi->mode; -+ chip->select = spi->chip_select; -+ spi_set_ctldata(spi, chip); -+ } -+ -+ return 0; -+} -+ -+static void spi_qup_cleanup(struct spi_device *spi) -+{ -+ struct spi_qup_device *chip = spi_get_ctldata(spi); -+ -+ if (!chip) -+ return; -+ -+ spi_set_ctldata(spi, NULL); -+ kfree(chip); -+} -+ -+static int spi_qup_probe(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct clk *iclk, *cclk; -+ struct spi_qup *controller; -+ struct resource *res; -+ struct device *dev; -+ void __iomem *base; -+ u32 data, max_freq, iomode; -+ int ret, irq, size; -+ -+ dev = &pdev->dev; -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ irq = platform_get_irq(pdev, 0); -+ -+ if (irq < 0) -+ return irq; -+ -+ cclk = devm_clk_get(dev, "core"); -+ if (IS_ERR(cclk)) -+ return PTR_ERR(cclk); -+ -+ iclk = devm_clk_get(dev, "iface"); -+ if (IS_ERR(iclk)) -+ return PTR_ERR(iclk); -+ -+ /* This is optional parameter */ -+ if (of_property_read_u32(dev->of_node, "spi-max-frequency", &max_freq)) -+ max_freq = SPI_MAX_RATE; -+ -+ if (!max_freq || max_freq > SPI_MAX_RATE) { -+ dev_err(dev, "invalid clock frequency %d\n", max_freq); -+ return -ENXIO; -+ } -+ -+ ret = clk_prepare_enable(cclk); -+ if (ret) { -+ dev_err(dev, "cannot enable core clock\n"); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(iclk); -+ if (ret) { -+ clk_disable_unprepare(cclk); -+ dev_err(dev, "cannot enable iface clock\n"); -+ return ret; -+ } -+ -+ data = readl_relaxed(base + QUP_HW_VERSION); -+ -+ if (data < QUP_HW_VERSION_2_1_1) { -+ clk_disable_unprepare(cclk); -+ clk_disable_unprepare(iclk); -+ dev_err(dev, "v.%08x is not supported\n", data); -+ return -ENXIO; -+ } -+ -+ master = spi_alloc_master(dev, sizeof(struct spi_qup)); -+ if (!master) { -+ clk_disable_unprepare(cclk); -+ clk_disable_unprepare(iclk); -+ dev_err(dev, "cannot allocate master\n"); -+ return -ENOMEM; -+ } -+ -+ master->bus_num = pdev->id; -+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; -+ master->num_chipselect = SPI_NUM_CHIPSELECTS; -+ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); -+ master->setup = spi_qup_setup; -+ master->cleanup = spi_qup_cleanup; -+ master->set_cs = spi_qup_set_cs; -+ master->transfer_one = spi_qup_transfer_one; -+ master->dev.of_node = pdev->dev.of_node; -+ master->auto_runtime_pm = true; -+ -+ platform_set_drvdata(pdev, master); -+ -+ controller = spi_master_get_devdata(master); -+ -+ controller->dev = dev; -+ controller->base = base; -+ controller->iclk = iclk; -+ controller->cclk = cclk; -+ controller->irq = irq; -+ controller->max_speed_hz = max_freq; -+ -+ spin_lock_init(&controller->lock); -+ init_completion(&controller->done); -+ -+ iomode = readl_relaxed(base + QUP_IO_M_MODES); -+ -+ size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode); -+ if (size) -+ controller->out_blk_sz = size * 16; -+ else -+ controller->out_blk_sz = 4; -+ -+ size = QUP_IO_M_INPUT_BLOCK_SIZE(iomode); -+ if (size) -+ controller->in_blk_sz = size * 16; -+ else -+ controller->in_blk_sz = 4; -+ -+ size = QUP_IO_M_OUTPUT_FIFO_SIZE(iomode); -+ controller->out_fifo_sz = controller->out_blk_sz * (2 << size); -+ -+ size = QUP_IO_M_INPUT_FIFO_SIZE(iomode); -+ controller->in_fifo_sz = controller->in_blk_sz * (2 << size); -+ -+ dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", -+ data, controller->in_blk_sz, controller->in_fifo_sz, -+ controller->out_blk_sz, controller->out_fifo_sz); -+ -+ writel_relaxed(1, base + QUP_SW_RESET); -+ -+ ret = spi_qup_set_state(controller, QUP_STATE_RESET); -+ if (ret) { -+ dev_err(dev, "cannot set RESET state\n"); -+ goto error; -+ } -+ -+ writel_relaxed(0, base + QUP_OPERATIONAL); -+ writel_relaxed(0, base + QUP_IO_M_MODES); -+ writel_relaxed(0, base + QUP_OPERATIONAL_MASK); -+ writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN, -+ base + SPI_ERROR_FLAGS_EN); -+ -+ writel_relaxed(0, base + SPI_CONFIG); -+ writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL); -+ -+ ret = devm_request_irq(dev, irq, spi_qup_qup_irq, -+ IRQF_TRIGGER_HIGH, pdev->name, controller); -+ if (ret) -+ goto error; -+ -+ ret = devm_spi_register_master(dev, master); -+ if (ret) -+ goto error; -+ -+ pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); -+ pm_runtime_use_autosuspend(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ return 0; -+ -+error: -+ clk_disable_unprepare(cclk); -+ clk_disable_unprepare(iclk); -+ spi_master_put(master); -+ return ret; -+} -+ -+#ifdef CONFIG_PM_RUNTIME -+static int spi_qup_pm_suspend_runtime(struct device *device) -+{ -+ struct spi_master *master = dev_get_drvdata(device); -+ struct spi_qup *controller = spi_master_get_devdata(master); -+ u32 config; -+ -+ /* Enable clocks auto gaiting */ -+ config = readl(controller->base + QUP_CONFIG); -+ config |= QUP_CLOCK_AUTO_GATE; -+ writel_relaxed(config, controller->base + QUP_CONFIG); -+ return 0; -+} -+ -+static int spi_qup_pm_resume_runtime(struct device *device) -+{ -+ struct spi_master *master = dev_get_drvdata(device); -+ struct spi_qup *controller = spi_master_get_devdata(master); -+ u32 config; -+ -+ /* Disable clocks auto gaiting */ -+ config = readl_relaxed(controller->base + QUP_CONFIG); -+ config &= ~QUP_CLOCK_AUTO_GATE; -+ writel_relaxed(config, controller->base + QUP_CONFIG); -+ return 0; -+} -+#endif /* CONFIG_PM_RUNTIME */ -+ -+#ifdef CONFIG_PM_SLEEP -+static int spi_qup_suspend(struct device *device) -+{ -+ struct spi_master *master = dev_get_drvdata(device); -+ struct spi_qup *controller = spi_master_get_devdata(master); -+ int ret; -+ -+ ret = spi_master_suspend(master); -+ if (ret) -+ return ret; -+ -+ ret = spi_qup_set_state(controller, QUP_STATE_RESET); -+ if (ret) -+ return ret; -+ -+ clk_disable_unprepare(controller->cclk); -+ clk_disable_unprepare(controller->iclk); -+ return 0; -+} -+ -+static int spi_qup_resume(struct device *device) -+{ -+ struct spi_master *master = dev_get_drvdata(device); -+ struct spi_qup *controller = spi_master_get_devdata(master); -+ int ret; -+ -+ ret = clk_prepare_enable(controller->iclk); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(controller->cclk); -+ if (ret) -+ return ret; -+ -+ ret = spi_qup_set_state(controller, QUP_STATE_RESET); -+ if (ret) -+ return ret; -+ -+ return spi_master_resume(master); -+} -+#endif /* CONFIG_PM_SLEEP */ -+ -+static int spi_qup_remove(struct platform_device *pdev) -+{ -+ struct spi_master *master = dev_get_drvdata(&pdev->dev); -+ struct spi_qup *controller = spi_master_get_devdata(master); -+ int ret; -+ -+ ret = pm_runtime_get_sync(&pdev->dev); -+ if (ret) -+ return ret; -+ -+ ret = spi_qup_set_state(controller, QUP_STATE_RESET); -+ if (ret) -+ return ret; -+ -+ clk_disable_unprepare(controller->cclk); -+ clk_disable_unprepare(controller->iclk); -+ -+ pm_runtime_put_noidle(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ spi_master_put(master); -+ return 0; -+} -+ -+static struct of_device_id spi_qup_dt_match[] = { -+ { .compatible = "qcom,spi-qup-v2.1.1", }, -+ { .compatible = "qcom,spi-qup-v2.2.1", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, spi_qup_dt_match); -+ -+static const struct dev_pm_ops spi_qup_dev_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(spi_qup_suspend, spi_qup_resume) -+ SET_RUNTIME_PM_OPS(spi_qup_pm_suspend_runtime, -+ spi_qup_pm_resume_runtime, -+ NULL) -+}; -+ -+static struct platform_driver spi_qup_driver = { -+ .driver = { -+ .name = "spi_qup", -+ .owner = THIS_MODULE, -+ .pm = &spi_qup_dev_pm_ops, -+ .of_match_table = spi_qup_dt_match, -+ }, -+ .probe = spi_qup_probe, -+ .remove = spi_qup_remove, -+}; -+module_platform_driver(spi_qup_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_VERSION("0.4"); -+MODULE_ALIAS("platform:spi_qup"); diff --git a/target/linux/ipq806x/patches/0066-spi-qup-Add-device-tree-bindings-information.patch b/target/linux/ipq806x/patches/0066-spi-qup-Add-device-tree-bindings-information.patch deleted file mode 100644 index 079d59ff0a..0000000000 --- a/target/linux/ipq806x/patches/0066-spi-qup-Add-device-tree-bindings-information.patch +++ /dev/null @@ -1,105 +0,0 @@ -From a8e8c90a3cc81c6a7a44ff7fb18ceb71978c9155 Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Thu, 13 Feb 2014 18:21:23 +0200 -Subject: [PATCH 066/182] spi: qup: Add device tree bindings information - -The Qualcomm Universal Peripheral (QUP) core is an -AHB slave that provides a common data path (an output -FIFO and an input FIFO) for serial peripheral interface -(SPI) mini-core. - -Signed-off-by: Ivan T. Ivanov -Signed-off-by: Mark Brown ---- - .../devicetree/bindings/spi/qcom,spi-qup.txt | 85 ++++++++++++++++++++ - 1 file changed, 85 insertions(+) - create mode 100644 Documentation/devicetree/bindings/spi/qcom,spi-qup.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt -@@ -0,0 +1,85 @@ -+Qualcomm Universal Peripheral (QUP) Serial Peripheral Interface (SPI) -+ -+The QUP core is an AHB slave that provides a common data path (an output FIFO -+and an input FIFO) for serial peripheral interface (SPI) mini-core. -+ -+SPI in master mode supports up to 50MHz, up to four chip selects, programmable -+data path from 4 bits to 32 bits and numerous protocol variants. -+ -+Required properties: -+- compatible: Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1" -+- reg: Should contain base register location and length -+- interrupts: Interrupt number used by this controller -+ -+- clocks: Should contain the core clock and the AHB clock. -+- clock-names: Should be "core" for the core clock and "iface" for the -+ AHB clock. -+ -+- #address-cells: Number of cells required to define a chip select -+ address on the SPI bus. Should be set to 1. -+- #size-cells: Should be zero. -+ -+Optional properties: -+- spi-max-frequency: Specifies maximum SPI clock frequency, -+ Units - Hz. Definition as per -+ Documentation/devicetree/bindings/spi/spi-bus.txt -+ -+SPI slave nodes must be children of the SPI master node and can contain -+properties described in Documentation/devicetree/bindings/spi/spi-bus.txt -+ -+Example: -+ -+ spi_8: spi@f9964000 { /* BLSP2 QUP2 */ -+ -+ compatible = "qcom,spi-qup-v2"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0xf9964000 0x1000>; -+ interrupts = <0 102 0>; -+ spi-max-frequency = <19200000>; -+ -+ clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>; -+ clock-names = "core", "iface"; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi8_default>; -+ -+ device@0 { -+ compatible = "arm,pl022-dummy"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0>; /* Chip select 0 */ -+ spi-max-frequency = <19200000>; -+ spi-cpol; -+ }; -+ -+ device@1 { -+ compatible = "arm,pl022-dummy"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <1>; /* Chip select 1 */ -+ spi-max-frequency = <9600000>; -+ spi-cpha; -+ }; -+ -+ device@2 { -+ compatible = "arm,pl022-dummy"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <2>; /* Chip select 2 */ -+ spi-max-frequency = <19200000>; -+ spi-cpol; -+ spi-cpha; -+ }; -+ -+ device@3 { -+ compatible = "arm,pl022-dummy"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <3>; /* Chip select 3 */ -+ spi-max-frequency = <19200000>; -+ spi-cpol; -+ spi-cpha; -+ spi-cs-high; -+ }; -+ }; diff --git a/target/linux/ipq806x/patches/0067-spi-qup-Remove-spi_master_put-in-spi_qup_remove.patch b/target/linux/ipq806x/patches/0067-spi-qup-Remove-spi_master_put-in-spi_qup_remove.patch deleted file mode 100644 index 128eb23ddb..0000000000 --- a/target/linux/ipq806x/patches/0067-spi-qup-Remove-spi_master_put-in-spi_qup_remove.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c6a3f7bda60cfd78c2b05e8b2ec0fbf0d39da9ea Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Fri, 21 Feb 2014 09:33:16 +0800 -Subject: [PATCH 067/182] spi: qup: Remove spi_master_put in spi_qup_remove - -This driver uses devm_spi_register_master() so don't explicitly call -spi_master_put() in spi_qup_remove(). - -Signed-off-by: Axel Lin -Acked-by: Ivan T. Ivanov -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qup.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -802,7 +802,6 @@ static int spi_qup_remove(struct platfor - - pm_runtime_put_noidle(&pdev->dev); - pm_runtime_disable(&pdev->dev); -- spi_master_put(master); - return 0; - } - diff --git a/target/linux/ipq806x/patches/0068-spi-qup-Convert-ot-let-spi-core-handle-checking-tran.patch b/target/linux/ipq806x/patches/0068-spi-qup-Convert-ot-let-spi-core-handle-checking-tran.patch deleted file mode 100644 index 4b025b59fd..0000000000 --- a/target/linux/ipq806x/patches/0068-spi-qup-Convert-ot-let-spi-core-handle-checking-tran.patch +++ /dev/null @@ -1,64 +0,0 @@ -From a4b122f945c564e47a42a9665b484785e86648de Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Fri, 21 Feb 2014 09:34:16 +0800 -Subject: [PATCH 068/182] spi: qup: Convert ot let spi core handle checking - transfer speed - -Set master->max_speed_hz then spi core will handle checking transfer speed. -So we can remove the same checking in this driver. - -Also remove checking spi->chip_select in spi_qup_setup(), the checking is done -by spi core. - -Signed-off-by: Axel Lin -Acked-by: Ivan T. Ivanov -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qup.c | 15 +-------------- - 1 file changed, 1 insertion(+), 14 deletions(-) - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -134,7 +134,6 @@ struct spi_qup { - struct clk *cclk; /* core clock */ - struct clk *iclk; /* interface clock */ - int irq; -- u32 max_speed_hz; - spinlock_t lock; - - int in_fifo_sz; -@@ -517,18 +516,6 @@ static int spi_qup_setup(struct spi_devi - struct spi_qup *controller = spi_master_get_devdata(spi->master); - struct spi_qup_device *chip = spi_get_ctldata(spi); - -- if (spi->chip_select >= spi->master->num_chipselect) { -- dev_err(controller->dev, "invalid chip_select %d\n", -- spi->chip_select); -- return -EINVAL; -- } -- -- if (spi->max_speed_hz > controller->max_speed_hz) { -- dev_err(controller->dev, "invalid max_speed_hz %d\n", -- spi->max_speed_hz); -- return -EINVAL; -- } -- - if (!chip) { - /* First setup */ - chip = kzalloc(sizeof(*chip), GFP_KERNEL); -@@ -629,6 +616,7 @@ static int spi_qup_probe(struct platform - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; - master->num_chipselect = SPI_NUM_CHIPSELECTS; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); -+ master->max_speed_hz = max_freq; - master->setup = spi_qup_setup; - master->cleanup = spi_qup_cleanup; - master->set_cs = spi_qup_set_cs; -@@ -645,7 +633,6 @@ static int spi_qup_probe(struct platform - controller->iclk = iclk; - controller->cclk = cclk; - controller->irq = irq; -- controller->max_speed_hz = max_freq; - - spin_lock_init(&controller->lock); - init_completion(&controller->done); diff --git a/target/linux/ipq806x/patches/0069-spi-qup-Fix-build-error-due-to-a-typo.patch b/target/linux/ipq806x/patches/0069-spi-qup-Fix-build-error-due-to-a-typo.patch deleted file mode 100644 index 4209485d12..0000000000 --- a/target/linux/ipq806x/patches/0069-spi-qup-Fix-build-error-due-to-a-typo.patch +++ /dev/null @@ -1,43 +0,0 @@ -From df7444fdd808111f7df507b00d357b44d3259376 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Sun, 23 Feb 2014 13:27:16 +0800 -Subject: [PATCH 069/182] spi: qup: Fix build error due to a typo - -Fix below build error when CONFIG_PM_RUNTIME=y: - -C [M] drivers/spi/spi-qup.o -drivers/spi/spi-qup.c: In function 'spi_qup_pm_suspend_runtime': -drivers/spi/spi-qup.c:712:12: error: 'QUP_CLOCK_AUTO_GATE' undeclared (first use in this function) -drivers/spi/spi-qup.c:712:12: note: each undeclared identifier is reported only once for each function it appears in -drivers/spi/spi-qup.c: In function 'spi_qup_pm_resume_runtime': -drivers/spi/spi-qup.c:725:13: error: 'QUP_CLOCK_AUTO_GATE' undeclared (first use in this function) -make[2]: *** [drivers/spi/spi-qup.o] Error 1 -make[1]: *** [drivers/spi] Error 2 -make: *** [drivers] Error 2 - -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qup.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -709,7 +709,7 @@ static int spi_qup_pm_suspend_runtime(st - - /* Enable clocks auto gaiting */ - config = readl(controller->base + QUP_CONFIG); -- config |= QUP_CLOCK_AUTO_GATE; -+ config |= QUP_CONFIG_CLOCK_AUTO_GATE; - writel_relaxed(config, controller->base + QUP_CONFIG); - return 0; - } -@@ -722,7 +722,7 @@ static int spi_qup_pm_resume_runtime(str - - /* Disable clocks auto gaiting */ - config = readl_relaxed(controller->base + QUP_CONFIG); -- config &= ~QUP_CLOCK_AUTO_GATE; -+ config &= ~QUP_CONFIG_CLOCK_AUTO_GATE; - writel_relaxed(config, controller->base + QUP_CONFIG); - return 0; - } diff --git a/target/linux/ipq806x/patches/0070-spi-qup-Enable-driver-compilation-with-COMPILE_TEST.patch b/target/linux/ipq806x/patches/0070-spi-qup-Enable-driver-compilation-with-COMPILE_TEST.patch deleted file mode 100644 index 00589925c5..0000000000 --- a/target/linux/ipq806x/patches/0070-spi-qup-Enable-driver-compilation-with-COMPILE_TEST.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 4706cb5844e0f1a08ab25e103f6415fde5328ddc Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Sun, 23 Feb 2014 13:28:33 +0800 -Subject: [PATCH 070/182] spi: qup: Enable driver compilation with - COMPILE_TEST - -This helps increasing build testing coverage. - -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown ---- - drivers/spi/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -392,7 +392,7 @@ config SPI_RSPI - - config SPI_QUP - tristate "Qualcomm SPI controller with QUP interface" -- depends on ARCH_MSM_DT -+ depends on ARCH_MSM_DT || COMPILE_TEST - help - Qualcomm Universal Peripheral (QUP) core is an AHB slave that - provides a common data path (an output FIFO and an input FIFO) diff --git a/target/linux/ipq806x/patches/0071-spi-qup-Depend-on-ARM-COMPILE_TEST-to-avoid-build-er.patch b/target/linux/ipq806x/patches/0071-spi-qup-Depend-on-ARM-COMPILE_TEST-to-avoid-build-er.patch deleted file mode 100644 index 2711a2aa50..0000000000 --- a/target/linux/ipq806x/patches/0071-spi-qup-Depend-on-ARM-COMPILE_TEST-to-avoid-build-er.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 7137376bc6415ab9b2f0c5983245a1273812e8b9 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Mon, 24 Feb 2014 12:07:51 +0800 -Subject: [PATCH 071/182] spi: qup: Depend on ARM && COMPILE_TEST to avoid - build error - -This driver uses writel_relaxed() which does not exist in x86, ppc, etc. -Make it depend on ARM && COMPILE_TEST to avoid below build error: - - CC [M] drivers/spi/spi-qup.o -drivers/spi/spi-qup.c: In function 'spi_qup_set_state': -drivers/spi/spi-qup.c:180:3: error: implicit declaration of function 'writel_relaxed' [-Werror=implicit-function-declaration] -cc1: some warnings being treated as errors -make[2]: *** [drivers/spi/spi-qup.o] Error 1 -make[1]: *** [drivers/spi] Error 2 -make: *** [drivers] Error 2 - -Reported-by: Stephen Rothwell -Signed-off-by: Axel Lin -Signed-off-by: Mark Brown ---- - drivers/spi/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -392,7 +392,7 @@ config SPI_RSPI - - config SPI_QUP - tristate "Qualcomm SPI controller with QUP interface" -- depends on ARCH_MSM_DT || COMPILE_TEST -+ depends on ARCH_MSM_DT || (ARM && COMPILE_TEST) - help - Qualcomm Universal Peripheral (QUP) core is an AHB slave that - provides a common data path (an output FIFO and an input FIFO) diff --git a/target/linux/ipq806x/patches/0072-spi-qup-Remove-module-version.patch b/target/linux/ipq806x/patches/0072-spi-qup-Remove-module-version.patch deleted file mode 100644 index 6708238ce5..0000000000 --- a/target/linux/ipq806x/patches/0072-spi-qup-Remove-module-version.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 7b8e00404cfc652abbd538df1365a8046ed0d782 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Mon, 24 Feb 2014 13:48:12 +0800 -Subject: [PATCH 072/182] spi: qup: Remove module version - -The module version is unlikely to be updated, use kernel version should be -enough. - -Signed-off-by: Axel Lin -Acked-by: Ivan T. Ivanov -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qup.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -819,5 +819,4 @@ static struct platform_driver spi_qup_dr - module_platform_driver(spi_qup_driver); - - MODULE_LICENSE("GPL v2"); --MODULE_VERSION("0.4"); - MODULE_ALIAS("platform:spi_qup"); diff --git a/target/linux/ipq806x/patches/0073-spi-qup-Get-rid-of-using-struct-spi_qup_device.patch b/target/linux/ipq806x/patches/0073-spi-qup-Get-rid-of-using-struct-spi_qup_device.patch deleted file mode 100644 index b527af9bd2..0000000000 --- a/target/linux/ipq806x/patches/0073-spi-qup-Get-rid-of-using-struct-spi_qup_device.patch +++ /dev/null @@ -1,162 +0,0 @@ -From 3027505ab8c8cb17291e53bca1d7bd770539d468 Mon Sep 17 00:00:00 2001 -From: Axel Lin -Date: Mon, 24 Feb 2014 23:07:36 +0800 -Subject: [PATCH 073/182] spi: qup: Get rid of using struct spi_qup_device - -Current code uses struct spi_qup_device to store spi->mode and spi->chip_select -settings. We can get these settings in spi_qup_transfer_one and spi_qup_set_cs -without using struct spi_qup_device. Refactor the code a bit to remove -spi_qup_setup(), spi_qup_cleanup(), and struct spi_qup_device. - -Signed-off-by: Axel Lin -Tested-by: Ivan T. Ivanov -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qup.c | 61 ++++++++----------------------------------------- - 1 file changed, 9 insertions(+), 52 deletions(-) - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -123,11 +123,6 @@ - #define SPI_DELAY_THRESHOLD 1 - #define SPI_DELAY_RETRY 10 - --struct spi_qup_device { -- int select; -- u16 mode; --}; -- - struct spi_qup { - void __iomem *base; - struct device *dev; -@@ -338,14 +333,13 @@ static irqreturn_t spi_qup_qup_irq(int i - - - /* set clock freq ... bits per word */ --static int spi_qup_io_config(struct spi_qup *controller, -- struct spi_qup_device *chip, -- struct spi_transfer *xfer) -+static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) - { -+ struct spi_qup *controller = spi_master_get_devdata(spi->master); - u32 config, iomode, mode; - int ret, n_words, w_size; - -- if (chip->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { -+ if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { - dev_err(controller->dev, "too big size for loopback %d > %d\n", - xfer->len, controller->in_fifo_sz); - return -EIO; -@@ -399,12 +393,12 @@ static int spi_qup_io_config(struct spi_ - - config = readl_relaxed(controller->base + SPI_CONFIG); - -- if (chip->mode & SPI_LOOP) -+ if (spi->mode & SPI_LOOP) - config |= SPI_CONFIG_LOOPBACK; - else - config &= ~SPI_CONFIG_LOOPBACK; - -- if (chip->mode & SPI_CPHA) -+ if (spi->mode & SPI_CPHA) - config &= ~SPI_CONFIG_INPUT_FIRST; - else - config |= SPI_CONFIG_INPUT_FIRST; -@@ -413,7 +407,7 @@ static int spi_qup_io_config(struct spi_ - * HS_MODE improves signal stability for spi-clk high rates, - * but is invalid in loop back mode. - */ -- if ((xfer->speed_hz >= SPI_HS_MIN_RATE) && !(chip->mode & SPI_LOOP)) -+ if ((xfer->speed_hz >= SPI_HS_MIN_RATE) && !(spi->mode & SPI_LOOP)) - config |= SPI_CONFIG_HS_MODE; - else - config &= ~SPI_CONFIG_HS_MODE; -@@ -433,7 +427,6 @@ static int spi_qup_io_config(struct spi_ - static void spi_qup_set_cs(struct spi_device *spi, bool enable) - { - struct spi_qup *controller = spi_master_get_devdata(spi->master); -- struct spi_qup_device *chip = spi_get_ctldata(spi); - - u32 iocontol, mask; - -@@ -444,9 +437,9 @@ static void spi_qup_set_cs(struct spi_de - iocontol |= SPI_IO_C_FORCE_CS; - - iocontol &= ~SPI_IO_C_CS_SELECT_MASK; -- iocontol |= SPI_IO_C_CS_SELECT(chip->select); -+ iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select); - -- mask = SPI_IO_C_CS_N_POLARITY_0 << chip->select; -+ mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select; - - if (enable) - iocontol |= mask; -@@ -461,11 +454,10 @@ static int spi_qup_transfer_one(struct s - struct spi_transfer *xfer) - { - struct spi_qup *controller = spi_master_get_devdata(master); -- struct spi_qup_device *chip = spi_get_ctldata(spi); - unsigned long timeout, flags; - int ret = -EIO; - -- ret = spi_qup_io_config(controller, chip, xfer); -+ ret = spi_qup_io_config(spi, xfer); - if (ret) - return ret; - -@@ -511,38 +503,6 @@ exit: - return ret; - } - --static int spi_qup_setup(struct spi_device *spi) --{ -- struct spi_qup *controller = spi_master_get_devdata(spi->master); -- struct spi_qup_device *chip = spi_get_ctldata(spi); -- -- if (!chip) { -- /* First setup */ -- chip = kzalloc(sizeof(*chip), GFP_KERNEL); -- if (!chip) { -- dev_err(controller->dev, "no memory for chip data\n"); -- return -ENOMEM; -- } -- -- chip->mode = spi->mode; -- chip->select = spi->chip_select; -- spi_set_ctldata(spi, chip); -- } -- -- return 0; --} -- --static void spi_qup_cleanup(struct spi_device *spi) --{ -- struct spi_qup_device *chip = spi_get_ctldata(spi); -- -- if (!chip) -- return; -- -- spi_set_ctldata(spi, NULL); -- kfree(chip); --} -- - static int spi_qup_probe(struct platform_device *pdev) - { - struct spi_master *master; -@@ -561,7 +521,6 @@ static int spi_qup_probe(struct platform - return PTR_ERR(base); - - irq = platform_get_irq(pdev, 0); -- - if (irq < 0) - return irq; - -@@ -617,8 +576,6 @@ static int spi_qup_probe(struct platform - master->num_chipselect = SPI_NUM_CHIPSELECTS; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); - master->max_speed_hz = max_freq; -- master->setup = spi_qup_setup; -- master->cleanup = spi_qup_cleanup; - master->set_cs = spi_qup_set_cs; - master->transfer_one = spi_qup_transfer_one; - master->dev.of_node = pdev->dev.of_node; diff --git a/target/linux/ipq806x/patches/0074-spi-qup-Depend-on-ARCH_QCOM.patch b/target/linux/ipq806x/patches/0074-spi-qup-Depend-on-ARCH_QCOM.patch deleted file mode 100644 index 7b924f125a..0000000000 --- a/target/linux/ipq806x/patches/0074-spi-qup-Depend-on-ARCH_QCOM.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 5148138d2b879c7b024fa3865fb3980c6dc84fcc Mon Sep 17 00:00:00 2001 -From: Paul Bolle -Date: Mon, 7 Apr 2014 16:15:45 +0200 -Subject: [PATCH 074/182] spi: qup: Depend on ARCH_QCOM - -Commit 8fc1b0f87d9f ("ARM: qcom: Split Qualcomm support into legacy and -multiplatform") removed Kconfig symbol ARCH_MSM_DT. But that commit -left one (optional) dependency on ARCH_MSM_DT untouched. - -Three Kconfig symbols used to depend on ARCH_MSM_DT: ARCH_MSM8X60, -ARCH_MSM8960, and ARCH_MSM8974. These three symbols now depend on -ARCH_QCOM. So it appears this driver needs to depend on ARCH_QCOM too. - -Signed-off-by: Paul Bolle -Reviewed-by: Stephen Boyd -Signed-off-by: Mark Brown ---- - drivers/spi/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -392,7 +392,7 @@ config SPI_RSPI - - config SPI_QUP - tristate "Qualcomm SPI controller with QUP interface" -- depends on ARCH_MSM_DT || (ARM && COMPILE_TEST) -+ depends on ARCH_QCOM || (ARM && COMPILE_TEST) - help - Qualcomm Universal Peripheral (QUP) core is an AHB slave that - provides a common data path (an output FIFO and an input FIFO) diff --git a/target/linux/ipq806x/patches/0075-spi-qup-Correct-selection-of-FIFO-Block-mode.patch b/target/linux/ipq806x/patches/0075-spi-qup-Correct-selection-of-FIFO-Block-mode.patch deleted file mode 100644 index 0fd095a9b6..0000000000 --- a/target/linux/ipq806x/patches/0075-spi-qup-Correct-selection-of-FIFO-Block-mode.patch +++ /dev/null @@ -1,34 +0,0 @@ -From e8e77359524e6629bac68db4183694fccffaed8e Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Tue, 13 May 2014 16:34:42 -0500 -Subject: [PATCH 075/182] spi: qup: Correct selection of FIFO/Block mode - -This patch fixes the calculation for determining whether to use FIFO or BLOCK -mode. - -Signed-off-by: Andy Gross -Signed-off-by: Mark Brown ---- - drivers/spi/spi-qup.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -287,7 +287,7 @@ static irqreturn_t spi_qup_qup_irq(int i - writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); - - if (!xfer) { -- dev_err_ratelimited(controller->dev, "unexpected irq %x08 %x08 %x08\n", -+ dev_err_ratelimited(controller->dev, "unexpected irq %08x %08x %08x\n", - qup_err, spi_err, opflags); - return IRQ_HANDLED; - } -@@ -366,7 +366,7 @@ static int spi_qup_io_config(struct spi_ - n_words = xfer->len / w_size; - controller->w_size = w_size; - -- if (n_words <= controller->in_fifo_sz) { -+ if (n_words <= (controller->in_fifo_sz / sizeof(u32))) { - mode = QUP_IO_M_MODE_FIFO; - writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT); - writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT); diff --git a/target/linux/ipq806x/patches/0078-clk-qcom-Consolidate-common-probe-code.patch b/target/linux/ipq806x/patches/0078-clk-qcom-Consolidate-common-probe-code.patch deleted file mode 100644 index 25b6ac2a38..0000000000 --- a/target/linux/ipq806x/patches/0078-clk-qcom-Consolidate-common-probe-code.patch +++ /dev/null @@ -1,734 +0,0 @@ -From d79cb0c583772f38a9367af106d61bcf8bfa08e4 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 21 Mar 2014 17:59:37 -0700 -Subject: [PATCH 078/182] clk: qcom: Consolidate common probe code - -Most of the probe code is the same between all the different -clock controllers. Consolidate the code into a common.c file. -This makes changes to the common probe parts easier and reduces -chances for bugs. - -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/common.c | 99 +++++++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/common.h | 34 ++++++++++++++ - drivers/clk/qcom/gcc-msm8660.c | 87 +++++----------------------------- - drivers/clk/qcom/gcc-msm8960.c | 77 +++++------------------------- - drivers/clk/qcom/gcc-msm8974.c | 77 +++++------------------------- - drivers/clk/qcom/mmcc-msm8960.c | 78 +++++------------------------- - drivers/clk/qcom/mmcc-msm8974.c | 80 +++++++------------------------ - 8 files changed, 196 insertions(+), 337 deletions(-) - create mode 100644 drivers/clk/qcom/common.c - create mode 100644 drivers/clk/qcom/common.h - ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -1,5 +1,6 @@ - obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o - -+clk-qcom-y += common.o - clk-qcom-y += clk-regmap.o - clk-qcom-y += clk-pll.o - clk-qcom-y += clk-rcg.o ---- /dev/null -+++ b/drivers/clk/qcom/common.c -@@ -0,0 +1,99 @@ -+/* -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "common.h" -+#include "clk-regmap.h" -+#include "reset.h" -+ -+struct qcom_cc { -+ struct qcom_reset_controller reset; -+ struct clk_onecell_data data; -+ struct clk *clks[]; -+}; -+ -+int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc) -+{ -+ void __iomem *base; -+ struct resource *res; -+ int i, ret; -+ struct device *dev = &pdev->dev; -+ struct clk *clk; -+ struct clk_onecell_data *data; -+ struct clk **clks; -+ struct regmap *regmap; -+ struct qcom_reset_controller *reset; -+ struct qcom_cc *cc; -+ size_t num_clks = desc->num_clks; -+ struct clk_regmap **rclks = desc->clks; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ regmap = devm_regmap_init_mmio(dev, base, desc->config); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, -+ GFP_KERNEL); -+ if (!cc) -+ return -ENOMEM; -+ -+ clks = cc->clks; -+ data = &cc->data; -+ data->clks = clks; -+ data->clk_num = num_clks; -+ -+ for (i = 0; i < num_clks; i++) { -+ if (!rclks[i]) -+ continue; -+ clk = devm_clk_register_regmap(dev, rclks[i]); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ clks[i] = clk; -+ } -+ -+ ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); -+ if (ret) -+ return ret; -+ -+ reset = &cc->reset; -+ reset->rcdev.of_node = dev->of_node; -+ reset->rcdev.ops = &qcom_reset_ops; -+ reset->rcdev.owner = dev->driver->owner; -+ reset->rcdev.nr_resets = desc->num_resets; -+ reset->regmap = regmap; -+ reset->reset_map = desc->resets; -+ platform_set_drvdata(pdev, &reset->rcdev); -+ -+ ret = reset_controller_register(&reset->rcdev); -+ if (ret) -+ of_clk_del_provider(dev->of_node); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(qcom_cc_probe); -+ -+void qcom_cc_remove(struct platform_device *pdev) -+{ -+ of_clk_del_provider(pdev->dev.of_node); -+ reset_controller_unregister(platform_get_drvdata(pdev)); -+} -+EXPORT_SYMBOL_GPL(qcom_cc_remove); ---- /dev/null -+++ b/drivers/clk/qcom/common.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#ifndef __QCOM_CLK_COMMON_H__ -+#define __QCOM_CLK_COMMON_H__ -+ -+struct platform_device; -+struct regmap_config; -+struct clk_regmap; -+struct qcom_reset_map; -+ -+struct qcom_cc_desc { -+ const struct regmap_config *config; -+ struct clk_regmap **clks; -+ size_t num_clks; -+ const struct qcom_reset_map *resets; -+ size_t num_resets; -+}; -+ -+extern int qcom_cc_probe(struct platform_device *pdev, -+ const struct qcom_cc_desc *desc); -+ -+extern void qcom_cc_remove(struct platform_device *pdev); -+ -+#endif ---- a/drivers/clk/qcom/gcc-msm8660.c -+++ b/drivers/clk/qcom/gcc-msm8660.c -@@ -25,6 +25,7 @@ - #include - #include - -+#include "common.h" - #include "clk-regmap.h" - #include "clk-pll.h" - #include "clk-rcg.h" -@@ -2701,94 +2702,28 @@ static const struct regmap_config gcc_ms - .fast_io = true, - }; - -+static const struct qcom_cc_desc gcc_msm8660_desc = { -+ .config = &gcc_msm8660_regmap_config, -+ .clks = gcc_msm8660_clks, -+ .num_clks = ARRAY_SIZE(gcc_msm8660_clks), -+ .resets = gcc_msm8660_resets, -+ .num_resets = ARRAY_SIZE(gcc_msm8660_resets), -+}; -+ - static const struct of_device_id gcc_msm8660_match_table[] = { - { .compatible = "qcom,gcc-msm8660" }, - { } - }; - MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table); - --struct qcom_cc { -- struct qcom_reset_controller reset; -- struct clk_onecell_data data; -- struct clk *clks[]; --}; -- - static int gcc_msm8660_probe(struct platform_device *pdev) - { -- void __iomem *base; -- struct resource *res; -- int i, ret; -- struct device *dev = &pdev->dev; -- struct clk *clk; -- struct clk_onecell_data *data; -- struct clk **clks; -- struct regmap *regmap; -- size_t num_clks; -- struct qcom_reset_controller *reset; -- struct qcom_cc *cc; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- base = devm_ioremap_resource(dev, res); -- if (IS_ERR(base)) -- return PTR_ERR(base); -- -- regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8660_regmap_config); -- if (IS_ERR(regmap)) -- return PTR_ERR(regmap); -- -- num_clks = ARRAY_SIZE(gcc_msm8660_clks); -- cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, -- GFP_KERNEL); -- if (!cc) -- return -ENOMEM; -- -- clks = cc->clks; -- data = &cc->data; -- data->clks = clks; -- data->clk_num = num_clks; -- -- /* Temporary until RPM clocks supported */ -- clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); -- if (IS_ERR(clk)) -- return PTR_ERR(clk); -- -- clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000); -- if (IS_ERR(clk)) -- return PTR_ERR(clk); -- -- for (i = 0; i < num_clks; i++) { -- if (!gcc_msm8660_clks[i]) -- continue; -- clk = devm_clk_register_regmap(dev, gcc_msm8660_clks[i]); -- if (IS_ERR(clk)) -- return PTR_ERR(clk); -- clks[i] = clk; -- } -- -- ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); -- if (ret) -- return ret; -- -- reset = &cc->reset; -- reset->rcdev.of_node = dev->of_node; -- reset->rcdev.ops = &qcom_reset_ops, -- reset->rcdev.owner = THIS_MODULE, -- reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8660_resets), -- reset->regmap = regmap; -- reset->reset_map = gcc_msm8660_resets, -- platform_set_drvdata(pdev, &reset->rcdev); -- -- ret = reset_controller_register(&reset->rcdev); -- if (ret) -- of_clk_del_provider(dev->of_node); -- -- return ret; -+ return qcom_cc_probe(pdev, &gcc_msm8660_desc); - } - - static int gcc_msm8660_remove(struct platform_device *pdev) - { -- of_clk_del_provider(pdev->dev.of_node); -- reset_controller_unregister(platform_get_drvdata(pdev)); -+ qcom_cc_remove(pdev); - return 0; - } - ---- a/drivers/clk/qcom/gcc-msm8960.c -+++ b/drivers/clk/qcom/gcc-msm8960.c -@@ -25,6 +25,7 @@ - #include - #include - -+#include "common.h" - #include "clk-regmap.h" - #include "clk-pll.h" - #include "clk-rcg.h" -@@ -2875,51 +2876,24 @@ static const struct regmap_config gcc_ms - .fast_io = true, - }; - -+static const struct qcom_cc_desc gcc_msm8960_desc = { -+ .config = &gcc_msm8960_regmap_config, -+ .clks = gcc_msm8960_clks, -+ .num_clks = ARRAY_SIZE(gcc_msm8960_clks), -+ .resets = gcc_msm8960_resets, -+ .num_resets = ARRAY_SIZE(gcc_msm8960_resets), -+}; -+ - static const struct of_device_id gcc_msm8960_match_table[] = { - { .compatible = "qcom,gcc-msm8960" }, - { } - }; - MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table); - --struct qcom_cc { -- struct qcom_reset_controller reset; -- struct clk_onecell_data data; -- struct clk *clks[]; --}; -- - static int gcc_msm8960_probe(struct platform_device *pdev) - { -- void __iomem *base; -- struct resource *res; -- int i, ret; -- struct device *dev = &pdev->dev; - struct clk *clk; -- struct clk_onecell_data *data; -- struct clk **clks; -- struct regmap *regmap; -- size_t num_clks; -- struct qcom_reset_controller *reset; -- struct qcom_cc *cc; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- base = devm_ioremap_resource(dev, res); -- if (IS_ERR(base)) -- return PTR_ERR(base); -- -- regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8960_regmap_config); -- if (IS_ERR(regmap)) -- return PTR_ERR(regmap); -- -- num_clks = ARRAY_SIZE(gcc_msm8960_clks); -- cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, -- GFP_KERNEL); -- if (!cc) -- return -ENOMEM; -- -- clks = cc->clks; -- data = &cc->data; -- data->clks = clks; -- data->clk_num = num_clks; -+ struct device *dev = &pdev->dev; - - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); -@@ -2930,39 +2904,12 @@ static int gcc_msm8960_probe(struct plat - if (IS_ERR(clk)) - return PTR_ERR(clk); - -- for (i = 0; i < num_clks; i++) { -- if (!gcc_msm8960_clks[i]) -- continue; -- clk = devm_clk_register_regmap(dev, gcc_msm8960_clks[i]); -- if (IS_ERR(clk)) -- return PTR_ERR(clk); -- clks[i] = clk; -- } -- -- ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); -- if (ret) -- return ret; -- -- reset = &cc->reset; -- reset->rcdev.of_node = dev->of_node; -- reset->rcdev.ops = &qcom_reset_ops, -- reset->rcdev.owner = THIS_MODULE, -- reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8960_resets), -- reset->regmap = regmap; -- reset->reset_map = gcc_msm8960_resets, -- platform_set_drvdata(pdev, &reset->rcdev); -- -- ret = reset_controller_register(&reset->rcdev); -- if (ret) -- of_clk_del_provider(dev->of_node); -- -- return ret; -+ return qcom_cc_probe(pdev, &gcc_msm8960_desc); - } - - static int gcc_msm8960_remove(struct platform_device *pdev) - { -- of_clk_del_provider(pdev->dev.of_node); -- reset_controller_unregister(platform_get_drvdata(pdev)); -+ qcom_cc_remove(pdev); - return 0; - } - ---- a/drivers/clk/qcom/gcc-msm8974.c -+++ b/drivers/clk/qcom/gcc-msm8974.c -@@ -25,6 +25,7 @@ - #include - #include - -+#include "common.h" - #include "clk-regmap.h" - #include "clk-pll.h" - #include "clk-rcg.h" -@@ -2574,51 +2575,24 @@ static const struct regmap_config gcc_ms - .fast_io = true, - }; - -+static const struct qcom_cc_desc gcc_msm8974_desc = { -+ .config = &gcc_msm8974_regmap_config, -+ .clks = gcc_msm8974_clocks, -+ .num_clks = ARRAY_SIZE(gcc_msm8974_clocks), -+ .resets = gcc_msm8974_resets, -+ .num_resets = ARRAY_SIZE(gcc_msm8974_resets), -+}; -+ - static const struct of_device_id gcc_msm8974_match_table[] = { - { .compatible = "qcom,gcc-msm8974" }, - { } - }; - MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); - --struct qcom_cc { -- struct qcom_reset_controller reset; -- struct clk_onecell_data data; -- struct clk *clks[]; --}; -- - static int gcc_msm8974_probe(struct platform_device *pdev) - { -- void __iomem *base; -- struct resource *res; -- int i, ret; -- struct device *dev = &pdev->dev; - struct clk *clk; -- struct clk_onecell_data *data; -- struct clk **clks; -- struct regmap *regmap; -- size_t num_clks; -- struct qcom_reset_controller *reset; -- struct qcom_cc *cc; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- base = devm_ioremap_resource(dev, res); -- if (IS_ERR(base)) -- return PTR_ERR(base); -- -- regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8974_regmap_config); -- if (IS_ERR(regmap)) -- return PTR_ERR(regmap); -- -- num_clks = ARRAY_SIZE(gcc_msm8974_clocks); -- cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, -- GFP_KERNEL); -- if (!cc) -- return -ENOMEM; -- -- clks = cc->clks; -- data = &cc->data; -- data->clks = clks; -- data->clk_num = num_clks; -+ struct device *dev = &pdev->dev; - - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); -@@ -2631,39 +2605,12 @@ static int gcc_msm8974_probe(struct plat - if (IS_ERR(clk)) - return PTR_ERR(clk); - -- for (i = 0; i < num_clks; i++) { -- if (!gcc_msm8974_clocks[i]) -- continue; -- clk = devm_clk_register_regmap(dev, gcc_msm8974_clocks[i]); -- if (IS_ERR(clk)) -- return PTR_ERR(clk); -- clks[i] = clk; -- } -- -- ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); -- if (ret) -- return ret; -- -- reset = &cc->reset; -- reset->rcdev.of_node = dev->of_node; -- reset->rcdev.ops = &qcom_reset_ops, -- reset->rcdev.owner = THIS_MODULE, -- reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8974_resets), -- reset->regmap = regmap; -- reset->reset_map = gcc_msm8974_resets, -- platform_set_drvdata(pdev, &reset->rcdev); -- -- ret = reset_controller_register(&reset->rcdev); -- if (ret) -- of_clk_del_provider(dev->of_node); -- -- return ret; -+ return qcom_cc_probe(pdev, &gcc_msm8974_desc); - } - - static int gcc_msm8974_remove(struct platform_device *pdev) - { -- of_clk_del_provider(pdev->dev.of_node); -- reset_controller_unregister(platform_get_drvdata(pdev)); -+ qcom_cc_remove(pdev); - return 0; - } - ---- a/drivers/clk/qcom/mmcc-msm8960.c -+++ b/drivers/clk/qcom/mmcc-msm8960.c -@@ -26,6 +26,7 @@ - #include - #include - -+#include "common.h" - #include "clk-regmap.h" - #include "clk-pll.h" - #include "clk-rcg.h" -@@ -2224,85 +2225,28 @@ static const struct regmap_config mmcc_m - .fast_io = true, - }; - -+static const struct qcom_cc_desc mmcc_msm8960_desc = { -+ .config = &mmcc_msm8960_regmap_config, -+ .clks = mmcc_msm8960_clks, -+ .num_clks = ARRAY_SIZE(mmcc_msm8960_clks), -+ .resets = mmcc_msm8960_resets, -+ .num_resets = ARRAY_SIZE(mmcc_msm8960_resets), -+}; -+ - static const struct of_device_id mmcc_msm8960_match_table[] = { - { .compatible = "qcom,mmcc-msm8960" }, - { } - }; - MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table); - --struct qcom_cc { -- struct qcom_reset_controller reset; -- struct clk_onecell_data data; -- struct clk *clks[]; --}; -- - static int mmcc_msm8960_probe(struct platform_device *pdev) - { -- void __iomem *base; -- struct resource *res; -- int i, ret; -- struct device *dev = &pdev->dev; -- struct clk *clk; -- struct clk_onecell_data *data; -- struct clk **clks; -- struct regmap *regmap; -- size_t num_clks; -- struct qcom_reset_controller *reset; -- struct qcom_cc *cc; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- base = devm_ioremap_resource(dev, res); -- if (IS_ERR(base)) -- return PTR_ERR(base); -- -- regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8960_regmap_config); -- if (IS_ERR(regmap)) -- return PTR_ERR(regmap); -- -- num_clks = ARRAY_SIZE(mmcc_msm8960_clks); -- cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, -- GFP_KERNEL); -- if (!cc) -- return -ENOMEM; -- -- clks = cc->clks; -- data = &cc->data; -- data->clks = clks; -- data->clk_num = num_clks; -- -- for (i = 0; i < num_clks; i++) { -- if (!mmcc_msm8960_clks[i]) -- continue; -- clk = devm_clk_register_regmap(dev, mmcc_msm8960_clks[i]); -- if (IS_ERR(clk)) -- return PTR_ERR(clk); -- clks[i] = clk; -- } -- -- ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); -- if (ret) -- return ret; -- -- reset = &cc->reset; -- reset->rcdev.of_node = dev->of_node; -- reset->rcdev.ops = &qcom_reset_ops, -- reset->rcdev.owner = THIS_MODULE, -- reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8960_resets), -- reset->regmap = regmap; -- reset->reset_map = mmcc_msm8960_resets, -- platform_set_drvdata(pdev, &reset->rcdev); -- -- ret = reset_controller_register(&reset->rcdev); -- if (ret) -- of_clk_del_provider(dev->of_node); -- -- return ret; -+ return qcom_cc_probe(pdev, &mmcc_msm8960_desc); - } - - static int mmcc_msm8960_remove(struct platform_device *pdev) - { -- of_clk_del_provider(pdev->dev.of_node); -- reset_controller_unregister(platform_get_drvdata(pdev)); -+ qcom_cc_remove(pdev); - return 0; - } - ---- a/drivers/clk/qcom/mmcc-msm8974.c -+++ b/drivers/clk/qcom/mmcc-msm8974.c -@@ -25,6 +25,7 @@ - #include - #include - -+#include "common.h" - #include "clk-regmap.h" - #include "clk-pll.h" - #include "clk-rcg.h" -@@ -2527,88 +2528,39 @@ static const struct regmap_config mmcc_m - .fast_io = true, - }; - -+static const struct qcom_cc_desc mmcc_msm8974_desc = { -+ .config = &mmcc_msm8974_regmap_config, -+ .clks = mmcc_msm8974_clocks, -+ .num_clks = ARRAY_SIZE(mmcc_msm8974_clocks), -+ .resets = mmcc_msm8974_resets, -+ .num_resets = ARRAY_SIZE(mmcc_msm8974_resets), -+}; -+ - static const struct of_device_id mmcc_msm8974_match_table[] = { - { .compatible = "qcom,mmcc-msm8974" }, - { } - }; - MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table); - --struct qcom_cc { -- struct qcom_reset_controller reset; -- struct clk_onecell_data data; -- struct clk *clks[]; --}; -- - static int mmcc_msm8974_probe(struct platform_device *pdev) - { -- void __iomem *base; -- struct resource *res; -- int i, ret; -- struct device *dev = &pdev->dev; -- struct clk *clk; -- struct clk_onecell_data *data; -- struct clk **clks; -+ int ret; - struct regmap *regmap; -- size_t num_clks; -- struct qcom_reset_controller *reset; -- struct qcom_cc *cc; -- -- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- base = devm_ioremap_resource(dev, res); -- if (IS_ERR(base)) -- return PTR_ERR(base); -- -- regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8974_regmap_config); -- if (IS_ERR(regmap)) -- return PTR_ERR(regmap); -- -- num_clks = ARRAY_SIZE(mmcc_msm8974_clocks); -- cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, -- GFP_KERNEL); -- if (!cc) -- return -ENOMEM; -- -- clks = cc->clks; -- data = &cc->data; -- data->clks = clks; -- data->clk_num = num_clks; -- -- clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true); -- clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false); - -- for (i = 0; i < num_clks; i++) { -- if (!mmcc_msm8974_clocks[i]) -- continue; -- clk = devm_clk_register_regmap(dev, mmcc_msm8974_clocks[i]); -- if (IS_ERR(clk)) -- return PTR_ERR(clk); -- clks[i] = clk; -- } -- -- ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); -+ ret = qcom_cc_probe(pdev, &mmcc_msm8974_desc); - if (ret) - return ret; - -- reset = &cc->reset; -- reset->rcdev.of_node = dev->of_node; -- reset->rcdev.ops = &qcom_reset_ops, -- reset->rcdev.owner = THIS_MODULE, -- reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8974_resets), -- reset->regmap = regmap; -- reset->reset_map = mmcc_msm8974_resets, -- platform_set_drvdata(pdev, &reset->rcdev); -- -- ret = reset_controller_register(&reset->rcdev); -- if (ret) -- of_clk_del_provider(dev->of_node); -+ regmap = dev_get_regmap(&pdev->dev, NULL); -+ clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true); -+ clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false); - -- return ret; -+ return 0; - } - - static int mmcc_msm8974_remove(struct platform_device *pdev) - { -- of_clk_del_provider(pdev->dev.of_node); -- reset_controller_unregister(platform_get_drvdata(pdev)); -+ qcom_cc_remove(pdev); - return 0; - } - diff --git a/target/linux/ipq806x/patches/0079-clk-qcom-Add-basic-support-for-APQ8064-global-clock-.patch b/target/linux/ipq806x/patches/0079-clk-qcom-Add-basic-support-for-APQ8064-global-clock-.patch deleted file mode 100644 index 307e797471..0000000000 --- a/target/linux/ipq806x/patches/0079-clk-qcom-Add-basic-support-for-APQ8064-global-clock-.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 0f171b8a6e1723f0ce6f98f8b3fba7d2583088c1 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 4 Apr 2014 11:31:29 -0500 -Subject: [PATCH 079/182] clk: qcom: Add basic support for APQ8064 global - clock controller clocks - -The APQ8064 and MSM8960 share a significant amount of clock data and -code between the two SoCs. Rather than duplicating the data we just add -support for a unqiue APQ8064 clock table into the MSM8960 code. - -For now add just enough clocks to get a basic serial port going on an -APQ8064 device. - -Signed-off-by: Kumar Gala -Reviewed-by: Stephen Boyd -Signed-off-by: Mike Turquette -[mturquette@linaro.org: trivial conflict due to missing ipq8064 support] ---- - .../devicetree/bindings/clock/qcom,gcc.txt | 1 + - drivers/clk/qcom/Kconfig | 4 +-- - drivers/clk/qcom/gcc-msm8960.c | 30 ++++++++++++++++++-- - 3 files changed, 30 insertions(+), 5 deletions(-) - ---- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt -+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt -@@ -4,6 +4,7 @@ Qualcomm Global Clock & Reset Controller - Required properties : - - compatible : shall contain only one of the following: - -+ "qcom,gcc-apq8064" - "qcom,gcc-msm8660" - "qcom,gcc-msm8960" - "qcom,gcc-msm8974" ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -13,10 +13,10 @@ config MSM_GCC_8660 - i2c, USB, SD/eMMC, etc. - - config MSM_GCC_8960 -- tristate "MSM8960 Global Clock Controller" -+ tristate "APQ8064/MSM8960 Global Clock Controller" - depends on COMMON_CLK_QCOM - help -- Support for the global clock controller on msm8960 devices. -+ Support for the global clock controller on apq8064/msm8960 devices. - Say Y if you want to use peripheral devices such as UART, SPI, - i2c, USB, SD/eMMC, SATA, PCIe, etc. - ---- a/drivers/clk/qcom/gcc-msm8960.c -+++ b/drivers/clk/qcom/gcc-msm8960.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2013, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and -@@ -2868,6 +2868,16 @@ static const struct qcom_reset_map gcc_m - [RIVA_RESET] = { 0x35e0 }, - }; - -+static struct clk_regmap *gcc_apq8064_clks[] = { -+ [PLL8] = &pll8.clkr, -+ [PLL8_VOTE] = &pll8_vote, -+ [GSBI7_UART_SRC] = &gsbi7_uart_src.clkr, -+ [GSBI7_UART_CLK] = &gsbi7_uart_clk.clkr, -+ [GSBI7_QUP_SRC] = &gsbi7_qup_src.clkr, -+ [GSBI7_QUP_CLK] = &gsbi7_qup_clk.clkr, -+ [GSBI7_H_CLK] = &gsbi7_h_clk.clkr, -+}; -+ - static const struct regmap_config gcc_msm8960_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, -@@ -2884,8 +2894,17 @@ static const struct qcom_cc_desc gcc_msm - .num_resets = ARRAY_SIZE(gcc_msm8960_resets), - }; - -+static const struct qcom_cc_desc gcc_apq8064_desc = { -+ .config = &gcc_msm8960_regmap_config, -+ .clks = gcc_apq8064_clks, -+ .num_clks = ARRAY_SIZE(gcc_apq8064_clks), -+ .resets = gcc_msm8960_resets, -+ .num_resets = ARRAY_SIZE(gcc_msm8960_resets), -+}; -+ - static const struct of_device_id gcc_msm8960_match_table[] = { -- { .compatible = "qcom,gcc-msm8960" }, -+ { .compatible = "qcom,gcc-msm8960", .data = &gcc_msm8960_desc }, -+ { .compatible = "qcom,gcc-apq8064", .data = &gcc_apq8064_desc }, - { } - }; - MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table); -@@ -2894,6 +2913,11 @@ static int gcc_msm8960_probe(struct plat - { - struct clk *clk; - struct device *dev = &pdev->dev; -+ const struct of_device_id *match; -+ -+ match = of_match_device(gcc_msm8960_match_table, &pdev->dev); -+ if (!match) -+ return -EINVAL; - - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); -@@ -2904,7 +2928,7 @@ static int gcc_msm8960_probe(struct plat - if (IS_ERR(clk)) - return PTR_ERR(clk); - -- return qcom_cc_probe(pdev, &gcc_msm8960_desc); -+ return qcom_cc_probe(pdev, match->data); - } - - static int gcc_msm8960_remove(struct platform_device *pdev) diff --git a/target/linux/ipq806x/patches/0080-clk-qcom-Various-fixes-for-MSM8960-s-global-clock-co.patch b/target/linux/ipq806x/patches/0080-clk-qcom-Various-fixes-for-MSM8960-s-global-clock-co.patch deleted file mode 100644 index 9731771fdc..0000000000 --- a/target/linux/ipq806x/patches/0080-clk-qcom-Various-fixes-for-MSM8960-s-global-clock-co.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 7456451e9df88d4c33479e3d4ea124d8a91ceb57 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 4 Apr 2014 11:32:56 -0500 -Subject: [PATCH 080/182] clk: qcom: Various fixes for MSM8960's global clock - controller - -* Remove CE2_SLEEP_CLK, doesn't exist on 8960 family SoCs -* Fix incorrect offset for PMIC_SSBI2_RESET -* Fix typo: - SIC_TIC -> SPS_TIC_H - SFAB_ADM0_M2_A_CLK -> SFAB_ADM0_M2_H_CLK -* Fix naming convention: - SFAB_CFPB_S_HCLK -> SFAB_CFPB_S_H_CLK - SATA_SRC_CLK -> SATA_CLK_SRC - -Signed-off-by: Kumar Gala -Reviewed-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - drivers/clk/qcom/gcc-msm8960.c | 4 ++-- - include/dt-bindings/clock/qcom,gcc-msm8960.h | 7 +++---- - include/dt-bindings/reset/qcom,gcc-msm8960.h | 2 +- - 3 files changed, 6 insertions(+), 7 deletions(-) - ---- a/drivers/clk/qcom/gcc-msm8960.c -+++ b/drivers/clk/qcom/gcc-msm8960.c -@@ -2810,7 +2810,7 @@ static const struct qcom_reset_map gcc_m - [PPSS_PROC_RESET] = { 0x2594, 1 }, - [PPSS_RESET] = { 0x2594}, - [DMA_BAM_RESET] = { 0x25c0, 7 }, -- [SIC_TIC_RESET] = { 0x2600, 7 }, -+ [SPS_TIC_H_RESET] = { 0x2600, 7 }, - [SLIMBUS_H_RESET] = { 0x2620, 7 }, - [SFAB_CFPB_M_RESET] = { 0x2680, 7 }, - [SFAB_CFPB_S_RESET] = { 0x26c0, 7 }, -@@ -2823,7 +2823,7 @@ static const struct qcom_reset_map gcc_m - [SFAB_SFPB_M_RESET] = { 0x2780, 7 }, - [SFAB_SFPB_S_RESET] = { 0x27a0, 7 }, - [RPM_PROC_RESET] = { 0x27c0, 7 }, -- [PMIC_SSBI2_RESET] = { 0x270c, 12 }, -+ [PMIC_SSBI2_RESET] = { 0x280c, 12 }, - [SDC1_RESET] = { 0x2830 }, - [SDC2_RESET] = { 0x2850 }, - [SDC3_RESET] = { 0x2870 }, ---- a/include/dt-bindings/clock/qcom,gcc-msm8960.h -+++ b/include/dt-bindings/clock/qcom,gcc-msm8960.h -@@ -51,7 +51,7 @@ - #define QDSS_TSCTR_CLK 34 - #define SFAB_ADM0_M0_A_CLK 35 - #define SFAB_ADM0_M1_A_CLK 36 --#define SFAB_ADM0_M2_A_CLK 37 -+#define SFAB_ADM0_M2_H_CLK 37 - #define ADM0_CLK 38 - #define ADM0_PBUS_CLK 39 - #define MSS_XPU_CLK 40 -@@ -99,7 +99,7 @@ - #define CFPB2_H_CLK 82 - #define SFAB_CFPB_M_H_CLK 83 - #define CFPB_MASTER_H_CLK 84 --#define SFAB_CFPB_S_HCLK 85 -+#define SFAB_CFPB_S_H_CLK 85 - #define CFPB_SPLITTER_H_CLK 86 - #define TSIF_H_CLK 87 - #define TSIF_INACTIVITY_TIMERS_CLK 88 -@@ -110,7 +110,6 @@ - #define CE1_SLEEP_CLK 93 - #define CE2_H_CLK 94 - #define CE2_CORE_CLK 95 --#define CE2_SLEEP_CLK 96 - #define SFPB_H_CLK_SRC 97 - #define SFPB_H_CLK 98 - #define SFAB_SFPB_M_H_CLK 99 -@@ -252,7 +251,7 @@ - #define MSS_S_H_CLK 235 - #define MSS_CXO_SRC_CLK 236 - #define SATA_H_CLK 237 --#define SATA_SRC_CLK 238 -+#define SATA_CLK_SRC 238 - #define SATA_RXOOB_CLK 239 - #define SATA_PMALIVE_CLK 240 - #define SATA_PHY_REF_CLK 241 ---- a/include/dt-bindings/reset/qcom,gcc-msm8960.h -+++ b/include/dt-bindings/reset/qcom,gcc-msm8960.h -@@ -58,7 +58,7 @@ - #define PPSS_PROC_RESET 41 - #define PPSS_RESET 42 - #define DMA_BAM_RESET 43 --#define SIC_TIC_RESET 44 -+#define SPS_TIC_H_RESET 44 - #define SLIMBUS_H_RESET 45 - #define SFAB_CFPB_M_RESET 46 - #define SFAB_CFPB_S_RESET 47 diff --git a/target/linux/ipq806x/patches/0081-ARM-config-Add-qcom_defconfig.patch b/target/linux/ipq806x/patches/0081-ARM-config-Add-qcom_defconfig.patch deleted file mode 100644 index dd87c1fb66..0000000000 --- a/target/linux/ipq806x/patches/0081-ARM-config-Add-qcom_defconfig.patch +++ /dev/null @@ -1,184 +0,0 @@ -From e1f51c2d41c8936b8383cf4ac53c1ff05b0e2e2f Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 27 Feb 2014 12:54:24 -0800 -Subject: [PATCH 081/182] ARM: config: Add qcom_defconfig - -Add a defconfig for mach-qcom platforms (copied from msm_defconfig). -Although these platforms are part of the multi-platform kernel, it's -useful to have a stripped down version of the defconfig that just -selects the DT based Qualcomm platforms and drivers. - -Signed-off-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/configs/qcom_defconfig | 164 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 164 insertions(+) - create mode 100644 arch/arm/configs/qcom_defconfig - ---- /dev/null -+++ b/arch/arm/configs/qcom_defconfig -@@ -0,0 +1,164 @@ -+CONFIG_SYSVIPC=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_SYSCTL_SYSCALL=y -+CONFIG_KALLSYMS_ALL=y -+CONFIG_EMBEDDED=y -+# CONFIG_SLUB_DEBUG is not set -+# CONFIG_COMPAT_BRK is not set -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=y -+CONFIG_KPROBES=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODULE_FORCE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_ARCH_QCOM=y -+CONFIG_ARCH_MSM8X60=y -+CONFIG_ARCH_MSM8960=y -+CONFIG_ARCH_MSM8974=y -+CONFIG_SMP=y -+CONFIG_PREEMPT=y -+CONFIG_AEABI=y -+CONFIG_HIGHMEM=y -+CONFIG_HIGHPTE=y -+CONFIG_CLEANCACHE=y -+CONFIG_ARM_APPENDED_DTB=y -+CONFIG_ARM_ATAG_DTB_COMPAT=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_INET=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -+# CONFIG_INET_XFRM_MODE_TUNNEL is not set -+# CONFIG_INET_XFRM_MODE_BEET is not set -+# CONFIG_INET_LRO is not set -+# CONFIG_IPV6 is not set -+CONFIG_CFG80211=y -+CONFIG_RFKILL=y -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_MTD=y -+CONFIG_MTD_BLOCK=y -+CONFIG_MTD_M25P80=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_SCSI=y -+CONFIG_SCSI_TGT=y -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_SG=y -+CONFIG_CHR_DEV_SCH=y -+CONFIG_SCSI_MULTI_LUN=y -+CONFIG_SCSI_CONSTANTS=y -+CONFIG_SCSI_LOGGING=y -+CONFIG_SCSI_SCAN_ASYNC=y -+CONFIG_NETDEVICES=y -+CONFIG_DUMMY=y -+CONFIG_MDIO_BITBANG=y -+CONFIG_MDIO_GPIO=y -+CONFIG_SLIP=y -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_MODE_SLIP6=y -+CONFIG_USB_USBNET=y -+# CONFIG_USB_NET_AX8817X is not set -+# CONFIG_USB_NET_ZAURUS is not set -+CONFIG_INPUT_EVDEV=y -+# CONFIG_KEYBOARD_ATKBD is not set -+# CONFIG_MOUSE_PS2 is not set -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_UINPUT=y -+CONFIG_SERIO_LIBPS2=y -+# CONFIG_LEGACY_PTYS is not set -+CONFIG_SERIAL_MSM=y -+CONFIG_SERIAL_MSM_CONSOLE=y -+CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_MSM=y -+CONFIG_I2C=y -+CONFIG_I2C_CHARDEV=y -+CONFIG_I2C_QUP=y -+CONFIG_SPI=y -+CONFIG_SPI_QUP=y -+CONFIG_SPMI=y -+CONFIG_PINCTRL_APQ8064=y -+CONFIG_PINCTRL_IPQ8064=y -+CONFIG_PINCTRL_MSM8X74=y -+CONFIG_DEBUG_GPIO=y -+CONFIG_GPIO_SYSFS=y -+CONFIG_POWER_SUPPLY=y -+CONFIG_POWER_RESET=y -+CONFIG_POWER_RESET_MSM=y -+CONFIG_THERMAL=y -+CONFIG_REGULATOR=y -+CONFIG_MEDIA_SUPPORT=y -+CONFIG_FB=y -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_DYNAMIC_MINORS=y -+# CONFIG_SND_ARM is not set -+# CONFIG_SND_SPI is not set -+# CONFIG_SND_USB is not set -+CONFIG_SND_SOC=y -+CONFIG_HID_BATTERY_STRENGTH=y -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_MON=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_ACM=y -+CONFIG_USB_SERIAL=y -+CONFIG_USB_GADGET=y -+CONFIG_USB_GADGET_DEBUG_FILES=y -+CONFIG_USB_GADGET_VBUS_DRAW=500 -+CONFIG_MMC=y -+CONFIG_MMC_BLOCK_MINORS=16 -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI_MSM=y -+CONFIG_RTC_CLASS=y -+CONFIG_DMADEVICES=y -+CONFIG_QCOM_BAM_DMA=y -+CONFIG_STAGING=y -+CONFIG_COMMON_CLK_QCOM=y -+CONFIG_MSM_GCC_8660=y -+CONFIG_MSM_MMCC_8960=y -+CONFIG_MSM_MMCC_8974=y -+CONFIG_MSM_IOMMU=y -+CONFIG_GENERIC_PHY=y -+CONFIG_EXT2_FS=y -+CONFIG_EXT2_FS_XATTR=y -+CONFIG_EXT3_FS=y -+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -+CONFIG_EXT4_FS=y -+CONFIG_FUSE_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_JFFS2_FS=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_CIFS=y -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_UTF8=y -+CONFIG_PRINTK_TIME=y -+CONFIG_DYNAMIC_DEBUG=y -+CONFIG_DEBUG_INFO=y -+CONFIG_MAGIC_SYSRQ=y -+CONFIG_LOCKUP_DETECTOR=y -+# CONFIG_DETECT_HUNG_TASK is not set -+# CONFIG_SCHED_DEBUG is not set -+CONFIG_TIMER_STATS=y diff --git a/target/linux/ipq806x/patches/0082-ARM-qcom-Enable-GSBI-driver-in-defconfig.patch b/target/linux/ipq806x/patches/0082-ARM-qcom-Enable-GSBI-driver-in-defconfig.patch deleted file mode 100644 index 180f102334..0000000000 --- a/target/linux/ipq806x/patches/0082-ARM-qcom-Enable-GSBI-driver-in-defconfig.patch +++ /dev/null @@ -1,20 +0,0 @@ -From d247fb8a019e4cc5a607c7fff9922e8e98c2c660 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 29 May 2014 11:25:24 -0500 -Subject: [PATCH 082/182] ARM: qcom: Enable GSBI driver in defconfig - -Signed-off-by: Kumar Gala ---- - arch/arm/configs/qcom_defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -131,6 +131,7 @@ CONFIG_RTC_CLASS=y - CONFIG_DMADEVICES=y - CONFIG_QCOM_BAM_DMA=y - CONFIG_STAGING=y -+CONFIG_QCOM_GSBI=y - CONFIG_COMMON_CLK_QCOM=y - CONFIG_MSM_GCC_8660=y - CONFIG_MSM_MMCC_8960=y diff --git a/target/linux/ipq806x/patches/0083-soc-Introduce-drivers-soc-place-holder-for-SOC-speci.patch b/target/linux/ipq806x/patches/0083-soc-Introduce-drivers-soc-place-holder-for-SOC-speci.patch deleted file mode 100644 index 5f173fb520..0000000000 --- a/target/linux/ipq806x/patches/0083-soc-Introduce-drivers-soc-place-holder-for-SOC-speci.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 2dac9498966c79a6abb09764419ffd42a44c78cf Mon Sep 17 00:00:00 2001 -From: Santosh Shilimkar -Date: Wed, 23 Apr 2014 19:46:17 -0400 -Subject: [PATCH 083/182] soc: Introduce drivers/soc place-holder for SOC - specific drivers - -Based on earlier thread "https://lkml.org/lkml/2013/10/7/662" and -discussion at Kernel Summit'2013, it was agreed to create -'driver/soc' for drivers which are quite SOC specific. - -Further discussion on the subject is in response to -the earlier version of the patch is here: - http://lwn.net/Articles/588942/ - -Cc: Greg Kroah-Hartman -Cc: Kumar Gala -Cc: Paul Walmsley -Cc: Olof Johansson -Cc: Arnd Bergmann -Signed-off-by: Sandeep Nair -Signed-off-by: Santosh Shilimkar -Signed-off-by: Kumar Gala ---- - drivers/Kconfig | 2 ++ - drivers/Makefile | 3 +++ - drivers/soc/Kconfig | 3 +++ - 3 files changed, 8 insertions(+) - create mode 100644 drivers/soc/Kconfig - ---- a/drivers/Kconfig -+++ b/drivers/Kconfig -@@ -132,6 +132,8 @@ source "drivers/staging/Kconfig" - - source "drivers/platform/Kconfig" - -+source "drivers/soc/Kconfig" -+ - source "drivers/clk/Kconfig" - - source "drivers/hwspinlock/Kconfig" ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -33,6 +33,9 @@ obj-y += amba/ - # really early. - obj-$(CONFIG_DMADEVICES) += dma/ - -+# SOC specific infrastructure drivers. -+obj-y += soc/ -+ - obj-$(CONFIG_VIRTIO) += virtio/ - obj-$(CONFIG_XEN) += xen/ - ---- /dev/null -+++ b/drivers/soc/Kconfig -@@ -0,0 +1,3 @@ -+menu "SOC (System On Chip) specific Drivers" -+ -+endmenu diff --git a/target/linux/ipq806x/patches/0084-soc-qcom-Add-GSBI-driver.patch b/target/linux/ipq806x/patches/0084-soc-qcom-Add-GSBI-driver.patch deleted file mode 100644 index 545c4be52d..0000000000 --- a/target/linux/ipq806x/patches/0084-soc-qcom-Add-GSBI-driver.patch +++ /dev/null @@ -1,145 +0,0 @@ -From a2f0fc20ea49e5dbbdbb21444683ea760fbdd38f Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 24 Apr 2014 11:31:21 -0500 -Subject: [PATCH 084/182] soc: qcom: Add GSBI driver - -The GSBI (General Serial Bus Interface) driver controls the overarching -configuration of the shared serial bus infrastructure on APQ8064, IPQ8064, and -earlier QCOM processors. The GSBI supports UART, I2C, SPI, and UIM -functionality in various combinations. - -Signed-off-by: Andy Gross -Signed-off-by: Kumar Gala ---- - drivers/soc/Kconfig | 2 + - drivers/soc/Makefile | 5 +++ - drivers/soc/qcom/Kconfig | 11 ++++++ - drivers/soc/qcom/Makefile | 1 + - drivers/soc/qcom/qcom_gsbi.c | 84 ++++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 103 insertions(+) - create mode 100644 drivers/soc/Makefile - create mode 100644 drivers/soc/qcom/Kconfig - create mode 100644 drivers/soc/qcom/Makefile - create mode 100644 drivers/soc/qcom/qcom_gsbi.c - ---- a/drivers/soc/Kconfig -+++ b/drivers/soc/Kconfig -@@ -1,3 +1,5 @@ - menu "SOC (System On Chip) specific Drivers" - -+source "drivers/soc/qcom/Kconfig" -+ - endmenu ---- /dev/null -+++ b/drivers/soc/Makefile -@@ -0,0 +1,5 @@ -+# -+# Makefile for the Linux Kernel SOC specific device drivers. -+# -+ -+obj-$(CONFIG_ARCH_QCOM) += qcom/ ---- /dev/null -+++ b/drivers/soc/qcom/Kconfig -@@ -0,0 +1,11 @@ -+# -+# QCOM Soc drivers -+# -+config QCOM_GSBI -+ tristate "QCOM General Serial Bus Interface" -+ depends on ARCH_QCOM -+ help -+ Say y here to enable GSBI support. The GSBI provides control -+ functions for connecting the underlying serial UART, SPI, and I2C -+ devices to the output pins. -+ ---- /dev/null -+++ b/drivers/soc/qcom/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o ---- /dev/null -+++ b/drivers/soc/qcom/qcom_gsbi.c -@@ -0,0 +1,84 @@ -+/* -+ * Copyright (c) 2014, The Linux foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License rev 2 and -+ * only rev 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define GSBI_CTRL_REG 0x0000 -+#define GSBI_PROTOCOL_SHIFT 4 -+ -+static int gsbi_probe(struct platform_device *pdev) -+{ -+ struct device_node *node = pdev->dev.of_node; -+ struct resource *res; -+ void __iomem *base; -+ struct clk *hclk; -+ u32 mode, crci = 0; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ if (of_property_read_u32(node, "qcom,mode", &mode)) { -+ dev_err(&pdev->dev, "missing mode configuration\n"); -+ return -EINVAL; -+ } -+ -+ /* not required, so default to 0 if not present */ -+ of_property_read_u32(node, "qcom,crci", &crci); -+ -+ dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n", mode, crci); -+ -+ hclk = devm_clk_get(&pdev->dev, "iface"); -+ if (IS_ERR(hclk)) -+ return PTR_ERR(hclk); -+ -+ clk_prepare_enable(hclk); -+ -+ writel_relaxed((mode << GSBI_PROTOCOL_SHIFT) | crci, -+ base + GSBI_CTRL_REG); -+ -+ /* make sure the gsbi control write is not reordered */ -+ wmb(); -+ -+ clk_disable_unprepare(hclk); -+ -+ return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); -+} -+ -+static const struct of_device_id gsbi_dt_match[] = { -+ { .compatible = "qcom,gsbi-v1.0.0", }, -+}; -+ -+MODULE_DEVICE_TABLE(of, gsbi_dt_match); -+ -+static struct platform_driver gsbi_driver = { -+ .driver = { -+ .name = "gsbi", -+ .owner = THIS_MODULE, -+ .of_match_table = gsbi_dt_match, -+ }, -+ .probe = gsbi_probe, -+}; -+ -+module_platform_driver(gsbi_driver); -+ -+MODULE_AUTHOR("Andy Gross "); -+MODULE_DESCRIPTION("QCOM GSBI driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0085-soc-qcom-fix-of_device_id-table.patch b/target/linux/ipq806x/patches/0085-soc-qcom-fix-of_device_id-table.patch deleted file mode 100644 index 3c58107dd3..0000000000 --- a/target/linux/ipq806x/patches/0085-soc-qcom-fix-of_device_id-table.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 8efaabc573e58f4b891340f4aedb34f9d0656067 Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Mon, 26 May 2014 18:07:05 +0200 -Subject: [PATCH 085/182] soc: qcom: fix of_device_id table - -The match tables must be zero-terminated, and Kbuild now helpfully -fails to link the kernel if that isn't the case. - -Signed-off-by: Arnd Bergmann ---- - drivers/soc/qcom/qcom_gsbi.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/soc/qcom/qcom_gsbi.c -+++ b/drivers/soc/qcom/qcom_gsbi.c -@@ -64,6 +64,7 @@ static int gsbi_probe(struct platform_de - - static const struct of_device_id gsbi_dt_match[] = { - { .compatible = "qcom,gsbi-v1.0.0", }, -+ { }, - }; - - MODULE_DEVICE_TABLE(of, gsbi_dt_match); diff --git a/target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch b/target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch deleted file mode 100644 index 68204c5347..0000000000 --- a/target/linux/ipq806x/patches/0086-msm_serial-Add-support-for-poll_-get-put-_char.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 48ab619dd6e308c57dac3e5d022a3099806bf79e Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 14 Jan 2014 12:34:55 -0800 -Subject: [PATCH 086/182] msm_serial: Add support for poll_{get,put}_char() - -Implement the polling functionality for the MSM serial driver. -This allows us to use KGDB on this hardware. - -Cc: David Brown -Signed-off-by: Stephen Boyd -Signed-off-by: Greg Kroah-Hartman ---- - drivers/tty/serial/msm_serial.c | 140 ++++++++++++++++++++++++++++++++++++++- - drivers/tty/serial/msm_serial.h | 9 +++ - 2 files changed, 146 insertions(+), 3 deletions(-) - ---- a/drivers/tty/serial/msm_serial.c -+++ b/drivers/tty/serial/msm_serial.c -@@ -39,6 +39,13 @@ - - #include "msm_serial.h" - -+enum { -+ UARTDM_1P1 = 1, -+ UARTDM_1P2, -+ UARTDM_1P3, -+ UARTDM_1P4, -+}; -+ - struct msm_port { - struct uart_port uart; - char name[16]; -@@ -309,6 +316,8 @@ static unsigned int msm_get_mctrl(struct - - static void msm_reset(struct uart_port *port) - { -+ struct msm_port *msm_port = UART_TO_MSM(port); -+ - /* reset everything */ - msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); - msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); -@@ -316,6 +325,10 @@ static void msm_reset(struct uart_port * - msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); - msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); - msm_write(port, UART_CR_CMD_SET_RFR, UART_CR); -+ -+ /* Disable DM modes */ -+ if (msm_port->is_uartdm) -+ msm_write(port, 0, UARTDM_DMEN); - } - - static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) -@@ -711,6 +724,117 @@ static void msm_power(struct uart_port * - } - } - -+#ifdef CONFIG_CONSOLE_POLL -+static int msm_poll_init(struct uart_port *port) -+{ -+ struct msm_port *msm_port = UART_TO_MSM(port); -+ -+ /* Enable single character mode on RX FIFO */ -+ if (msm_port->is_uartdm >= UARTDM_1P4) -+ msm_write(port, UARTDM_DMEN_RX_SC_ENABLE, UARTDM_DMEN); -+ -+ return 0; -+} -+ -+static int msm_poll_get_char_single(struct uart_port *port) -+{ -+ struct msm_port *msm_port = UART_TO_MSM(port); -+ unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF; -+ -+ if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) -+ return NO_POLL_CHAR; -+ else -+ return msm_read(port, rf_reg) & 0xff; -+} -+ -+static int msm_poll_get_char_dm_1p3(struct uart_port *port) -+{ -+ int c; -+ static u32 slop; -+ static int count; -+ unsigned char *sp = (unsigned char *)&slop; -+ -+ /* Check if a previous read had more than one char */ -+ if (count) { -+ c = sp[sizeof(slop) - count]; -+ count--; -+ /* Or if FIFO is empty */ -+ } else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) { -+ /* -+ * If RX packing buffer has less than a word, force stale to -+ * push contents into RX FIFO -+ */ -+ count = msm_read(port, UARTDM_RXFS); -+ count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK; -+ if (count) { -+ msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR); -+ slop = msm_read(port, UARTDM_RF); -+ c = sp[0]; -+ count--; -+ } else { -+ c = NO_POLL_CHAR; -+ } -+ /* FIFO has a word */ -+ } else { -+ slop = msm_read(port, UARTDM_RF); -+ c = sp[0]; -+ count = sizeof(slop) - 1; -+ } -+ -+ return c; -+} -+ -+static int msm_poll_get_char(struct uart_port *port) -+{ -+ u32 imr; -+ int c; -+ struct msm_port *msm_port = UART_TO_MSM(port); -+ -+ /* Disable all interrupts */ -+ imr = msm_read(port, UART_IMR); -+ msm_write(port, 0, UART_IMR); -+ -+ if (msm_port->is_uartdm == UARTDM_1P3) -+ c = msm_poll_get_char_dm_1p3(port); -+ else -+ c = msm_poll_get_char_single(port); -+ -+ /* Enable interrupts */ -+ msm_write(port, imr, UART_IMR); -+ -+ return c; -+} -+ -+static void msm_poll_put_char(struct uart_port *port, unsigned char c) -+{ -+ u32 imr; -+ struct msm_port *msm_port = UART_TO_MSM(port); -+ -+ /* Disable all interrupts */ -+ imr = msm_read(port, UART_IMR); -+ msm_write(port, 0, UART_IMR); -+ -+ if (msm_port->is_uartdm) -+ reset_dm_count(port, 1); -+ -+ /* Wait until FIFO is empty */ -+ while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) -+ cpu_relax(); -+ -+ /* Write a character */ -+ msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF); -+ -+ /* Wait until FIFO is empty */ -+ while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) -+ cpu_relax(); -+ -+ /* Enable interrupts */ -+ msm_write(port, imr, UART_IMR); -+ -+ return; -+} -+#endif -+ - static struct uart_ops msm_uart_pops = { - .tx_empty = msm_tx_empty, - .set_mctrl = msm_set_mctrl, -@@ -729,6 +853,11 @@ static struct uart_ops msm_uart_pops = { - .config_port = msm_config_port, - .verify_port = msm_verify_port, - .pm = msm_power, -+#ifdef CONFIG_CONSOLE_POLL -+ .poll_init = msm_poll_init, -+ .poll_get_char = msm_poll_get_char, -+ .poll_put_char = msm_poll_put_char, -+#endif - }; - - static struct msm_port msm_uart_ports[] = { -@@ -900,7 +1029,10 @@ static struct uart_driver msm_uart_drive - static atomic_t msm_uart_next_id = ATOMIC_INIT(0); - - static const struct of_device_id msm_uartdm_table[] = { -- { .compatible = "qcom,msm-uartdm" }, -+ { .compatible = "qcom,msm-uartdm-v1.1", .data = (void *)UARTDM_1P1 }, -+ { .compatible = "qcom,msm-uartdm-v1.2", .data = (void *)UARTDM_1P2 }, -+ { .compatible = "qcom,msm-uartdm-v1.3", .data = (void *)UARTDM_1P3 }, -+ { .compatible = "qcom,msm-uartdm-v1.4", .data = (void *)UARTDM_1P4 }, - { } - }; - -@@ -909,6 +1041,7 @@ static int __init msm_serial_probe(struc - struct msm_port *msm_port; - struct resource *resource; - struct uart_port *port; -+ const struct of_device_id *id; - int irq; - - if (pdev->id == -1) -@@ -923,8 +1056,9 @@ static int __init msm_serial_probe(struc - port->dev = &pdev->dev; - msm_port = UART_TO_MSM(port); - -- if (of_match_device(msm_uartdm_table, &pdev->dev)) -- msm_port->is_uartdm = 1; -+ id = of_match_device(msm_uartdm_table, &pdev->dev); -+ if (id) -+ msm_port->is_uartdm = (unsigned long)id->data; - else - msm_port->is_uartdm = 0; - ---- a/drivers/tty/serial/msm_serial.h -+++ b/drivers/tty/serial/msm_serial.h -@@ -59,6 +59,7 @@ - #define UART_CR_CMD_RESET_RFR (14 << 4) - #define UART_CR_CMD_PROTECTION_EN (16 << 4) - #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) -+#define UART_CR_CMD_FORCE_STALE (4 << 8) - #define UART_CR_CMD_RESET_TX_READY (3 << 8) - #define UART_CR_TX_DISABLE (1 << 3) - #define UART_CR_TX_ENABLE (1 << 2) -@@ -113,6 +114,14 @@ - #define GSBI_PROTOCOL_UART 0x40 - #define GSBI_PROTOCOL_IDLE 0x0 - -+#define UARTDM_RXFS 0x50 -+#define UARTDM_RXFS_BUF_SHIFT 0x7 -+#define UARTDM_RXFS_BUF_MASK 0x7 -+ -+#define UARTDM_DMEN 0x3C -+#define UARTDM_DMEN_RX_SC_ENABLE BIT(5) -+#define UARTDM_DMEN_TX_SC_ENABLE BIT(4) -+ - #define UARTDM_DMRX 0x34 - #define UARTDM_NCF_TX 0x40 - #define UARTDM_RX_TOTAL_SNAP 0x38 diff --git a/target/linux/ipq806x/patches/0087-tty-serial-msm-Remove-direct-access-to-GSBI.patch b/target/linux/ipq806x/patches/0087-tty-serial-msm-Remove-direct-access-to-GSBI.patch deleted file mode 100644 index 9eb71382e4..0000000000 --- a/target/linux/ipq806x/patches/0087-tty-serial-msm-Remove-direct-access-to-GSBI.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 025909cbf933cc20c2ff5ea9f87de8e17a739a08 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 24 Apr 2014 11:31:22 -0500 -Subject: [PATCH 087/182] tty: serial: msm: Remove direct access to GSBI - -This patch removes direct access of the GSBI registers. GSBI configuration -should be done through the GSBI driver directly. - -Signed-off-by: Andy Gross -Signed-off-by: Kumar Gala ---- - drivers/tty/serial/msm_serial.c | 48 ++------------------------------------- - drivers/tty/serial/msm_serial.h | 5 ---- - 2 files changed, 2 insertions(+), 51 deletions(-) - ---- a/drivers/tty/serial/msm_serial.c -+++ b/drivers/tty/serial/msm_serial.c -@@ -52,7 +52,6 @@ struct msm_port { - struct clk *clk; - struct clk *pclk; - unsigned int imr; -- void __iomem *gsbi_base; - int is_uartdm; - unsigned int old_snap_state; - }; -@@ -599,9 +598,7 @@ static const char *msm_type(struct uart_ - static void msm_release_port(struct uart_port *port) - { - struct platform_device *pdev = to_platform_device(port->dev); -- struct msm_port *msm_port = UART_TO_MSM(port); - struct resource *uart_resource; -- struct resource *gsbi_resource; - resource_size_t size; - - uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); -@@ -612,28 +609,12 @@ static void msm_release_port(struct uart - release_mem_region(port->mapbase, size); - iounmap(port->membase); - port->membase = NULL; -- -- if (msm_port->gsbi_base) { -- writel_relaxed(GSBI_PROTOCOL_IDLE, -- msm_port->gsbi_base + GSBI_CONTROL); -- -- gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1); -- if (unlikely(!gsbi_resource)) -- return; -- -- size = resource_size(gsbi_resource); -- release_mem_region(gsbi_resource->start, size); -- iounmap(msm_port->gsbi_base); -- msm_port->gsbi_base = NULL; -- } - } - - static int msm_request_port(struct uart_port *port) - { -- struct msm_port *msm_port = UART_TO_MSM(port); - struct platform_device *pdev = to_platform_device(port->dev); - struct resource *uart_resource; -- struct resource *gsbi_resource; - resource_size_t size; - int ret; - -@@ -652,30 +633,8 @@ static int msm_request_port(struct uart_ - goto fail_release_port; - } - -- gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1); -- /* Is this a GSBI-based port? */ -- if (gsbi_resource) { -- size = resource_size(gsbi_resource); -- -- if (!request_mem_region(gsbi_resource->start, size, -- "msm_serial")) { -- ret = -EBUSY; -- goto fail_release_port_membase; -- } -- -- msm_port->gsbi_base = ioremap(gsbi_resource->start, size); -- if (!msm_port->gsbi_base) { -- ret = -EBUSY; -- goto fail_release_gsbi; -- } -- } -- - return 0; - --fail_release_gsbi: -- release_mem_region(gsbi_resource->start, size); --fail_release_port_membase: -- iounmap(port->membase); - fail_release_port: - release_mem_region(port->mapbase, size); - return ret; -@@ -683,7 +642,6 @@ fail_release_port: - - static void msm_config_port(struct uart_port *port, int flags) - { -- struct msm_port *msm_port = UART_TO_MSM(port); - int ret; - if (flags & UART_CONFIG_TYPE) { - port->type = PORT_MSM; -@@ -691,9 +649,6 @@ static void msm_config_port(struct uart_ - if (ret) - return; - } -- if (msm_port->gsbi_base) -- writel_relaxed(GSBI_PROTOCOL_UART, -- msm_port->gsbi_base + GSBI_CONTROL); - } - - static int msm_verify_port(struct uart_port *port, struct serial_struct *ser) -@@ -1110,6 +1065,7 @@ static struct of_device_id msm_match_tab - - static struct platform_driver msm_platform_driver = { - .remove = msm_serial_remove, -+ .probe = msm_serial_probe, - .driver = { - .name = "msm_serial", - .owner = THIS_MODULE, -@@ -1125,7 +1081,7 @@ static int __init msm_serial_init(void) - if (unlikely(ret)) - return ret; - -- ret = platform_driver_probe(&msm_platform_driver, msm_serial_probe); -+ ret = platform_driver_register(&msm_platform_driver); - if (unlikely(ret)) - uart_unregister_driver(&msm_uart_driver); - ---- a/drivers/tty/serial/msm_serial.h -+++ b/drivers/tty/serial/msm_serial.h -@@ -109,11 +109,6 @@ - #define UART_ISR 0x0014 - #define UART_ISR_TX_READY (1 << 7) - --#define GSBI_CONTROL 0x0 --#define GSBI_PROTOCOL_CODE 0x30 --#define GSBI_PROTOCOL_UART 0x40 --#define GSBI_PROTOCOL_IDLE 0x0 -- - #define UARTDM_RXFS 0x50 - #define UARTDM_RXFS_BUF_SHIFT 0x7 - #define UARTDM_RXFS_BUF_MASK 0x7 diff --git a/target/linux/ipq806x/patches/0088-soc-qcom-Add-device-tree-binding-for-GSBI.patch b/target/linux/ipq806x/patches/0088-soc-qcom-Add-device-tree-binding-for-GSBI.patch deleted file mode 100644 index 523d5cbabf..0000000000 --- a/target/linux/ipq806x/patches/0088-soc-qcom-Add-device-tree-binding-for-GSBI.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 5a58dbf4d82c29f7e6d89abc3520bed1aa2af05c Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 24 Apr 2014 11:31:20 -0500 -Subject: [PATCH 088/182] soc: qcom: Add device tree binding for GSBI - -Add device tree binding support for the QCOM GSBI driver. - -Signed-off-by: Andy Gross -Signed-off-by: Kumar Gala ---- - .../devicetree/bindings/soc/qcom/qcom,gsbi.txt | 78 ++++++++++++++++++++ - include/dt-bindings/soc/qcom,gsbi.h | 26 +++++++ - 2 files changed, 104 insertions(+) - create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,gsbi.txt - create mode 100644 include/dt-bindings/soc/qcom,gsbi.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,gsbi.txt -@@ -0,0 +1,78 @@ -+QCOM GSBI (General Serial Bus Interface) Driver -+ -+The GSBI controller is modeled as a node with zero or more child nodes, each -+representing a serial sub-node device that is mux'd as part of the GSBI -+configuration settings. The mode setting will govern the input/output mode of -+the 4 GSBI IOs. -+ -+Required properties: -+- compatible: must contain "qcom,gsbi-v1.0.0" for APQ8064/IPQ8064 -+- reg: Address range for GSBI registers -+- clocks: required clock -+- clock-names: must contain "iface" entry -+- qcom,mode : indicates MUX value for configuration of the serial interface. -+ Please reference dt-bindings/soc/qcom,gsbi.h for valid mux values. -+ -+Optional properties: -+- qcom,crci : indicates CRCI MUX value for QUP CRCI ports. Please reference -+ dt-bindings/soc/qcom,gsbi.h for valid CRCI mux values. -+ -+Required properties if child node exists: -+- #address-cells: Must be 1 -+- #size-cells: Must be 1 -+- ranges: Must be present -+ -+Properties for children: -+ -+A GSBI controller node can contain 0 or more child nodes representing serial -+devices. These serial devices can be a QCOM UART, I2C controller, spi -+controller, or some combination of aforementioned devices. -+ -+See the following for child node definitions: -+Documentation/devicetree/bindings/i2c/qcom,i2c-qup.txt -+Documentation/devicetree/bindings/spi/qcom,spi-qup.txt -+Documentation/devicetree/bindings/serial/qcom,msm-uartdm.txt -+ -+Example for APQ8064: -+ -+#include -+ -+ gsbi4@16300000 { -+ compatible = "qcom,gsbi-v1.0.0"; -+ reg = <0x16300000 0x100>; -+ clocks = <&gcc GSBI4_H_CLK>; -+ clock-names = "iface"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ qcom,mode = ; -+ qcom,crci = ; -+ -+ /* child nodes go under here */ -+ -+ i2c_qup4: i2c@16380000 { -+ compatible = "qcom,i2c-qup-v1.1.1"; -+ reg = <0x16380000 0x1000>; -+ interrupts = <0 153 0>; -+ -+ clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>; -+ clock-names = "core", "iface"; -+ -+ clock-frequency = <200000>; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ }; -+ -+ uart4: serial@16340000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x16340000 0x1000>, -+ <0x16300000 0x1000>; -+ interrupts = <0 152 0x0>; -+ clocks = <&gcc GSBI4_UART_CLK>, <&gcc GSBI4_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "ok"; -+ }; -+ }; -+ ---- /dev/null -+++ b/include/dt-bindings/soc/qcom,gsbi.h -@@ -0,0 +1,26 @@ -+/* Copyright (c) 2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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_QCOM_GSBI_H -+#define __DT_BINDINGS_QCOM_GSBI_H -+ -+#define GSBI_PROT_IDLE 0 -+#define GSBI_PROT_I2C_UIM 1 -+#define GSBI_PROT_I2C 2 -+#define GSBI_PROT_SPI 3 -+#define GSBI_PROT_UART_W_FC 4 -+#define GSBI_PROT_UIM 5 -+#define GSBI_PROT_I2C_UART 6 -+ -+#define GSBI_CRCI_QUP 0 -+#define GSBI_CRCI_UART 1 -+ -+#endif diff --git a/target/linux/ipq806x/patches/0089-ARM-dts-MSM8974-Add-pinctrl-node.patch b/target/linux/ipq806x/patches/0089-ARM-dts-MSM8974-Add-pinctrl-node.patch deleted file mode 100644 index ca064288a9..0000000000 --- a/target/linux/ipq806x/patches/0089-ARM-dts-MSM8974-Add-pinctrl-node.patch +++ /dev/null @@ -1,52 +0,0 @@ -From b3a77c7cab10272988231482e2c654c5f10a910c Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Thu, 6 Feb 2014 17:28:49 +0200 -Subject: [PATCH 089/182] ARM: dts: MSM8974: Add pinctrl node - -Add the pin control node and pin definitions of SPI8. - -Signed-off-by: Ivan T. Ivanov -Reviewed-by: Bjorn Andersson -Acked-by: Linus Walleij -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-msm8974.dtsi | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -198,5 +198,34 @@ - clocks = <&gcc GCC_PRNG_AHB_CLK>; - clock-names = "core"; - }; -+ -+ msmgpio: pinctrl@fd510000 { -+ compatible = "qcom,msm8974-pinctrl"; -+ reg = <0xfd510000 0x4000>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupts = <0 208 0>; -+ -+ spi8_default: spi8_default { -+ mosi { -+ pins = "gpio45"; -+ function = "blsp_spi8"; -+ }; -+ miso { -+ pins = "gpio46"; -+ function = "blsp_spi8"; -+ }; -+ cs { -+ pins = "gpio47"; -+ function = "blsp_spi8"; -+ }; -+ clk { -+ pins = "gpio48"; -+ function = "blsp_spi8"; -+ }; -+ }; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0090-ARM-dts-msm-Add-SDHC-controller-nodes-for-MSM8974-an.patch b/target/linux/ipq806x/patches/0090-ARM-dts-msm-Add-SDHC-controller-nodes-for-MSM8974-an.patch deleted file mode 100644 index 7788f8a5df..0000000000 --- a/target/linux/ipq806x/patches/0090-ARM-dts-msm-Add-SDHC-controller-nodes-for-MSM8974-an.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 6632619d49f0f90c4d74caad67749864f154cae4 Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Fri, 31 Jan 2014 16:21:56 +0200 -Subject: [PATCH 090/182] ARM: dts: msm: Add SDHC controller nodes for MSM8974 - and DB8074 board - -Add support for the 2 SDHC controllers on the DB8074 board. The first -controller (at 0xf9824900) is connected to an on board soldered eMMC. -The second controller (at 0xf98a4900) is connected to a uSD card slot. - -Signed-off-by: Georgi Djakov -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-apq8074-dragonboard.dts | 13 +++++++++++++ - arch/arm/boot/dts/qcom-msm8974.dtsi | 22 ++++++++++++++++++++++ - 2 files changed, 35 insertions(+) - ---- a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts -+++ b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts -@@ -3,4 +3,17 @@ - / { - model = "Qualcomm APQ8074 Dragonboard"; - compatible = "qcom,apq8074-dragonboard", "qcom,apq8074"; -+ -+ soc: soc { -+ sdhci@f9824900 { -+ bus-width = <8>; -+ non-removable; -+ status = "ok"; -+ }; -+ -+ sdhci@f98a4900 { -+ cd-gpios = <&msmgpio 62 0x1>; -+ bus-width = <4>; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -192,6 +192,28 @@ - clock-names = "core", "iface"; - }; - -+ sdhci@f9824900 { -+ compatible = "qcom,sdhci-msm-v4"; -+ reg = <0xf9824900 0x11c>, <0xf9824000 0x800>; -+ reg-names = "hc_mem", "core_mem"; -+ interrupts = <0 123 0>, <0 138 0>; -+ interrupt-names = "hc_irq", "pwr_irq"; -+ clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ -+ sdhci@f98a4900 { -+ compatible = "qcom,sdhci-msm-v4"; -+ reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>; -+ reg-names = "hc_mem", "core_mem"; -+ interrupts = <0 125 0>, <0 221 0>; -+ interrupt-names = "hc_irq", "pwr_irq"; -+ clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ - rng@f9bff000 { - compatible = "qcom,prng"; - reg = <0xf9bff000 0x200>; diff --git a/target/linux/ipq806x/patches/0091-ARM-dts-qcom-Update-msm8974-apq8074-device-trees.patch b/target/linux/ipq806x/patches/0091-ARM-dts-qcom-Update-msm8974-apq8074-device-trees.patch deleted file mode 100644 index 0f6764d22b..0000000000 --- a/target/linux/ipq806x/patches/0091-ARM-dts-qcom-Update-msm8974-apq8074-device-trees.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 63495b04141e60ceb40d4632a41b7cd4a3d23dd2 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Wed, 28 May 2014 12:01:29 -0500 -Subject: [PATCH 091/182] ARM: dts: qcom: Update msm8974/apq8074 device trees - -* Move SoC peripherals into an SoC container node -* Move serial enabling into board file (qcom-apq8074-dragonboard.dts) -* Move spi pinctrl into board file -* Cleanup cpu node to match binding spec, enable-method and compatible - should be per cpu, not part of the container -* Drop interrupts property from l2-cache node as its not part of the - binding spec -* Move timer node out of SoC container - -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-apq8074-dragonboard.dts | 28 +++++++++++++- - arch/arm/boot/dts/qcom-msm8974.dtsi | 49 +++++++++--------------- - 2 files changed, 45 insertions(+), 32 deletions(-) - ---- a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts -+++ b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts -@@ -4,7 +4,11 @@ - model = "Qualcomm APQ8074 Dragonboard"; - compatible = "qcom,apq8074-dragonboard", "qcom,apq8074"; - -- soc: soc { -+ soc { -+ serial@f991e000 { -+ status = "ok"; -+ }; -+ - sdhci@f9824900 { - bus-width = <8>; - non-removable; -@@ -15,5 +19,27 @@ - cd-gpios = <&msmgpio 62 0x1>; - bus-width = <4>; - }; -+ -+ -+ pinctrl@fd510000 { -+ spi8_default: spi8_default { -+ mosi { -+ pins = "gpio45"; -+ function = "blsp_spi8"; -+ }; -+ miso { -+ pins = "gpio46"; -+ function = "blsp_spi8"; -+ }; -+ cs { -+ pins = "gpio47"; -+ function = "blsp_spi8"; -+ }; -+ clk { -+ pins = "gpio48"; -+ function = "blsp_spi8"; -+ }; -+ }; -+ }; - }; - }; ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -13,10 +13,10 @@ - #address-cells = <1>; - #size-cells = <0>; - interrupts = <1 9 0xf04>; -- compatible = "qcom,krait"; -- enable-method = "qcom,kpss-acc-v2"; - - cpu@0 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v2"; - device_type = "cpu"; - reg = <0>; - next-level-cache = <&L2>; -@@ -24,6 +24,8 @@ - }; - - cpu@1 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v2"; - device_type = "cpu"; - reg = <1>; - next-level-cache = <&L2>; -@@ -31,6 +33,8 @@ - }; - - cpu@2 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v2"; - device_type = "cpu"; - reg = <2>; - next-level-cache = <&L2>; -@@ -38,6 +42,8 @@ - }; - - cpu@3 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v2"; - device_type = "cpu"; - reg = <3>; - next-level-cache = <&L2>; -@@ -47,7 +53,6 @@ - L2: l2-cache { - compatible = "cache"; - cache-level = <2>; -- interrupts = <0 2 0x4>; - qcom,saw = <&saw_l2>; - }; - }; -@@ -57,6 +62,15 @@ - interrupts = <1 7 0xf04>; - }; - -+ timer { -+ compatible = "arm,armv7-timer"; -+ interrupts = <1 2 0xf08>, -+ <1 3 0xf08>, -+ <1 4 0xf08>, -+ <1 1 0xf08>; -+ clock-frequency = <19200000>; -+ }; -+ - soc: soc { - #address-cells = <1>; - #size-cells = <1>; -@@ -71,15 +85,6 @@ - <0xf9002000 0x1000>; - }; - -- timer { -- compatible = "arm,armv7-timer"; -- interrupts = <1 2 0xf08>, -- <1 3 0xf08>, -- <1 4 0xf08>, -- <1 1 0xf08>; -- clock-frequency = <19200000>; -- }; -- - timer@f9020000 { - #address-cells = <1>; - #size-cells = <1>; -@@ -190,6 +195,7 @@ - interrupts = <0 108 0x0>; - clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>; - clock-names = "core", "iface"; -+ status = "disabled"; - }; - - sdhci@f9824900 { -@@ -229,25 +235,6 @@ - interrupt-controller; - #interrupt-cells = <2>; - interrupts = <0 208 0>; -- -- spi8_default: spi8_default { -- mosi { -- pins = "gpio45"; -- function = "blsp_spi8"; -- }; -- miso { -- pins = "gpio46"; -- function = "blsp_spi8"; -- }; -- cs { -- pins = "gpio47"; -- function = "blsp_spi8"; -- }; -- clk { -- pins = "gpio48"; -- function = "blsp_spi8"; -- }; -- }; - }; - }; - }; diff --git a/target/linux/ipq806x/patches/0092-ARM-dts-qcom-Update-msm8960-device-trees.patch b/target/linux/ipq806x/patches/0092-ARM-dts-qcom-Update-msm8960-device-trees.patch deleted file mode 100644 index 5b24b4a9bb..0000000000 --- a/target/linux/ipq806x/patches/0092-ARM-dts-qcom-Update-msm8960-device-trees.patch +++ /dev/null @@ -1,261 +0,0 @@ -From 881200420e6ece87d9abbb13c0653d26455cdbdd Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Wed, 28 May 2014 12:09:53 -0500 -Subject: [PATCH 092/182] ARM: dts: qcom: Update msm8960 device trees - -* Move SoC peripherals into an SoC container node -* Move serial enabling into board file (qcom-msm8960-cdp.dts) -* Cleanup cpu node to match binding spec, enable-method and compatible - should be per cpu, not part of the container -* Drop interrupts property from l2-cache node as its not part of the - binding spec -* Add GSBI node and configuration of GSBI controller - -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-msm8960-cdp.dts | 10 ++ - arch/arm/boot/dts/qcom-msm8960.dtsi | 176 ++++++++++++++++++-------------- - 2 files changed, 108 insertions(+), 78 deletions(-) - ---- a/arch/arm/boot/dts/qcom-msm8960-cdp.dts -+++ b/arch/arm/boot/dts/qcom-msm8960-cdp.dts -@@ -3,4 +3,14 @@ - / { - model = "Qualcomm MSM8960 CDP"; - compatible = "qcom,msm8960-cdp", "qcom,msm8960"; -+ -+ soc { -+ gsbi@16400000 { -+ status = "ok"; -+ qcom,mode = ; -+ serial@16440000 { -+ status = "ok"; -+ }; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/qcom-msm8960.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi -@@ -3,6 +3,7 @@ - /include/ "skeleton.dtsi" - - #include -+#include - - / { - model = "Qualcomm MSM8960"; -@@ -13,10 +14,10 @@ - #address-cells = <1>; - #size-cells = <0>; - interrupts = <1 14 0x304>; -- compatible = "qcom,krait"; -- enable-method = "qcom,kpss-acc-v1"; - - cpu@0 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; - device_type = "cpu"; - reg = <0>; - next-level-cache = <&L2>; -@@ -25,6 +26,8 @@ - }; - - cpu@1 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; - device_type = "cpu"; - reg = <1>; - next-level-cache = <&L2>; -@@ -35,7 +38,6 @@ - L2: l2-cache { - compatible = "cache"; - cache-level = <2>; -- interrupts = <0 2 0x4>; - }; - }; - -@@ -45,91 +47,109 @@ - qcom,no-pc-write; - }; - -- intc: interrupt-controller@2000000 { -- compatible = "qcom,msm-qgic2"; -- interrupt-controller; -- #interrupt-cells = <3>; -- reg = < 0x02000000 0x1000 >, -- < 0x02002000 0x1000 >; -- }; -+ soc: soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ compatible = "simple-bus"; -+ -+ intc: interrupt-controller@2000000 { -+ compatible = "qcom,msm-qgic2"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = <0x02000000 0x1000>, -+ <0x02002000 0x1000>; -+ }; - -- timer@200a000 { -- compatible = "qcom,kpss-timer", "qcom,msm-timer"; -- interrupts = <1 1 0x301>, -- <1 2 0x301>, -- <1 3 0x301>; -- reg = <0x0200a000 0x100>; -- clock-frequency = <27000000>, -- <32768>; -- cpu-offset = <0x80000>; -- }; -+ timer@200a000 { -+ compatible = "qcom,kpss-timer", "qcom,msm-timer"; -+ interrupts = <1 1 0x301>, -+ <1 2 0x301>, -+ <1 3 0x301>; -+ reg = <0x0200a000 0x100>; -+ clock-frequency = <27000000>, -+ <32768>; -+ cpu-offset = <0x80000>; -+ }; - -- msmgpio: gpio@800000 { -- compatible = "qcom,msm-gpio"; -- gpio-controller; -- #gpio-cells = <2>; -- ngpio = <150>; -- interrupts = <0 16 0x4>; -- interrupt-controller; -- #interrupt-cells = <2>; -- reg = <0x800000 0x4000>; -- }; -+ msmgpio: gpio@800000 { -+ compatible = "qcom,msm-gpio"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ ngpio = <150>; -+ interrupts = <0 16 0x4>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ reg = <0x800000 0x4000>; -+ }; - -- gcc: clock-controller@900000 { -- compatible = "qcom,gcc-msm8960"; -- #clock-cells = <1>; -- #reset-cells = <1>; -- reg = <0x900000 0x4000>; -- }; -+ gcc: clock-controller@900000 { -+ compatible = "qcom,gcc-msm8960"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ reg = <0x900000 0x4000>; -+ }; - -- clock-controller@4000000 { -- compatible = "qcom,mmcc-msm8960"; -- reg = <0x4000000 0x1000>; -- #clock-cells = <1>; -- #reset-cells = <1>; -- }; -+ clock-controller@4000000 { -+ compatible = "qcom,mmcc-msm8960"; -+ reg = <0x4000000 0x1000>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; - -- acc0: clock-controller@2088000 { -- compatible = "qcom,kpss-acc-v1"; -- reg = <0x02088000 0x1000>, <0x02008000 0x1000>; -- }; -+ acc0: clock-controller@2088000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02088000 0x1000>, <0x02008000 0x1000>; -+ }; - -- acc1: clock-controller@2098000 { -- compatible = "qcom,kpss-acc-v1"; -- reg = <0x02098000 0x1000>, <0x02008000 0x1000>; -- }; -+ acc1: clock-controller@2098000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02098000 0x1000>, <0x02008000 0x1000>; -+ }; - -- saw0: regulator@2089000 { -- compatible = "qcom,saw2"; -- reg = <0x02089000 0x1000>, <0x02009000 0x1000>; -- regulator; -- }; -+ saw0: regulator@2089000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02089000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; - -- saw1: regulator@2099000 { -- compatible = "qcom,saw2"; -- reg = <0x02099000 0x1000>, <0x02009000 0x1000>; -- regulator; -- }; -+ saw1: regulator@2099000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02099000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; - -- serial@16440000 { -- compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -- reg = <0x16440000 0x1000>, -- <0x16400000 0x1000>; -- interrupts = <0 154 0x0>; -- clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>; -- clock-names = "core", "iface"; -- }; -+ gsbi5: gsbi@16400000 { -+ compatible = "qcom,gsbi-v1.0.0"; -+ reg = <0x16400000 0x100>; -+ clocks = <&gcc GSBI5_H_CLK>; -+ clock-names = "iface"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ serial@16440000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x16440000 0x1000>, -+ <0x16400000 0x1000>; -+ interrupts = <0 154 0x0>; -+ clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ }; - -- qcom,ssbi@500000 { -- compatible = "qcom,ssbi"; -- reg = <0x500000 0x1000>; -- qcom,controller-type = "pmic-arbiter"; -- }; -+ qcom,ssbi@500000 { -+ compatible = "qcom,ssbi"; -+ reg = <0x500000 0x1000>; -+ qcom,controller-type = "pmic-arbiter"; -+ }; - -- rng@1a500000 { -- compatible = "qcom,prng"; -- reg = <0x1a500000 0x200>; -- clocks = <&gcc PRNG_CLK>; -- clock-names = "core"; -+ rng@1a500000 { -+ compatible = "qcom,prng"; -+ reg = <0x1a500000 0x200>; -+ clocks = <&gcc PRNG_CLK>; -+ clock-names = "core"; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0093-ARM-dts-qcom-Update-msm8660-device-trees.patch b/target/linux/ipq806x/patches/0093-ARM-dts-qcom-Update-msm8660-device-trees.patch deleted file mode 100644 index 8359faffaa..0000000000 --- a/target/linux/ipq806x/patches/0093-ARM-dts-qcom-Update-msm8660-device-trees.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 355bf7c6410f5b6e37b5c2b28ebe59bb701c42d6 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Wed, 28 May 2014 12:12:40 -0500 -Subject: [PATCH 093/182] ARM: dts: qcom: Update msm8660 device trees - -* Move SoC peripherals into an SoC container node -* Move serial enabling into board file (qcom-msm8660-surf.dts) -* Cleanup cpu node to match binding spec, enable-method and compatible - should be per cpu, not part of the container -* Add GSBI node and configuration of GSBI controller - -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-msm8660-surf.dts | 10 +++ - arch/arm/boot/dts/qcom-msm8660.dtsi | 115 ++++++++++++++++++------------- - 2 files changed, 78 insertions(+), 47 deletions(-) - ---- a/arch/arm/boot/dts/qcom-msm8660-surf.dts -+++ b/arch/arm/boot/dts/qcom-msm8660-surf.dts -@@ -3,4 +3,14 @@ - / { - model = "Qualcomm MSM8660 SURF"; - compatible = "qcom,msm8660-surf", "qcom,msm8660"; -+ -+ soc { -+ gsbi@19c00000 { -+ status = "ok"; -+ qcom,mode = ; -+ serial@19c40000 { -+ status = "ok"; -+ }; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/qcom-msm8660.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi -@@ -3,6 +3,7 @@ - /include/ "skeleton.dtsi" - - #include -+#include - - / { - model = "Qualcomm MSM8660"; -@@ -12,16 +13,18 @@ - cpus { - #address-cells = <1>; - #size-cells = <0>; -- compatible = "qcom,scorpion"; -- enable-method = "qcom,gcc-msm8660"; - - cpu@0 { -+ compatible = "qcom,scorpion"; -+ enable-method = "qcom,gcc-msm8660"; - device_type = "cpu"; - reg = <0>; - next-level-cache = <&L2>; - }; - - cpu@1 { -+ compatible = "qcom,scorpion"; -+ enable-method = "qcom,gcc-msm8660"; - device_type = "cpu"; - reg = <1>; - next-level-cache = <&L2>; -@@ -33,55 +36,73 @@ - }; - }; - -- intc: interrupt-controller@2080000 { -- compatible = "qcom,msm-8660-qgic"; -- interrupt-controller; -- #interrupt-cells = <3>; -- reg = < 0x02080000 0x1000 >, -- < 0x02081000 0x1000 >; -- }; -+ soc: soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ compatible = "simple-bus"; -+ -+ intc: interrupt-controller@2080000 { -+ compatible = "qcom,msm-8660-qgic"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = < 0x02080000 0x1000 >, -+ < 0x02081000 0x1000 >; -+ }; - -- timer@2000000 { -- compatible = "qcom,scss-timer", "qcom,msm-timer"; -- interrupts = <1 0 0x301>, -- <1 1 0x301>, -- <1 2 0x301>; -- reg = <0x02000000 0x100>; -- clock-frequency = <27000000>, -- <32768>; -- cpu-offset = <0x40000>; -- }; -+ timer@2000000 { -+ compatible = "qcom,scss-timer", "qcom,msm-timer"; -+ interrupts = <1 0 0x301>, -+ <1 1 0x301>, -+ <1 2 0x301>; -+ reg = <0x02000000 0x100>; -+ clock-frequency = <27000000>, -+ <32768>; -+ cpu-offset = <0x40000>; -+ }; - -- msmgpio: gpio@800000 { -- compatible = "qcom,msm-gpio"; -- reg = <0x00800000 0x4000>; -- gpio-controller; -- #gpio-cells = <2>; -- ngpio = <173>; -- interrupts = <0 16 0x4>; -- interrupt-controller; -- #interrupt-cells = <2>; -- }; -+ msmgpio: gpio@800000 { -+ compatible = "qcom,msm-gpio"; -+ reg = <0x00800000 0x4000>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ ngpio = <173>; -+ interrupts = <0 16 0x4>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; - -- gcc: clock-controller@900000 { -- compatible = "qcom,gcc-msm8660"; -- #clock-cells = <1>; -- #reset-cells = <1>; -- reg = <0x900000 0x4000>; -- }; -+ gcc: clock-controller@900000 { -+ compatible = "qcom,gcc-msm8660"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ reg = <0x900000 0x4000>; -+ }; - -- serial@19c40000 { -- compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -- reg = <0x19c40000 0x1000>, -- <0x19c00000 0x1000>; -- interrupts = <0 195 0x0>; -- clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>; -- clock-names = "core", "iface"; -- }; -+ gsbi12: gsbi@19c00000 { -+ compatible = "qcom,gsbi-v1.0.0"; -+ reg = <0x19c00000 0x100>; -+ clocks = <&gcc GSBI12_H_CLK>; -+ clock-names = "iface"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ serial@19c40000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x19c40000 0x1000>, -+ <0x19c00000 0x1000>; -+ interrupts = <0 195 0x0>; -+ clocks = <&gcc GSBI12_UART_CLK>, <&gcc GSBI12_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ }; - -- qcom,ssbi@500000 { -- compatible = "qcom,ssbi"; -- reg = <0x500000 0x1000>; -- qcom,controller-type = "pmic-arbiter"; -+ qcom,ssbi@500000 { -+ compatible = "qcom,ssbi"; -+ reg = <0x500000 0x1000>; -+ qcom,controller-type = "pmic-arbiter"; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0094-ARM-dts-qcom-Add-initial-APQ8064-SoC-and-IFC6410-boa.patch b/target/linux/ipq806x/patches/0094-ARM-dts-qcom-Add-initial-APQ8064-SoC-and-IFC6410-boa.patch deleted file mode 100644 index fb2910b749..0000000000 --- a/target/linux/ipq806x/patches/0094-ARM-dts-qcom-Add-initial-APQ8064-SoC-and-IFC6410-boa.patch +++ /dev/null @@ -1,249 +0,0 @@ -From 07d7d95706c1bf373bd6b30c42f95c7b8dc8b9ce Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 3 Apr 2014 14:48:22 -0500 -Subject: [PATCH 094/182] ARM: dts: qcom: Add initial APQ8064 SoC and IFC6410 - board device trees - -Add basic APQ8064 SoC include device tree and support for basic booting on -the IFC6410 board. Also, keep dtb build list and qcom_dt_match in sorted -order. - -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/Makefile | 8 +- - arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | 16 +++ - arch/arm/boot/dts/qcom-apq8064-v2.0.dtsi | 1 + - arch/arm/boot/dts/qcom-apq8064.dtsi | 170 ++++++++++++++++++++++++++++ - arch/arm/mach-qcom/board.c | 3 +- - 5 files changed, 194 insertions(+), 4 deletions(-) - create mode 100644 arch/arm/boot/dts/qcom-apq8064-ifc6410.dts - create mode 100644 arch/arm/boot/dts/qcom-apq8064-v2.0.dtsi - create mode 100644 arch/arm/boot/dts/qcom-apq8064.dtsi - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -231,9 +231,11 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420 - dra7-evm.dtb - dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb - dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb --dtb-$(CONFIG_ARCH_QCOM) += qcom-msm8660-surf.dtb \ -- qcom-msm8960-cdp.dtb \ -- qcom-apq8074-dragonboard.dtb -+dtb-$(CONFIG_ARCH_QCOM) += \ -+ qcom-apq8064-ifc6410.dtb \ -+ qcom-apq8074-dragonboard.dtb \ -+ qcom-msm8660-surf.dtb \ -+ qcom-msm8960-cdp.dtb - dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ - ste-hrefprev60-stuib.dtb \ - ste-hrefprev60-tvk.dtb \ ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts -@@ -0,0 +1,16 @@ -+#include "qcom-apq8064-v2.0.dtsi" -+ -+/ { -+ model = "Qualcomm APQ8064/IFC6410"; -+ compatible = "qcom,apq8064-ifc6410", "qcom,apq8064"; -+ -+ soc { -+ gsbi@16600000 { -+ status = "ok"; -+ qcom,mode = ; -+ serial@16640000 { -+ status = "ok"; -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-apq8064-v2.0.dtsi -@@ -0,0 +1 @@ -+#include "qcom-apq8064.dtsi" ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi -@@ -0,0 +1,170 @@ -+/dts-v1/; -+ -+#include "skeleton.dtsi" -+#include -+#include -+ -+/ { -+ model = "Qualcomm APQ8064"; -+ compatible = "qcom,apq8064"; -+ interrupt-parent = <&intc>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; -+ device_type = "cpu"; -+ reg = <0>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc0>; -+ qcom,saw = <&saw0>; -+ }; -+ -+ cpu@1 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; -+ device_type = "cpu"; -+ reg = <1>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc1>; -+ qcom,saw = <&saw1>; -+ }; -+ -+ cpu@2 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; -+ device_type = "cpu"; -+ reg = <2>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc2>; -+ qcom,saw = <&saw2>; -+ }; -+ -+ cpu@3 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; -+ device_type = "cpu"; -+ reg = <3>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc3>; -+ qcom,saw = <&saw3>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "cache"; -+ cache-level = <2>; -+ }; -+ }; -+ -+ cpu-pmu { -+ compatible = "qcom,krait-pmu"; -+ interrupts = <1 10 0x304>; -+ }; -+ -+ soc: soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ compatible = "simple-bus"; -+ -+ intc: interrupt-controller@2000000 { -+ compatible = "qcom,msm-qgic2"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = <0x02000000 0x1000>, -+ <0x02002000 0x1000>; -+ }; -+ -+ timer@200a000 { -+ compatible = "qcom,kpss-timer", "qcom,msm-timer"; -+ interrupts = <1 1 0x301>, -+ <1 2 0x301>, -+ <1 3 0x301>; -+ reg = <0x0200a000 0x100>; -+ clock-frequency = <27000000>, -+ <32768>; -+ cpu-offset = <0x80000>; -+ }; -+ -+ acc0: clock-controller@2088000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02088000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ acc1: clock-controller@2098000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02098000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ acc2: clock-controller@20a8000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x020a8000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ acc3: clock-controller@20b8000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x020b8000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ saw0: regulator@2089000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02089000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ -+ saw1: regulator@2099000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02099000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ -+ saw2: regulator@20a9000 { -+ compatible = "qcom,saw2"; -+ reg = <0x020a9000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ -+ saw3: regulator@20b9000 { -+ compatible = "qcom,saw2"; -+ reg = <0x020b9000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ -+ gsbi7: gsbi@16600000 { -+ status = "disabled"; -+ compatible = "qcom,gsbi-v1.0.0"; -+ reg = <0x16600000 0x100>; -+ clocks = <&gcc GSBI7_H_CLK>; -+ clock-names = "iface"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ serial@16640000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x16640000 0x1000>, -+ <0x16600000 0x1000>; -+ interrupts = <0 158 0x0>; -+ clocks = <&gcc GSBI7_UART_CLK>, <&gcc GSBI7_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ }; -+ -+ qcom,ssbi@500000 { -+ compatible = "qcom,ssbi"; -+ reg = <0x00500000 0x1000>; -+ qcom,controller-type = "pmic-arbiter"; -+ }; -+ -+ gcc: clock-controller@900000 { -+ compatible = "qcom,gcc-apq8064"; -+ reg = <0x00900000 0x4000>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; -+ }; -+}; ---- a/arch/arm/mach-qcom/board.c -+++ b/arch/arm/mach-qcom/board.c -@@ -15,9 +15,10 @@ - #include - - static const char * const qcom_dt_match[] __initconst = { -+ "qcom,apq8064", -+ "qcom,apq8074-dragonboard", - "qcom,msm8660-surf", - "qcom,msm8960-cdp", -- "qcom,apq8074-dragonboard", - NULL - }; - diff --git a/target/linux/ipq806x/patches/0095-ARM-dts-qcom-Add-APQ8084-MTP-board-support.patch b/target/linux/ipq806x/patches/0095-ARM-dts-qcom-Add-APQ8084-MTP-board-support.patch deleted file mode 100644 index 3c4f22114a..0000000000 --- a/target/linux/ipq806x/patches/0095-ARM-dts-qcom-Add-APQ8084-MTP-board-support.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9b06bc14f21463cf687ac6fdd07ca04b99c15466 Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Fri, 23 May 2014 18:12:30 +0300 -Subject: [PATCH 095/182] ARM: dts: qcom: Add APQ8084-MTP board support - -Add device-tree file for APQ8084-MTP board, which belongs -to the Snapdragon 805 family. - -Signed-off-by: Georgi Djakov -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/qcom-apq8084-mtp.dts | 6 ++++++ - 2 files changed, 7 insertions(+) - create mode 100644 arch/arm/boot/dts/qcom-apq8084-mtp.dts - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -234,6 +234,7 @@ dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb. - dtb-$(CONFIG_ARCH_QCOM) += \ - qcom-apq8064-ifc6410.dtb \ - qcom-apq8074-dragonboard.dtb \ -+ qcom-apq8084-mtp.dtb \ - qcom-msm8660-surf.dtb \ - qcom-msm8960-cdp.dtb - dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-apq8084-mtp.dts -@@ -0,0 +1,6 @@ -+#include "qcom-apq8084.dtsi" -+ -+/ { -+ model = "Qualcomm APQ 8084-MTP"; -+ compatible = "qcom,apq8084-mtp", "qcom,apq8084"; -+}; diff --git a/target/linux/ipq806x/patches/0096-ARM-dts-qcom-Add-APQ8084-SoC-support.patch b/target/linux/ipq806x/patches/0096-ARM-dts-qcom-Add-APQ8084-SoC-support.patch deleted file mode 100644 index 18630595c4..0000000000 --- a/target/linux/ipq806x/patches/0096-ARM-dts-qcom-Add-APQ8084-SoC-support.patch +++ /dev/null @@ -1,208 +0,0 @@ -From 8c52931421759b70fc37771be3390813a2a2f9f5 Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Fri, 23 May 2014 18:12:29 +0300 -Subject: [PATCH 096/182] ARM: dts: qcom: Add APQ8084 SoC support - -Add support for the Qualcomm Snapdragon 805 APQ8084 SoC. It is -used on APQ8084-MTP and other boards. - -Signed-off-by: Georgi Djakov -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/qcom-apq8084.dtsi | 179 +++++++++++++++++++++++++++++++++++ - arch/arm/mach-qcom/board.c | 1 + - 2 files changed, 180 insertions(+) - create mode 100644 arch/arm/boot/dts/qcom-apq8084.dtsi - ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi -@@ -0,0 +1,179 @@ -+/dts-v1/; -+ -+#include "skeleton.dtsi" -+ -+/ { -+ model = "Qualcomm APQ 8084"; -+ compatible = "qcom,apq8084"; -+ interrupt-parent = <&intc>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "qcom,krait"; -+ reg = <0>; -+ enable-method = "qcom,kpss-acc-v2"; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "qcom,krait"; -+ reg = <1>; -+ enable-method = "qcom,kpss-acc-v2"; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc1>; -+ }; -+ -+ cpu@2 { -+ device_type = "cpu"; -+ compatible = "qcom,krait"; -+ reg = <2>; -+ enable-method = "qcom,kpss-acc-v2"; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc2>; -+ }; -+ -+ cpu@3 { -+ device_type = "cpu"; -+ compatible = "qcom,krait"; -+ reg = <3>; -+ enable-method = "qcom,kpss-acc-v2"; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc3>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "qcom,arch-cache"; -+ cache-level = <2>; -+ qcom,saw = <&saw_l2>; -+ }; -+ }; -+ -+ cpu-pmu { -+ compatible = "qcom,krait-pmu"; -+ interrupts = <1 7 0xf04>; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ interrupts = <1 2 0xf08>, -+ <1 3 0xf08>, -+ <1 4 0xf08>, -+ <1 1 0xf08>; -+ clock-frequency = <19200000>; -+ }; -+ -+ soc: soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ compatible = "simple-bus"; -+ -+ intc: interrupt-controller@f9000000 { -+ compatible = "qcom,msm-qgic2"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = <0xf9000000 0x1000>, -+ <0xf9002000 0x1000>; -+ }; -+ -+ timer@f9020000 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ compatible = "arm,armv7-timer-mem"; -+ reg = <0xf9020000 0x1000>; -+ clock-frequency = <19200000>; -+ -+ frame@f9021000 { -+ frame-number = <0>; -+ interrupts = <0 8 0x4>, -+ <0 7 0x4>; -+ reg = <0xf9021000 0x1000>, -+ <0xf9022000 0x1000>; -+ }; -+ -+ frame@f9023000 { -+ frame-number = <1>; -+ interrupts = <0 9 0x4>; -+ reg = <0xf9023000 0x1000>; -+ status = "disabled"; -+ }; -+ -+ frame@f9024000 { -+ frame-number = <2>; -+ interrupts = <0 10 0x4>; -+ reg = <0xf9024000 0x1000>; -+ status = "disabled"; -+ }; -+ -+ frame@f9025000 { -+ frame-number = <3>; -+ interrupts = <0 11 0x4>; -+ reg = <0xf9025000 0x1000>; -+ status = "disabled"; -+ }; -+ -+ frame@f9026000 { -+ frame-number = <4>; -+ interrupts = <0 12 0x4>; -+ reg = <0xf9026000 0x1000>; -+ status = "disabled"; -+ }; -+ -+ frame@f9027000 { -+ frame-number = <5>; -+ interrupts = <0 13 0x4>; -+ reg = <0xf9027000 0x1000>; -+ status = "disabled"; -+ }; -+ -+ frame@f9028000 { -+ frame-number = <6>; -+ interrupts = <0 14 0x4>; -+ reg = <0xf9028000 0x1000>; -+ status = "disabled"; -+ }; -+ }; -+ -+ saw_l2: regulator@f9012000 { -+ compatible = "qcom,saw2"; -+ reg = <0xf9012000 0x1000>; -+ regulator; -+ }; -+ -+ acc0: clock-controller@f9088000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf9088000 0x1000>, -+ <0xf9008000 0x1000>; -+ }; -+ -+ acc1: clock-controller@f9098000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf9098000 0x1000>, -+ <0xf9008000 0x1000>; -+ }; -+ -+ acc2: clock-controller@f90a8000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf90a8000 0x1000>, -+ <0xf9008000 0x1000>; -+ }; -+ -+ acc3: clock-controller@f90b8000 { -+ compatible = "qcom,kpss-acc-v2"; -+ reg = <0xf90b8000 0x1000>, -+ <0xf9008000 0x1000>; -+ }; -+ -+ restart@fc4ab000 { -+ compatible = "qcom,pshold"; -+ reg = <0xfc4ab000 0x4>; -+ }; -+ }; -+}; ---- a/arch/arm/mach-qcom/board.c -+++ b/arch/arm/mach-qcom/board.c -@@ -17,6 +17,7 @@ - static const char * const qcom_dt_match[] __initconst = { - "qcom,apq8064", - "qcom,apq8074-dragonboard", -+ "qcom,apq8084", - "qcom,msm8660-surf", - "qcom,msm8960-cdp", - NULL diff --git a/target/linux/ipq806x/patches/0097-ARM-debug-qcom-make-UART-address-selection-configura.patch b/target/linux/ipq806x/patches/0097-ARM-debug-qcom-make-UART-address-selection-configura.patch deleted file mode 100644 index 1c67fb70ea..0000000000 --- a/target/linux/ipq806x/patches/0097-ARM-debug-qcom-make-UART-address-selection-configura.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 48167d4a55890a783cc8b1590bc8071253ae4b83 Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Mon, 14 Apr 2014 16:47:34 +0300 -Subject: [PATCH 097/182] ARM: debug: qcom: make UART address selection - configuration option - -Separate Qualcomm low-level debugging UART to two options. - -DEBUG_MSM_UART is used in earlier non-multi platform arches, -like MSM7X00A, QSD8X50 and MSM7X30. - -DEBUG_QCOM_UARTDM is used in multi-plafrom arches and have -embedded data mover. - -Make DEBUG_UART_PHYS and DEBUG_UART_BASE user adjustable by -Kconfig menu. - -Signed-off-by: Ivan T. Ivanov -Reviewed-by: Stephen Boyd -Tested-by: Stephen Boyd -Signed-off-by: Kumar Gala ---- - arch/arm/Kconfig.debug | 81 +++++++++++++++++------------------------- - arch/arm/include/debug/msm.S | 46 +++--------------------- - arch/arm/mach-msm/Kconfig | 3 -- - 3 files changed, 38 insertions(+), 92 deletions(-) - ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -353,56 +353,39 @@ choice - Say Y here if you want kernel low-level debugging support - on MMP UART3. - -- config DEBUG_MSM_UART1 -- bool "Kernel low-level debugging messages via MSM UART1" -- depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 -- select DEBUG_MSM_UART -+ config DEBUG_MSM_UART -+ bool "Kernel low-level debugging messages via MSM UART" -+ depends on ARCH_MSM - help - Say Y here if you want the debug print routines to direct -- their output to the first serial port on MSM devices. -+ their output to the serial port on MSM devices. - -- config DEBUG_MSM_UART2 -- bool "Kernel low-level debugging messages via MSM UART2" -- depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 -- select DEBUG_MSM_UART -- help -- Say Y here if you want the debug print routines to direct -- their output to the second serial port on MSM devices. -+ ARCH DEBUG_UART_PHYS DEBUG_UART_BASE # -+ MSM7X00A, QSD8X50 0xa9a00000 0xe1000000 UART1 -+ MSM7X00A, QSD8X50 0xa9b00000 0xe1000000 UART2 -+ MSM7X00A, QSD8X50 0xa9c00000 0xe1000000 UART3 - -- config DEBUG_MSM_UART3 -- bool "Kernel low-level debugging messages via MSM UART3" -- depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 -- select DEBUG_MSM_UART -- help -- Say Y here if you want the debug print routines to direct -- their output to the third serial port on MSM devices. -+ MSM7X30 0xaca00000 0xe1000000 UART1 -+ MSM7X30 0xacb00000 0xe1000000 UART2 -+ MSM7X30 0xacc00000 0xe1000000 UART3 - -- config DEBUG_MSM8660_UART -- bool "Kernel low-level debugging messages via MSM 8660 UART" -- depends on ARCH_MSM8X60 -- select MSM_HAS_DEBUG_UART_HS -- select DEBUG_MSM_UART -- help -- Say Y here if you want the debug print routines to direct -- their output to the serial port on MSM 8660 devices. -+ Please adjust DEBUG_UART_PHYS and DEBUG_UART_BASE configuration -+ options based on your needs. - -- config DEBUG_MSM8960_UART -- bool "Kernel low-level debugging messages via MSM 8960 UART" -- depends on ARCH_MSM8960 -- select MSM_HAS_DEBUG_UART_HS -- select DEBUG_MSM_UART -+ config DEBUG_QCOM_UARTDM -+ bool "Kernel low-level debugging messages via QCOM UARTDM" -+ depends on ARCH_QCOM - help - Say Y here if you want the debug print routines to direct -- their output to the serial port on MSM 8960 devices. -+ their output to the serial port on Qualcomm devices. - -- config DEBUG_MSM8974_UART -- bool "Kernel low-level debugging messages via MSM 8974 UART" -- depends on ARCH_MSM8974 -- select MSM_HAS_DEBUG_UART_HS -- select DEBUG_MSM_UART -- help -- Say Y here if you want the debug print routines to direct -- their output to the serial port on MSM 8974 devices. -+ ARCH DEBUG_UART_PHYS DEBUG_UART_BASE -+ MSM8X60 0x19c40000 0xf0040000 -+ MSM8960 0x16440000 0xf0040000 -+ MSM8974 0xf991e000 0xfa71e000 -+ -+ Please adjust DEBUG_UART_PHYS and DEBUG_UART_BASE configuration -+ options based on your needs. - - config DEBUG_MVEBU_UART - bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)" -@@ -954,10 +937,6 @@ config DEBUG_STI_UART - bool - depends on ARCH_STI - --config DEBUG_MSM_UART -- bool -- depends on ARCH_MSM || ARCH_QCOM -- - config DEBUG_LL_INCLUDE - string - default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250 -@@ -975,7 +954,7 @@ config DEBUG_LL_INCLUDE - DEBUG_IMX53_UART ||\ - DEBUG_IMX6Q_UART || \ - DEBUG_IMX6SL_UART -- default "debug/msm.S" if DEBUG_MSM_UART -+ default "debug/msm.S" if DEBUG_MSM_UART || DEBUG_QCOM_UARTDM - default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART - default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1 - default "debug/sti.S" if DEBUG_STI_UART -@@ -1039,6 +1018,7 @@ config DEBUG_UART_PHYS - default 0x80074000 if DEBUG_IMX28_UART - default 0x808c0000 if ARCH_EP93XX - default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART -+ default 0xa9a00000 if DEBUG_MSM_UART - default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX - default 0xc0013000 if DEBUG_U300_UART - default 0xc8000000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN -@@ -1054,6 +1034,7 @@ config DEBUG_UART_PHYS - ARCH_ORION5X - default 0xf7fc9000 if DEBUG_BERLIN_UART - default 0xf8b00000 if DEBUG_HI3716_UART -+ default 0xf991e000 if DEBUG_QCOM_UARTDM - default 0xfcb00000 if DEBUG_HI3620_UART - default 0xfe800000 if ARCH_IOP32X - default 0xffc02000 if DEBUG_SOCFPGA_UART -@@ -1062,11 +1043,13 @@ config DEBUG_UART_PHYS - default 0xfffff700 if ARCH_IOP33X - depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \ - DEBUG_LL_UART_EFM32 || \ -- DEBUG_UART_8250 || DEBUG_UART_PL01X -+ DEBUG_UART_8250 || DEBUG_UART_PL01X || \ -+ DEBUG_MSM_UART || DEBUG_QCOM_UARTDM - - config DEBUG_UART_VIRT - hex "Virtual base address of debug UART" - default 0xe0010fe0 if ARCH_RPC -+ default 0xe1000000 if DEBUG_MSM_UART - default 0xf0000be0 if ARCH_EBSA110 - default 0xf0009000 if DEBUG_CNS3XXX - default 0xf01fb000 if DEBUG_NOMADIK_UART -@@ -1081,6 +1064,7 @@ config DEBUG_UART_VIRT - default 0xf7fc9000 if DEBUG_BERLIN_UART - default 0xf8009000 if DEBUG_VEXPRESS_UART0_CA9 - default 0xf8090000 if DEBUG_VEXPRESS_UART0_RS1 -+ default 0xfa71e000 if DEBUG_QCOM_UARTDM - default 0xfb009000 if DEBUG_REALVIEW_STD_PORT - default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT - default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX -@@ -1120,7 +1104,8 @@ config DEBUG_UART_VIRT - default 0xff003000 if DEBUG_U300_UART - default DEBUG_UART_PHYS if !MMU - depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \ -- DEBUG_UART_8250 || DEBUG_UART_PL01X -+ DEBUG_UART_8250 || DEBUG_UART_PL01X || \ -+ DEBUG_MSM_UART || DEBUG_QCOM_UARTDM - - config DEBUG_UART_8250_SHIFT - int "Register offset shift for the 8250 debug UART" ---- a/arch/arm/include/debug/msm.S -+++ b/arch/arm/include/debug/msm.S -@@ -15,51 +15,15 @@ - * - */ - --#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_QSD8X50) --#define MSM_UART1_PHYS 0xA9A00000 --#define MSM_UART2_PHYS 0xA9B00000 --#define MSM_UART3_PHYS 0xA9C00000 --#elif defined(CONFIG_ARCH_MSM7X30) --#define MSM_UART1_PHYS 0xACA00000 --#define MSM_UART2_PHYS 0xACB00000 --#define MSM_UART3_PHYS 0xACC00000 --#endif -- --#if defined(CONFIG_DEBUG_MSM_UART1) --#define MSM_DEBUG_UART_BASE 0xE1000000 --#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS --#elif defined(CONFIG_DEBUG_MSM_UART2) --#define MSM_DEBUG_UART_BASE 0xE1000000 --#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS --#elif defined(CONFIG_DEBUG_MSM_UART3) --#define MSM_DEBUG_UART_BASE 0xE1000000 --#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS --#endif -- --#ifdef CONFIG_DEBUG_MSM8660_UART --#define MSM_DEBUG_UART_BASE 0xF0040000 --#define MSM_DEBUG_UART_PHYS 0x19C40000 --#endif -- --#ifdef CONFIG_DEBUG_MSM8960_UART --#define MSM_DEBUG_UART_BASE 0xF0040000 --#define MSM_DEBUG_UART_PHYS 0x16440000 --#endif -- --#ifdef CONFIG_DEBUG_MSM8974_UART --#define MSM_DEBUG_UART_BASE 0xFA71E000 --#define MSM_DEBUG_UART_PHYS 0xF991E000 --#endif -- - .macro addruart, rp, rv, tmp --#ifdef MSM_DEBUG_UART_PHYS -- ldr \rp, =MSM_DEBUG_UART_PHYS -- ldr \rv, =MSM_DEBUG_UART_BASE -+#ifdef CONFIG_DEBUG_UART_PHYS -+ ldr \rp, =CONFIG_DEBUG_UART_PHYS -+ ldr \rv, =CONFIG_DEBUG_UART_VIRT - #endif - .endm - - .macro senduart, rd, rx --#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS -+#ifdef CONFIG_DEBUG_QCOM_UARTDM - @ Write the 1 character to UARTDM_TF - str \rd, [\rx, #0x70] - #else -@@ -68,7 +32,7 @@ - .endm - - .macro waituart, rd, rx --#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS -+#ifdef CONFIG_DEBUG_QCOM_UARTDM - @ check for TX_EMT in UARTDM_SR - ldr \rd, [\rx, #0x08] - tst \rd, #0x08 ---- a/arch/arm/mach-msm/Kconfig -+++ b/arch/arm/mach-msm/Kconfig -@@ -42,9 +42,6 @@ config ARCH_QSD8X50 - - endchoice - --config MSM_HAS_DEBUG_UART_HS -- bool -- - config MSM_SOC_REV_A - bool - diff --git a/target/linux/ipq806x/patches/0098-ARM-debug-qcom-add-UART-addresses-to-Kconfig-help-fo.patch b/target/linux/ipq806x/patches/0098-ARM-debug-qcom-add-UART-addresses-to-Kconfig-help-fo.patch deleted file mode 100644 index a94a7c9a95..0000000000 --- a/target/linux/ipq806x/patches/0098-ARM-debug-qcom-add-UART-addresses-to-Kconfig-help-fo.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0a551e04e9a36ca1f8332071787b0e26bc5f8ecc Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Fri, 23 May 2014 18:12:32 +0300 -Subject: [PATCH 098/182] ARM: debug: qcom: add UART addresses to Kconfig help - for APQ8084 - -Add information about the APQ8084 debug UART physical and virtual -addresses in the DEBUG_QCOM_UARTDM Kconfig help section. - -Signed-off-by: Georgi Djakov -Signed-off-by: Kumar Gala ---- - arch/arm/Kconfig.debug | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -380,6 +380,7 @@ choice - their output to the serial port on Qualcomm devices. - - ARCH DEBUG_UART_PHYS DEBUG_UART_BASE -+ APQ8084 0xf995e000 0xfa75e000 - MSM8X60 0x19c40000 0xf0040000 - MSM8960 0x16440000 0xf0040000 - MSM8974 0xf991e000 0xfa71e000 diff --git a/target/linux/ipq806x/patches/0099-ARM-qcom-Enable-ARM_AMBA-option-for-Qualcomm-SOCs.patch b/target/linux/ipq806x/patches/0099-ARM-qcom-Enable-ARM_AMBA-option-for-Qualcomm-SOCs.patch deleted file mode 100644 index 1212da2204..0000000000 --- a/target/linux/ipq806x/patches/0099-ARM-qcom-Enable-ARM_AMBA-option-for-Qualcomm-SOCs.patch +++ /dev/null @@ -1,26 +0,0 @@ -From b6ee2071ec3af3ec90d93b8b70aa17d741590148 Mon Sep 17 00:00:00 2001 -From: Srinivas Kandagatla -Date: Thu, 15 May 2014 11:08:55 +0100 -Subject: [PATCH 099/182] ARM: qcom: Enable ARM_AMBA option for Qualcomm SOCs. - -As some of the IPs on Qualcomm SOCs are based on ARM PrimeCell IPs. -For example SDCC controller is PrimeCell MCI pl180. Adding this option will -give flexibility to reuse the existing drivers as it is without major -modifications. - -Signed-off-by: Srinivas Kandagatla -Signed-off-by: Kumar Gala ---- - arch/arm/mach-qcom/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/mach-qcom/Kconfig -+++ b/arch/arm/mach-qcom/Kconfig -@@ -2,6 +2,7 @@ config ARCH_QCOM - bool "Qualcomm Support" if ARCH_MULTI_V7 - select ARCH_REQUIRE_GPIOLIB - select ARM_GIC -+ select ARM_AMBA - select CLKSRC_OF - select GENERIC_CLOCKEVENTS - select HAVE_SMP diff --git a/target/linux/ipq806x/patches/0100-clk-qcom-Fix-msm8660-GCC-probe.patch b/target/linux/ipq806x/patches/0100-clk-qcom-Fix-msm8660-GCC-probe.patch deleted file mode 100644 index f1f1445a44..0000000000 --- a/target/linux/ipq806x/patches/0100-clk-qcom-Fix-msm8660-GCC-probe.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d54996ddc69b69fe21f776e1de1eace04bca01c3 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 16 May 2014 10:05:14 -0700 -Subject: [PATCH 100/182] clk: qcom: Fix msm8660 GCC probe - -When consolidating the msm8660 GCC probe code I forgot to keep -around these temporary clock registrations. Put them back so the -clock tree is not entirely orphaned. - -Fixes: 49fc825f0cc2 (clk: qcom: Consolidate common probe code) -Signed-off-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - drivers/clk/qcom/gcc-msm8660.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/drivers/clk/qcom/gcc-msm8660.c -+++ b/drivers/clk/qcom/gcc-msm8660.c -@@ -2718,6 +2718,18 @@ MODULE_DEVICE_TABLE(of, gcc_msm8660_matc - - static int gcc_msm8660_probe(struct platform_device *pdev) - { -+ struct clk *clk; -+ struct device *dev = &pdev->dev; -+ -+ /* Temporary until RPM clocks supported */ -+ clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ - return qcom_cc_probe(pdev, &gcc_msm8660_desc); - } - diff --git a/target/linux/ipq806x/patches/0101-clk-qcom-Fix-blsp2_ahb_clk-register-offset.patch b/target/linux/ipq806x/patches/0101-clk-qcom-Fix-blsp2_ahb_clk-register-offset.patch deleted file mode 100644 index 705582f538..0000000000 --- a/target/linux/ipq806x/patches/0101-clk-qcom-Fix-blsp2_ahb_clk-register-offset.patch +++ /dev/null @@ -1,25 +0,0 @@ -From b11c02becb4dadf5c375fef4b98f92af67106f18 Mon Sep 17 00:00:00 2001 -From: Georgi Djakov -Date: Tue, 20 May 2014 19:50:54 +0300 -Subject: [PATCH 101/182] clk: qcom: Fix blsp2_ahb_clk register offset - -The address of the blsp2_ahb_clk register is incorrect. Fix it. - -Signed-off-by: Georgi Djakov -Reviewed-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - drivers/clk/qcom/gcc-msm8974.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/clk/qcom/gcc-msm8974.c -+++ b/drivers/clk/qcom/gcc-msm8974.c -@@ -1341,7 +1341,7 @@ static struct clk_branch gcc_blsp1_uart6 - }; - - static struct clk_branch gcc_blsp2_ahb_clk = { -- .halt_reg = 0x05c4, -+ .halt_reg = 0x0944, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x1484, diff --git a/target/linux/ipq806x/patches/0104-clk-qcom-Return-highest-rate-when-round_rate-exceeds.patch b/target/linux/ipq806x/patches/0104-clk-qcom-Return-highest-rate-when-round_rate-exceeds.patch deleted file mode 100644 index 3312f2fc65..0000000000 --- a/target/linux/ipq806x/patches/0104-clk-qcom-Return-highest-rate-when-round_rate-exceeds.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 6417bb8469eb495d7f4e4b6b0ac08cbc1b8606cb Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 16 May 2014 16:07:10 -0700 -Subject: [PATCH 104/182] clk: qcom: Return highest rate when round_rate() - exceeds plan - -Some drivers may want to call clk_set_rate() with a very large -number to force the clock to go as fast as it possibly can -without having to know the range between the highest rate and -second highest rate. Add support for this by defaulting to the -highest rate in the frequency table if we can't find a frequency -greater than what is requested. - -Signed-off-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - drivers/clk/qcom/clk-rcg2.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/drivers/clk/qcom/clk-rcg2.c -+++ b/drivers/clk/qcom/clk-rcg2.c -@@ -181,7 +181,8 @@ struct freq_tbl *find_freq(const struct - if (rate <= f->freq) - return f; - -- return NULL; -+ /* Default to our fastest rate */ -+ return f - 1; - } - - static long _freq_tbl_determine_rate(struct clk_hw *hw, diff --git a/target/linux/ipq806x/patches/0105-clk-qcom-Support-display-RCG-clocks.patch b/target/linux/ipq806x/patches/0105-clk-qcom-Support-display-RCG-clocks.patch deleted file mode 100644 index befdfebe1a..0000000000 --- a/target/linux/ipq806x/patches/0105-clk-qcom-Support-display-RCG-clocks.patch +++ /dev/null @@ -1,371 +0,0 @@ -From 3123079878e29eb8c541111e30de4d1bb42ac6f9 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 16 May 2014 16:07:11 -0700 -Subject: [PATCH 105/182] clk: qcom: Support display RCG clocks - -Add support for the DSI/EDP/HDMI RCG clocks. With the proper -display driver in place this should allow us to support display -clocks on msm8974 based devices. - -Signed-off-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - drivers/clk/qcom/clk-rcg.h | 3 + - drivers/clk/qcom/clk-rcg2.c | 299 ++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 287 insertions(+), 15 deletions(-) - ---- a/drivers/clk/qcom/clk-rcg.h -+++ b/drivers/clk/qcom/clk-rcg.h -@@ -155,5 +155,8 @@ struct clk_rcg2 { - #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr) - - extern const struct clk_ops clk_rcg2_ops; -+extern const struct clk_ops clk_edp_pixel_ops; -+extern const struct clk_ops clk_byte_ops; -+extern const struct clk_ops clk_pixel_ops; - - #endif ---- a/drivers/clk/qcom/clk-rcg2.c -+++ b/drivers/clk/qcom/clk-rcg2.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include - -@@ -225,31 +226,25 @@ static long clk_rcg2_determine_rate(stru - return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p); - } - --static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) -+static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) - { -- struct clk_rcg2 *rcg = to_clk_rcg2(hw); -- const struct freq_tbl *f; - u32 cfg, mask; - int ret; - -- f = find_freq(rcg->freq_tbl, rate); -- if (!f) -- return -EINVAL; -- - if (rcg->mnd_width && f->n) { - mask = BIT(rcg->mnd_width) - 1; -- ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, -- mask, f->m); -+ ret = regmap_update_bits(rcg->clkr.regmap, -+ rcg->cmd_rcgr + M_REG, mask, f->m); - if (ret) - return ret; - -- ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, -- mask, ~(f->n - f->m)); -+ ret = regmap_update_bits(rcg->clkr.regmap, -+ rcg->cmd_rcgr + N_REG, mask, ~(f->n - f->m)); - if (ret) - return ret; - -- ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + D_REG, -- mask, ~f->n); -+ ret = regmap_update_bits(rcg->clkr.regmap, -+ rcg->cmd_rcgr + D_REG, mask, ~f->n); - if (ret) - return ret; - } -@@ -260,14 +255,26 @@ static int __clk_rcg2_set_rate(struct cl - cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT; - if (rcg->mnd_width && f->n) - cfg |= CFG_MODE_DUAL_EDGE; -- ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask, -- cfg); -+ ret = regmap_update_bits(rcg->clkr.regmap, -+ rcg->cmd_rcgr + CFG_REG, mask, cfg); - if (ret) - return ret; - - return update_config(rcg); - } - -+static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) -+{ -+ struct clk_rcg2 *rcg = to_clk_rcg2(hw); -+ const struct freq_tbl *f; -+ -+ f = find_freq(rcg->freq_tbl, rate); -+ if (!f) -+ return -EINVAL; -+ -+ return clk_rcg2_configure(rcg, f); -+} -+ - static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { -@@ -290,3 +297,265 @@ const struct clk_ops clk_rcg2_ops = { - .set_rate_and_parent = clk_rcg2_set_rate_and_parent, - }; - EXPORT_SYMBOL_GPL(clk_rcg2_ops); -+ -+struct frac_entry { -+ int num; -+ int den; -+}; -+ -+static const struct frac_entry frac_table_675m[] = { /* link rate of 270M */ -+ { 52, 295 }, /* 119 M */ -+ { 11, 57 }, /* 130.25 M */ -+ { 63, 307 }, /* 138.50 M */ -+ { 11, 50 }, /* 148.50 M */ -+ { 47, 206 }, /* 154 M */ -+ { 31, 100 }, /* 205.25 M */ -+ { 107, 269 }, /* 268.50 M */ -+ { }, -+}; -+ -+static struct frac_entry frac_table_810m[] = { /* Link rate of 162M */ -+ { 31, 211 }, /* 119 M */ -+ { 32, 199 }, /* 130.25 M */ -+ { 63, 307 }, /* 138.50 M */ -+ { 11, 60 }, /* 148.50 M */ -+ { 50, 263 }, /* 154 M */ -+ { 31, 120 }, /* 205.25 M */ -+ { 119, 359 }, /* 268.50 M */ -+ { }, -+}; -+ -+static int clk_edp_pixel_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_rcg2 *rcg = to_clk_rcg2(hw); -+ struct freq_tbl f = *rcg->freq_tbl; -+ const struct frac_entry *frac; -+ int delta = 100000; -+ s64 src_rate = parent_rate; -+ s64 request; -+ u32 mask = BIT(rcg->hid_width) - 1; -+ u32 hid_div; -+ -+ if (src_rate == 810000000) -+ frac = frac_table_810m; -+ else -+ frac = frac_table_675m; -+ -+ for (; frac->num; frac++) { -+ request = rate; -+ request *= frac->den; -+ request = div_s64(request, frac->num); -+ if ((src_rate < (request - delta)) || -+ (src_rate > (request + delta))) -+ continue; -+ -+ regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, -+ &hid_div); -+ f.pre_div = hid_div; -+ f.pre_div >>= CFG_SRC_DIV_SHIFT; -+ f.pre_div &= mask; -+ f.m = frac->num; -+ f.n = frac->den; -+ -+ return clk_rcg2_configure(rcg, &f); -+ } -+ -+ return -EINVAL; -+} -+ -+static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw, -+ unsigned long rate, unsigned long parent_rate, u8 index) -+{ -+ /* Parent index is set statically in frequency table */ -+ return clk_edp_pixel_set_rate(hw, rate, parent_rate); -+} -+ -+static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *p_rate, struct clk **p) -+{ -+ struct clk_rcg2 *rcg = to_clk_rcg2(hw); -+ const struct freq_tbl *f = rcg->freq_tbl; -+ const struct frac_entry *frac; -+ int delta = 100000; -+ s64 src_rate = *p_rate; -+ s64 request; -+ u32 mask = BIT(rcg->hid_width) - 1; -+ u32 hid_div; -+ -+ /* Force the correct parent */ -+ *p = clk_get_parent_by_index(hw->clk, f->src); -+ -+ if (src_rate == 810000000) -+ frac = frac_table_810m; -+ else -+ frac = frac_table_675m; -+ -+ for (; frac->num; frac++) { -+ request = rate; -+ request *= frac->den; -+ request = div_s64(request, frac->num); -+ if ((src_rate < (request - delta)) || -+ (src_rate > (request + delta))) -+ continue; -+ -+ regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, -+ &hid_div); -+ hid_div >>= CFG_SRC_DIV_SHIFT; -+ hid_div &= mask; -+ -+ return calc_rate(src_rate, frac->num, frac->den, !!frac->den, -+ hid_div); -+ } -+ -+ return -EINVAL; -+} -+ -+const struct clk_ops clk_edp_pixel_ops = { -+ .is_enabled = clk_rcg2_is_enabled, -+ .get_parent = clk_rcg2_get_parent, -+ .set_parent = clk_rcg2_set_parent, -+ .recalc_rate = clk_rcg2_recalc_rate, -+ .set_rate = clk_edp_pixel_set_rate, -+ .set_rate_and_parent = clk_edp_pixel_set_rate_and_parent, -+ .determine_rate = clk_edp_pixel_determine_rate, -+}; -+EXPORT_SYMBOL_GPL(clk_edp_pixel_ops); -+ -+static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *p_rate, struct clk **p) -+{ -+ struct clk_rcg2 *rcg = to_clk_rcg2(hw); -+ const struct freq_tbl *f = rcg->freq_tbl; -+ unsigned long parent_rate, div; -+ u32 mask = BIT(rcg->hid_width) - 1; -+ -+ if (rate == 0) -+ return -EINVAL; -+ -+ *p = clk_get_parent_by_index(hw->clk, f->src); -+ *p_rate = parent_rate = __clk_round_rate(*p, rate); -+ -+ div = DIV_ROUND_UP((2 * parent_rate), rate) - 1; -+ div = min_t(u32, div, mask); -+ -+ return calc_rate(parent_rate, 0, 0, 0, div); -+} -+ -+static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_rcg2 *rcg = to_clk_rcg2(hw); -+ struct freq_tbl f = *rcg->freq_tbl; -+ unsigned long div; -+ u32 mask = BIT(rcg->hid_width) - 1; -+ -+ div = DIV_ROUND_UP((2 * parent_rate), rate) - 1; -+ div = min_t(u32, div, mask); -+ -+ f.pre_div = div; -+ -+ return clk_rcg2_configure(rcg, &f); -+} -+ -+static int clk_byte_set_rate_and_parent(struct clk_hw *hw, -+ unsigned long rate, unsigned long parent_rate, u8 index) -+{ -+ /* Parent index is set statically in frequency table */ -+ return clk_byte_set_rate(hw, rate, parent_rate); -+} -+ -+const struct clk_ops clk_byte_ops = { -+ .is_enabled = clk_rcg2_is_enabled, -+ .get_parent = clk_rcg2_get_parent, -+ .set_parent = clk_rcg2_set_parent, -+ .recalc_rate = clk_rcg2_recalc_rate, -+ .set_rate = clk_byte_set_rate, -+ .set_rate_and_parent = clk_byte_set_rate_and_parent, -+ .determine_rate = clk_byte_determine_rate, -+}; -+EXPORT_SYMBOL_GPL(clk_byte_ops); -+ -+static const struct frac_entry frac_table_pixel[] = { -+ { 3, 8 }, -+ { 2, 9 }, -+ { 4, 9 }, -+ { 1, 1 }, -+ { } -+}; -+ -+static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *p_rate, struct clk **p) -+{ -+ struct clk_rcg2 *rcg = to_clk_rcg2(hw); -+ unsigned long request, src_rate; -+ int delta = 100000; -+ const struct freq_tbl *f = rcg->freq_tbl; -+ const struct frac_entry *frac = frac_table_pixel; -+ struct clk *parent = *p = clk_get_parent_by_index(hw->clk, f->src); -+ -+ for (; frac->num; frac++) { -+ request = (rate * frac->den) / frac->num; -+ -+ src_rate = __clk_round_rate(parent, request); -+ if ((src_rate < (request - delta)) || -+ (src_rate > (request + delta))) -+ continue; -+ -+ *p_rate = src_rate; -+ return (src_rate * frac->num) / frac->den; -+ } -+ -+ return -EINVAL; -+} -+ -+static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_rcg2 *rcg = to_clk_rcg2(hw); -+ struct freq_tbl f = *rcg->freq_tbl; -+ const struct frac_entry *frac = frac_table_pixel; -+ unsigned long request, src_rate; -+ int delta = 100000; -+ u32 mask = BIT(rcg->hid_width) - 1; -+ u32 hid_div; -+ struct clk *parent = clk_get_parent_by_index(hw->clk, f.src); -+ -+ for (; frac->num; frac++) { -+ request = (rate * frac->den) / frac->num; -+ -+ src_rate = __clk_round_rate(parent, request); -+ if ((src_rate < (request - delta)) || -+ (src_rate > (request + delta))) -+ continue; -+ -+ regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, -+ &hid_div); -+ f.pre_div = hid_div; -+ f.pre_div >>= CFG_SRC_DIV_SHIFT; -+ f.pre_div &= mask; -+ f.m = frac->num; -+ f.n = frac->den; -+ -+ return clk_rcg2_configure(rcg, &f); -+ } -+ return -EINVAL; -+} -+ -+static int clk_pixel_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate, u8 index) -+{ -+ /* Parent index is set statically in frequency table */ -+ return clk_pixel_set_rate(hw, rate, parent_rate); -+} -+ -+const struct clk_ops clk_pixel_ops = { -+ .is_enabled = clk_rcg2_is_enabled, -+ .get_parent = clk_rcg2_get_parent, -+ .set_parent = clk_rcg2_set_parent, -+ .recalc_rate = clk_rcg2_recalc_rate, -+ .set_rate = clk_pixel_set_rate, -+ .set_rate_and_parent = clk_pixel_set_rate_and_parent, -+ .determine_rate = clk_pixel_determine_rate, -+}; -+EXPORT_SYMBOL_GPL(clk_pixel_ops); diff --git a/target/linux/ipq806x/patches/0106-clk-qcom-Properly-support-display-clocks-on-msm8974.patch b/target/linux/ipq806x/patches/0106-clk-qcom-Properly-support-display-clocks-on-msm8974.patch deleted file mode 100644 index c7989171fc..0000000000 --- a/target/linux/ipq806x/patches/0106-clk-qcom-Properly-support-display-clocks-on-msm8974.patch +++ /dev/null @@ -1,254 +0,0 @@ -From 4ccbe584ecb970f86bab58c0ca93998cccc9e810 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 16 May 2014 16:07:12 -0700 -Subject: [PATCH 106/182] clk: qcom: Properly support display clocks on - msm8974 - -The display clocks all source from dedicated phy PLLs within their -respective multimedia hardware block. Hook up these PLLs to the -display clocks with the appropriate parent mappings, clock flags, -and the appropriate clock ops. This should allow the display -clocks to work once the appropriate phy PLL driver registers their -PLL clocks. - -Signed-off-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - drivers/clk/qcom/mmcc-msm8974.c | 105 ++++++++++++++++++++------------------- - 1 file changed, 54 insertions(+), 51 deletions(-) - ---- a/drivers/clk/qcom/mmcc-msm8974.c -+++ b/drivers/clk/qcom/mmcc-msm8974.c -@@ -41,9 +41,11 @@ - #define P_EDPVCO 3 - #define P_GPLL1 4 - #define P_DSI0PLL 4 -+#define P_DSI0PLL_BYTE 4 - #define P_MMPLL2 4 - #define P_MMPLL3 4 - #define P_DSI1PLL 5 -+#define P_DSI1PLL_BYTE 5 - - static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = { - [P_XO] = 0, -@@ -161,6 +163,24 @@ static const char *mmcc_xo_dsi_hdmi_edp_ - "dsi1pll", - }; - -+static const u8 mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = { -+ [P_XO] = 0, -+ [P_EDPLINK] = 4, -+ [P_HDMIPLL] = 3, -+ [P_GPLL0] = 5, -+ [P_DSI0PLL_BYTE] = 1, -+ [P_DSI1PLL_BYTE] = 2, -+}; -+ -+static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = { -+ "xo", -+ "edp_link_clk", -+ "hdmipll", -+ "gpll0_vote", -+ "dsi0pllbyte", -+ "dsi1pllbyte", -+}; -+ - #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } - - static struct clk_pll mmpll0 = { -@@ -500,15 +520,8 @@ static struct clk_rcg2 jpeg2_clk_src = { - }, - }; - --static struct freq_tbl ftbl_mdss_pclk0_clk[] = { -- F(125000000, P_DSI0PLL, 2, 0, 0), -- F(250000000, P_DSI0PLL, 1, 0, 0), -- { } --}; -- --static struct freq_tbl ftbl_mdss_pclk1_clk[] = { -- F(125000000, P_DSI1PLL, 2, 0, 0), -- F(250000000, P_DSI1PLL, 1, 0, 0), -+static struct freq_tbl pixel_freq_tbl[] = { -+ { .src = P_DSI0PLL }, - { } - }; - -@@ -517,12 +530,13 @@ static struct clk_rcg2 pclk0_clk_src = { - .mnd_width = 8, - .hid_width = 5, - .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, -- .freq_tbl = ftbl_mdss_pclk0_clk, -+ .freq_tbl = pixel_freq_tbl, - .clkr.hw.init = &(struct clk_init_data){ - .name = "pclk0_clk_src", - .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, - .num_parents = 6, -- .ops = &clk_rcg2_ops, -+ .ops = &clk_pixel_ops, -+ .flags = CLK_SET_RATE_PARENT, - }, - }; - -@@ -531,12 +545,13 @@ static struct clk_rcg2 pclk1_clk_src = { - .mnd_width = 8, - .hid_width = 5, - .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, -- .freq_tbl = ftbl_mdss_pclk1_clk, -+ .freq_tbl = pixel_freq_tbl, - .clkr.hw.init = &(struct clk_init_data){ - .name = "pclk1_clk_src", - .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, - .num_parents = 6, -- .ops = &clk_rcg2_ops, -+ .ops = &clk_pixel_ops, -+ .flags = CLK_SET_RATE_PARENT, - }, - }; - -@@ -754,41 +769,36 @@ static struct clk_rcg2 cpp_clk_src = { - }, - }; - --static struct freq_tbl ftbl_mdss_byte0_clk[] = { -- F(93750000, P_DSI0PLL, 8, 0, 0), -- F(187500000, P_DSI0PLL, 4, 0, 0), -- { } --}; -- --static struct freq_tbl ftbl_mdss_byte1_clk[] = { -- F(93750000, P_DSI1PLL, 8, 0, 0), -- F(187500000, P_DSI1PLL, 4, 0, 0), -+static struct freq_tbl byte_freq_tbl[] = { -+ { .src = P_DSI0PLL_BYTE }, - { } - }; - - static struct clk_rcg2 byte0_clk_src = { - .cmd_rcgr = 0x2120, - .hid_width = 5, -- .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, -- .freq_tbl = ftbl_mdss_byte0_clk, -+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, -+ .freq_tbl = byte_freq_tbl, - .clkr.hw.init = &(struct clk_init_data){ - .name = "byte0_clk_src", -- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, -+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, - .num_parents = 6, -- .ops = &clk_rcg2_ops, -+ .ops = &clk_byte_ops, -+ .flags = CLK_SET_RATE_PARENT, - }, - }; - - static struct clk_rcg2 byte1_clk_src = { - .cmd_rcgr = 0x2140, - .hid_width = 5, -- .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, -- .freq_tbl = ftbl_mdss_byte1_clk, -+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, -+ .freq_tbl = byte_freq_tbl, - .clkr.hw.init = &(struct clk_init_data){ - .name = "byte1_clk_src", -- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, -+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, - .num_parents = 6, -- .ops = &clk_rcg2_ops, -+ .ops = &clk_byte_ops, -+ .flags = CLK_SET_RATE_PARENT, - }, - }; - -@@ -826,12 +836,12 @@ static struct clk_rcg2 edplink_clk_src = - .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, - .num_parents = 6, - .ops = &clk_rcg2_ops, -+ .flags = CLK_SET_RATE_PARENT, - }, - }; - --static struct freq_tbl ftbl_mdss_edppixel_clk[] = { -- F(175000000, P_EDPVCO, 2, 0, 0), -- F(350000000, P_EDPVCO, 11, 0, 0), -+static struct freq_tbl edp_pixel_freq_tbl[] = { -+ { .src = P_EDPVCO }, - { } - }; - -@@ -840,12 +850,12 @@ static struct clk_rcg2 edppixel_clk_src - .mnd_width = 8, - .hid_width = 5, - .parent_map = mmcc_xo_dsi_hdmi_edp_map, -- .freq_tbl = ftbl_mdss_edppixel_clk, -+ .freq_tbl = edp_pixel_freq_tbl, - .clkr.hw.init = &(struct clk_init_data){ - .name = "edppixel_clk_src", - .parent_names = mmcc_xo_dsi_hdmi_edp, - .num_parents = 6, -- .ops = &clk_rcg2_ops, -+ .ops = &clk_edp_pixel_ops, - }, - }; - -@@ -857,11 +867,11 @@ static struct freq_tbl ftbl_mdss_esc0_1_ - static struct clk_rcg2 esc0_clk_src = { - .cmd_rcgr = 0x2160, - .hid_width = 5, -- .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, -+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, - .freq_tbl = ftbl_mdss_esc0_1_clk, - .clkr.hw.init = &(struct clk_init_data){ - .name = "esc0_clk_src", -- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, -+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, - .num_parents = 6, - .ops = &clk_rcg2_ops, - }, -@@ -870,26 +880,18 @@ static struct clk_rcg2 esc0_clk_src = { - static struct clk_rcg2 esc1_clk_src = { - .cmd_rcgr = 0x2180, - .hid_width = 5, -- .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, -+ .parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map, - .freq_tbl = ftbl_mdss_esc0_1_clk, - .clkr.hw.init = &(struct clk_init_data){ - .name = "esc1_clk_src", -- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, -+ .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0, - .num_parents = 6, - .ops = &clk_rcg2_ops, - }, - }; - --static struct freq_tbl ftbl_mdss_extpclk_clk[] = { -- F(25200000, P_HDMIPLL, 1, 0, 0), -- F(27000000, P_HDMIPLL, 1, 0, 0), -- F(27030000, P_HDMIPLL, 1, 0, 0), -- F(65000000, P_HDMIPLL, 1, 0, 0), -- F(74250000, P_HDMIPLL, 1, 0, 0), -- F(108000000, P_HDMIPLL, 1, 0, 0), -- F(148500000, P_HDMIPLL, 1, 0, 0), -- F(268500000, P_HDMIPLL, 1, 0, 0), -- F(297000000, P_HDMIPLL, 1, 0, 0), -+static struct freq_tbl extpclk_freq_tbl[] = { -+ { .src = P_HDMIPLL }, - { } - }; - -@@ -897,12 +899,13 @@ static struct clk_rcg2 extpclk_clk_src = - .cmd_rcgr = 0x2060, - .hid_width = 5, - .parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map, -- .freq_tbl = ftbl_mdss_extpclk_clk, -+ .freq_tbl = extpclk_freq_tbl, - .clkr.hw.init = &(struct clk_init_data){ - .name = "extpclk_clk_src", - .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0, - .num_parents = 6, -- .ops = &clk_rcg2_ops, -+ .ops = &clk_byte_ops, -+ .flags = CLK_SET_RATE_PARENT, - }, - }; - diff --git a/target/linux/ipq806x/patches/0107-clk-qcom-Support-msm8974pro-global-clock-control-har.patch b/target/linux/ipq806x/patches/0107-clk-qcom-Support-msm8974pro-global-clock-control-har.patch deleted file mode 100644 index 670acad9dc..0000000000 --- a/target/linux/ipq806x/patches/0107-clk-qcom-Support-msm8974pro-global-clock-control-har.patch +++ /dev/null @@ -1,236 +0,0 @@ -From a740d2b024c5b71c6f9989976049f03b634bb13d Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 16 May 2014 16:07:13 -0700 -Subject: [PATCH 107/182] clk: qcom: Support msm8974pro global clock control - hardware - -A new PLL (gpll4) is added on msm8974 PRO devices to support a -faster sdc1 clock rate. Add support for this and the two new sdcc -cal clocks. - -Signed-off-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - .../devicetree/bindings/clock/qcom,gcc.txt | 2 + - drivers/clk/qcom/gcc-msm8974.c | 130 +++++++++++++++++++- - include/dt-bindings/clock/qcom,gcc-msm8974.h | 4 + - 3 files changed, 130 insertions(+), 6 deletions(-) - ---- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt -+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt -@@ -8,6 +8,8 @@ Required properties : - "qcom,gcc-msm8660" - "qcom,gcc-msm8960" - "qcom,gcc-msm8974" -+ "qcom,gcc-msm8974pro" -+ "qcom,gcc-msm8974pro-ac" - - - reg : shall contain base register location and length - - #clock-cells : shall contain 1 ---- a/drivers/clk/qcom/gcc-msm8974.c -+++ b/drivers/clk/qcom/gcc-msm8974.c -@@ -35,6 +35,7 @@ - #define P_XO 0 - #define P_GPLL0 1 - #define P_GPLL1 1 -+#define P_GPLL4 2 - - static const u8 gcc_xo_gpll0_map[] = { - [P_XO] = 0, -@@ -46,6 +47,18 @@ static const char *gcc_xo_gpll0[] = { - "gpll0_vote", - }; - -+static const u8 gcc_xo_gpll0_gpll4_map[] = { -+ [P_XO] = 0, -+ [P_GPLL0] = 1, -+ [P_GPLL4] = 5, -+}; -+ -+static const char *gcc_xo_gpll0_gpll4[] = { -+ "xo", -+ "gpll0_vote", -+ "gpll4_vote", -+}; -+ - #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } - - static struct clk_pll gpll0 = { -@@ -138,6 +151,33 @@ static struct clk_regmap gpll1_vote = { - }, - }; - -+static struct clk_pll gpll4 = { -+ .l_reg = 0x1dc4, -+ .m_reg = 0x1dc8, -+ .n_reg = 0x1dcc, -+ .config_reg = 0x1dd4, -+ .mode_reg = 0x1dc0, -+ .status_reg = 0x1ddc, -+ .status_bit = 17, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "gpll4", -+ .parent_names = (const char *[]){ "xo" }, -+ .num_parents = 1, -+ .ops = &clk_pll_ops, -+ }, -+}; -+ -+static struct clk_regmap gpll4_vote = { -+ .enable_reg = 0x1480, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gpll4_vote", -+ .parent_names = (const char *[]){ "gpll4" }, -+ .num_parents = 1, -+ .ops = &clk_pll_vote_ops, -+ }, -+}; -+ - static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = { - F(125000000, P_GPLL0, 1, 5, 24), - { } -@@ -812,18 +852,33 @@ static const struct freq_tbl ftbl_gcc_sd - { } - }; - -+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_pro[] = { -+ F(144000, P_XO, 16, 3, 25), -+ F(400000, P_XO, 12, 1, 4), -+ F(20000000, P_GPLL0, 15, 1, 2), -+ F(25000000, P_GPLL0, 12, 1, 2), -+ F(50000000, P_GPLL0, 12, 0, 0), -+ F(100000000, P_GPLL0, 6, 0, 0), -+ F(192000000, P_GPLL4, 4, 0, 0), -+ F(200000000, P_GPLL0, 3, 0, 0), -+ F(384000000, P_GPLL4, 2, 0, 0), -+ { } -+}; -+ -+static struct clk_init_data sdcc1_apps_clk_src_init = { -+ .name = "sdcc1_apps_clk_src", -+ .parent_names = gcc_xo_gpll0, -+ .num_parents = 2, -+ .ops = &clk_rcg2_ops, -+}; -+ - static struct clk_rcg2 sdcc1_apps_clk_src = { - .cmd_rcgr = 0x04d0, - .mnd_width = 8, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_map, - .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk, -- .clkr.hw.init = &(struct clk_init_data){ -- .name = "sdcc1_apps_clk_src", -- .parent_names = gcc_xo_gpll0, -- .num_parents = 2, -- .ops = &clk_rcg2_ops, -- }, -+ .clkr.hw.init = &sdcc1_apps_clk_src_init, - }; - - static struct clk_rcg2 sdcc2_apps_clk_src = { -@@ -1995,6 +2050,38 @@ static struct clk_branch gcc_sdcc1_apps_ - }, - }; - -+static struct clk_branch gcc_sdcc1_cdccal_ff_clk = { -+ .halt_reg = 0x04e8, -+ .clkr = { -+ .enable_reg = 0x04e8, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_sdcc1_cdccal_ff_clk", -+ .parent_names = (const char *[]){ -+ "xo" -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gcc_sdcc1_cdccal_sleep_clk = { -+ .halt_reg = 0x04e4, -+ .clkr = { -+ .enable_reg = 0x04e4, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gcc_sdcc1_cdccal_sleep_clk", -+ .parent_names = (const char *[]){ -+ "sleep_clk_src" -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ - static struct clk_branch gcc_sdcc2_ahb_clk = { - .halt_reg = 0x0508, - .clkr = { -@@ -2484,6 +2571,10 @@ static struct clk_regmap *gcc_msm8974_cl - [GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr, - [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, - [GCC_MMSS_GPLL0_CLK_SRC] = &gcc_mmss_gpll0_clk_src, -+ [GPLL4] = NULL, -+ [GPLL4_VOTE] = NULL, -+ [GCC_SDCC1_CDCCAL_SLEEP_CLK] = NULL, -+ [GCC_SDCC1_CDCCAL_FF_CLK] = NULL, - }; - - static const struct qcom_reset_map gcc_msm8974_resets[] = { -@@ -2585,14 +2676,41 @@ static const struct qcom_cc_desc gcc_msm - - static const struct of_device_id gcc_msm8974_match_table[] = { - { .compatible = "qcom,gcc-msm8974" }, -+ { .compatible = "qcom,gcc-msm8974pro" , .data = (void *)1UL }, -+ { .compatible = "qcom,gcc-msm8974pro-ac", .data = (void *)1UL }, - { } - }; - MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); - -+static void msm8974_pro_clock_override(void) -+{ -+ sdcc1_apps_clk_src_init.parent_names = gcc_xo_gpll0_gpll4; -+ sdcc1_apps_clk_src_init.num_parents = 3; -+ sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_pro; -+ sdcc1_apps_clk_src.parent_map = gcc_xo_gpll0_gpll4_map; -+ -+ gcc_msm8974_clocks[GPLL4] = &gpll4.clkr; -+ gcc_msm8974_clocks[GPLL4_VOTE] = &gpll4_vote; -+ gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_SLEEP_CLK] = -+ &gcc_sdcc1_cdccal_sleep_clk.clkr; -+ gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_FF_CLK] = -+ &gcc_sdcc1_cdccal_ff_clk.clkr; -+} -+ - static int gcc_msm8974_probe(struct platform_device *pdev) - { - struct clk *clk; - struct device *dev = &pdev->dev; -+ bool pro; -+ const struct of_device_id *id; -+ -+ id = of_match_device(gcc_msm8974_match_table, dev); -+ if (!id) -+ return -ENODEV; -+ pro = !!(id->data); -+ -+ if (pro) -+ msm8974_pro_clock_override(); - - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); ---- a/include/dt-bindings/clock/qcom,gcc-msm8974.h -+++ b/include/dt-bindings/clock/qcom,gcc-msm8974.h -@@ -316,5 +316,9 @@ - #define GCC_CE2_CLK_SLEEP_ENA 299 - #define GCC_CE2_AXI_CLK_SLEEP_ENA 300 - #define GCC_CE2_AHB_CLK_SLEEP_ENA 301 -+#define GPLL4 302 -+#define GPLL4_VOTE 303 -+#define GCC_SDCC1_CDCCAL_SLEEP_CLK 304 -+#define GCC_SDCC1_CDCCAL_FF_CLK 305 - - #endif diff --git a/target/linux/ipq806x/patches/0108-clk-qcom-Return-error-pointers-for-unimplemented-clo.patch b/target/linux/ipq806x/patches/0108-clk-qcom-Return-error-pointers-for-unimplemented-clo.patch deleted file mode 100644 index 52d497fea7..0000000000 --- a/target/linux/ipq806x/patches/0108-clk-qcom-Return-error-pointers-for-unimplemented-clo.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 77b7f864b03d6b49c143a9c8c19432feef3032b5 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 16 May 2014 16:07:14 -0700 -Subject: [PATCH 108/182] clk: qcom: Return error pointers for unimplemented - clocks - -Not all clocks are implemented but client drivers can still -request them. Currently we will return a NULL pointer to them if -the clock isn't implemented in software but NULL pointers are -valid clock pointers. Return an error pointer so that driver's -don't proceed without a clock they may actually need. - -Signed-off-by: Stephen Boyd -Signed-off-by: Mike Turquette ---- - drivers/clk/qcom/common.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/clk/qcom/common.c -+++ b/drivers/clk/qcom/common.c -@@ -62,8 +62,10 @@ int qcom_cc_probe(struct platform_device - data->clk_num = num_clks; - - for (i = 0; i < num_clks; i++) { -- if (!rclks[i]) -+ if (!rclks[i]) { -+ clks[i] = ERR_PTR(-ENOENT); - continue; -+ } - clk = devm_clk_register_regmap(dev, rclks[i]); - if (IS_ERR(clk)) - return PTR_ERR(clk); diff --git a/target/linux/ipq806x/patches/0109-libahci-Allow-drivers-to-override-start_engine.patch b/target/linux/ipq806x/patches/0109-libahci-Allow-drivers-to-override-start_engine.patch deleted file mode 100644 index aa2fee6ed3..0000000000 --- a/target/linux/ipq806x/patches/0109-libahci-Allow-drivers-to-override-start_engine.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 10f3c772363e549c3dbd3cc3755d270c5656d5b8 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 16:53:30 +0100 -Subject: [PATCH 109/182] libahci: Allow drivers to override start_engine - -Allwinner A10 and A20 ARM SoCs have an AHCI sata controller which needs a -special register to be poked before starting the DMA engine. - -This register gets reset on an ahci_stop_engine call, so there is no other -place then ahci_start_engine where this poking can be done. - -This commit allows drivers to override ahci_start_engine behavior for use by -the Allwinner AHCI driver (and potentially other drivers in the future). - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci.c | 6 ++++-- - drivers/ata/ahci.h | 6 ++++++ - drivers/ata/libahci.c | 26 +++++++++++++++++++------- - drivers/ata/sata_highbank.c | 3 ++- - 4 files changed, 31 insertions(+), 10 deletions(-) - ---- a/drivers/ata/ahci.c -+++ b/drivers/ata/ahci.c -@@ -606,6 +606,7 @@ static int ahci_vt8251_hardreset(struct - unsigned long deadline) - { - struct ata_port *ap = link->ap; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - bool online; - int rc; - -@@ -616,7 +617,7 @@ static int ahci_vt8251_hardreset(struct - rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), - deadline, &online, NULL); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); - -@@ -631,6 +632,7 @@ static int ahci_p5wdh_hardreset(struct a - { - struct ata_port *ap = link->ap; - struct ahci_port_priv *pp = ap->private_data; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; - struct ata_taskfile tf; - bool online; -@@ -646,7 +648,7 @@ static int ahci_p5wdh_hardreset(struct a - rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), - deadline, &online, NULL); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - /* The pseudo configuration device on SIMG4726 attached to - * ASUS P5W-DH Deluxe doesn't send signature FIS after ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -324,6 +324,12 @@ struct ahci_host_priv { - u32 em_msg_type; /* EM message type */ - struct clk *clk; /* Only for platforms supporting clk */ - void *plat_data; /* Other platform data */ -+ /* -+ * Optional ahci_start_engine override, if not set this gets set to the -+ * default ahci_start_engine during ahci_save_initial_config, this can -+ * be overridden anytime before the host is activated. -+ */ -+ void (*start_engine)(struct ata_port *ap); - }; - - extern int ahci_ignore_sss; ---- a/drivers/ata/libahci.c -+++ b/drivers/ata/libahci.c -@@ -394,6 +394,9 @@ static ssize_t ahci_show_em_supported(st - * - * If inconsistent, config values are fixed up by this function. - * -+ * If it is not set already this function sets hpriv->start_engine to -+ * ahci_start_engine. -+ * - * LOCKING: - * None. - */ -@@ -500,6 +503,9 @@ void ahci_save_initial_config(struct dev - hpriv->cap = cap; - hpriv->cap2 = cap2; - hpriv->port_map = port_map; -+ -+ if (!hpriv->start_engine) -+ hpriv->start_engine = ahci_start_engine; - } - EXPORT_SYMBOL_GPL(ahci_save_initial_config); - -@@ -766,7 +772,7 @@ static void ahci_start_port(struct ata_p - - /* enable DMA */ - if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - /* turn on LEDs */ - if (ap->flags & ATA_FLAG_EM) { -@@ -1234,7 +1240,7 @@ int ahci_kick_engine(struct ata_port *ap - - /* restart engine */ - out_restart: -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - return rc; - } - EXPORT_SYMBOL_GPL(ahci_kick_engine); -@@ -1426,6 +1432,7 @@ static int ahci_hardreset(struct ata_lin - const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); - struct ata_port *ap = link->ap; - struct ahci_port_priv *pp = ap->private_data; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; - struct ata_taskfile tf; - bool online; -@@ -1443,7 +1450,7 @@ static int ahci_hardreset(struct ata_lin - rc = sata_link_hardreset(link, timing, deadline, &online, - ahci_check_ready); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - if (online) - *class = ahci_dev_classify(ap); -@@ -2007,10 +2014,12 @@ static void ahci_thaw(struct ata_port *a - - void ahci_error_handler(struct ata_port *ap) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; -+ - if (!(ap->pflags & ATA_PFLAG_FROZEN)) { - /* restart engine */ - ahci_stop_engine(ap); -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - } - - sata_pmp_error_handler(ap); -@@ -2031,6 +2040,7 @@ static void ahci_post_internal_cmd(struc - - static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; - void __iomem *port_mmio = ahci_port_base(ap); - struct ata_device *dev = ap->link.device; - u32 devslp, dm, dito, mdat, deto; -@@ -2094,7 +2104,7 @@ static void ahci_set_aggressive_devslp(s - PORT_DEVSLP_ADSE); - writel(devslp, port_mmio + PORT_DEVSLP); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - /* enable device sleep feature for the drive */ - err_mask = ata_dev_set_feature(dev, -@@ -2106,6 +2116,7 @@ static void ahci_set_aggressive_devslp(s - - static void ahci_enable_fbs(struct ata_port *ap) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; - struct ahci_port_priv *pp = ap->private_data; - void __iomem *port_mmio = ahci_port_base(ap); - u32 fbs; -@@ -2134,11 +2145,12 @@ static void ahci_enable_fbs(struct ata_p - } else - dev_err(ap->host->dev, "Failed to enable FBS\n"); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - } - - static void ahci_disable_fbs(struct ata_port *ap) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; - struct ahci_port_priv *pp = ap->private_data; - void __iomem *port_mmio = ahci_port_base(ap); - u32 fbs; -@@ -2166,7 +2178,7 @@ static void ahci_disable_fbs(struct ata_ - pp->fbs_enabled = false; - } - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - } - - static void ahci_pmp_attach(struct ata_port *ap) ---- a/drivers/ata/sata_highbank.c -+++ b/drivers/ata/sata_highbank.c -@@ -403,6 +403,7 @@ static int ahci_highbank_hardreset(struc - static const unsigned long timing[] = { 5, 100, 500}; - struct ata_port *ap = link->ap; - struct ahci_port_priv *pp = ap->private_data; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; - struct ata_taskfile tf; - bool online; -@@ -431,7 +432,7 @@ static int ahci_highbank_hardreset(struc - break; - } while (!online && retry--); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - if (online) - *class = ahci_dev_classify(ap); diff --git a/target/linux/ipq806x/patches/0110-ahci-platform-Add-support-for-devices-with-more-then.patch b/target/linux/ipq806x/patches/0110-ahci-platform-Add-support-for-devices-with-more-then.patch deleted file mode 100644 index 54f84ee072..0000000000 --- a/target/linux/ipq806x/patches/0110-ahci-platform-Add-support-for-devices-with-more-then.patch +++ /dev/null @@ -1,242 +0,0 @@ -From b7ad421c184b827806c7f65be3a980cfc855b589 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 16:53:31 +0100 -Subject: [PATCH 110/182] ahci-platform: Add support for devices with more - then 1 clock - -The allwinner-sun4i AHCI controller needs 2 clocks to be enabled and the -imx AHCI controller needs 3 clocks to be enabled. - -tj: Minor comment formatting updates. - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - .../devicetree/bindings/ata/ahci-platform.txt | 1 + - drivers/ata/ahci.h | 3 +- - drivers/ata/ahci_platform.c | 113 +++++++++++++++----- - include/linux/ahci_platform.h | 4 + - 4 files changed, 93 insertions(+), 28 deletions(-) - ---- a/Documentation/devicetree/bindings/ata/ahci-platform.txt -+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt -@@ -10,6 +10,7 @@ Required properties: - - Optional properties: - - dma-coherent : Present if dma operations are coherent -+- clocks : a list of phandle + clock specifier pairs - - Example: - sata@ffe08000 { ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -51,6 +51,7 @@ - - enum { - AHCI_MAX_PORTS = 32, -+ AHCI_MAX_CLKS = 3, - AHCI_MAX_SG = 168, /* hardware max is 64K */ - AHCI_DMA_BOUNDARY = 0xffffffff, - AHCI_MAX_CMDS = 32, -@@ -322,7 +323,7 @@ struct ahci_host_priv { - u32 em_loc; /* enclosure management location */ - u32 em_buf_sz; /* EM buffer size in byte */ - u32 em_msg_type; /* EM message type */ -- struct clk *clk; /* Only for platforms supporting clk */ -+ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ - void *plat_data; /* Other platform data */ - /* - * Optional ahci_start_engine override, if not set this gets set to the ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -87,6 +87,60 @@ static struct scsi_host_template ahci_pl - AHCI_SHT("ahci_platform"), - }; - -+/** -+ * ahci_platform_enable_clks - Enable platform clocks -+ * @hpriv: host private area to store config values -+ * -+ * This function enables all the clks found in hpriv->clks, starting at -+ * index 0. If any clk fails to enable it disables all the clks already -+ * enabled in reverse order, and then returns an error. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) -+{ -+ int c, rc; -+ -+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { -+ rc = clk_prepare_enable(hpriv->clks[c]); -+ if (rc) -+ goto disable_unprepare_clk; -+ } -+ return 0; -+ -+disable_unprepare_clk: -+ while (--c >= 0) -+ clk_disable_unprepare(hpriv->clks[c]); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); -+ -+/** -+ * ahci_platform_disable_clks - Disable platform clocks -+ * @hpriv: host private area to store config values -+ * -+ * This function disables all the clks found in hpriv->clks, in reverse -+ * order of ahci_platform_enable_clks (starting at the end of the array). -+ */ -+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) -+{ -+ int c; -+ -+ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) -+ if (hpriv->clks[c]) -+ clk_disable_unprepare(hpriv->clks[c]); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); -+ -+static void ahci_put_clks(struct ahci_host_priv *hpriv) -+{ -+ int c; -+ -+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) -+ clk_put(hpriv->clks[c]); -+} -+ - static int ahci_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -97,6 +151,7 @@ static int ahci_probe(struct platform_de - struct ahci_host_priv *hpriv; - struct ata_host *host; - struct resource *mem; -+ struct clk *clk; - int irq; - int n_ports; - int i; -@@ -131,17 +186,31 @@ static int ahci_probe(struct platform_de - return -ENOMEM; - } - -- hpriv->clk = clk_get(dev, NULL); -- if (IS_ERR(hpriv->clk)) { -- dev_err(dev, "can't get clock\n"); -- } else { -- rc = clk_prepare_enable(hpriv->clk); -- if (rc) { -- dev_err(dev, "clock prepare enable failed"); -- goto free_clk; -+ for (i = 0; i < AHCI_MAX_CLKS; i++) { -+ /* -+ * For now we must use clk_get(dev, NULL) for the first clock, -+ * because some platforms (da850, spear13xx) are not yet -+ * converted to use devicetree for clocks. For new platforms -+ * this is equivalent to of_clk_get(dev->of_node, 0). -+ */ -+ if (i == 0) -+ clk = clk_get(dev, NULL); -+ else -+ clk = of_clk_get(dev->of_node, i); -+ -+ if (IS_ERR(clk)) { -+ rc = PTR_ERR(clk); -+ if (rc == -EPROBE_DEFER) -+ goto free_clk; -+ break; - } -+ hpriv->clks[i] = clk; - } - -+ rc = ahci_enable_clks(dev, hpriv); -+ if (rc) -+ goto free_clk; -+ - /* - * Some platforms might need to prepare for mmio region access, - * which could be done in the following init call. So, the mmio -@@ -222,11 +291,9 @@ pdata_exit: - if (pdata && pdata->exit) - pdata->exit(dev); - disable_unprepare_clk: -- if (!IS_ERR(hpriv->clk)) -- clk_disable_unprepare(hpriv->clk); -+ ahci_disable_clks(hpriv); - free_clk: -- if (!IS_ERR(hpriv->clk)) -- clk_put(hpriv->clk); -+ ahci_put_clks(hpriv); - return rc; - } - -@@ -239,10 +306,8 @@ static void ahci_host_stop(struct ata_ho - if (pdata && pdata->exit) - pdata->exit(dev); - -- if (!IS_ERR(hpriv->clk)) { -- clk_disable_unprepare(hpriv->clk); -- clk_put(hpriv->clk); -- } -+ ahci_disable_clks(hpriv); -+ ahci_put_clks(hpriv); - } - - #ifdef CONFIG_PM_SLEEP -@@ -277,8 +342,7 @@ static int ahci_suspend(struct device *d - if (pdata && pdata->suspend) - return pdata->suspend(dev); - -- if (!IS_ERR(hpriv->clk)) -- clk_disable_unprepare(hpriv->clk); -+ ahci_disable_clks(hpriv); - - return 0; - } -@@ -290,13 +354,9 @@ static int ahci_resume(struct device *de - struct ahci_host_priv *hpriv = host->private_data; - int rc; - -- if (!IS_ERR(hpriv->clk)) { -- rc = clk_prepare_enable(hpriv->clk); -- if (rc) { -- dev_err(dev, "clock prepare enable failed"); -- return rc; -- } -- } -+ rc = ahci_enable_clks(dev, hpriv); -+ if (rc) -+ return rc; - - if (pdata && pdata->resume) { - rc = pdata->resume(dev); -@@ -317,8 +377,7 @@ static int ahci_resume(struct device *de - return 0; - - disable_unprepare_clk: -- if (!IS_ERR(hpriv->clk)) -- clk_disable_unprepare(hpriv->clk); -+ ahci_disable_clks(hpriv); - - return rc; - } ---- a/include/linux/ahci_platform.h -+++ b/include/linux/ahci_platform.h -@@ -19,6 +19,7 @@ - - struct device; - struct ata_port_info; -+struct ahci_host_priv; - - struct ahci_platform_data { - int (*init)(struct device *dev, void __iomem *addr); -@@ -30,4 +31,7 @@ struct ahci_platform_data { - unsigned int mask_port_map; - }; - -+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); -+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); -+ - #endif /* _AHCI_PLATFORM_H */ diff --git a/target/linux/ipq806x/patches/0111-ahci-platform-Add-support-for-an-optional-regulator-.patch b/target/linux/ipq806x/patches/0111-ahci-platform-Add-support-for-an-optional-regulator-.patch deleted file mode 100644 index a8b1c6f8dd..0000000000 --- a/target/linux/ipq806x/patches/0111-ahci-platform-Add-support-for-an-optional-regulator-.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 967f4a7821a3356d9d3c8b641537cd6d5eb15439 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 16:53:32 +0100 -Subject: [PATCH 111/182] ahci-platform: Add support for an optional regulator - for sata-target power - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - .../devicetree/bindings/ata/ahci-platform.txt | 1 + - drivers/ata/ahci.h | 2 ++ - drivers/ata/ahci_platform.c | 36 ++++++++++++++++++-- - 3 files changed, 37 insertions(+), 2 deletions(-) - ---- a/Documentation/devicetree/bindings/ata/ahci-platform.txt -+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt -@@ -11,6 +11,7 @@ Required properties: - Optional properties: - - dma-coherent : Present if dma operations are coherent - - clocks : a list of phandle + clock specifier pairs -+- target-supply : regulator for SATA target power - - Example: - sata@ffe08000 { ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -37,6 +37,7 @@ - - #include - #include -+#include - - /* Enclosure Management Control */ - #define EM_CTRL_MSG_TYPE 0x000f0000 -@@ -324,6 +325,7 @@ struct ahci_host_priv { - u32 em_buf_sz; /* EM buffer size in byte */ - u32 em_msg_type; /* EM message type */ - struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ -+ struct regulator *target_pwr; /* Optional */ - void *plat_data; /* Other platform data */ - /* - * Optional ahci_start_engine override, if not set this gets set to the ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -186,6 +186,14 @@ static int ahci_probe(struct platform_de - return -ENOMEM; - } - -+ hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); -+ if (IS_ERR(hpriv->target_pwr)) { -+ rc = PTR_ERR(hpriv->target_pwr); -+ if (rc == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ hpriv->target_pwr = NULL; -+ } -+ - for (i = 0; i < AHCI_MAX_CLKS; i++) { - /* - * For now we must use clk_get(dev, NULL) for the first clock, -@@ -207,9 +215,15 @@ static int ahci_probe(struct platform_de - hpriv->clks[i] = clk; - } - -+ if (hpriv->target_pwr) { -+ rc = regulator_enable(hpriv->target_pwr); -+ if (rc) -+ goto free_clk; -+ } -+ - rc = ahci_enable_clks(dev, hpriv); - if (rc) -- goto free_clk; -+ goto disable_regulator; - - /* - * Some platforms might need to prepare for mmio region access, -@@ -292,6 +306,9 @@ pdata_exit: - pdata->exit(dev); - disable_unprepare_clk: - ahci_disable_clks(hpriv); -+disable_regulator: -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); - free_clk: - ahci_put_clks(hpriv); - return rc; -@@ -308,6 +325,9 @@ static void ahci_host_stop(struct ata_ho - - ahci_disable_clks(hpriv); - ahci_put_clks(hpriv); -+ -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); - } - - #ifdef CONFIG_PM_SLEEP -@@ -344,6 +364,9 @@ static int ahci_suspend(struct device *d - - ahci_disable_clks(hpriv); - -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+ - return 0; - } - -@@ -354,9 +377,15 @@ static int ahci_resume(struct device *de - struct ahci_host_priv *hpriv = host->private_data; - int rc; - -+ if (hpriv->target_pwr) { -+ rc = regulator_enable(hpriv->target_pwr); -+ if (rc) -+ return rc; -+ } -+ - rc = ahci_enable_clks(dev, hpriv); - if (rc) -- return rc; -+ goto disable_regulator; - - if (pdata && pdata->resume) { - rc = pdata->resume(dev); -@@ -378,6 +407,9 @@ static int ahci_resume(struct device *de - - disable_unprepare_clk: - ahci_disable_clks(hpriv); -+disable_regulator: -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); - - return rc; - } diff --git a/target/linux/ipq806x/patches/0112-ahci-platform-Add-enable_-disable_resources-helper-f.patch b/target/linux/ipq806x/patches/0112-ahci-platform-Add-enable_-disable_resources-helper-f.patch deleted file mode 100644 index 888ee324f8..0000000000 --- a/target/linux/ipq806x/patches/0112-ahci-platform-Add-enable_-disable_resources-helper-f.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 3b2df84624b38362cb84c2d4c6d1d3540c5069d3 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 16:53:33 +0100 -Subject: [PATCH 112/182] ahci-platform: Add enable_ / disable_resources - helper functions - -tj: Minor comment formatting updates. - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 106 +++++++++++++++++++++++++++-------------- - include/linux/ahci_platform.h | 2 + - 2 files changed, 71 insertions(+), 37 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -133,6 +133,62 @@ void ahci_platform_disable_clks(struct a - } - EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); - -+/** -+ * ahci_platform_enable_resources - Enable platform resources -+ * @hpriv: host private area to store config values -+ * -+ * This function enables all ahci_platform managed resources in the -+ * following order: -+ * 1) Regulator -+ * 2) Clocks (through ahci_platform_enable_clks) -+ * -+ * If resource enabling fails at any point the previous enabled resources -+ * are disabled in reverse order. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) -+{ -+ int rc; -+ -+ if (hpriv->target_pwr) { -+ rc = regulator_enable(hpriv->target_pwr); -+ if (rc) -+ return rc; -+ } -+ -+ rc = ahci_platform_enable_clks(hpriv); -+ if (rc) -+ goto disable_regulator; -+ -+ return 0; -+ -+disable_regulator: -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); -+ -+/** -+ * ahci_platform_disable_resources - Disable platform resources -+ * @hpriv: host private area to store config values -+ * -+ * This function disables all ahci_platform managed resources in the -+ * following order: -+ * 1) Clocks (through ahci_platform_disable_clks) -+ * 2) Regulator -+ */ -+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) -+{ -+ ahci_platform_disable_clks(hpriv); -+ -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); -+ - static void ahci_put_clks(struct ahci_host_priv *hpriv) - { - int c; -@@ -215,15 +271,9 @@ static int ahci_probe(struct platform_de - hpriv->clks[i] = clk; - } - -- if (hpriv->target_pwr) { -- rc = regulator_enable(hpriv->target_pwr); -- if (rc) -- goto free_clk; -- } -- -- rc = ahci_enable_clks(dev, hpriv); -+ rc = ahci_platform_enable_resources(hpriv); - if (rc) -- goto disable_regulator; -+ goto free_clk; - - /* - * Some platforms might need to prepare for mmio region access, -@@ -234,7 +284,7 @@ static int ahci_probe(struct platform_de - if (pdata && pdata->init) { - rc = pdata->init(dev, hpriv->mmio); - if (rc) -- goto disable_unprepare_clk; -+ goto disable_resources; - } - - ahci_save_initial_config(dev, hpriv, -@@ -304,11 +354,8 @@ static int ahci_probe(struct platform_de - pdata_exit: - if (pdata && pdata->exit) - pdata->exit(dev); --disable_unprepare_clk: -- ahci_disable_clks(hpriv); --disable_regulator: -- if (hpriv->target_pwr) -- regulator_disable(hpriv->target_pwr); -+disable_resources: -+ ahci_platform_disable_resources(hpriv); - free_clk: - ahci_put_clks(hpriv); - return rc; -@@ -323,11 +370,8 @@ static void ahci_host_stop(struct ata_ho - if (pdata && pdata->exit) - pdata->exit(dev); - -- ahci_disable_clks(hpriv); -+ ahci_platform_disable_resources(hpriv); - ahci_put_clks(hpriv); -- -- if (hpriv->target_pwr) -- regulator_disable(hpriv->target_pwr); - } - - #ifdef CONFIG_PM_SLEEP -@@ -362,10 +406,7 @@ static int ahci_suspend(struct device *d - if (pdata && pdata->suspend) - return pdata->suspend(dev); - -- ahci_disable_clks(hpriv); -- -- if (hpriv->target_pwr) -- regulator_disable(hpriv->target_pwr); -+ ahci_platform_disable_resources(hpriv); - - return 0; - } -@@ -377,26 +418,20 @@ static int ahci_resume(struct device *de - struct ahci_host_priv *hpriv = host->private_data; - int rc; - -- if (hpriv->target_pwr) { -- rc = regulator_enable(hpriv->target_pwr); -- if (rc) -- return rc; -- } -- -- rc = ahci_enable_clks(dev, hpriv); -+ rc = ahci_platform_enable_resources(hpriv); - if (rc) -- goto disable_regulator; -+ return rc; - - if (pdata && pdata->resume) { - rc = pdata->resume(dev); - if (rc) -- goto disable_unprepare_clk; -+ goto disable_resources; - } - - if (dev->power.power_state.event == PM_EVENT_SUSPEND) { - rc = ahci_reset_controller(host); - if (rc) -- goto disable_unprepare_clk; -+ goto disable_resources; - - ahci_init_controller(host); - } -@@ -405,11 +440,8 @@ static int ahci_resume(struct device *de - - return 0; - --disable_unprepare_clk: -- ahci_disable_clks(hpriv); --disable_regulator: -- if (hpriv->target_pwr) -- regulator_disable(hpriv->target_pwr); -+disable_resources: -+ ahci_platform_disable_resources(hpriv); - - return rc; - } ---- a/include/linux/ahci_platform.h -+++ b/include/linux/ahci_platform.h -@@ -33,5 +33,7 @@ struct ahci_platform_data { - - int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); - void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); -+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv); -+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv); - - #endif /* _AHCI_PLATFORM_H */ diff --git a/target/linux/ipq806x/patches/0113-ata-delete-non-required-instances-of-include-linux-i.patch b/target/linux/ipq806x/patches/0113-ata-delete-non-required-instances-of-include-linux-i.patch deleted file mode 100644 index 18e034e23e..0000000000 --- a/target/linux/ipq806x/patches/0113-ata-delete-non-required-instances-of-include-linux-i.patch +++ /dev/null @@ -1,765 +0,0 @@ -From 01b380db3c35bbd87cb3765573fd049bce3d7640 Mon Sep 17 00:00:00 2001 -From: Paul Gortmaker -Date: Tue, 21 Jan 2014 16:22:51 -0500 -Subject: [PATCH 113/182] ata: delete non-required instances of include - - -None of these files are actually using any __init type directives -and hence don't need to include . Most are just a -left over from __devinit and __cpuinit removal, or simply due to -code getting copied from one driver to the next. - -Cc: linux-ide@vger.kernel.org -Signed-off-by: Paul Gortmaker -Signed-off-by: Tejun Heo ---- - drivers/ata/acard-ahci.c | 1 - - drivers/ata/ahci.c | 1 - - drivers/ata/ahci_platform.c | 1 - - drivers/ata/ata_generic.c | 1 - - drivers/ata/libahci.c | 1 - - drivers/ata/pata_acpi.c | 1 - - drivers/ata/pata_amd.c | 1 - - drivers/ata/pata_artop.c | 1 - - drivers/ata/pata_at91.c | 1 - - drivers/ata/pata_atiixp.c | 1 - - drivers/ata/pata_atp867x.c | 1 - - drivers/ata/pata_cmd640.c | 1 - - drivers/ata/pata_cmd64x.c | 1 - - drivers/ata/pata_cs5520.c | 1 - - drivers/ata/pata_cs5530.c | 1 - - drivers/ata/pata_cs5535.c | 1 - - drivers/ata/pata_cs5536.c | 1 - - drivers/ata/pata_cypress.c | 1 - - drivers/ata/pata_efar.c | 1 - - drivers/ata/pata_ep93xx.c | 1 - - drivers/ata/pata_hpt366.c | 1 - - drivers/ata/pata_hpt37x.c | 1 - - drivers/ata/pata_hpt3x2n.c | 1 - - drivers/ata/pata_hpt3x3.c | 1 - - drivers/ata/pata_imx.c | 1 - - drivers/ata/pata_it8213.c | 1 - - drivers/ata/pata_it821x.c | 1 - - drivers/ata/pata_jmicron.c | 1 - - drivers/ata/pata_marvell.c | 1 - - drivers/ata/pata_mpiix.c | 1 - - drivers/ata/pata_netcell.c | 1 - - drivers/ata/pata_ninja32.c | 1 - - drivers/ata/pata_ns87410.c | 1 - - drivers/ata/pata_ns87415.c | 1 - - drivers/ata/pata_oldpiix.c | 1 - - drivers/ata/pata_opti.c | 1 - - drivers/ata/pata_optidma.c | 1 - - drivers/ata/pata_pcmcia.c | 1 - - drivers/ata/pata_pdc2027x.c | 1 - - drivers/ata/pata_pdc202xx_old.c | 1 - - drivers/ata/pata_piccolo.c | 1 - - drivers/ata/pata_platform.c | 1 - - drivers/ata/pata_pxa.c | 1 - - drivers/ata/pata_radisys.c | 1 - - drivers/ata/pata_rdc.c | 1 - - drivers/ata/pata_rz1000.c | 1 - - drivers/ata/pata_sc1200.c | 1 - - drivers/ata/pata_scc.c | 1 - - drivers/ata/pata_sch.c | 1 - - drivers/ata/pata_serverworks.c | 1 - - drivers/ata/pata_sil680.c | 1 - - drivers/ata/pata_sis.c | 1 - - drivers/ata/pata_sl82c105.c | 1 - - drivers/ata/pata_triflex.c | 1 - - drivers/ata/pata_via.c | 1 - - drivers/ata/pdc_adma.c | 1 - - drivers/ata/sata_dwc_460ex.c | 1 - - drivers/ata/sata_highbank.c | 1 - - drivers/ata/sata_nv.c | 1 - - drivers/ata/sata_promise.c | 1 - - drivers/ata/sata_qstor.c | 1 - - drivers/ata/sata_sil.c | 1 - - drivers/ata/sata_sis.c | 1 - - drivers/ata/sata_svw.c | 1 - - drivers/ata/sata_sx4.c | 1 - - drivers/ata/sata_uli.c | 1 - - drivers/ata/sata_via.c | 1 - - drivers/ata/sata_vsc.c | 1 - - 68 files changed, 68 deletions(-) - ---- a/drivers/ata/acard-ahci.c -+++ b/drivers/ata/acard-ahci.c -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/ahci.c -+++ b/drivers/ata/ahci.c -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -17,7 +17,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/ata_generic.c -+++ b/drivers/ata/ata_generic.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/libahci.c -+++ b/drivers/ata/libahci.c -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_acpi.c -+++ b/drivers/ata/pata_acpi.c -@@ -7,7 +7,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_amd.c -+++ b/drivers/ata/pata_amd.c -@@ -17,7 +17,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_artop.c -+++ b/drivers/ata/pata_artop.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_at91.c -+++ b/drivers/ata/pata_at91.c -@@ -18,7 +18,6 @@ - - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_atiixp.c -+++ b/drivers/ata/pata_atiixp.c -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_atp867x.c -+++ b/drivers/ata/pata_atp867x.c -@@ -29,7 +29,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_cmd640.c -+++ b/drivers/ata/pata_cmd640.c -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_cmd64x.c -+++ b/drivers/ata/pata_cmd64x.c -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_cs5520.c -+++ b/drivers/ata/pata_cs5520.c -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_cs5530.c -+++ b/drivers/ata/pata_cs5530.c -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_cs5535.c -+++ b/drivers/ata/pata_cs5535.c -@@ -31,7 +31,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_cs5536.c -+++ b/drivers/ata/pata_cs5536.c -@@ -33,7 +33,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_cypress.c -+++ b/drivers/ata/pata_cypress.c -@@ -11,7 +11,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_efar.c -+++ b/drivers/ata/pata_efar.c -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_ep93xx.c -+++ b/drivers/ata/pata_ep93xx.c -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_hpt366.c -+++ b/drivers/ata/pata_hpt366.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_hpt37x.c -+++ b/drivers/ata/pata_hpt37x.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_hpt3x2n.c -+++ b/drivers/ata/pata_hpt3x2n.c -@@ -20,7 +20,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_hpt3x3.c -+++ b/drivers/ata/pata_hpt3x3.c -@@ -16,7 +16,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_imx.c -+++ b/drivers/ata/pata_imx.c -@@ -15,7 +15,6 @@ - */ - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_it8213.c -+++ b/drivers/ata/pata_it8213.c -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_it821x.c -+++ b/drivers/ata/pata_it821x.c -@@ -72,7 +72,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_jmicron.c -+++ b/drivers/ata/pata_jmicron.c -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_marvell.c -+++ b/drivers/ata/pata_marvell.c -@@ -11,7 +11,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_mpiix.c -+++ b/drivers/ata/pata_mpiix.c -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_netcell.c -+++ b/drivers/ata/pata_netcell.c -@@ -7,7 +7,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_ninja32.c -+++ b/drivers/ata/pata_ninja32.c -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_ns87410.c -+++ b/drivers/ata/pata_ns87410.c -@@ -20,7 +20,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_ns87415.c -+++ b/drivers/ata/pata_ns87415.c -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_oldpiix.c -+++ b/drivers/ata/pata_oldpiix.c -@@ -16,7 +16,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_opti.c -+++ b/drivers/ata/pata_opti.c -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_optidma.c -+++ b/drivers/ata/pata_optidma.c -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_pcmcia.c -+++ b/drivers/ata/pata_pcmcia.c -@@ -26,7 +26,6 @@ - - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_pdc2027x.c -+++ b/drivers/ata/pata_pdc2027x.c -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_pdc202xx_old.c -+++ b/drivers/ata/pata_pdc202xx_old.c -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_piccolo.c -+++ b/drivers/ata/pata_piccolo.c -@@ -18,7 +18,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_platform.c -+++ b/drivers/ata/pata_platform.c -@@ -13,7 +13,6 @@ - */ - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_pxa.c -+++ b/drivers/ata/pata_pxa.c -@@ -20,7 +20,6 @@ - - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_radisys.c -+++ b/drivers/ata/pata_radisys.c -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_rdc.c -+++ b/drivers/ata/pata_rdc.c -@@ -24,7 +24,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_rz1000.c -+++ b/drivers/ata/pata_rz1000.c -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_sc1200.c -+++ b/drivers/ata/pata_sc1200.c -@@ -32,7 +32,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_scc.c -+++ b/drivers/ata/pata_scc.c -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_sch.c -+++ b/drivers/ata/pata_sch.c -@@ -27,7 +27,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_serverworks.c -+++ b/drivers/ata/pata_serverworks.c -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_sil680.c -+++ b/drivers/ata/pata_sil680.c -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_sis.c -+++ b/drivers/ata/pata_sis.c -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_sl82c105.c -+++ b/drivers/ata/pata_sl82c105.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_triflex.c -+++ b/drivers/ata/pata_triflex.c -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pata_via.c -+++ b/drivers/ata/pata_via.c -@@ -55,7 +55,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/pdc_adma.c -+++ b/drivers/ata/pdc_adma.c -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_dwc_460ex.c -+++ b/drivers/ata/sata_dwc_460ex.c -@@ -29,7 +29,6 @@ - - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_highbank.c -+++ b/drivers/ata/sata_highbank.c -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_nv.c -+++ b/drivers/ata/sata_nv.c -@@ -40,7 +40,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_promise.c -+++ b/drivers/ata/sata_promise.c -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_qstor.c -+++ b/drivers/ata/sata_qstor.c -@@ -31,7 +31,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_sil.c -+++ b/drivers/ata/sata_sil.c -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_sis.c -+++ b/drivers/ata/sata_sis.c -@@ -33,7 +33,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_svw.c -+++ b/drivers/ata/sata_svw.c -@@ -39,7 +39,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_sx4.c -+++ b/drivers/ata/sata_sx4.c -@@ -82,7 +82,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_uli.c -+++ b/drivers/ata/sata_uli.c -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_via.c -+++ b/drivers/ata/sata_via.c -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include ---- a/drivers/ata/sata_vsc.c -+++ b/drivers/ata/sata_vsc.c -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - #include - #include diff --git a/target/linux/ipq806x/patches/0114-ahci-platform-Library-ise-ahci_probe-functionality.patch b/target/linux/ipq806x/patches/0114-ahci-platform-Library-ise-ahci_probe-functionality.patch deleted file mode 100644 index 3b638d45ac..0000000000 --- a/target/linux/ipq806x/patches/0114-ahci-platform-Library-ise-ahci_probe-functionality.patch +++ /dev/null @@ -1,334 +0,0 @@ -From 8be4987340a101253fb871556894a002f1afb51f Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 16:53:34 +0100 -Subject: [PATCH 114/182] ahci-platform: "Library-ise" ahci_probe - functionality - -ahci_probe consists of 3 steps: -1) Get resources (get mmio, clks, regulator) -2) Enable resources, handled by ahci_platform_enable_resouces -3) The more or less standard ahci-host controller init sequence - -This commit refactors step 1 and 3 into separate functions, so the platform -drivers for AHCI implementations which need a specific order in step 2, -and / or need to do some custom register poking at some time, can re-use -ahci-platform.c code without needing to copy and paste it. - -Note that ahci_platform_init_host's prototype takes the 3 non function -members of ahci_platform_data as arguments, the idea is that drivers using -the new exported utility functions will not use ahci_platform_data at all, -and hopefully in the future ahci_platform_data can go away entirely. - -tj: Minor comment formatting updates. - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 188 +++++++++++++++++++++++++++-------------- - include/linux/ahci_platform.h | 14 +++ - 2 files changed, 137 insertions(+), 65 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -188,64 +188,60 @@ void ahci_platform_disable_resources(str - } - EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); - --static void ahci_put_clks(struct ahci_host_priv *hpriv) -+static void ahci_platform_put_resources(struct device *dev, void *res) - { -+ struct ahci_host_priv *hpriv = res; - int c; - - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) - clk_put(hpriv->clks[c]); - } - --static int ahci_probe(struct platform_device *pdev) -+/** -+ * ahci_platform_get_resources - Get platform resources -+ * @pdev: platform device to get resources for -+ * -+ * This function allocates an ahci_host_priv struct, and gets the following -+ * resources, storing a reference to them inside the returned struct: -+ * -+ * 1) mmio registers (IORESOURCE_MEM 0, mandatory) -+ * 2) regulator for controlling the targets power (optional) -+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, -+ * or for non devicetree enabled platforms a single clock -+ * -+ * RETURNS: -+ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value -+ */ -+struct ahci_host_priv *ahci_platform_get_resources( -+ struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -- struct ahci_platform_data *pdata = dev_get_platdata(dev); -- const struct platform_device_id *id = platform_get_device_id(pdev); -- struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0]; -- const struct ata_port_info *ppi[] = { &pi, NULL }; - struct ahci_host_priv *hpriv; -- struct ata_host *host; -- struct resource *mem; - struct clk *clk; -- int irq; -- int n_ports; -- int i; -- int rc; -+ int i, rc = -ENOMEM; - -- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!mem) { -- dev_err(dev, "no mmio space\n"); -- return -EINVAL; -- } -+ if (!devres_open_group(dev, NULL, GFP_KERNEL)) -+ return ERR_PTR(-ENOMEM); - -- irq = platform_get_irq(pdev, 0); -- if (irq <= 0) { -- dev_err(dev, "no irq\n"); -- return -EINVAL; -- } -- -- if (pdata && pdata->ata_port_info) -- pi = *pdata->ata_port_info; -+ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), -+ GFP_KERNEL); -+ if (!hpriv) -+ goto err_out; - -- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); -- if (!hpriv) { -- dev_err(dev, "can't alloc ahci_host_priv\n"); -- return -ENOMEM; -- } -+ devres_add(dev, hpriv); - -- hpriv->flags |= (unsigned long)pi.private_data; -- -- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); -+ hpriv->mmio = devm_ioremap_resource(dev, -+ platform_get_resource(pdev, IORESOURCE_MEM, 0)); - if (!hpriv->mmio) { -- dev_err(dev, "can't map %pR\n", mem); -- return -ENOMEM; -+ dev_err(dev, "no mmio space\n"); -+ goto err_out; - } - - hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); - if (IS_ERR(hpriv->target_pwr)) { - rc = PTR_ERR(hpriv->target_pwr); - if (rc == -EPROBE_DEFER) -- return -EPROBE_DEFER; -+ goto err_out; - hpriv->target_pwr = NULL; - } - -@@ -264,33 +260,59 @@ static int ahci_probe(struct platform_de - if (IS_ERR(clk)) { - rc = PTR_ERR(clk); - if (rc == -EPROBE_DEFER) -- goto free_clk; -+ goto err_out; - break; - } - hpriv->clks[i] = clk; - } - -- rc = ahci_platform_enable_resources(hpriv); -- if (rc) -- goto free_clk; -+ devres_remove_group(dev, NULL); -+ return hpriv; - -- /* -- * Some platforms might need to prepare for mmio region access, -- * which could be done in the following init call. So, the mmio -- * region shouldn't be accessed before init (if provided) has -- * returned successfully. -- */ -- if (pdata && pdata->init) { -- rc = pdata->init(dev, hpriv->mmio); -- if (rc) -- goto disable_resources; -- } -+err_out: -+ devres_release_group(dev, NULL); -+ return ERR_PTR(rc); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_get_resources); -+ -+/** -+ * ahci_platform_init_host - Bring up an ahci-platform host -+ * @pdev: platform device pointer for the host -+ * @hpriv: ahci-host private data for the host -+ * @pi_template: template for the ata_port_info to use -+ * @force_port_map: param passed to ahci_save_initial_config -+ * @mask_port_map: param passed to ahci_save_initial_config -+ * -+ * This function does all the usual steps needed to bring up an -+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -+ * must be initialized / enabled before calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_init_host(struct platform_device *pdev, -+ struct ahci_host_priv *hpriv, -+ const struct ata_port_info *pi_template, -+ unsigned int force_port_map, -+ unsigned int mask_port_map) -+{ -+ struct device *dev = &pdev->dev; -+ struct ata_port_info pi = *pi_template; -+ const struct ata_port_info *ppi[] = { &pi, NULL }; -+ struct ata_host *host; -+ int i, irq, n_ports, rc; - -- ahci_save_initial_config(dev, hpriv, -- pdata ? pdata->force_port_map : 0, -- pdata ? pdata->mask_port_map : 0); -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "no irq\n"); -+ return -EINVAL; -+ } - - /* prepare host */ -+ hpriv->flags |= (unsigned long)pi.private_data; -+ -+ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map); -+ - if (hpriv->cap & HOST_CAP_NCQ) - pi.flags |= ATA_FLAG_NCQ; - -@@ -307,10 +329,8 @@ static int ahci_probe(struct platform_de - n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); - - host = ata_host_alloc_pinfo(dev, ppi, n_ports); -- if (!host) { -- rc = -ENOMEM; -- goto pdata_exit; -- } -+ if (!host) -+ return -ENOMEM; - - host->private_data = hpriv; - -@@ -325,7 +345,8 @@ static int ahci_probe(struct platform_de - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - -- ata_port_desc(ap, "mmio %pR", mem); -+ ata_port_desc(ap, "mmio %pR", -+ platform_get_resource(pdev, IORESOURCE_MEM, 0)); - ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); - - /* set enclosure management message type */ -@@ -339,13 +360,53 @@ static int ahci_probe(struct platform_de - - rc = ahci_reset_controller(host); - if (rc) -- goto pdata_exit; -+ return rc; - - ahci_init_controller(host); - ahci_print_info(host, "platform"); - -- rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, -- &ahci_platform_sht); -+ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, -+ &ahci_platform_sht); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_init_host); -+ -+static int ahci_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ const struct platform_device_id *id = platform_get_device_id(pdev); -+ const struct ata_port_info *pi_template; -+ struct ahci_host_priv *hpriv; -+ int rc; -+ -+ hpriv = ahci_platform_get_resources(pdev); -+ if (IS_ERR(hpriv)) -+ return PTR_ERR(hpriv); -+ -+ rc = ahci_platform_enable_resources(hpriv); -+ if (rc) -+ return rc; -+ -+ /* -+ * Some platforms might need to prepare for mmio region access, -+ * which could be done in the following init call. So, the mmio -+ * region shouldn't be accessed before init (if provided) has -+ * returned successfully. -+ */ -+ if (pdata && pdata->init) { -+ rc = pdata->init(dev, hpriv->mmio); -+ if (rc) -+ goto disable_resources; -+ } -+ -+ if (pdata && pdata->ata_port_info) -+ pi_template = pdata->ata_port_info; -+ else -+ pi_template = &ahci_port_info[id ? id->driver_data : 0]; -+ -+ rc = ahci_platform_init_host(pdev, hpriv, pi_template, -+ pdata ? pdata->force_port_map : 0, -+ pdata ? pdata->mask_port_map : 0); - if (rc) - goto pdata_exit; - -@@ -355,8 +416,6 @@ pdata_exit: - pdata->exit(dev); - disable_resources: - ahci_platform_disable_resources(hpriv); --free_clk: -- ahci_put_clks(hpriv); - return rc; - } - -@@ -370,7 +429,6 @@ static void ahci_host_stop(struct ata_ho - pdata->exit(dev); - - ahci_platform_disable_resources(hpriv); -- ahci_put_clks(hpriv); - } - - #ifdef CONFIG_PM_SLEEP ---- a/include/linux/ahci_platform.h -+++ b/include/linux/ahci_platform.h -@@ -20,7 +20,14 @@ - struct device; - struct ata_port_info; - struct ahci_host_priv; -+struct platform_device; - -+/* -+ * Note ahci_platform_data is deprecated, it is only kept around for use -+ * by the old da850 and spear13xx ahci code. -+ * New drivers should instead declare their own platform_driver struct, and -+ * use ahci_platform* functions in their own probe, suspend and resume methods. -+ */ - struct ahci_platform_data { - int (*init)(struct device *dev, void __iomem *addr); - void (*exit)(struct device *dev); -@@ -35,5 +42,12 @@ int ahci_platform_enable_clks(struct ahc - void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); - int ahci_platform_enable_resources(struct ahci_host_priv *hpriv); - void ahci_platform_disable_resources(struct ahci_host_priv *hpriv); -+struct ahci_host_priv *ahci_platform_get_resources( -+ struct platform_device *pdev); -+int ahci_platform_init_host(struct platform_device *pdev, -+ struct ahci_host_priv *hpriv, -+ const struct ata_port_info *pi_template, -+ unsigned int force_port_map, -+ unsigned int mask_port_map); - - #endif /* _AHCI_PLATFORM_H */ diff --git a/target/linux/ipq806x/patches/0115-ahci-platform-Library-ise-suspend-resume-functionali.patch b/target/linux/ipq806x/patches/0115-ahci-platform-Library-ise-suspend-resume-functionali.patch deleted file mode 100644 index 8cc7d7acc9..0000000000 --- a/target/linux/ipq806x/patches/0115-ahci-platform-Library-ise-suspend-resume-functionali.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 8121ed9c7ea2d56f5e0a98c2db396214f85d7485 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 16:53:35 +0100 -Subject: [PATCH 115/182] ahci-platform: "Library-ise" suspend / resume - functionality - -Split suspend / resume code into host suspend / resume functionality and -resource enable / disabling phases, and export the new suspend_ / resume_host -functions. - -tj: Minor comment formatting updates. - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 97 ++++++++++++++++++++++++++++++++++------- - include/linux/ahci_platform.h | 5 +++ - 2 files changed, 87 insertions(+), 15 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -432,14 +432,23 @@ static void ahci_host_stop(struct ata_ho - } - - #ifdef CONFIG_PM_SLEEP --static int ahci_suspend(struct device *dev) -+/** -+ * ahci_platform_suspend_host - Suspend an ahci-platform host -+ * @dev: device pointer for the host -+ * -+ * This function does all the usual steps needed to suspend an -+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -+ * must be disabled after calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_suspend_host(struct device *dev) - { -- struct ahci_platform_data *pdata = dev_get_platdata(dev); - struct ata_host *host = dev_get_drvdata(dev); - struct ahci_host_priv *hpriv = host->private_data; - void __iomem *mmio = hpriv->mmio; - u32 ctl; -- int rc; - - if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { - dev_err(dev, "firmware update required for suspend/resume\n"); -@@ -456,7 +465,58 @@ static int ahci_suspend(struct device *d - writel(ctl, mmio + HOST_CTL); - readl(mmio + HOST_CTL); /* flush */ - -- rc = ata_host_suspend(host, PMSG_SUSPEND); -+ return ata_host_suspend(host, PMSG_SUSPEND); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); -+ -+/** -+ * ahci_platform_resume_host - Resume an ahci-platform host -+ * @dev: device pointer for the host -+ * -+ * This function does all the usual steps needed to resume an ahci-platform -+ * host, note any necessary resources (ie clks, phy, etc.) must be -+ * initialized / enabled before calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_resume_host(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ int rc; -+ -+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -+ rc = ahci_reset_controller(host); -+ if (rc) -+ return rc; -+ -+ ahci_init_controller(host); -+ } -+ -+ ata_host_resume(host); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_resume_host); -+ -+/** -+ * ahci_platform_suspend - Suspend an ahci-platform device -+ * @dev: the platform device to suspend -+ * -+ * This function suspends the host associated with the device, followed by -+ * disabling all the resources of the device. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_suspend(struct device *dev) -+{ -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ int rc; -+ -+ rc = ahci_platform_suspend_host(dev); - if (rc) - return rc; - -@@ -467,8 +527,19 @@ static int ahci_suspend(struct device *d - - return 0; - } -+EXPORT_SYMBOL_GPL(ahci_platform_suspend); - --static int ahci_resume(struct device *dev) -+/** -+ * ahci_platform_resume - Resume an ahci-platform device -+ * @dev: the platform device to resume -+ * -+ * This function enables all the resources of the device followed by -+ * resuming the host associated with the device. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_resume(struct device *dev) - { - struct ahci_platform_data *pdata = dev_get_platdata(dev); - struct ata_host *host = dev_get_drvdata(dev); -@@ -485,15 +556,9 @@ static int ahci_resume(struct device *de - goto disable_resources; - } - -- if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -- rc = ahci_reset_controller(host); -- if (rc) -- goto disable_resources; -- -- ahci_init_controller(host); -- } -- -- ata_host_resume(host); -+ rc = ahci_platform_resume_host(dev); -+ if (rc) -+ goto disable_resources; - - return 0; - -@@ -502,9 +567,11 @@ disable_resources: - - return rc; - } -+EXPORT_SYMBOL_GPL(ahci_platform_resume); - #endif - --static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); -+static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, -+ ahci_platform_resume); - - static const struct of_device_id ahci_of_match[] = { - { .compatible = "snps,spear-ahci", }, ---- a/include/linux/ahci_platform.h -+++ b/include/linux/ahci_platform.h -@@ -50,4 +50,9 @@ int ahci_platform_init_host(struct platf - unsigned int force_port_map, - unsigned int mask_port_map); - -+int ahci_platform_suspend_host(struct device *dev); -+int ahci_platform_resume_host(struct device *dev); -+int ahci_platform_suspend(struct device *dev); -+int ahci_platform_resume(struct device *dev); -+ - #endif /* _AHCI_PLATFORM_H */ diff --git a/target/linux/ipq806x/patches/0116-ata-ahci_platform-Add-DT-compatible-for-Synopsis-DWC.patch b/target/linux/ipq806x/patches/0116-ata-ahci_platform-Add-DT-compatible-for-Synopsis-DWC.patch deleted file mode 100644 index e64e5c9eaa..0000000000 --- a/target/linux/ipq806x/patches/0116-ata-ahci_platform-Add-DT-compatible-for-Synopsis-DWC.patch +++ /dev/null @@ -1,27 +0,0 @@ -From bab3492791ade083c172a898b6f7a3692ffb89d5 Mon Sep 17 00:00:00 2001 -From: Roger Quadros -Date: Sat, 22 Feb 2014 16:53:38 +0100 -Subject: [PATCH 116/182] ata: ahci_platform: Add DT compatible for Synopsis - DWC AHCI controller - -Add compatible string "snps,dwc-ahci", which should be used -for Synopsis Designware SATA cores. e.g. on TI OMAP5 and DRA7 platforms. - -Signed-off-by: Roger Quadros -Reviewed-by: Bartlomiej Zolnierkiewicz -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -577,6 +577,7 @@ static const struct of_device_id ahci_of - { .compatible = "snps,spear-ahci", }, - { .compatible = "snps,exynos5440-ahci", }, - { .compatible = "ibm,476gtr-ahci", }, -+ { .compatible = "snps,dwc-ahci", }, - {}, - }; - MODULE_DEVICE_TABLE(of, ahci_of_match); diff --git a/target/linux/ipq806x/patches/0117-ata-ahci_platform-Manage-SATA-PHY.patch b/target/linux/ipq806x/patches/0117-ata-ahci_platform-Manage-SATA-PHY.patch deleted file mode 100644 index 20211dcc1d..0000000000 --- a/target/linux/ipq806x/patches/0117-ata-ahci_platform-Manage-SATA-PHY.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 05b9b8d1035944af25694d2ebe53077cf1ccb067 Mon Sep 17 00:00:00 2001 -From: Roger Quadros -Date: Sat, 22 Feb 2014 16:53:40 +0100 -Subject: [PATCH 117/182] ata: ahci_platform: Manage SATA PHY - -Some platforms have a PHY hooked up to the SATA controller. The PHY -needs to be initialized and powered up for SATA to work. We do that -using the PHY framework. - -tj: Minor comment formatting updates. - -CC: Balaji T K -Signed-off-by: Roger Quadros -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci.h | 2 ++ - drivers/ata/ahci_platform.c | 47 +++++++++++++++++++++++++++++++++++++++++-- - 2 files changed, 47 insertions(+), 2 deletions(-) - ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -37,6 +37,7 @@ - - #include - #include -+#include - #include - - /* Enclosure Management Control */ -@@ -326,6 +327,7 @@ struct ahci_host_priv { - u32 em_msg_type; /* EM message type */ - struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ - struct regulator *target_pwr; /* Optional */ -+ struct phy *phy; /* If platform uses phy */ - void *plat_data; /* Other platform data */ - /* - * Optional ahci_start_engine override, if not set this gets set to the ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include "ahci.h" - - static void ahci_host_stop(struct ata_host *host); -@@ -140,6 +141,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_ - * following order: - * 1) Regulator - * 2) Clocks (through ahci_platform_enable_clks) -+ * 3) Phy - * - * If resource enabling fails at any point the previous enabled resources - * are disabled in reverse order. -@@ -161,8 +163,23 @@ int ahci_platform_enable_resources(struc - if (rc) - goto disable_regulator; - -+ if (hpriv->phy) { -+ rc = phy_init(hpriv->phy); -+ if (rc) -+ goto disable_clks; -+ -+ rc = phy_power_on(hpriv->phy); -+ if (rc) { -+ phy_exit(hpriv->phy); -+ goto disable_clks; -+ } -+ } -+ - return 0; - -+disable_clks: -+ ahci_platform_disable_clks(hpriv); -+ - disable_regulator: - if (hpriv->target_pwr) - regulator_disable(hpriv->target_pwr); -@@ -176,11 +193,17 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_r - * - * This function disables all ahci_platform managed resources in the - * following order: -- * 1) Clocks (through ahci_platform_disable_clks) -- * 2) Regulator -+ * 1) Phy -+ * 2) Clocks (through ahci_platform_disable_clks) -+ * 3) Regulator - */ - void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) - { -+ if (hpriv->phy) { -+ phy_power_off(hpriv->phy); -+ phy_exit(hpriv->phy); -+ } -+ - ahci_platform_disable_clks(hpriv); - - if (hpriv->target_pwr) -@@ -208,6 +231,7 @@ static void ahci_platform_put_resources( - * 2) regulator for controlling the targets power (optional) - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, - * or for non devicetree enabled platforms a single clock -+ * 4) phy (optional) - * - * RETURNS: - * The allocated ahci_host_priv on success, otherwise an ERR_PTR value -@@ -266,6 +290,25 @@ struct ahci_host_priv *ahci_platform_get - hpriv->clks[i] = clk; - } - -+ hpriv->phy = devm_phy_get(dev, "sata-phy"); -+ if (IS_ERR(hpriv->phy)) { -+ rc = PTR_ERR(hpriv->phy); -+ switch (rc) { -+ case -ENODEV: -+ case -ENOSYS: -+ /* continue normally */ -+ hpriv->phy = NULL; -+ break; -+ -+ case -EPROBE_DEFER: -+ goto err_out; -+ -+ default: -+ dev_err(dev, "couldn't get sata-phy\n"); -+ goto err_out; -+ } -+ } -+ - devres_remove_group(dev, NULL); - return hpriv; - diff --git a/target/linux/ipq806x/patches/0118-ata-ahci_platform-runtime-resume-the-device-before-u.patch b/target/linux/ipq806x/patches/0118-ata-ahci_platform-runtime-resume-the-device-before-u.patch deleted file mode 100644 index 6603bb9537..0000000000 --- a/target/linux/ipq806x/patches/0118-ata-ahci_platform-runtime-resume-the-device-before-u.patch +++ /dev/null @@ -1,79 +0,0 @@ -From abe309ab531f22b9b89329bd825606f6b68a95a1 Mon Sep 17 00:00:00 2001 -From: Roger Quadros -Date: Sat, 22 Feb 2014 16:53:41 +0100 -Subject: [PATCH 118/182] ata: ahci_platform: runtime resume the device before - use - -On OMAP platforms the device needs to be runtime resumed before it can -be accessed. The OMAP HWMOD framework takes care of enabling the -module and its resources based on the device's runtime PM state. - -In this patch we runtime resume during .probe() and runtime suspend -after .remove(). - -We also update the runtime PM state during .resume(). - -CC: Balaji T K -Signed-off-by: Roger Quadros -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci.h | 1 + - drivers/ata/ahci_platform.c | 15 +++++++++++++++ - 2 files changed, 16 insertions(+) - ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -325,6 +325,7 @@ struct ahci_host_priv { - u32 em_loc; /* enclosure management location */ - u32 em_buf_sz; /* EM buffer size in byte */ - u32 em_msg_type; /* EM message type */ -+ bool got_runtime_pm; /* Did we do pm_runtime_get? */ - struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ - struct regulator *target_pwr; /* Optional */ - struct phy *phy; /* If platform uses phy */ ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include "ahci.h" - - static void ahci_host_stop(struct ata_host *host); -@@ -216,6 +217,11 @@ static void ahci_platform_put_resources( - struct ahci_host_priv *hpriv = res; - int c; - -+ if (hpriv->got_runtime_pm) { -+ pm_runtime_put_sync(dev); -+ pm_runtime_disable(dev); -+ } -+ - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) - clk_put(hpriv->clks[c]); - } -@@ -309,6 +315,10 @@ struct ahci_host_priv *ahci_platform_get - } - } - -+ pm_runtime_enable(dev); -+ pm_runtime_get_sync(dev); -+ hpriv->got_runtime_pm = true; -+ - devres_remove_group(dev, NULL); - return hpriv; - -@@ -603,6 +613,11 @@ int ahci_platform_resume(struct device * - if (rc) - goto disable_resources; - -+ /* We resumed so update PM runtime state */ -+ pm_runtime_disable(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ - return 0; - - disable_resources: diff --git a/target/linux/ipq806x/patches/0119-ahci_platform-Drop-support-for-ahci-strict-platform-.patch b/target/linux/ipq806x/patches/0119-ahci_platform-Drop-support-for-ahci-strict-platform-.patch deleted file mode 100644 index 2e833ce757..0000000000 --- a/target/linux/ipq806x/patches/0119-ahci_platform-Drop-support-for-ahci-strict-platform-.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 474c436aebe260b0e6e7042ce5291137b7c87b57 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 17:22:53 +0100 -Subject: [PATCH 119/182] ahci_platform: Drop support for ahci-strict platform - device type - -I've done a grep over the entire kernel tree and nothing is using this -(anymore?). - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 11 ----------- - 1 file changed, 11 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -31,7 +31,6 @@ static void ahci_host_stop(struct ata_ho - enum ahci_type { - AHCI, /* standard platform ahci */ - IMX53_AHCI, /* ahci on i.mx53 */ -- STRICT_AHCI, /* delayed DMA engine start */ - }; - - static struct platform_device_id ahci_devtype[] = { -@@ -42,9 +41,6 @@ static struct platform_device_id ahci_de - .name = "imx53-ahci", - .driver_data = IMX53_AHCI, - }, { -- .name = "strict-ahci", -- .driver_data = STRICT_AHCI, -- }, { - /* sentinel */ - } - }; -@@ -75,13 +71,6 @@ static const struct ata_port_info ahci_p - .udma_mask = ATA_UDMA6, - .port_ops = &ahci_platform_retry_srst_ops, - }, -- [STRICT_AHCI] = { -- AHCI_HFLAGS (AHCI_HFLAG_DELAY_ENGINE), -- .flags = AHCI_FLAG_COMMON, -- .pio_mask = ATA_PIO4, -- .udma_mask = ATA_UDMA6, -- .port_ops = &ahci_platform_ops, -- }, - }; - - static struct scsi_host_template ahci_platform_sht = { diff --git a/target/linux/ipq806x/patches/0120-ahci_platform-Drop-support-for-imx53-ahci-platform-d.patch b/target/linux/ipq806x/patches/0120-ahci_platform-Drop-support-for-imx53-ahci-platform-d.patch deleted file mode 100644 index b18c04f8ee..0000000000 --- a/target/linux/ipq806x/patches/0120-ahci_platform-Drop-support-for-imx53-ahci-platform-d.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 0d153bacb749d9291324ef0282ea9d235baca499 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 17:22:54 +0100 -Subject: [PATCH 120/182] ahci_platform: Drop support for imx53-ahci platform - device type - -Since the 3.13 release the ahci_imx driver has proper devicetree enabled -support for ahci on imx53 and that is used instead of the old board file -created imx53-ahci platform device. - -Note this patch also complete drops the id-table, an id-table is not needed -for a single id platform driver, the name field in the driver struct suffices. - -And the code already has an explicit "MODULE_ALIAS("platform:ahci");" so the -id-table is not needed for that either. - -Cc: Marek Vasut -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 46 ++++++------------------------------------- - 1 file changed, 6 insertions(+), 40 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -28,49 +28,17 @@ - - static void ahci_host_stop(struct ata_host *host); - --enum ahci_type { -- AHCI, /* standard platform ahci */ -- IMX53_AHCI, /* ahci on i.mx53 */ --}; -- --static struct platform_device_id ahci_devtype[] = { -- { -- .name = "ahci", -- .driver_data = AHCI, -- }, { -- .name = "imx53-ahci", -- .driver_data = IMX53_AHCI, -- }, { -- /* sentinel */ -- } --}; --MODULE_DEVICE_TABLE(platform, ahci_devtype); -- - struct ata_port_operations ahci_platform_ops = { - .inherits = &ahci_ops, - .host_stop = ahci_host_stop, - }; - EXPORT_SYMBOL_GPL(ahci_platform_ops); - --static struct ata_port_operations ahci_platform_retry_srst_ops = { -- .inherits = &ahci_pmp_retry_srst_ops, -- .host_stop = ahci_host_stop, --}; -- --static const struct ata_port_info ahci_port_info[] = { -- /* by features */ -- [AHCI] = { -- .flags = AHCI_FLAG_COMMON, -- .pio_mask = ATA_PIO4, -- .udma_mask = ATA_UDMA6, -- .port_ops = &ahci_platform_ops, -- }, -- [IMX53_AHCI] = { -- .flags = AHCI_FLAG_COMMON, -- .pio_mask = ATA_PIO4, -- .udma_mask = ATA_UDMA6, -- .port_ops = &ahci_platform_retry_srst_ops, -- }, -+static const struct ata_port_info ahci_port_info = { -+ .flags = AHCI_FLAG_COMMON, -+ .pio_mask = ATA_PIO4, -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &ahci_platform_ops, - }; - - static struct scsi_host_template ahci_platform_sht = { -@@ -416,7 +384,6 @@ static int ahci_probe(struct platform_de - { - struct device *dev = &pdev->dev; - struct ahci_platform_data *pdata = dev_get_platdata(dev); -- const struct platform_device_id *id = platform_get_device_id(pdev); - const struct ata_port_info *pi_template; - struct ahci_host_priv *hpriv; - int rc; -@@ -444,7 +411,7 @@ static int ahci_probe(struct platform_de - if (pdata && pdata->ata_port_info) - pi_template = pdata->ata_port_info; - else -- pi_template = &ahci_port_info[id ? id->driver_data : 0]; -+ pi_template = &ahci_port_info; - - rc = ahci_platform_init_host(pdev, hpriv, pi_template, - pdata ? pdata->force_port_map : 0, -@@ -638,7 +605,6 @@ static struct platform_driver ahci_drive - .of_match_table = ahci_of_match, - .pm = &ahci_pm_ops, - }, -- .id_table = ahci_devtype, - }; - module_platform_driver(ahci_driver); - diff --git a/target/linux/ipq806x/patches/0121-ahci_platform-Drop-unused-ahci_platform_data-members.patch b/target/linux/ipq806x/patches/0121-ahci_platform-Drop-unused-ahci_platform_data-members.patch deleted file mode 100644 index 2895a2b6e5..0000000000 --- a/target/linux/ipq806x/patches/0121-ahci_platform-Drop-unused-ahci_platform_data-members.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 438df60c6bff1b12a407fefcfb8a2e5d9b29ac6a Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Sat, 22 Feb 2014 17:22:55 +0100 -Subject: [PATCH 121/182] ahci_platform: Drop unused ahci_platform_data - members - -These members are not used anywhere, and in the future we want -ahci_platform_data to go away entirely so there is no reason to keep these -around. - -Signed-off-by: Hans de Goede -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 10 +--------- - include/linux/ahci_platform.h | 3 --- - 2 files changed, 1 insertion(+), 12 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -384,7 +384,6 @@ static int ahci_probe(struct platform_de - { - struct device *dev = &pdev->dev; - struct ahci_platform_data *pdata = dev_get_platdata(dev); -- const struct ata_port_info *pi_template; - struct ahci_host_priv *hpriv; - int rc; - -@@ -408,14 +407,7 @@ static int ahci_probe(struct platform_de - goto disable_resources; - } - -- if (pdata && pdata->ata_port_info) -- pi_template = pdata->ata_port_info; -- else -- pi_template = &ahci_port_info; -- -- rc = ahci_platform_init_host(pdev, hpriv, pi_template, -- pdata ? pdata->force_port_map : 0, -- pdata ? pdata->mask_port_map : 0); -+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 0, 0); - if (rc) - goto pdata_exit; - ---- a/include/linux/ahci_platform.h -+++ b/include/linux/ahci_platform.h -@@ -33,9 +33,6 @@ struct ahci_platform_data { - void (*exit)(struct device *dev); - int (*suspend)(struct device *dev); - int (*resume)(struct device *dev); -- const struct ata_port_info *ata_port_info; -- unsigned int force_port_map; -- unsigned int mask_port_map; - }; - - int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); diff --git a/target/linux/ipq806x/patches/0122-ata-ahci_platform-fix-devm_ioremap_resource-return-v.patch b/target/linux/ipq806x/patches/0122-ata-ahci_platform-fix-devm_ioremap_resource-return-v.patch deleted file mode 100644 index 322a039606..0000000000 --- a/target/linux/ipq806x/patches/0122-ata-ahci_platform-fix-devm_ioremap_resource-return-v.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0db91c83bcb5f7307aaa16c093b8c6bb3f44be52 Mon Sep 17 00:00:00 2001 -From: Bartlomiej Zolnierkiewicz -Date: Fri, 14 Mar 2014 18:22:09 +0100 -Subject: [PATCH 122/182] ata: ahci_platform: fix devm_ioremap_resource() - return value checking - -devm_ioremap_resource() returns a pointer to the remapped memory or -an ERR_PTR() encoded error code on failure. Fix the check inside -ahci_platform_get_resources() accordingly. - -Also while at it remove a needless line break. - -Signed-off-by: Bartlomiej Zolnierkiewicz -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -199,8 +199,7 @@ static void ahci_platform_put_resources( - * RETURNS: - * The allocated ahci_host_priv on success, otherwise an ERR_PTR value - */ --struct ahci_host_priv *ahci_platform_get_resources( -- struct platform_device *pdev) -+struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - struct ahci_host_priv *hpriv; -@@ -219,8 +218,9 @@ struct ahci_host_priv *ahci_platform_get - - hpriv->mmio = devm_ioremap_resource(dev, - platform_get_resource(pdev, IORESOURCE_MEM, 0)); -- if (!hpriv->mmio) { -+ if (IS_ERR(hpriv->mmio)) { - dev_err(dev, "no mmio space\n"); -+ rc = PTR_ERR(hpriv->mmio); - goto err_out; - } - diff --git a/target/linux/ipq806x/patches/0123-ata-ahci_platform-fix-ahci_platform_data-suspend-met.patch b/target/linux/ipq806x/patches/0123-ata-ahci_platform-fix-ahci_platform_data-suspend-met.patch deleted file mode 100644 index 1a9e6d174c..0000000000 --- a/target/linux/ipq806x/patches/0123-ata-ahci_platform-fix-ahci_platform_data-suspend-met.patch +++ /dev/null @@ -1,45 +0,0 @@ -From bc26554ffa0223015edb474a4877ec544167dfba Mon Sep 17 00:00:00 2001 -From: Bartlomiej Zolnierkiewicz -Date: Tue, 25 Mar 2014 19:51:38 +0100 -Subject: [PATCH 123/182] ata: ahci_platform: fix ahci_platform_data->suspend - method handling - -Looking at ST SPEAr1340 AHCI code (the only user of the deprecated -pdata->suspend and pdata->resume) it is obvious the we should return -after calling pdata->suspend() only if the function have returned -non-zero return value. The code has been broken since commit 1e70c2 -("ata/ahci_platform: Add clock framework support"). Fix it. - -Cc: Viresh Kumar -Cc: Shiraz Hashim -Acked-by: Hans de Goede -Signed-off-by: Bartlomiej Zolnierkiewicz -Signed-off-by: Tejun Heo ---- - drivers/ata/ahci_platform.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -521,12 +521,19 @@ int ahci_platform_suspend(struct device - if (rc) - return rc; - -- if (pdata && pdata->suspend) -- return pdata->suspend(dev); -+ if (pdata && pdata->suspend) { -+ rc = pdata->suspend(dev); -+ if (rc) -+ goto resume_host; -+ } - - ahci_platform_disable_resources(hpriv); - - return 0; -+ -+resume_host: -+ ahci_platform_resume_host(dev); -+ return rc; - } - EXPORT_SYMBOL_GPL(ahci_platform_suspend); - diff --git a/target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch b/target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch deleted file mode 100644 index eca606b150..0000000000 --- a/target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch +++ /dev/null @@ -1,1145 +0,0 @@ -From 04800db1047afbf6701379435bff1a6fa64215f7 Mon Sep 17 00:00:00 2001 -From: Bartlomiej Zolnierkiewicz -Date: Tue, 25 Mar 2014 19:51:39 +0100 -Subject: [PATCH 124/182] ata: move library code from ahci_platform.c to - libahci_platform.c - -Move AHCI platform library code from ahci_platform.c to -libahci_platform.c and fix dependencies for ahci_st, -ahci_imx and ahci_sunxi drivers. - -Acked-by: Hans de Goede -Signed-off-by: Bartlomiej Zolnierkiewicz -Signed-off-by: Tejun Heo - -Conflicts: - drivers/ata/Kconfig - drivers/ata/Makefile ---- - drivers/ata/Kconfig | 2 +- - drivers/ata/Makefile | 4 +- - drivers/ata/ahci_platform.c | 515 -------------------------------------- - drivers/ata/libahci_platform.c | 541 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 544 insertions(+), 518 deletions(-) - create mode 100644 drivers/ata/libahci_platform.c - ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -115,7 +115,7 @@ config SATA_AHCI_PLATFORM - - config AHCI_IMX - tristate "Freescale i.MX AHCI SATA support" -- depends on SATA_AHCI_PLATFORM && MFD_SYSCON -+ depends on MFD_SYSCON - help - This option enables support for the Freescale i.MX SoC's - onboard AHCI SATA. ---- a/drivers/ata/Makefile -+++ b/drivers/ata/Makefile -@@ -4,13 +4,13 @@ obj-$(CONFIG_ATA) += libata.o - # non-SFF interface - obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o - obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o --obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o -+obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o - obj-$(CONFIG_SATA_FSL) += sata_fsl.o - obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o - obj-$(CONFIG_SATA_SIL24) += sata_sil24.o - obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o - obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o --obj-$(CONFIG_AHCI_IMX) += ahci_imx.o -+obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o - - # SFF w/ custom DMA - obj-$(CONFIG_PDC_ADMA) += pdc_adma.o ---- a/drivers/ata/ahci_platform.c -+++ b/drivers/ata/ahci_platform.c -@@ -12,28 +12,15 @@ - * any later version. - */ - --#include - #include --#include - #include - #include --#include - #include - #include - #include - #include --#include --#include - #include "ahci.h" - --static void ahci_host_stop(struct ata_host *host); -- --struct ata_port_operations ahci_platform_ops = { -- .inherits = &ahci_ops, -- .host_stop = ahci_host_stop, --}; --EXPORT_SYMBOL_GPL(ahci_platform_ops); -- - static const struct ata_port_info ahci_port_info = { - .flags = AHCI_FLAG_COMMON, - .pio_mask = ATA_PIO4, -@@ -41,345 +28,6 @@ static const struct ata_port_info ahci_p - .port_ops = &ahci_platform_ops, - }; - --static struct scsi_host_template ahci_platform_sht = { -- AHCI_SHT("ahci_platform"), --}; -- --/** -- * ahci_platform_enable_clks - Enable platform clocks -- * @hpriv: host private area to store config values -- * -- * This function enables all the clks found in hpriv->clks, starting at -- * index 0. If any clk fails to enable it disables all the clks already -- * enabled in reverse order, and then returns an error. -- * -- * RETURNS: -- * 0 on success otherwise a negative error code -- */ --int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) --{ -- int c, rc; -- -- for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { -- rc = clk_prepare_enable(hpriv->clks[c]); -- if (rc) -- goto disable_unprepare_clk; -- } -- return 0; -- --disable_unprepare_clk: -- while (--c >= 0) -- clk_disable_unprepare(hpriv->clks[c]); -- return rc; --} --EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); -- --/** -- * ahci_platform_disable_clks - Disable platform clocks -- * @hpriv: host private area to store config values -- * -- * This function disables all the clks found in hpriv->clks, in reverse -- * order of ahci_platform_enable_clks (starting at the end of the array). -- */ --void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) --{ -- int c; -- -- for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) -- if (hpriv->clks[c]) -- clk_disable_unprepare(hpriv->clks[c]); --} --EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); -- --/** -- * ahci_platform_enable_resources - Enable platform resources -- * @hpriv: host private area to store config values -- * -- * This function enables all ahci_platform managed resources in the -- * following order: -- * 1) Regulator -- * 2) Clocks (through ahci_platform_enable_clks) -- * 3) Phy -- * -- * If resource enabling fails at any point the previous enabled resources -- * are disabled in reverse order. -- * -- * RETURNS: -- * 0 on success otherwise a negative error code -- */ --int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) --{ -- int rc; -- -- if (hpriv->target_pwr) { -- rc = regulator_enable(hpriv->target_pwr); -- if (rc) -- return rc; -- } -- -- rc = ahci_platform_enable_clks(hpriv); -- if (rc) -- goto disable_regulator; -- -- if (hpriv->phy) { -- rc = phy_init(hpriv->phy); -- if (rc) -- goto disable_clks; -- -- rc = phy_power_on(hpriv->phy); -- if (rc) { -- phy_exit(hpriv->phy); -- goto disable_clks; -- } -- } -- -- return 0; -- --disable_clks: -- ahci_platform_disable_clks(hpriv); -- --disable_regulator: -- if (hpriv->target_pwr) -- regulator_disable(hpriv->target_pwr); -- return rc; --} --EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); -- --/** -- * ahci_platform_disable_resources - Disable platform resources -- * @hpriv: host private area to store config values -- * -- * This function disables all ahci_platform managed resources in the -- * following order: -- * 1) Phy -- * 2) Clocks (through ahci_platform_disable_clks) -- * 3) Regulator -- */ --void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) --{ -- if (hpriv->phy) { -- phy_power_off(hpriv->phy); -- phy_exit(hpriv->phy); -- } -- -- ahci_platform_disable_clks(hpriv); -- -- if (hpriv->target_pwr) -- regulator_disable(hpriv->target_pwr); --} --EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); -- --static void ahci_platform_put_resources(struct device *dev, void *res) --{ -- struct ahci_host_priv *hpriv = res; -- int c; -- -- if (hpriv->got_runtime_pm) { -- pm_runtime_put_sync(dev); -- pm_runtime_disable(dev); -- } -- -- for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) -- clk_put(hpriv->clks[c]); --} -- --/** -- * ahci_platform_get_resources - Get platform resources -- * @pdev: platform device to get resources for -- * -- * This function allocates an ahci_host_priv struct, and gets the following -- * resources, storing a reference to them inside the returned struct: -- * -- * 1) mmio registers (IORESOURCE_MEM 0, mandatory) -- * 2) regulator for controlling the targets power (optional) -- * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, -- * or for non devicetree enabled platforms a single clock -- * 4) phy (optional) -- * -- * RETURNS: -- * The allocated ahci_host_priv on success, otherwise an ERR_PTR value -- */ --struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) --{ -- struct device *dev = &pdev->dev; -- struct ahci_host_priv *hpriv; -- struct clk *clk; -- int i, rc = -ENOMEM; -- -- if (!devres_open_group(dev, NULL, GFP_KERNEL)) -- return ERR_PTR(-ENOMEM); -- -- hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), -- GFP_KERNEL); -- if (!hpriv) -- goto err_out; -- -- devres_add(dev, hpriv); -- -- hpriv->mmio = devm_ioremap_resource(dev, -- platform_get_resource(pdev, IORESOURCE_MEM, 0)); -- if (IS_ERR(hpriv->mmio)) { -- dev_err(dev, "no mmio space\n"); -- rc = PTR_ERR(hpriv->mmio); -- goto err_out; -- } -- -- hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); -- if (IS_ERR(hpriv->target_pwr)) { -- rc = PTR_ERR(hpriv->target_pwr); -- if (rc == -EPROBE_DEFER) -- goto err_out; -- hpriv->target_pwr = NULL; -- } -- -- for (i = 0; i < AHCI_MAX_CLKS; i++) { -- /* -- * For now we must use clk_get(dev, NULL) for the first clock, -- * because some platforms (da850, spear13xx) are not yet -- * converted to use devicetree for clocks. For new platforms -- * this is equivalent to of_clk_get(dev->of_node, 0). -- */ -- if (i == 0) -- clk = clk_get(dev, NULL); -- else -- clk = of_clk_get(dev->of_node, i); -- -- if (IS_ERR(clk)) { -- rc = PTR_ERR(clk); -- if (rc == -EPROBE_DEFER) -- goto err_out; -- break; -- } -- hpriv->clks[i] = clk; -- } -- -- hpriv->phy = devm_phy_get(dev, "sata-phy"); -- if (IS_ERR(hpriv->phy)) { -- rc = PTR_ERR(hpriv->phy); -- switch (rc) { -- case -ENODEV: -- case -ENOSYS: -- /* continue normally */ -- hpriv->phy = NULL; -- break; -- -- case -EPROBE_DEFER: -- goto err_out; -- -- default: -- dev_err(dev, "couldn't get sata-phy\n"); -- goto err_out; -- } -- } -- -- pm_runtime_enable(dev); -- pm_runtime_get_sync(dev); -- hpriv->got_runtime_pm = true; -- -- devres_remove_group(dev, NULL); -- return hpriv; -- --err_out: -- devres_release_group(dev, NULL); -- return ERR_PTR(rc); --} --EXPORT_SYMBOL_GPL(ahci_platform_get_resources); -- --/** -- * ahci_platform_init_host - Bring up an ahci-platform host -- * @pdev: platform device pointer for the host -- * @hpriv: ahci-host private data for the host -- * @pi_template: template for the ata_port_info to use -- * @force_port_map: param passed to ahci_save_initial_config -- * @mask_port_map: param passed to ahci_save_initial_config -- * -- * This function does all the usual steps needed to bring up an -- * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -- * must be initialized / enabled before calling this. -- * -- * RETURNS: -- * 0 on success otherwise a negative error code -- */ --int ahci_platform_init_host(struct platform_device *pdev, -- struct ahci_host_priv *hpriv, -- const struct ata_port_info *pi_template, -- unsigned int force_port_map, -- unsigned int mask_port_map) --{ -- struct device *dev = &pdev->dev; -- struct ata_port_info pi = *pi_template; -- const struct ata_port_info *ppi[] = { &pi, NULL }; -- struct ata_host *host; -- int i, irq, n_ports, rc; -- -- irq = platform_get_irq(pdev, 0); -- if (irq <= 0) { -- dev_err(dev, "no irq\n"); -- return -EINVAL; -- } -- -- /* prepare host */ -- hpriv->flags |= (unsigned long)pi.private_data; -- -- ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map); -- -- if (hpriv->cap & HOST_CAP_NCQ) -- pi.flags |= ATA_FLAG_NCQ; -- -- if (hpriv->cap & HOST_CAP_PMP) -- pi.flags |= ATA_FLAG_PMP; -- -- ahci_set_em_messages(hpriv, &pi); -- -- /* CAP.NP sometimes indicate the index of the last enabled -- * port, at other times, that of the last possible port, so -- * determining the maximum port number requires looking at -- * both CAP.NP and port_map. -- */ -- n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); -- -- host = ata_host_alloc_pinfo(dev, ppi, n_ports); -- if (!host) -- return -ENOMEM; -- -- host->private_data = hpriv; -- -- if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) -- host->flags |= ATA_HOST_PARALLEL_SCAN; -- else -- dev_info(dev, "SSS flag set, parallel bus scan disabled\n"); -- -- if (pi.flags & ATA_FLAG_EM) -- ahci_reset_em(host); -- -- for (i = 0; i < host->n_ports; i++) { -- struct ata_port *ap = host->ports[i]; -- -- ata_port_desc(ap, "mmio %pR", -- platform_get_resource(pdev, IORESOURCE_MEM, 0)); -- ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); -- -- /* set enclosure management message type */ -- if (ap->flags & ATA_FLAG_EM) -- ap->em_message_type = hpriv->em_msg_type; -- -- /* disabled/not-implemented port */ -- if (!(hpriv->port_map & (1 << i))) -- ap->ops = &ata_dummy_port_ops; -- } -- -- rc = ahci_reset_controller(host); -- if (rc) -- return rc; -- -- ahci_init_controller(host); -- ahci_print_info(host, "platform"); -- -- return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, -- &ahci_platform_sht); --} --EXPORT_SYMBOL_GPL(ahci_platform_init_host); -- - static int ahci_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -420,169 +68,6 @@ disable_resources: - return rc; - } - --static void ahci_host_stop(struct ata_host *host) --{ -- struct device *dev = host->dev; -- struct ahci_platform_data *pdata = dev_get_platdata(dev); -- struct ahci_host_priv *hpriv = host->private_data; -- -- if (pdata && pdata->exit) -- pdata->exit(dev); -- -- ahci_platform_disable_resources(hpriv); --} -- --#ifdef CONFIG_PM_SLEEP --/** -- * ahci_platform_suspend_host - Suspend an ahci-platform host -- * @dev: device pointer for the host -- * -- * This function does all the usual steps needed to suspend an -- * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -- * must be disabled after calling this. -- * -- * RETURNS: -- * 0 on success otherwise a negative error code -- */ --int ahci_platform_suspend_host(struct device *dev) --{ -- struct ata_host *host = dev_get_drvdata(dev); -- struct ahci_host_priv *hpriv = host->private_data; -- void __iomem *mmio = hpriv->mmio; -- u32 ctl; -- -- if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { -- dev_err(dev, "firmware update required for suspend/resume\n"); -- return -EIO; -- } -- -- /* -- * AHCI spec rev1.1 section 8.3.3: -- * Software must disable interrupts prior to requesting a -- * transition of the HBA to D3 state. -- */ -- ctl = readl(mmio + HOST_CTL); -- ctl &= ~HOST_IRQ_EN; -- writel(ctl, mmio + HOST_CTL); -- readl(mmio + HOST_CTL); /* flush */ -- -- return ata_host_suspend(host, PMSG_SUSPEND); --} --EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); -- --/** -- * ahci_platform_resume_host - Resume an ahci-platform host -- * @dev: device pointer for the host -- * -- * This function does all the usual steps needed to resume an ahci-platform -- * host, note any necessary resources (ie clks, phy, etc.) must be -- * initialized / enabled before calling this. -- * -- * RETURNS: -- * 0 on success otherwise a negative error code -- */ --int ahci_platform_resume_host(struct device *dev) --{ -- struct ata_host *host = dev_get_drvdata(dev); -- int rc; -- -- if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -- rc = ahci_reset_controller(host); -- if (rc) -- return rc; -- -- ahci_init_controller(host); -- } -- -- ata_host_resume(host); -- -- return 0; --} --EXPORT_SYMBOL_GPL(ahci_platform_resume_host); -- --/** -- * ahci_platform_suspend - Suspend an ahci-platform device -- * @dev: the platform device to suspend -- * -- * This function suspends the host associated with the device, followed by -- * disabling all the resources of the device. -- * -- * RETURNS: -- * 0 on success otherwise a negative error code -- */ --int ahci_platform_suspend(struct device *dev) --{ -- struct ahci_platform_data *pdata = dev_get_platdata(dev); -- struct ata_host *host = dev_get_drvdata(dev); -- struct ahci_host_priv *hpriv = host->private_data; -- int rc; -- -- rc = ahci_platform_suspend_host(dev); -- if (rc) -- return rc; -- -- if (pdata && pdata->suspend) { -- rc = pdata->suspend(dev); -- if (rc) -- goto resume_host; -- } -- -- ahci_platform_disable_resources(hpriv); -- -- return 0; -- --resume_host: -- ahci_platform_resume_host(dev); -- return rc; --} --EXPORT_SYMBOL_GPL(ahci_platform_suspend); -- --/** -- * ahci_platform_resume - Resume an ahci-platform device -- * @dev: the platform device to resume -- * -- * This function enables all the resources of the device followed by -- * resuming the host associated with the device. -- * -- * RETURNS: -- * 0 on success otherwise a negative error code -- */ --int ahci_platform_resume(struct device *dev) --{ -- struct ahci_platform_data *pdata = dev_get_platdata(dev); -- struct ata_host *host = dev_get_drvdata(dev); -- struct ahci_host_priv *hpriv = host->private_data; -- int rc; -- -- rc = ahci_platform_enable_resources(hpriv); -- if (rc) -- return rc; -- -- if (pdata && pdata->resume) { -- rc = pdata->resume(dev); -- if (rc) -- goto disable_resources; -- } -- -- rc = ahci_platform_resume_host(dev); -- if (rc) -- goto disable_resources; -- -- /* We resumed so update PM runtime state */ -- pm_runtime_disable(dev); -- pm_runtime_set_active(dev); -- pm_runtime_enable(dev); -- -- return 0; -- --disable_resources: -- ahci_platform_disable_resources(hpriv); -- -- return rc; --} --EXPORT_SYMBOL_GPL(ahci_platform_resume); --#endif -- - static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, - ahci_platform_resume); - ---- /dev/null -+++ b/drivers/ata/libahci_platform.c -@@ -0,0 +1,541 @@ -+/* -+ * AHCI SATA platform library -+ * -+ * Copyright 2004-2005 Red Hat, Inc. -+ * Jeff Garzik -+ * Copyright 2010 MontaVista Software, LLC. -+ * Anton Vorontsov -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2, or (at your option) -+ * any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "ahci.h" -+ -+static void ahci_host_stop(struct ata_host *host); -+ -+struct ata_port_operations ahci_platform_ops = { -+ .inherits = &ahci_ops, -+ .host_stop = ahci_host_stop, -+}; -+EXPORT_SYMBOL_GPL(ahci_platform_ops); -+ -+static struct scsi_host_template ahci_platform_sht = { -+ AHCI_SHT("ahci_platform"), -+}; -+ -+/** -+ * ahci_platform_enable_clks - Enable platform clocks -+ * @hpriv: host private area to store config values -+ * -+ * This function enables all the clks found in hpriv->clks, starting at -+ * index 0. If any clk fails to enable it disables all the clks already -+ * enabled in reverse order, and then returns an error. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) -+{ -+ int c, rc; -+ -+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { -+ rc = clk_prepare_enable(hpriv->clks[c]); -+ if (rc) -+ goto disable_unprepare_clk; -+ } -+ return 0; -+ -+disable_unprepare_clk: -+ while (--c >= 0) -+ clk_disable_unprepare(hpriv->clks[c]); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); -+ -+/** -+ * ahci_platform_disable_clks - Disable platform clocks -+ * @hpriv: host private area to store config values -+ * -+ * This function disables all the clks found in hpriv->clks, in reverse -+ * order of ahci_platform_enable_clks (starting at the end of the array). -+ */ -+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) -+{ -+ int c; -+ -+ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) -+ if (hpriv->clks[c]) -+ clk_disable_unprepare(hpriv->clks[c]); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); -+ -+/** -+ * ahci_platform_enable_resources - Enable platform resources -+ * @hpriv: host private area to store config values -+ * -+ * This function enables all ahci_platform managed resources in the -+ * following order: -+ * 1) Regulator -+ * 2) Clocks (through ahci_platform_enable_clks) -+ * 3) Phy -+ * -+ * If resource enabling fails at any point the previous enabled resources -+ * are disabled in reverse order. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) -+{ -+ int rc; -+ -+ if (hpriv->target_pwr) { -+ rc = regulator_enable(hpriv->target_pwr); -+ if (rc) -+ return rc; -+ } -+ -+ rc = ahci_platform_enable_clks(hpriv); -+ if (rc) -+ goto disable_regulator; -+ -+ if (hpriv->phy) { -+ rc = phy_init(hpriv->phy); -+ if (rc) -+ goto disable_clks; -+ -+ rc = phy_power_on(hpriv->phy); -+ if (rc) { -+ phy_exit(hpriv->phy); -+ goto disable_clks; -+ } -+ } -+ -+ return 0; -+ -+disable_clks: -+ ahci_platform_disable_clks(hpriv); -+ -+disable_regulator: -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); -+ -+/** -+ * ahci_platform_disable_resources - Disable platform resources -+ * @hpriv: host private area to store config values -+ * -+ * This function disables all ahci_platform managed resources in the -+ * following order: -+ * 1) Phy -+ * 2) Clocks (through ahci_platform_disable_clks) -+ * 3) Regulator -+ */ -+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) -+{ -+ if (hpriv->phy) { -+ phy_power_off(hpriv->phy); -+ phy_exit(hpriv->phy); -+ } -+ -+ ahci_platform_disable_clks(hpriv); -+ -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); -+ -+static void ahci_platform_put_resources(struct device *dev, void *res) -+{ -+ struct ahci_host_priv *hpriv = res; -+ int c; -+ -+ if (hpriv->got_runtime_pm) { -+ pm_runtime_put_sync(dev); -+ pm_runtime_disable(dev); -+ } -+ -+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) -+ clk_put(hpriv->clks[c]); -+} -+ -+/** -+ * ahci_platform_get_resources - Get platform resources -+ * @pdev: platform device to get resources for -+ * -+ * This function allocates an ahci_host_priv struct, and gets the following -+ * resources, storing a reference to them inside the returned struct: -+ * -+ * 1) mmio registers (IORESOURCE_MEM 0, mandatory) -+ * 2) regulator for controlling the targets power (optional) -+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, -+ * or for non devicetree enabled platforms a single clock -+ * 4) phy (optional) -+ * -+ * RETURNS: -+ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value -+ */ -+struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ahci_host_priv *hpriv; -+ struct clk *clk; -+ int i, rc = -ENOMEM; -+ -+ if (!devres_open_group(dev, NULL, GFP_KERNEL)) -+ return ERR_PTR(-ENOMEM); -+ -+ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), -+ GFP_KERNEL); -+ if (!hpriv) -+ goto err_out; -+ -+ devres_add(dev, hpriv); -+ -+ hpriv->mmio = devm_ioremap_resource(dev, -+ platform_get_resource(pdev, IORESOURCE_MEM, 0)); -+ if (IS_ERR(hpriv->mmio)) { -+ dev_err(dev, "no mmio space\n"); -+ rc = PTR_ERR(hpriv->mmio); -+ goto err_out; -+ } -+ -+ hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); -+ if (IS_ERR(hpriv->target_pwr)) { -+ rc = PTR_ERR(hpriv->target_pwr); -+ if (rc == -EPROBE_DEFER) -+ goto err_out; -+ hpriv->target_pwr = NULL; -+ } -+ -+ for (i = 0; i < AHCI_MAX_CLKS; i++) { -+ /* -+ * For now we must use clk_get(dev, NULL) for the first clock, -+ * because some platforms (da850, spear13xx) are not yet -+ * converted to use devicetree for clocks. For new platforms -+ * this is equivalent to of_clk_get(dev->of_node, 0). -+ */ -+ if (i == 0) -+ clk = clk_get(dev, NULL); -+ else -+ clk = of_clk_get(dev->of_node, i); -+ -+ if (IS_ERR(clk)) { -+ rc = PTR_ERR(clk); -+ if (rc == -EPROBE_DEFER) -+ goto err_out; -+ break; -+ } -+ hpriv->clks[i] = clk; -+ } -+ -+ hpriv->phy = devm_phy_get(dev, "sata-phy"); -+ if (IS_ERR(hpriv->phy)) { -+ rc = PTR_ERR(hpriv->phy); -+ switch (rc) { -+ case -ENODEV: -+ case -ENOSYS: -+ /* continue normally */ -+ hpriv->phy = NULL; -+ break; -+ -+ case -EPROBE_DEFER: -+ goto err_out; -+ -+ default: -+ dev_err(dev, "couldn't get sata-phy\n"); -+ goto err_out; -+ } -+ } -+ -+ pm_runtime_enable(dev); -+ pm_runtime_get_sync(dev); -+ hpriv->got_runtime_pm = true; -+ -+ devres_remove_group(dev, NULL); -+ return hpriv; -+ -+err_out: -+ devres_release_group(dev, NULL); -+ return ERR_PTR(rc); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_get_resources); -+ -+/** -+ * ahci_platform_init_host - Bring up an ahci-platform host -+ * @pdev: platform device pointer for the host -+ * @hpriv: ahci-host private data for the host -+ * @pi_template: template for the ata_port_info to use -+ * @force_port_map: param passed to ahci_save_initial_config -+ * @mask_port_map: param passed to ahci_save_initial_config -+ * -+ * This function does all the usual steps needed to bring up an -+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -+ * must be initialized / enabled before calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_init_host(struct platform_device *pdev, -+ struct ahci_host_priv *hpriv, -+ const struct ata_port_info *pi_template, -+ unsigned int force_port_map, -+ unsigned int mask_port_map) -+{ -+ struct device *dev = &pdev->dev; -+ struct ata_port_info pi = *pi_template; -+ const struct ata_port_info *ppi[] = { &pi, NULL }; -+ struct ata_host *host; -+ int i, irq, n_ports, rc; -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "no irq\n"); -+ return -EINVAL; -+ } -+ -+ /* prepare host */ -+ hpriv->flags |= (unsigned long)pi.private_data; -+ -+ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map); -+ -+ if (hpriv->cap & HOST_CAP_NCQ) -+ pi.flags |= ATA_FLAG_NCQ; -+ -+ if (hpriv->cap & HOST_CAP_PMP) -+ pi.flags |= ATA_FLAG_PMP; -+ -+ ahci_set_em_messages(hpriv, &pi); -+ -+ /* CAP.NP sometimes indicate the index of the last enabled -+ * port, at other times, that of the last possible port, so -+ * determining the maximum port number requires looking at -+ * both CAP.NP and port_map. -+ */ -+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); -+ -+ host = ata_host_alloc_pinfo(dev, ppi, n_ports); -+ if (!host) -+ return -ENOMEM; -+ -+ host->private_data = hpriv; -+ -+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) -+ host->flags |= ATA_HOST_PARALLEL_SCAN; -+ else -+ dev_info(dev, "SSS flag set, parallel bus scan disabled\n"); -+ -+ if (pi.flags & ATA_FLAG_EM) -+ ahci_reset_em(host); -+ -+ for (i = 0; i < host->n_ports; i++) { -+ struct ata_port *ap = host->ports[i]; -+ -+ ata_port_desc(ap, "mmio %pR", -+ platform_get_resource(pdev, IORESOURCE_MEM, 0)); -+ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); -+ -+ /* set enclosure management message type */ -+ if (ap->flags & ATA_FLAG_EM) -+ ap->em_message_type = hpriv->em_msg_type; -+ -+ /* disabled/not-implemented port */ -+ if (!(hpriv->port_map & (1 << i))) -+ ap->ops = &ata_dummy_port_ops; -+ } -+ -+ rc = ahci_reset_controller(host); -+ if (rc) -+ return rc; -+ -+ ahci_init_controller(host); -+ ahci_print_info(host, "platform"); -+ -+ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, -+ &ahci_platform_sht); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_init_host); -+ -+static void ahci_host_stop(struct ata_host *host) -+{ -+ struct device *dev = host->dev; -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ -+ if (pdata && pdata->exit) -+ pdata->exit(dev); -+ -+ ahci_platform_disable_resources(hpriv); -+} -+ -+#ifdef CONFIG_PM_SLEEP -+/** -+ * ahci_platform_suspend_host - Suspend an ahci-platform host -+ * @dev: device pointer for the host -+ * -+ * This function does all the usual steps needed to suspend an -+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -+ * must be disabled after calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_suspend_host(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ void __iomem *mmio = hpriv->mmio; -+ u32 ctl; -+ -+ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { -+ dev_err(dev, "firmware update required for suspend/resume\n"); -+ return -EIO; -+ } -+ -+ /* -+ * AHCI spec rev1.1 section 8.3.3: -+ * Software must disable interrupts prior to requesting a -+ * transition of the HBA to D3 state. -+ */ -+ ctl = readl(mmio + HOST_CTL); -+ ctl &= ~HOST_IRQ_EN; -+ writel(ctl, mmio + HOST_CTL); -+ readl(mmio + HOST_CTL); /* flush */ -+ -+ return ata_host_suspend(host, PMSG_SUSPEND); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); -+ -+/** -+ * ahci_platform_resume_host - Resume an ahci-platform host -+ * @dev: device pointer for the host -+ * -+ * This function does all the usual steps needed to resume an ahci-platform -+ * host, note any necessary resources (ie clks, phy, etc.) must be -+ * initialized / enabled before calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_resume_host(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ int rc; -+ -+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -+ rc = ahci_reset_controller(host); -+ if (rc) -+ return rc; -+ -+ ahci_init_controller(host); -+ } -+ -+ ata_host_resume(host); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_resume_host); -+ -+/** -+ * ahci_platform_suspend - Suspend an ahci-platform device -+ * @dev: the platform device to suspend -+ * -+ * This function suspends the host associated with the device, followed by -+ * disabling all the resources of the device. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_suspend(struct device *dev) -+{ -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ int rc; -+ -+ rc = ahci_platform_suspend_host(dev); -+ if (rc) -+ return rc; -+ -+ if (pdata && pdata->suspend) { -+ rc = pdata->suspend(dev); -+ if (rc) -+ goto resume_host; -+ } -+ -+ ahci_platform_disable_resources(hpriv); -+ -+ return 0; -+ -+resume_host: -+ ahci_platform_resume_host(dev); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_suspend); -+ -+/** -+ * ahci_platform_resume - Resume an ahci-platform device -+ * @dev: the platform device to resume -+ * -+ * This function enables all the resources of the device followed by -+ * resuming the host associated with the device. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_resume(struct device *dev) -+{ -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ int rc; -+ -+ rc = ahci_platform_enable_resources(hpriv); -+ if (rc) -+ return rc; -+ -+ if (pdata && pdata->resume) { -+ rc = pdata->resume(dev); -+ if (rc) -+ goto disable_resources; -+ } -+ -+ rc = ahci_platform_resume_host(dev); -+ if (rc) -+ goto disable_resources; -+ -+ /* We resumed so update PM runtime state */ -+ pm_runtime_disable(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ -+ return 0; -+ -+disable_resources: -+ ahci_platform_disable_resources(hpriv); -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_resume); -+#endif -+ -+MODULE_DESCRIPTION("AHCI SATA platform library"); -+MODULE_AUTHOR("Anton Vorontsov "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ipq806x/patches/0125-clk-qcom-Add-support-for-IPQ8064-s-global-clock-cont.patch b/target/linux/ipq806x/patches/0125-clk-qcom-Add-support-for-IPQ8064-s-global-clock-cont.patch deleted file mode 100644 index 4c4e2634f7..0000000000 --- a/target/linux/ipq806x/patches/0125-clk-qcom-Add-support-for-IPQ8064-s-global-clock-cont.patch +++ /dev/null @@ -1,2921 +0,0 @@ -From 2e6dfaa714ba4bd70fa5dda07c525b6c15e44552 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 3 Apr 2014 13:47:07 -0500 -Subject: [PATCH 125/182] clk: qcom: Add support for IPQ8064's global clock - controller (GCC) - -Add a driver for the global clock controller found on IPQ8064 based -platforms. This should allow most non-multimedia device drivers to probe -and control their clocks. - -This is currently missing clocks for USB HSIC and networking devices. - -Signed-off-by: Kumar Gala -Signed-off-by: Stephen Boyd ---- - .../devicetree/bindings/clock/qcom,gcc.txt | 1 + - drivers/clk/qcom/Kconfig | 8 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/gcc-ipq806x.c | 2424 ++++++++++++++++++++ - include/dt-bindings/clock/qcom,gcc-ipq806x.h | 293 +++ - include/dt-bindings/reset/qcom,gcc-ipq806x.h | 132 ++ - 6 files changed, 2859 insertions(+) - create mode 100644 drivers/clk/qcom/gcc-ipq806x.c - create mode 100644 include/dt-bindings/clock/qcom,gcc-ipq806x.h - create mode 100644 include/dt-bindings/reset/qcom,gcc-ipq806x.h - ---- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt -+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt -@@ -5,6 +5,7 @@ Required properties : - - compatible : shall contain only one of the following: - - "qcom,gcc-apq8064" -+ "qcom,gcc-ipq8064" - "qcom,gcc-msm8660" - "qcom,gcc-msm8960" - "qcom,gcc-msm8974" ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -4,6 +4,14 @@ config COMMON_CLK_QCOM - select REGMAP_MMIO - select RESET_CONTROLLER - -+config IPQ_GCC_806X -+ tristate "IPQ806x Global Clock Controller" -+ depends on COMMON_CLK_QCOM -+ help -+ Support for the global clock controller on ipq806x devices. -+ Say Y if you want to use peripheral devices such as UART, SPI, -+ i2c, USB, SD/eMMC, etc. -+ - config MSM_GCC_8660 - tristate "MSM8660 Global Clock Controller" - depends on COMMON_CLK_QCOM ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -8,6 +8,7 @@ clk-qcom-y += clk-rcg2.o - clk-qcom-y += clk-branch.o - clk-qcom-y += reset.o - -+obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o - obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o - obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o - obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o ---- /dev/null -+++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -0,0 +1,2424 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "common.h" -+#include "clk-regmap.h" -+#include "clk-pll.h" -+#include "clk-rcg.h" -+#include "clk-branch.h" -+#include "reset.h" -+ -+static struct clk_pll pll3 = { -+ .l_reg = 0x3164, -+ .m_reg = 0x3168, -+ .n_reg = 0x316c, -+ .config_reg = 0x3174, -+ .mode_reg = 0x3160, -+ .status_reg = 0x3178, -+ .status_bit = 16, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "pll3", -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .ops = &clk_pll_ops, -+ }, -+}; -+ -+static struct clk_pll pll8 = { -+ .l_reg = 0x3144, -+ .m_reg = 0x3148, -+ .n_reg = 0x314c, -+ .config_reg = 0x3154, -+ .mode_reg = 0x3140, -+ .status_reg = 0x3158, -+ .status_bit = 16, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "pll8", -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .ops = &clk_pll_ops, -+ }, -+}; -+ -+static struct clk_regmap pll8_vote = { -+ .enable_reg = 0x34c0, -+ .enable_mask = BIT(8), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pll8_vote", -+ .parent_names = (const char *[]){ "pll8" }, -+ .num_parents = 1, -+ .ops = &clk_pll_vote_ops, -+ }, -+}; -+ -+static struct clk_pll pll14 = { -+ .l_reg = 0x31c4, -+ .m_reg = 0x31c8, -+ .n_reg = 0x31cc, -+ .config_reg = 0x31d4, -+ .mode_reg = 0x31c0, -+ .status_reg = 0x31d8, -+ .status_bit = 16, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "pll14", -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .ops = &clk_pll_ops, -+ }, -+}; -+ -+static struct clk_regmap pll14_vote = { -+ .enable_reg = 0x34c0, -+ .enable_mask = BIT(14), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pll14_vote", -+ .parent_names = (const char *[]){ "pll14" }, -+ .num_parents = 1, -+ .ops = &clk_pll_vote_ops, -+ }, -+}; -+ -+#define P_PXO 0 -+#define P_PLL8 1 -+#define P_PLL3 1 -+#define P_PLL0 2 -+#define P_CXO 2 -+ -+static const u8 gcc_pxo_pll8_map[] = { -+ [P_PXO] = 0, -+ [P_PLL8] = 3, -+}; -+ -+static const char *gcc_pxo_pll8[] = { -+ "pxo", -+ "pll8_vote", -+}; -+ -+static const u8 gcc_pxo_pll8_cxo_map[] = { -+ [P_PXO] = 0, -+ [P_PLL8] = 3, -+ [P_CXO] = 5, -+}; -+ -+static const char *gcc_pxo_pll8_cxo[] = { -+ "pxo", -+ "pll8_vote", -+ "cxo", -+}; -+ -+static const u8 gcc_pxo_pll3_map[] = { -+ [P_PXO] = 0, -+ [P_PLL3] = 1, -+}; -+ -+static const u8 gcc_pxo_pll3_sata_map[] = { -+ [P_PXO] = 0, -+ [P_PLL3] = 6, -+}; -+ -+static const char *gcc_pxo_pll3[] = { -+ "pxo", -+ "pll3", -+}; -+ -+static const u8 gcc_pxo_pll8_pll0[] = { -+ [P_PXO] = 0, -+ [P_PLL8] = 3, -+ [P_PLL0] = 2, -+}; -+ -+static const char *gcc_pxo_pll8_pll0_map[] = { -+ "pxo", -+ "pll8_vote", -+ "pll0", -+}; -+ -+static struct freq_tbl clk_tbl_gsbi_uart[] = { -+ { 1843200, P_PLL8, 2, 6, 625 }, -+ { 3686400, P_PLL8, 2, 12, 625 }, -+ { 7372800, P_PLL8, 2, 24, 625 }, -+ { 14745600, P_PLL8, 2, 48, 625 }, -+ { 16000000, P_PLL8, 4, 1, 6 }, -+ { 24000000, P_PLL8, 4, 1, 4 }, -+ { 32000000, P_PLL8, 4, 1, 3 }, -+ { 40000000, P_PLL8, 1, 5, 48 }, -+ { 46400000, P_PLL8, 1, 29, 240 }, -+ { 48000000, P_PLL8, 4, 1, 2 }, -+ { 51200000, P_PLL8, 1, 2, 15 }, -+ { 56000000, P_PLL8, 1, 7, 48 }, -+ { 58982400, P_PLL8, 1, 96, 625 }, -+ { 64000000, P_PLL8, 2, 1, 3 }, -+ { } -+}; -+ -+static struct clk_rcg gsbi1_uart_src = { -+ .ns_reg = 0x29d4, -+ .md_reg = 0x29d0, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 16, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_uart, -+ .clkr = { -+ .enable_reg = 0x29d4, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi1_uart_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi1_uart_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 12, -+ .clkr = { -+ .enable_reg = 0x29d4, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi1_uart_clk", -+ .parent_names = (const char *[]){ -+ "gsbi1_uart_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi2_uart_src = { -+ .ns_reg = 0x29f4, -+ .md_reg = 0x29f0, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 16, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_uart, -+ .clkr = { -+ .enable_reg = 0x29f4, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi2_uart_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi2_uart_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 8, -+ .clkr = { -+ .enable_reg = 0x29f4, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi2_uart_clk", -+ .parent_names = (const char *[]){ -+ "gsbi2_uart_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi4_uart_src = { -+ .ns_reg = 0x2a34, -+ .md_reg = 0x2a30, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 16, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_uart, -+ .clkr = { -+ .enable_reg = 0x2a34, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi4_uart_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi4_uart_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 26, -+ .clkr = { -+ .enable_reg = 0x2a34, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi4_uart_clk", -+ .parent_names = (const char *[]){ -+ "gsbi4_uart_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi5_uart_src = { -+ .ns_reg = 0x2a54, -+ .md_reg = 0x2a50, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 16, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_uart, -+ .clkr = { -+ .enable_reg = 0x2a54, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi5_uart_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi5_uart_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 22, -+ .clkr = { -+ .enable_reg = 0x2a54, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi5_uart_clk", -+ .parent_names = (const char *[]){ -+ "gsbi5_uart_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi6_uart_src = { -+ .ns_reg = 0x2a74, -+ .md_reg = 0x2a70, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 16, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_uart, -+ .clkr = { -+ .enable_reg = 0x2a74, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi6_uart_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi6_uart_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 18, -+ .clkr = { -+ .enable_reg = 0x2a74, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi6_uart_clk", -+ .parent_names = (const char *[]){ -+ "gsbi6_uart_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi7_uart_src = { -+ .ns_reg = 0x2a94, -+ .md_reg = 0x2a90, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 16, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_uart, -+ .clkr = { -+ .enable_reg = 0x2a94, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi7_uart_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi7_uart_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 14, -+ .clkr = { -+ .enable_reg = 0x2a94, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi7_uart_clk", -+ .parent_names = (const char *[]){ -+ "gsbi7_uart_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct freq_tbl clk_tbl_gsbi_qup[] = { -+ { 1100000, P_PXO, 1, 2, 49 }, -+ { 5400000, P_PXO, 1, 1, 5 }, -+ { 10800000, P_PXO, 1, 2, 5 }, -+ { 15060000, P_PLL8, 1, 2, 51 }, -+ { 24000000, P_PLL8, 4, 1, 4 }, -+ { 25600000, P_PLL8, 1, 1, 15 }, -+ { 27000000, P_PXO, 1, 0, 0 }, -+ { 48000000, P_PLL8, 4, 1, 2 }, -+ { 51200000, P_PLL8, 1, 2, 15 }, -+ { } -+}; -+ -+static struct clk_rcg gsbi1_qup_src = { -+ .ns_reg = 0x29cc, -+ .md_reg = 0x29c8, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_qup, -+ .clkr = { -+ .enable_reg = 0x29cc, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi1_qup_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi1_qup_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 11, -+ .clkr = { -+ .enable_reg = 0x29cc, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi1_qup_clk", -+ .parent_names = (const char *[]){ "gsbi1_qup_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi2_qup_src = { -+ .ns_reg = 0x29ec, -+ .md_reg = 0x29e8, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_qup, -+ .clkr = { -+ .enable_reg = 0x29ec, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi2_qup_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi2_qup_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 6, -+ .clkr = { -+ .enable_reg = 0x29ec, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi2_qup_clk", -+ .parent_names = (const char *[]){ "gsbi2_qup_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi4_qup_src = { -+ .ns_reg = 0x2a2c, -+ .md_reg = 0x2a28, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_qup, -+ .clkr = { -+ .enable_reg = 0x2a2c, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi4_qup_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi4_qup_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 24, -+ .clkr = { -+ .enable_reg = 0x2a2c, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi4_qup_clk", -+ .parent_names = (const char *[]){ "gsbi4_qup_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi5_qup_src = { -+ .ns_reg = 0x2a4c, -+ .md_reg = 0x2a48, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_qup, -+ .clkr = { -+ .enable_reg = 0x2a4c, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi5_qup_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi5_qup_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 20, -+ .clkr = { -+ .enable_reg = 0x2a4c, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi5_qup_clk", -+ .parent_names = (const char *[]){ "gsbi5_qup_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi6_qup_src = { -+ .ns_reg = 0x2a6c, -+ .md_reg = 0x2a68, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_qup, -+ .clkr = { -+ .enable_reg = 0x2a6c, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi6_qup_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi6_qup_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 16, -+ .clkr = { -+ .enable_reg = 0x2a6c, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi6_qup_clk", -+ .parent_names = (const char *[]){ "gsbi6_qup_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gsbi7_qup_src = { -+ .ns_reg = 0x2a8c, -+ .md_reg = 0x2a88, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_gsbi_qup, -+ .clkr = { -+ .enable_reg = 0x2a8c, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi7_qup_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi7_qup_clk = { -+ .halt_reg = 0x2fd0, -+ .halt_bit = 12, -+ .clkr = { -+ .enable_reg = 0x2a8c, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi7_qup_clk", -+ .parent_names = (const char *[]){ "gsbi7_qup_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi1_h_clk = { -+ .hwcg_reg = 0x29c0, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fcc, -+ .halt_bit = 13, -+ .clkr = { -+ .enable_reg = 0x29c0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi1_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi2_h_clk = { -+ .hwcg_reg = 0x29e0, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fcc, -+ .halt_bit = 9, -+ .clkr = { -+ .enable_reg = 0x29e0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi2_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi4_h_clk = { -+ .hwcg_reg = 0x2a20, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fd0, -+ .halt_bit = 27, -+ .clkr = { -+ .enable_reg = 0x2a20, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi4_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi5_h_clk = { -+ .hwcg_reg = 0x2a40, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fd0, -+ .halt_bit = 23, -+ .clkr = { -+ .enable_reg = 0x2a40, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi5_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi6_h_clk = { -+ .hwcg_reg = 0x2a60, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fd0, -+ .halt_bit = 19, -+ .clkr = { -+ .enable_reg = 0x2a60, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi6_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch gsbi7_h_clk = { -+ .hwcg_reg = 0x2a80, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fd0, -+ .halt_bit = 15, -+ .clkr = { -+ .enable_reg = 0x2a80, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gsbi7_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_gp[] = { -+ { 12500000, P_PXO, 2, 0, 0 }, -+ { 25000000, P_PXO, 1, 0, 0 }, -+ { 64000000, P_PLL8, 2, 1, 3 }, -+ { 76800000, P_PLL8, 1, 1, 5 }, -+ { 96000000, P_PLL8, 4, 0, 0 }, -+ { 128000000, P_PLL8, 3, 0, 0 }, -+ { 192000000, P_PLL8, 2, 0, 0 }, -+ { } -+}; -+ -+static struct clk_rcg gp0_src = { -+ .ns_reg = 0x2d24, -+ .md_reg = 0x2d00, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_cxo_map, -+ }, -+ .freq_tbl = clk_tbl_gp, -+ .clkr = { -+ .enable_reg = 0x2d24, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gp0_src", -+ .parent_names = gcc_pxo_pll8_cxo, -+ .num_parents = 3, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_PARENT_GATE, -+ }, -+ } -+}; -+ -+static struct clk_branch gp0_clk = { -+ .halt_reg = 0x2fd8, -+ .halt_bit = 7, -+ .clkr = { -+ .enable_reg = 0x2d24, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gp0_clk", -+ .parent_names = (const char *[]){ "gp0_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gp1_src = { -+ .ns_reg = 0x2d44, -+ .md_reg = 0x2d40, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_cxo_map, -+ }, -+ .freq_tbl = clk_tbl_gp, -+ .clkr = { -+ .enable_reg = 0x2d44, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gp1_src", -+ .parent_names = gcc_pxo_pll8_cxo, -+ .num_parents = 3, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ } -+}; -+ -+static struct clk_branch gp1_clk = { -+ .halt_reg = 0x2fd8, -+ .halt_bit = 6, -+ .clkr = { -+ .enable_reg = 0x2d44, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gp1_clk", -+ .parent_names = (const char *[]){ "gp1_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg gp2_src = { -+ .ns_reg = 0x2d64, -+ .md_reg = 0x2d60, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_cxo_map, -+ }, -+ .freq_tbl = clk_tbl_gp, -+ .clkr = { -+ .enable_reg = 0x2d64, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gp2_src", -+ .parent_names = gcc_pxo_pll8_cxo, -+ .num_parents = 3, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ } -+}; -+ -+static struct clk_branch gp2_clk = { -+ .halt_reg = 0x2fd8, -+ .halt_bit = 5, -+ .clkr = { -+ .enable_reg = 0x2d64, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gp2_clk", -+ .parent_names = (const char *[]){ "gp2_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pmem_clk = { -+ .hwcg_reg = 0x25a0, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fc8, -+ .halt_bit = 20, -+ .clkr = { -+ .enable_reg = 0x25a0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pmem_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg prng_src = { -+ .ns_reg = 0x2e80, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .clkr = { -+ .hw.init = &(struct clk_init_data){ -+ .name = "prng_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch prng_clk = { -+ .halt_reg = 0x2fd8, -+ .halt_check = BRANCH_HALT_VOTED, -+ .halt_bit = 10, -+ .clkr = { -+ .enable_reg = 0x3080, -+ .enable_mask = BIT(10), -+ .hw.init = &(struct clk_init_data){ -+ .name = "prng_clk", -+ .parent_names = (const char *[]){ "prng_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_sdc[] = { -+ { 144000, P_PXO, 5, 18,625 }, -+ { 400000, P_PLL8, 4, 1, 240 }, -+ { 16000000, P_PLL8, 4, 1, 6 }, -+ { 17070000, P_PLL8, 1, 2, 45 }, -+ { 20210000, P_PLL8, 1, 1, 19 }, -+ { 24000000, P_PLL8, 4, 1, 4 }, -+ { 48000000, P_PLL8, 4, 1, 2 }, -+ { 64000000, P_PLL8, 3, 1, 2 }, -+ { 96000000, P_PLL8, 4, 0, 0 }, -+ { 192000000, P_PLL8, 2, 0, 0 }, -+ { } -+}; -+ -+static struct clk_rcg sdc1_src = { -+ .ns_reg = 0x282c, -+ .md_reg = 0x2828, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_sdc, -+ .clkr = { -+ .enable_reg = 0x282c, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sdc1_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ } -+}; -+ -+static struct clk_branch sdc1_clk = { -+ .halt_reg = 0x2fc8, -+ .halt_bit = 6, -+ .clkr = { -+ .enable_reg = 0x282c, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sdc1_clk", -+ .parent_names = (const char *[]){ "sdc1_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg sdc3_src = { -+ .ns_reg = 0x286c, -+ .md_reg = 0x2868, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_sdc, -+ .clkr = { -+ .enable_reg = 0x286c, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sdc3_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ } -+}; -+ -+static struct clk_branch sdc3_clk = { -+ .halt_reg = 0x2fc8, -+ .halt_bit = 4, -+ .clkr = { -+ .enable_reg = 0x286c, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sdc3_clk", -+ .parent_names = (const char *[]){ "sdc3_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch sdc1_h_clk = { -+ .hwcg_reg = 0x2820, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fc8, -+ .halt_bit = 11, -+ .clkr = { -+ .enable_reg = 0x2820, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sdc1_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch sdc3_h_clk = { -+ .hwcg_reg = 0x2860, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fc8, -+ .halt_bit = 9, -+ .clkr = { -+ .enable_reg = 0x2860, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sdc3_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_tsif_ref[] = { -+ { 105000, P_PXO, 1, 1, 256 }, -+ { } -+}; -+ -+static struct clk_rcg tsif_ref_src = { -+ .ns_reg = 0x2710, -+ .md_reg = 0x270c, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 16, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_map, -+ }, -+ .freq_tbl = clk_tbl_tsif_ref, -+ .clkr = { -+ .enable_reg = 0x2710, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "tsif_ref_src", -+ .parent_names = gcc_pxo_pll8, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ } -+}; -+ -+static struct clk_branch tsif_ref_clk = { -+ .halt_reg = 0x2fd4, -+ .halt_bit = 5, -+ .clkr = { -+ .enable_reg = 0x2710, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "tsif_ref_clk", -+ .parent_names = (const char *[]){ "tsif_ref_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch tsif_h_clk = { -+ .hwcg_reg = 0x2700, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fd4, -+ .halt_bit = 7, -+ .clkr = { -+ .enable_reg = 0x2700, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "tsif_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch dma_bam_h_clk = { -+ .hwcg_reg = 0x25c0, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fc8, -+ .halt_bit = 12, -+ .clkr = { -+ .enable_reg = 0x25c0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "dma_bam_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch adm0_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_check = BRANCH_HALT_VOTED, -+ .halt_bit = 12, -+ .clkr = { -+ .enable_reg = 0x3080, -+ .enable_mask = BIT(2), -+ .hw.init = &(struct clk_init_data){ -+ .name = "adm0_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch adm0_pbus_clk = { -+ .hwcg_reg = 0x2208, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fdc, -+ .halt_check = BRANCH_HALT_VOTED, -+ .halt_bit = 11, -+ .clkr = { -+ .enable_reg = 0x3080, -+ .enable_mask = BIT(3), -+ .hw.init = &(struct clk_init_data){ -+ .name = "adm0_pbus_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pmic_arb0_h_clk = { -+ .halt_reg = 0x2fd8, -+ .halt_check = BRANCH_HALT_VOTED, -+ .halt_bit = 22, -+ .clkr = { -+ .enable_reg = 0x3080, -+ .enable_mask = BIT(8), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pmic_arb0_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pmic_arb1_h_clk = { -+ .halt_reg = 0x2fd8, -+ .halt_check = BRANCH_HALT_VOTED, -+ .halt_bit = 21, -+ .clkr = { -+ .enable_reg = 0x3080, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pmic_arb1_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pmic_ssbi2_clk = { -+ .halt_reg = 0x2fd8, -+ .halt_check = BRANCH_HALT_VOTED, -+ .halt_bit = 23, -+ .clkr = { -+ .enable_reg = 0x3080, -+ .enable_mask = BIT(7), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pmic_ssbi2_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch rpm_msg_ram_h_clk = { -+ .hwcg_reg = 0x27e0, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fd8, -+ .halt_check = BRANCH_HALT_VOTED, -+ .halt_bit = 12, -+ .clkr = { -+ .enable_reg = 0x3080, -+ .enable_mask = BIT(6), -+ .hw.init = &(struct clk_init_data){ -+ .name = "rpm_msg_ram_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_pcie_ref[] = { -+ { 100000000, P_PLL3, 12, 0, 0 }, -+ { } -+}; -+ -+static struct clk_rcg pcie_ref_src = { -+ .ns_reg = 0x3860, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll3_map, -+ }, -+ .freq_tbl = clk_tbl_pcie_ref, -+ .clkr = { -+ .enable_reg = 0x3860, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie_ref_src", -+ .parent_names = gcc_pxo_pll3, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie_ref_src_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 30, -+ .clkr = { -+ .enable_reg = 0x3860, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie_ref_src_clk", -+ .parent_names = (const char *[]){ "pcie_ref_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie_a_clk = { -+ .halt_reg = 0x2fc0, -+ .halt_bit = 13, -+ .clkr = { -+ .enable_reg = 0x22c0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie_a_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie_aux_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 31, -+ .clkr = { -+ .enable_reg = 0x22c8, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie_aux_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie_h_clk = { -+ .halt_reg = 0x2fd4, -+ .halt_bit = 8, -+ .clkr = { -+ .enable_reg = 0x22cc, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie_phy_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 29, -+ .clkr = { -+ .enable_reg = 0x22d0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie_phy_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg pcie1_ref_src = { -+ .ns_reg = 0x3aa0, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll3_map, -+ }, -+ .freq_tbl = clk_tbl_pcie_ref, -+ .clkr = { -+ .enable_reg = 0x3aa0, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie1_ref_src", -+ .parent_names = gcc_pxo_pll3, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie1_ref_src_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 27, -+ .clkr = { -+ .enable_reg = 0x3aa0, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie1_ref_src_clk", -+ .parent_names = (const char *[]){ "pcie1_ref_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie1_a_clk = { -+ .halt_reg = 0x2fc0, -+ .halt_bit = 10, -+ .clkr = { -+ .enable_reg = 0x3a80, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie1_a_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie1_aux_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 28, -+ .clkr = { -+ .enable_reg = 0x3a88, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie1_aux_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie1_h_clk = { -+ .halt_reg = 0x2fd4, -+ .halt_bit = 9, -+ .clkr = { -+ .enable_reg = 0x3a8c, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie1_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie1_phy_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 26, -+ .clkr = { -+ .enable_reg = 0x3a90, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie1_phy_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg pcie2_ref_src = { -+ .ns_reg = 0x3ae0, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll3_map, -+ }, -+ .freq_tbl = clk_tbl_pcie_ref, -+ .clkr = { -+ .enable_reg = 0x3ae0, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie2_ref_src", -+ .parent_names = gcc_pxo_pll3, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie2_ref_src_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 24, -+ .clkr = { -+ .enable_reg = 0x3ae0, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie2_ref_src_clk", -+ .parent_names = (const char *[]){ "pcie2_ref_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie2_a_clk = { -+ .halt_reg = 0x2fc0, -+ .halt_bit = 9, -+ .clkr = { -+ .enable_reg = 0x3ac0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie2_a_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie2_aux_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 25, -+ .clkr = { -+ .enable_reg = 0x3ac8, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie2_aux_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie2_h_clk = { -+ .halt_reg = 0x2fd4, -+ .halt_bit = 10, -+ .clkr = { -+ .enable_reg = 0x3acc, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie2_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch pcie2_phy_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 23, -+ .clkr = { -+ .enable_reg = 0x3ad0, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pcie2_phy_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_sata_ref[] = { -+ { 100000000, P_PLL3, 12, 0, 0 }, -+ { } -+}; -+ -+static struct clk_rcg sata_ref_src = { -+ .ns_reg = 0x2c08, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll3_sata_map, -+ }, -+ .freq_tbl = clk_tbl_sata_ref, -+ .clkr = { -+ .enable_reg = 0x2c08, -+ .enable_mask = BIT(7), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sata_ref_src", -+ .parent_names = gcc_pxo_pll3, -+ .num_parents = 2, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch sata_rxoob_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 20, -+ .clkr = { -+ .enable_reg = 0x2c0c, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sata_rxoob_clk", -+ .parent_names = (const char *[]){ "sata_ref_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch sata_pmalive_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 19, -+ .clkr = { -+ .enable_reg = 0x2c10, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sata_pmalive_clk", -+ .parent_names = (const char *[]){ "sata_ref_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch sata_phy_ref_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 18, -+ .clkr = { -+ .enable_reg = 0x2c14, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sata_phy_ref_clk", -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch sata_a_clk = { -+ .halt_reg = 0x2fc0, -+ .halt_bit = 12, -+ .clkr = { -+ .enable_reg = 0x2c20, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sata_a_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch sata_h_clk = { -+ .halt_reg = 0x2fdc, -+ .halt_bit = 21, -+ .clkr = { -+ .enable_reg = 0x2c00, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sata_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch sfab_sata_s_h_clk = { -+ .halt_reg = 0x2fc4, -+ .halt_bit = 14, -+ .clkr = { -+ .enable_reg = 0x2480, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sfab_sata_s_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_branch sata_phy_cfg_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 14, -+ .clkr = { -+ .enable_reg = 0x2c40, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "sata_phy_cfg_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_usb30_master[] = { -+ { 125000000, P_PLL0, 1, 5, 32 }, -+ { } -+}; -+ -+static struct clk_rcg usb30_master_clk_src = { -+ .ns_reg = 0x3b2c, -+ .md_reg = 0x3b28, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll0, -+ }, -+ .freq_tbl = clk_tbl_usb30_master, -+ .clkr = { -+ .enable_reg = 0x3b2c, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb30_master_ref_src", -+ .parent_names = gcc_pxo_pll8_pll0_map, -+ .num_parents = 3, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb30_0_branch_clk = { -+ .halt_reg = 0x2fc4, -+ .halt_bit = 22, -+ .clkr = { -+ .enable_reg = 0x3b24, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb30_0_branch_clk", -+ .parent_names = (const char *[]){ "usb30_master_ref_src", }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb30_1_branch_clk = { -+ .halt_reg = 0x2fc4, -+ .halt_bit = 17, -+ .clkr = { -+ .enable_reg = 0x3b34, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb30_1_branch_clk", -+ .parent_names = (const char *[]){ "usb30_master_ref_src", }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_usb30_utmi[] = { -+ { 60000000, P_PLL0, 1, 1, 40 }, -+ { } -+}; -+ -+static struct clk_rcg usb30_utmi_clk = { -+ .ns_reg = 0x3b44, -+ .md_reg = 0x3b40, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll0, -+ }, -+ .freq_tbl = clk_tbl_usb30_utmi, -+ .clkr = { -+ .enable_reg = 0x3b44, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb30_utmi_clk", -+ .parent_names = gcc_pxo_pll8_pll0_map, -+ .num_parents = 3, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb30_0_utmi_clk_ctl = { -+ .halt_reg = 0x2fc4, -+ .halt_bit = 21, -+ .clkr = { -+ .enable_reg = 0x3b48, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb30_0_utmi_clk_ctl", -+ .parent_names = (const char *[]){ "usb30_utmi_clk", }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb30_1_utmi_clk_ctl = { -+ .halt_reg = 0x2fc4, -+ .halt_bit = 15, -+ .clkr = { -+ .enable_reg = 0x3b4c, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb30_1_utmi_clk_ctl", -+ .parent_names = (const char *[]){ "usb30_utmi_clk", }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_usb[] = { -+ { 60000000, P_PLL8, 1, 5, 32 }, -+ { } -+}; -+ -+static struct clk_rcg usb_hs1_xcvr_clk_src = { -+ .ns_reg = 0x290C, -+ .md_reg = 0x2908, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll0, -+ }, -+ .freq_tbl = clk_tbl_usb, -+ .clkr = { -+ .enable_reg = 0x2968, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb_hs1_xcvr_src", -+ .parent_names = gcc_pxo_pll8_pll0_map, -+ .num_parents = 3, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb_hs1_xcvr_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 17, -+ .clkr = { -+ .enable_reg = 0x290c, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb_hs1_xcvr_clk", -+ .parent_names = (const char *[]){ "usb_hs1_xcvr_src" }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb_hs1_h_clk = { -+ .hwcg_reg = 0x2900, -+ .hwcg_bit = 6, -+ .halt_reg = 0x2fc8, -+ .halt_bit = 1, -+ .clkr = { -+ .enable_reg = 0x2900, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb_hs1_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_rcg usb_fs1_xcvr_clk_src = { -+ .ns_reg = 0x2968, -+ .md_reg = 0x2964, -+ .mn = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .p = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .s = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll0, -+ }, -+ .freq_tbl = clk_tbl_usb, -+ .clkr = { -+ .enable_reg = 0x2968, -+ .enable_mask = BIT(11), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb_fs1_xcvr_src", -+ .parent_names = gcc_pxo_pll8_pll0_map, -+ .num_parents = 3, -+ .ops = &clk_rcg_ops, -+ .flags = CLK_SET_RATE_GATE, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb_fs1_xcvr_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 17, -+ .clkr = { -+ .enable_reg = 0x2968, -+ .enable_mask = BIT(9), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb_fs1_xcvr_clk", -+ .parent_names = (const char *[]){ "usb_fs1_xcvr_src", }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb_fs1_sys_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 18, -+ .clkr = { -+ .enable_reg = 0x296c, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb_fs1_sys_clk", -+ .parent_names = (const char *[]){ "usb_fs1_xcvr_src", }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_branch usb_fs1_h_clk = { -+ .halt_reg = 0x2fcc, -+ .halt_bit = 19, -+ .clkr = { -+ .enable_reg = 0x2960, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "usb_fs1_h_clk", -+ .ops = &clk_branch_ops, -+ .flags = CLK_IS_ROOT, -+ }, -+ }, -+}; -+ -+static struct clk_regmap *gcc_ipq806x_clks[] = { -+ [PLL3] = &pll3.clkr, -+ [PLL8] = &pll8.clkr, -+ [PLL8_VOTE] = &pll8_vote, -+ [PLL14] = &pll14.clkr, -+ [PLL14_VOTE] = &pll14_vote, -+ [GSBI1_UART_SRC] = &gsbi1_uart_src.clkr, -+ [GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr, -+ [GSBI2_UART_SRC] = &gsbi2_uart_src.clkr, -+ [GSBI2_UART_CLK] = &gsbi2_uart_clk.clkr, -+ [GSBI4_UART_SRC] = &gsbi4_uart_src.clkr, -+ [GSBI4_UART_CLK] = &gsbi4_uart_clk.clkr, -+ [GSBI5_UART_SRC] = &gsbi5_uart_src.clkr, -+ [GSBI5_UART_CLK] = &gsbi5_uart_clk.clkr, -+ [GSBI6_UART_SRC] = &gsbi6_uart_src.clkr, -+ [GSBI6_UART_CLK] = &gsbi6_uart_clk.clkr, -+ [GSBI7_UART_SRC] = &gsbi7_uart_src.clkr, -+ [GSBI7_UART_CLK] = &gsbi7_uart_clk.clkr, -+ [GSBI1_QUP_SRC] = &gsbi1_qup_src.clkr, -+ [GSBI1_QUP_CLK] = &gsbi1_qup_clk.clkr, -+ [GSBI2_QUP_SRC] = &gsbi2_qup_src.clkr, -+ [GSBI2_QUP_CLK] = &gsbi2_qup_clk.clkr, -+ [GSBI4_QUP_SRC] = &gsbi4_qup_src.clkr, -+ [GSBI4_QUP_CLK] = &gsbi4_qup_clk.clkr, -+ [GSBI5_QUP_SRC] = &gsbi5_qup_src.clkr, -+ [GSBI5_QUP_CLK] = &gsbi5_qup_clk.clkr, -+ [GSBI6_QUP_SRC] = &gsbi6_qup_src.clkr, -+ [GSBI6_QUP_CLK] = &gsbi6_qup_clk.clkr, -+ [GSBI7_QUP_SRC] = &gsbi7_qup_src.clkr, -+ [GSBI7_QUP_CLK] = &gsbi7_qup_clk.clkr, -+ [GP0_SRC] = &gp0_src.clkr, -+ [GP0_CLK] = &gp0_clk.clkr, -+ [GP1_SRC] = &gp1_src.clkr, -+ [GP1_CLK] = &gp1_clk.clkr, -+ [GP2_SRC] = &gp2_src.clkr, -+ [GP2_CLK] = &gp2_clk.clkr, -+ [PMEM_A_CLK] = &pmem_clk.clkr, -+ [PRNG_SRC] = &prng_src.clkr, -+ [PRNG_CLK] = &prng_clk.clkr, -+ [SDC1_SRC] = &sdc1_src.clkr, -+ [SDC1_CLK] = &sdc1_clk.clkr, -+ [SDC3_SRC] = &sdc3_src.clkr, -+ [SDC3_CLK] = &sdc3_clk.clkr, -+ [TSIF_REF_SRC] = &tsif_ref_src.clkr, -+ [TSIF_REF_CLK] = &tsif_ref_clk.clkr, -+ [DMA_BAM_H_CLK] = &dma_bam_h_clk.clkr, -+ [GSBI1_H_CLK] = &gsbi1_h_clk.clkr, -+ [GSBI2_H_CLK] = &gsbi2_h_clk.clkr, -+ [GSBI4_H_CLK] = &gsbi4_h_clk.clkr, -+ [GSBI5_H_CLK] = &gsbi5_h_clk.clkr, -+ [GSBI6_H_CLK] = &gsbi6_h_clk.clkr, -+ [GSBI7_H_CLK] = &gsbi7_h_clk.clkr, -+ [TSIF_H_CLK] = &tsif_h_clk.clkr, -+ [SDC1_H_CLK] = &sdc1_h_clk.clkr, -+ [SDC3_H_CLK] = &sdc3_h_clk.clkr, -+ [ADM0_CLK] = &adm0_clk.clkr, -+ [ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr, -+ [PCIE_A_CLK] = &pcie_a_clk.clkr, -+ [PCIE_AUX_CLK] = &pcie_aux_clk.clkr, -+ [PCIE_H_CLK] = &pcie_h_clk.clkr, -+ [PCIE_PHY_CLK] = &pcie_phy_clk.clkr, -+ [SFAB_SATA_S_H_CLK] = &sfab_sata_s_h_clk.clkr, -+ [PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.clkr, -+ [PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr, -+ [PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr, -+ [RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr, -+ [SATA_H_CLK] = &sata_h_clk.clkr, -+ [SATA_CLK_SRC] = &sata_ref_src.clkr, -+ [SATA_RXOOB_CLK] = &sata_rxoob_clk.clkr, -+ [SATA_PMALIVE_CLK] = &sata_pmalive_clk.clkr, -+ [SATA_PHY_REF_CLK] = &sata_phy_ref_clk.clkr, -+ [SATA_A_CLK] = &sata_a_clk.clkr, -+ [SATA_PHY_CFG_CLK] = &sata_phy_cfg_clk.clkr, -+ [PCIE_ALT_REF_SRC] = &pcie_ref_src.clkr, -+ [PCIE_ALT_REF_CLK] = &pcie_ref_src_clk.clkr, -+ [PCIE_1_A_CLK] = &pcie1_a_clk.clkr, -+ [PCIE_1_AUX_CLK] = &pcie1_aux_clk.clkr, -+ [PCIE_1_H_CLK] = &pcie1_h_clk.clkr, -+ [PCIE_1_PHY_CLK] = &pcie1_phy_clk.clkr, -+ [PCIE_1_ALT_REF_SRC] = &pcie1_ref_src.clkr, -+ [PCIE_1_ALT_REF_CLK] = &pcie1_ref_src_clk.clkr, -+ [PCIE_2_A_CLK] = &pcie2_a_clk.clkr, -+ [PCIE_2_AUX_CLK] = &pcie2_aux_clk.clkr, -+ [PCIE_2_H_CLK] = &pcie2_h_clk.clkr, -+ [PCIE_2_PHY_CLK] = &pcie2_phy_clk.clkr, -+ [PCIE_2_ALT_REF_SRC] = &pcie2_ref_src.clkr, -+ [PCIE_2_ALT_REF_CLK] = &pcie2_ref_src_clk.clkr, -+ [USB30_MASTER_SRC] = &usb30_master_clk_src.clkr, -+ [USB30_0_MASTER_CLK] = &usb30_0_branch_clk.clkr, -+ [USB30_1_MASTER_CLK] = &usb30_1_branch_clk.clkr, -+ [USB30_UTMI_SRC] = &usb30_utmi_clk.clkr, -+ [USB30_0_UTMI_CLK] = &usb30_0_utmi_clk_ctl.clkr, -+ [USB30_1_UTMI_CLK] = &usb30_1_utmi_clk_ctl.clkr, -+ [USB_HS1_H_CLK] = &usb_hs1_h_clk.clkr, -+ [USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_clk_src.clkr, -+ [USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.clkr, -+ [USB_FS1_H_CLK] = &usb_fs1_h_clk.clkr, -+ [USB_FS1_XCVR_SRC] = &usb_fs1_xcvr_clk_src.clkr, -+ [USB_FS1_XCVR_CLK] = &usb_fs1_xcvr_clk.clkr, -+ [USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr, -+}; -+ -+static const struct qcom_reset_map gcc_ipq806x_resets[] = { -+ [QDSS_STM_RESET] = { 0x2060, 6 }, -+ [AFAB_SMPSS_S_RESET] = { 0x20b8, 2 }, -+ [AFAB_SMPSS_M1_RESET] = { 0x20b8, 1 }, -+ [AFAB_SMPSS_M0_RESET] = { 0x20b8, 0 }, -+ [AFAB_EBI1_CH0_RESET] = { 0x20c0, 7 }, -+ [AFAB_EBI1_CH1_RESET] = { 0x20c4, 7 }, -+ [SFAB_ADM0_M0_RESET] = { 0x21e0, 7 }, -+ [SFAB_ADM0_M1_RESET] = { 0x21e4, 7 }, -+ [SFAB_ADM0_M2_RESET] = { 0x21e8, 7 }, -+ [ADM0_C2_RESET] = { 0x220c, 4 }, -+ [ADM0_C1_RESET] = { 0x220c, 3 }, -+ [ADM0_C0_RESET] = { 0x220c, 2 }, -+ [ADM0_PBUS_RESET] = { 0x220c, 1 }, -+ [ADM0_RESET] = { 0x220c, 0 }, -+ [QDSS_CLKS_SW_RESET] = { 0x2260, 5 }, -+ [QDSS_POR_RESET] = { 0x2260, 4 }, -+ [QDSS_TSCTR_RESET] = { 0x2260, 3 }, -+ [QDSS_HRESET_RESET] = { 0x2260, 2 }, -+ [QDSS_AXI_RESET] = { 0x2260, 1 }, -+ [QDSS_DBG_RESET] = { 0x2260, 0 }, -+ [SFAB_PCIE_M_RESET] = { 0x22d8, 1 }, -+ [SFAB_PCIE_S_RESET] = { 0x22d8, 0 }, -+ [PCIE_EXT_RESET] = { 0x22dc, 6 }, -+ [PCIE_PHY_RESET] = { 0x22dc, 5 }, -+ [PCIE_PCI_RESET] = { 0x22dc, 4 }, -+ [PCIE_POR_RESET] = { 0x22dc, 3 }, -+ [PCIE_HCLK_RESET] = { 0x22dc, 2 }, -+ [PCIE_ACLK_RESET] = { 0x22dc, 0 }, -+ [SFAB_LPASS_RESET] = { 0x23a0, 7 }, -+ [SFAB_AFAB_M_RESET] = { 0x23e0, 7 }, -+ [AFAB_SFAB_M0_RESET] = { 0x2420, 7 }, -+ [AFAB_SFAB_M1_RESET] = { 0x2424, 7 }, -+ [SFAB_SATA_S_RESET] = { 0x2480, 7 }, -+ [SFAB_DFAB_M_RESET] = { 0x2500, 7 }, -+ [DFAB_SFAB_M_RESET] = { 0x2520, 7 }, -+ [DFAB_SWAY0_RESET] = { 0x2540, 7 }, -+ [DFAB_SWAY1_RESET] = { 0x2544, 7 }, -+ [DFAB_ARB0_RESET] = { 0x2560, 7 }, -+ [DFAB_ARB1_RESET] = { 0x2564, 7 }, -+ [PPSS_PROC_RESET] = { 0x2594, 1 }, -+ [PPSS_RESET] = { 0x2594, 0 }, -+ [DMA_BAM_RESET] = { 0x25c0, 7 }, -+ [SPS_TIC_H_RESET] = { 0x2600, 7 }, -+ [SFAB_CFPB_M_RESET] = { 0x2680, 7 }, -+ [SFAB_CFPB_S_RESET] = { 0x26c0, 7 }, -+ [TSIF_H_RESET] = { 0x2700, 7 }, -+ [CE1_H_RESET] = { 0x2720, 7 }, -+ [CE1_CORE_RESET] = { 0x2724, 7 }, -+ [CE1_SLEEP_RESET] = { 0x2728, 7 }, -+ [CE2_H_RESET] = { 0x2740, 7 }, -+ [CE2_CORE_RESET] = { 0x2744, 7 }, -+ [SFAB_SFPB_M_RESET] = { 0x2780, 7 }, -+ [SFAB_SFPB_S_RESET] = { 0x27a0, 7 }, -+ [RPM_PROC_RESET] = { 0x27c0, 7 }, -+ [PMIC_SSBI2_RESET] = { 0x280c, 12 }, -+ [SDC1_RESET] = { 0x2830, 0 }, -+ [SDC2_RESET] = { 0x2850, 0 }, -+ [SDC3_RESET] = { 0x2870, 0 }, -+ [SDC4_RESET] = { 0x2890, 0 }, -+ [USB_HS1_RESET] = { 0x2910, 0 }, -+ [USB_HSIC_RESET] = { 0x2934, 0 }, -+ [USB_FS1_XCVR_RESET] = { 0x2974, 1 }, -+ [USB_FS1_RESET] = { 0x2974, 0 }, -+ [GSBI1_RESET] = { 0x29dc, 0 }, -+ [GSBI2_RESET] = { 0x29fc, 0 }, -+ [GSBI3_RESET] = { 0x2a1c, 0 }, -+ [GSBI4_RESET] = { 0x2a3c, 0 }, -+ [GSBI5_RESET] = { 0x2a5c, 0 }, -+ [GSBI6_RESET] = { 0x2a7c, 0 }, -+ [GSBI7_RESET] = { 0x2a9c, 0 }, -+ [SPDM_RESET] = { 0x2b6c, 0 }, -+ [SEC_CTRL_RESET] = { 0x2b80, 7 }, -+ [TLMM_H_RESET] = { 0x2ba0, 7 }, -+ [SFAB_SATA_M_RESET] = { 0x2c18, 0 }, -+ [SATA_RESET] = { 0x2c1c, 0 }, -+ [TSSC_RESET] = { 0x2ca0, 7 }, -+ [PDM_RESET] = { 0x2cc0, 12 }, -+ [MPM_H_RESET] = { 0x2da0, 7 }, -+ [MPM_RESET] = { 0x2da4, 0 }, -+ [SFAB_SMPSS_S_RESET] = { 0x2e00, 7 }, -+ [PRNG_RESET] = { 0x2e80, 12 }, -+ [SFAB_CE3_M_RESET] = { 0x36c8, 1 }, -+ [SFAB_CE3_S_RESET] = { 0x36c8, 0 }, -+ [CE3_SLEEP_RESET] = { 0x36d0, 7 }, -+ [PCIE_1_M_RESET] = { 0x3a98, 1 }, -+ [PCIE_1_S_RESET] = { 0x3a98, 0 }, -+ [PCIE_1_EXT_RESET] = { 0x3a9c, 6 }, -+ [PCIE_1_PHY_RESET] = { 0x3a9c, 5 }, -+ [PCIE_1_PCI_RESET] = { 0x3a9c, 4 }, -+ [PCIE_1_POR_RESET] = { 0x3a9c, 3 }, -+ [PCIE_1_HCLK_RESET] = { 0x3a9c, 2 }, -+ [PCIE_1_ACLK_RESET] = { 0x3a9c, 0 }, -+ [PCIE_2_M_RESET] = { 0x3ad8, 1 }, -+ [PCIE_2_S_RESET] = { 0x3ad8, 0 }, -+ [PCIE_2_EXT_RESET] = { 0x3adc, 6 }, -+ [PCIE_2_PHY_RESET] = { 0x3adc, 5 }, -+ [PCIE_2_PCI_RESET] = { 0x3adc, 4 }, -+ [PCIE_2_POR_RESET] = { 0x3adc, 3 }, -+ [PCIE_2_HCLK_RESET] = { 0x3adc, 2 }, -+ [PCIE_2_ACLK_RESET] = { 0x3adc, 0 }, -+ [SFAB_USB30_S_RESET] = { 0x3b54, 1 }, -+ [SFAB_USB30_M_RESET] = { 0x3b54, 0 }, -+ [USB30_0_PORT2_HS_PHY_RESET] = { 0x3b50, 5 }, -+ [USB30_0_MASTER_RESET] = { 0x3b50, 4 }, -+ [USB30_0_SLEEP_RESET] = { 0x3b50, 3 }, -+ [USB30_0_UTMI_PHY_RESET] = { 0x3b50, 2 }, -+ [USB30_0_POWERON_RESET] = { 0x3b50, 1 }, -+ [USB30_0_PHY_RESET] = { 0x3b50, 0 }, -+ [USB30_1_MASTER_RESET] = { 0x3b58, 4 }, -+ [USB30_1_SLEEP_RESET] = { 0x3b58, 3 }, -+ [USB30_1_UTMI_PHY_RESET] = { 0x3b58, 2 }, -+ [USB30_1_POWERON_RESET] = { 0x3b58, 1 }, -+ [USB30_1_PHY_RESET] = { 0x3b58, 0 }, -+ [NSSFB0_RESET] = { 0x3b60, 6 }, -+ [NSSFB1_RESET] = { 0x3b60, 7 }, -+}; -+ -+static const struct regmap_config gcc_ipq806x_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x3e40, -+ .fast_io = true, -+}; -+ -+static const struct qcom_cc_desc gcc_ipq806x_desc = { -+ .config = &gcc_ipq806x_regmap_config, -+ .clks = gcc_ipq806x_clks, -+ .num_clks = ARRAY_SIZE(gcc_ipq806x_clks), -+ .resets = gcc_ipq806x_resets, -+ .num_resets = ARRAY_SIZE(gcc_ipq806x_resets), -+}; -+ -+static const struct of_device_id gcc_ipq806x_match_table[] = { -+ { .compatible = "qcom,gcc-ipq8064" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, gcc_ipq806x_match_table); -+ -+static int gcc_ipq806x_probe(struct platform_device *pdev) -+{ -+ struct clk *clk; -+ struct device *dev = &pdev->dev; -+ -+ /* Temporary until RPM clocks supported */ -+ clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 25000000); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ return qcom_cc_probe(pdev, &gcc_ipq806x_desc); -+} -+ -+static int gcc_ipq806x_remove(struct platform_device *pdev) -+{ -+ qcom_cc_remove(pdev); -+ return 0; -+} -+ -+static struct platform_driver gcc_ipq806x_driver = { -+ .probe = gcc_ipq806x_probe, -+ .remove = gcc_ipq806x_remove, -+ .driver = { -+ .name = "gcc-ipq806x", -+ .owner = THIS_MODULE, -+ .of_match_table = gcc_ipq806x_match_table, -+ }, -+}; -+ -+static int __init gcc_ipq806x_init(void) -+{ -+ return platform_driver_register(&gcc_ipq806x_driver); -+} -+core_initcall(gcc_ipq806x_init); -+ -+static void __exit gcc_ipq806x_exit(void) -+{ -+ platform_driver_unregister(&gcc_ipq806x_driver); -+} -+module_exit(gcc_ipq806x_exit); -+ -+MODULE_DESCRIPTION("QCOM GCC IPQ806x Driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:gcc-ipq806x"); ---- /dev/null -+++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h -@@ -0,0 +1,293 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef _DT_BINDINGS_CLK_GCC_IPQ806X_H -+#define _DT_BINDINGS_CLK_GCC_IPQ806X_H -+ -+#define AFAB_CLK_SRC 0 -+#define QDSS_STM_CLK 1 -+#define SCSS_A_CLK 2 -+#define SCSS_H_CLK 3 -+#define AFAB_CORE_CLK 4 -+#define SCSS_XO_SRC_CLK 5 -+#define AFAB_EBI1_CH0_A_CLK 6 -+#define AFAB_EBI1_CH1_A_CLK 7 -+#define AFAB_AXI_S0_FCLK 8 -+#define AFAB_AXI_S1_FCLK 9 -+#define AFAB_AXI_S2_FCLK 10 -+#define AFAB_AXI_S3_FCLK 11 -+#define AFAB_AXI_S4_FCLK 12 -+#define SFAB_CORE_CLK 13 -+#define SFAB_AXI_S0_FCLK 14 -+#define SFAB_AXI_S1_FCLK 15 -+#define SFAB_AXI_S2_FCLK 16 -+#define SFAB_AXI_S3_FCLK 17 -+#define SFAB_AXI_S4_FCLK 18 -+#define SFAB_AXI_S5_FCLK 19 -+#define SFAB_AHB_S0_FCLK 20 -+#define SFAB_AHB_S1_FCLK 21 -+#define SFAB_AHB_S2_FCLK 22 -+#define SFAB_AHB_S3_FCLK 23 -+#define SFAB_AHB_S4_FCLK 24 -+#define SFAB_AHB_S5_FCLK 25 -+#define SFAB_AHB_S6_FCLK 26 -+#define SFAB_AHB_S7_FCLK 27 -+#define QDSS_AT_CLK_SRC 28 -+#define QDSS_AT_CLK 29 -+#define QDSS_TRACECLKIN_CLK_SRC 30 -+#define QDSS_TRACECLKIN_CLK 31 -+#define QDSS_TSCTR_CLK_SRC 32 -+#define QDSS_TSCTR_CLK 33 -+#define SFAB_ADM0_M0_A_CLK 34 -+#define SFAB_ADM0_M1_A_CLK 35 -+#define SFAB_ADM0_M2_H_CLK 36 -+#define ADM0_CLK 37 -+#define ADM0_PBUS_CLK 38 -+#define IMEM0_A_CLK 39 -+#define QDSS_H_CLK 40 -+#define PCIE_A_CLK 41 -+#define PCIE_AUX_CLK 42 -+#define PCIE_H_CLK 43 -+#define PCIE_PHY_CLK 44 -+#define SFAB_CLK_SRC 45 -+#define SFAB_LPASS_Q6_A_CLK 46 -+#define SFAB_AFAB_M_A_CLK 47 -+#define AFAB_SFAB_M0_A_CLK 48 -+#define AFAB_SFAB_M1_A_CLK 49 -+#define SFAB_SATA_S_H_CLK 50 -+#define DFAB_CLK_SRC 51 -+#define DFAB_CLK 52 -+#define SFAB_DFAB_M_A_CLK 53 -+#define DFAB_SFAB_M_A_CLK 54 -+#define DFAB_SWAY0_H_CLK 55 -+#define DFAB_SWAY1_H_CLK 56 -+#define DFAB_ARB0_H_CLK 57 -+#define DFAB_ARB1_H_CLK 58 -+#define PPSS_H_CLK 59 -+#define PPSS_PROC_CLK 60 -+#define PPSS_TIMER0_CLK 61 -+#define PPSS_TIMER1_CLK 62 -+#define PMEM_A_CLK 63 -+#define DMA_BAM_H_CLK 64 -+#define SIC_H_CLK 65 -+#define SPS_TIC_H_CLK 66 -+#define CFPB_2X_CLK_SRC 67 -+#define CFPB_CLK 68 -+#define CFPB0_H_CLK 69 -+#define CFPB1_H_CLK 70 -+#define CFPB2_H_CLK 71 -+#define SFAB_CFPB_M_H_CLK 72 -+#define CFPB_MASTER_H_CLK 73 -+#define SFAB_CFPB_S_H_CLK 74 -+#define CFPB_SPLITTER_H_CLK 75 -+#define TSIF_H_CLK 76 -+#define TSIF_INACTIVITY_TIMERS_CLK 77 -+#define TSIF_REF_SRC 78 -+#define TSIF_REF_CLK 79 -+#define CE1_H_CLK 80 -+#define CE1_CORE_CLK 81 -+#define CE1_SLEEP_CLK 82 -+#define CE2_H_CLK 83 -+#define CE2_CORE_CLK 84 -+#define SFPB_H_CLK_SRC 85 -+#define SFPB_H_CLK 86 -+#define SFAB_SFPB_M_H_CLK 87 -+#define SFAB_SFPB_S_H_CLK 88 -+#define RPM_PROC_CLK 89 -+#define RPM_BUS_H_CLK 90 -+#define RPM_SLEEP_CLK 91 -+#define RPM_TIMER_CLK 92 -+#define RPM_MSG_RAM_H_CLK 93 -+#define PMIC_ARB0_H_CLK 94 -+#define PMIC_ARB1_H_CLK 95 -+#define PMIC_SSBI2_SRC 96 -+#define PMIC_SSBI2_CLK 97 -+#define SDC1_H_CLK 98 -+#define SDC2_H_CLK 99 -+#define SDC3_H_CLK 100 -+#define SDC4_H_CLK 101 -+#define SDC1_SRC 102 -+#define SDC1_CLK 103 -+#define SDC2_SRC 104 -+#define SDC2_CLK 105 -+#define SDC3_SRC 106 -+#define SDC3_CLK 107 -+#define SDC4_SRC 108 -+#define SDC4_CLK 109 -+#define USB_HS1_H_CLK 110 -+#define USB_HS1_XCVR_SRC 111 -+#define USB_HS1_XCVR_CLK 112 -+#define USB_HSIC_H_CLK 113 -+#define USB_HSIC_XCVR_SRC 114 -+#define USB_HSIC_XCVR_CLK 115 -+#define USB_HSIC_SYSTEM_CLK_SRC 116 -+#define USB_HSIC_SYSTEM_CLK 117 -+#define CFPB0_C0_H_CLK 118 -+#define CFPB0_D0_H_CLK 119 -+#define CFPB0_C1_H_CLK 120 -+#define CFPB0_D1_H_CLK 121 -+#define USB_FS1_H_CLK 122 -+#define USB_FS1_XCVR_SRC 123 -+#define USB_FS1_XCVR_CLK 124 -+#define USB_FS1_SYSTEM_CLK 125 -+#define GSBI_COMMON_SIM_SRC 126 -+#define GSBI1_H_CLK 127 -+#define GSBI2_H_CLK 128 -+#define GSBI3_H_CLK 129 -+#define GSBI4_H_CLK 130 -+#define GSBI5_H_CLK 131 -+#define GSBI6_H_CLK 132 -+#define GSBI7_H_CLK 133 -+#define GSBI1_QUP_SRC 134 -+#define GSBI1_QUP_CLK 135 -+#define GSBI2_QUP_SRC 136 -+#define GSBI2_QUP_CLK 137 -+#define GSBI3_QUP_SRC 138 -+#define GSBI3_QUP_CLK 139 -+#define GSBI4_QUP_SRC 140 -+#define GSBI4_QUP_CLK 141 -+#define GSBI5_QUP_SRC 142 -+#define GSBI5_QUP_CLK 143 -+#define GSBI6_QUP_SRC 144 -+#define GSBI6_QUP_CLK 145 -+#define GSBI7_QUP_SRC 146 -+#define GSBI7_QUP_CLK 147 -+#define GSBI1_UART_SRC 148 -+#define GSBI1_UART_CLK 149 -+#define GSBI2_UART_SRC 150 -+#define GSBI2_UART_CLK 151 -+#define GSBI3_UART_SRC 152 -+#define GSBI3_UART_CLK 153 -+#define GSBI4_UART_SRC 154 -+#define GSBI4_UART_CLK 155 -+#define GSBI5_UART_SRC 156 -+#define GSBI5_UART_CLK 157 -+#define GSBI6_UART_SRC 158 -+#define GSBI6_UART_CLK 159 -+#define GSBI7_UART_SRC 160 -+#define GSBI7_UART_CLK 161 -+#define GSBI1_SIM_CLK 162 -+#define GSBI2_SIM_CLK 163 -+#define GSBI3_SIM_CLK 164 -+#define GSBI4_SIM_CLK 165 -+#define GSBI5_SIM_CLK 166 -+#define GSBI6_SIM_CLK 167 -+#define GSBI7_SIM_CLK 168 -+#define USB_HSIC_HSIC_CLK_SRC 169 -+#define USB_HSIC_HSIC_CLK 170 -+#define USB_HSIC_HSIO_CAL_CLK 171 -+#define SPDM_CFG_H_CLK 172 -+#define SPDM_MSTR_H_CLK 173 -+#define SPDM_FF_CLK_SRC 174 -+#define SPDM_FF_CLK 175 -+#define SEC_CTRL_CLK 176 -+#define SEC_CTRL_ACC_CLK_SRC 177 -+#define SEC_CTRL_ACC_CLK 178 -+#define TLMM_H_CLK 179 -+#define TLMM_CLK 180 -+#define SATA_H_CLK 181 -+#define SATA_CLK_SRC 182 -+#define SATA_RXOOB_CLK 183 -+#define SATA_PMALIVE_CLK 184 -+#define SATA_PHY_REF_CLK 185 -+#define SATA_A_CLK 186 -+#define SATA_PHY_CFG_CLK 187 -+#define TSSC_CLK_SRC 188 -+#define TSSC_CLK 189 -+#define PDM_SRC 190 -+#define PDM_CLK 191 -+#define GP0_SRC 192 -+#define GP0_CLK 193 -+#define GP1_SRC 194 -+#define GP1_CLK 195 -+#define GP2_SRC 196 -+#define GP2_CLK 197 -+#define MPM_CLK 198 -+#define EBI1_CLK_SRC 199 -+#define EBI1_CH0_CLK 200 -+#define EBI1_CH1_CLK 201 -+#define EBI1_2X_CLK 202 -+#define EBI1_CH0_DQ_CLK 203 -+#define EBI1_CH1_DQ_CLK 204 -+#define EBI1_CH0_CA_CLK 205 -+#define EBI1_CH1_CA_CLK 206 -+#define EBI1_XO_CLK 207 -+#define SFAB_SMPSS_S_H_CLK 208 -+#define PRNG_SRC 209 -+#define PRNG_CLK 210 -+#define PXO_SRC 211 -+#define SPDM_CY_PORT0_CLK 212 -+#define SPDM_CY_PORT1_CLK 213 -+#define SPDM_CY_PORT2_CLK 214 -+#define SPDM_CY_PORT3_CLK 215 -+#define SPDM_CY_PORT4_CLK 216 -+#define SPDM_CY_PORT5_CLK 217 -+#define SPDM_CY_PORT6_CLK 218 -+#define SPDM_CY_PORT7_CLK 219 -+#define PLL0 220 -+#define PLL0_VOTE 221 -+#define PLL3 222 -+#define PLL3_VOTE 223 -+#define PLL4 224 -+#define PLL4_VOTE 225 -+#define PLL8 226 -+#define PLL8_VOTE 227 -+#define PLL9 228 -+#define PLL10 229 -+#define PLL11 230 -+#define PLL12 231 -+#define PLL14 232 -+#define PLL14_VOTE 233 -+#define PLL18 234 -+#define CE5_SRC 235 -+#define CE5_H_CLK 236 -+#define CE5_CORE_CLK 237 -+#define CE3_SLEEP_CLK 238 -+#define SFAB_AHB_S8_FCLK 239 -+#define SPDM_CY_PORT8_CLK 246 -+#define PCIE_ALT_REF_SRC 247 -+#define PCIE_ALT_REF_CLK 248 -+#define PCIE_1_A_CLK 249 -+#define PCIE_1_AUX_CLK 250 -+#define PCIE_1_H_CLK 251 -+#define PCIE_1_PHY_CLK 252 -+#define PCIE_1_ALT_REF_SRC 253 -+#define PCIE_1_ALT_REF_CLK 254 -+#define PCIE_2_A_CLK 255 -+#define PCIE_2_AUX_CLK 256 -+#define PCIE_2_H_CLK 257 -+#define PCIE_2_PHY_CLK 258 -+#define PCIE_2_ALT_REF_SRC 259 -+#define PCIE_2_ALT_REF_CLK 260 -+#define EBI2_CLK 261 -+#define USB30_SLEEP_CLK 262 -+#define USB30_UTMI_SRC 263 -+#define USB30_0_UTMI_CLK 264 -+#define USB30_1_UTMI_CLK 264 -+#define USB30_MASTER_SRC 265 -+#define USB30_0_MASTER_CLK 266 -+#define USB30_1_MASTER_CLK 267 -+#define GMAC_CORE1_CLK_SRC 268 -+#define GMAC_CORE2_CLK_SRC 269 -+#define GMAC_CORE3_CLK_SRC 270 -+#define GMAC_CORE4_CLK_SRC 271 -+#define GMAC_CORE1_CLK 272 -+#define GMAC_CORE2_CLK 273 -+#define GMAC_CORE3_CLK 274 -+#define GMAC_CORE4_CLK 275 -+#define UBI32_CORE1_CLK_SRC 276 -+#define UBI32_CORE2_CLK_SRC 277 -+#define UBI32_CORE1_CLK 278 -+#define UBI32_CORE2_CLK 279 -+ -+#endif ---- /dev/null -+++ b/include/dt-bindings/reset/qcom,gcc-ipq806x.h -@@ -0,0 +1,132 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef _DT_BINDINGS_RESET_IPQ_806X_H -+#define _DT_BINDINGS_RESET_IPQ_806X_H -+ -+#define QDSS_STM_RESET 0 -+#define AFAB_SMPSS_S_RESET 1 -+#define AFAB_SMPSS_M1_RESET 2 -+#define AFAB_SMPSS_M0_RESET 3 -+#define AFAB_EBI1_CH0_RESET 4 -+#define AFAB_EBI1_CH1_RESET 5 -+#define SFAB_ADM0_M0_RESET 6 -+#define SFAB_ADM0_M1_RESET 7 -+#define SFAB_ADM0_M2_RESET 8 -+#define ADM0_C2_RESET 9 -+#define ADM0_C1_RESET 10 -+#define ADM0_C0_RESET 11 -+#define ADM0_PBUS_RESET 12 -+#define ADM0_RESET 13 -+#define QDSS_CLKS_SW_RESET 14 -+#define QDSS_POR_RESET 15 -+#define QDSS_TSCTR_RESET 16 -+#define QDSS_HRESET_RESET 17 -+#define QDSS_AXI_RESET 18 -+#define QDSS_DBG_RESET 19 -+#define SFAB_PCIE_M_RESET 20 -+#define SFAB_PCIE_S_RESET 21 -+#define PCIE_EXT_RESET 22 -+#define PCIE_PHY_RESET 23 -+#define PCIE_PCI_RESET 24 -+#define PCIE_POR_RESET 25 -+#define PCIE_HCLK_RESET 26 -+#define PCIE_ACLK_RESET 27 -+#define SFAB_LPASS_RESET 28 -+#define SFAB_AFAB_M_RESET 29 -+#define AFAB_SFAB_M0_RESET 30 -+#define AFAB_SFAB_M1_RESET 31 -+#define SFAB_SATA_S_RESET 32 -+#define SFAB_DFAB_M_RESET 33 -+#define DFAB_SFAB_M_RESET 34 -+#define DFAB_SWAY0_RESET 35 -+#define DFAB_SWAY1_RESET 36 -+#define DFAB_ARB0_RESET 37 -+#define DFAB_ARB1_RESET 38 -+#define PPSS_PROC_RESET 39 -+#define PPSS_RESET 40 -+#define DMA_BAM_RESET 41 -+#define SPS_TIC_H_RESET 42 -+#define SFAB_CFPB_M_RESET 43 -+#define SFAB_CFPB_S_RESET 44 -+#define TSIF_H_RESET 45 -+#define CE1_H_RESET 46 -+#define CE1_CORE_RESET 47 -+#define CE1_SLEEP_RESET 48 -+#define CE2_H_RESET 49 -+#define CE2_CORE_RESET 50 -+#define SFAB_SFPB_M_RESET 51 -+#define SFAB_SFPB_S_RESET 52 -+#define RPM_PROC_RESET 53 -+#define PMIC_SSBI2_RESET 54 -+#define SDC1_RESET 55 -+#define SDC2_RESET 56 -+#define SDC3_RESET 57 -+#define SDC4_RESET 58 -+#define USB_HS1_RESET 59 -+#define USB_HSIC_RESET 60 -+#define USB_FS1_XCVR_RESET 61 -+#define USB_FS1_RESET 62 -+#define GSBI1_RESET 63 -+#define GSBI2_RESET 64 -+#define GSBI3_RESET 65 -+#define GSBI4_RESET 66 -+#define GSBI5_RESET 67 -+#define GSBI6_RESET 68 -+#define GSBI7_RESET 69 -+#define SPDM_RESET 70 -+#define SEC_CTRL_RESET 71 -+#define TLMM_H_RESET 72 -+#define SFAB_SATA_M_RESET 73 -+#define SATA_RESET 74 -+#define TSSC_RESET 75 -+#define PDM_RESET 76 -+#define MPM_H_RESET 77 -+#define MPM_RESET 78 -+#define SFAB_SMPSS_S_RESET 79 -+#define PRNG_RESET 80 -+#define SFAB_CE3_M_RESET 81 -+#define SFAB_CE3_S_RESET 82 -+#define CE3_SLEEP_RESET 83 -+#define PCIE_1_M_RESET 84 -+#define PCIE_1_S_RESET 85 -+#define PCIE_1_EXT_RESET 86 -+#define PCIE_1_PHY_RESET 87 -+#define PCIE_1_PCI_RESET 88 -+#define PCIE_1_POR_RESET 89 -+#define PCIE_1_HCLK_RESET 90 -+#define PCIE_1_ACLK_RESET 91 -+#define PCIE_2_M_RESET 92 -+#define PCIE_2_S_RESET 93 -+#define PCIE_2_EXT_RESET 94 -+#define PCIE_2_PHY_RESET 95 -+#define PCIE_2_PCI_RESET 96 -+#define PCIE_2_POR_RESET 97 -+#define PCIE_2_HCLK_RESET 98 -+#define PCIE_2_ACLK_RESET 99 -+#define SFAB_USB30_S_RESET 100 -+#define SFAB_USB30_M_RESET 101 -+#define USB30_0_PORT2_HS_PHY_RESET 102 -+#define USB30_0_MASTER_RESET 103 -+#define USB30_0_SLEEP_RESET 104 -+#define USB30_0_UTMI_PHY_RESET 105 -+#define USB30_0_POWERON_RESET 106 -+#define USB30_0_PHY_RESET 107 -+#define USB30_1_MASTER_RESET 108 -+#define USB30_1_SLEEP_RESET 109 -+#define USB30_1_UTMI_PHY_RESET 110 -+#define USB30_1_POWERON_RESET 111 -+#define USB30_1_PHY_RESET 112 -+#define NSSFB0_RESET 113 -+#define NSSFB1_RESET 114 -+#endif diff --git a/target/linux/ipq806x/patches/0126-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches/0126-clk-Add-safe-switch-hook.patch deleted file mode 100644 index a78319ff52..0000000000 --- a/target/linux/ipq806x/patches/0126-clk-Add-safe-switch-hook.patch +++ /dev/null @@ -1,146 +0,0 @@ -From b7b3ceec506179d59e46e3a8ea8b370872cc7fcb Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Mon, 31 Mar 2014 16:52:29 -0700 -Subject: [PATCH 126/182] clk: Add safe switch hook - -Sometimes clocks can't accept their parent source turning off -while the source is reprogrammed to a different rate. Most -notably CPU clocks require a way to switch away from the current -PLL they're running on, reprogram that PLL to a new rate, and -then switch back to the PLL with the new rate once they're done. -Add a hook that drivers can implement allowing them to return a -'safe parent' that they can switch their parent to while the -upstream source is reprogrammed to support this. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk.c | 53 ++++++++++++++++++++++++++++++++++++------ - include/linux/clk-private.h | 2 ++ - include/linux/clk-provider.h | 1 + - 3 files changed, 49 insertions(+), 7 deletions(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -1356,6 +1356,7 @@ static void clk_calc_subtree(struct clk - struct clk *new_parent, u8 p_index) - { - struct clk *child; -+ struct clk *parent; - - clk->new_rate = new_rate; - clk->new_parent = new_parent; -@@ -1365,6 +1366,17 @@ static void clk_calc_subtree(struct clk - if (new_parent && new_parent != clk->parent) - new_parent->new_child = clk; - -+ if (clk->ops->get_safe_parent) { -+ parent = clk->ops->get_safe_parent(clk->hw); -+ if (parent) { -+ p_index = clk_fetch_parent_index(clk, parent); -+ clk->safe_parent_index = p_index; -+ clk->safe_parent = parent; -+ } -+ } else { -+ clk->safe_parent = NULL; -+ } -+ - hlist_for_each_entry(child, &clk->children, child_node) { - if (child->ops->recalc_rate) - child->new_rate = child->ops->recalc_rate(child->hw, new_rate); -@@ -1450,14 +1462,42 @@ out: - static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event) - { - struct clk *child, *tmp_clk, *fail_clk = NULL; -+ struct clk *old_parent; - int ret = NOTIFY_DONE; - -- if (clk->rate == clk->new_rate) -+ if (clk->rate == clk->new_rate && event != POST_RATE_CHANGE) - return NULL; - -+ switch (event) { -+ case PRE_RATE_CHANGE: -+ if (clk->safe_parent) -+ clk->ops->set_parent(clk->hw, clk->safe_parent_index); -+ break; -+ case POST_RATE_CHANGE: -+ if (clk->safe_parent) { -+ old_parent = __clk_set_parent_before(clk, -+ clk->new_parent); -+ if (clk->ops->set_rate_and_parent) { -+ clk->ops->set_rate_and_parent(clk->hw, -+ clk->new_rate, -+ clk->new_parent ? -+ clk->new_parent->rate : 0, -+ clk->new_parent_index); -+ } else if (clk->ops->set_parent) { -+ clk->ops->set_parent(clk->hw, -+ clk->new_parent_index); -+ } -+ __clk_set_parent_after(clk, clk->new_parent, -+ old_parent); -+ } -+ break; -+ } -+ - if (clk->notifier_count) { -- ret = __clk_notify(clk, event, clk->rate, clk->new_rate); -- if (ret & NOTIFY_STOP_MASK) -+ if (event != POST_RATE_CHANGE) -+ ret = __clk_notify(clk, event, clk->rate, -+ clk->new_rate); -+ if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE) - fail_clk = clk; - } - -@@ -1500,7 +1540,8 @@ static void clk_change_rate(struct clk * - else if (clk->parent) - best_parent_rate = clk->parent->rate; - -- if (clk->new_parent && clk->new_parent != clk->parent) { -+ if (clk->new_parent && clk->new_parent != clk->parent && -+ !clk->safe_parent) { - old_parent = __clk_set_parent_before(clk, clk->new_parent); - - if (clk->ops->set_rate_and_parent) { -@@ -1523,9 +1564,6 @@ static void clk_change_rate(struct clk * - else - clk->rate = best_parent_rate; - -- if (clk->notifier_count && old_rate != clk->rate) -- __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); -- - /* - * Use safe iteration, as change_rate can actually swap parents - * for certain clock types. -@@ -1603,6 +1641,7 @@ int clk_set_rate(struct clk *clk, unsign - /* change the rates */ - clk_change_rate(top); - -+ clk_propagate_rate_change(top, POST_RATE_CHANGE); - out: - clk_prepare_unlock(); - ---- a/include/linux/clk-private.h -+++ b/include/linux/clk-private.h -@@ -38,8 +38,10 @@ struct clk { - struct clk **parents; - u8 num_parents; - u8 new_parent_index; -+ u8 safe_parent_index; - unsigned long rate; - unsigned long new_rate; -+ struct clk *safe_parent; - struct clk *new_parent; - struct clk *new_child; - unsigned long flags; ---- a/include/linux/clk-provider.h -+++ b/include/linux/clk-provider.h -@@ -157,6 +157,7 @@ struct clk_ops { - struct clk **best_parent_clk); - int (*set_parent)(struct clk_hw *hw, u8 index); - u8 (*get_parent)(struct clk_hw *hw); -+ struct clk *(*get_safe_parent)(struct clk_hw *hw); - int (*set_rate)(struct clk_hw *hw, unsigned long, - unsigned long); - int (*set_rate_and_parent)(struct clk_hw *hw, diff --git a/target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch b/target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch deleted file mode 100644 index 07ffdacc77..0000000000 --- a/target/linux/ipq806x/patches/0127-clk-qcom-Add-support-for-setting-rates-on-PLLs.patch +++ /dev/null @@ -1,148 +0,0 @@ -From fd06a2cc719296f65a280cb1533b125f63cfcb34 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Mon, 28 Apr 2014 15:58:11 -0700 -Subject: [PATCH 127/182] clk: qcom: Add support for setting rates on PLLs - -Some PLLs may require changing their rate at runtime. Add support -for these PLLs. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/clk-pll.c | 68 +++++++++++++++++++++++++++++++++++++++++++- - drivers/clk/qcom/clk-pll.h | 20 +++++++++++++ - 2 files changed, 87 insertions(+), 1 deletion(-) - ---- a/drivers/clk/qcom/clk-pll.c -+++ b/drivers/clk/qcom/clk-pll.c -@@ -97,7 +97,7 @@ static unsigned long - clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) - { - struct clk_pll *pll = to_clk_pll(hw); -- u32 l, m, n; -+ u32 l, m, n, config; - unsigned long rate; - u64 tmp; - -@@ -116,13 +116,79 @@ clk_pll_recalc_rate(struct clk_hw *hw, u - do_div(tmp, n); - rate += tmp; - } -+ if (pll->post_div_width) { -+ regmap_read(pll->clkr.regmap, pll->config_reg, &config); -+ config >>= pll->post_div_shift; -+ config &= BIT(pll->post_div_width) - 1; -+ rate /= config + 1; -+ } -+ - return rate; - } - -+static const -+struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate) -+{ -+ if (!f) -+ return NULL; -+ -+ for (; f->freq; f++) -+ if (rate <= f->freq) -+ return f; -+ -+ return NULL; -+} -+ -+static long -+clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *p_rate, struct clk **p) -+{ -+ struct clk_pll *pll = to_clk_pll(hw); -+ const struct pll_freq_tbl *f; -+ -+ f = find_freq(pll->freq_tbl, rate); -+ if (!f) -+ return clk_pll_recalc_rate(hw, *p_rate); -+ -+ return f->freq; -+} -+ -+static int -+clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate) -+{ -+ struct clk_pll *pll = to_clk_pll(hw); -+ const struct pll_freq_tbl *f; -+ bool enabled; -+ u32 mode; -+ u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N; -+ -+ f = find_freq(pll->freq_tbl, rate); -+ if (!f) -+ return -EINVAL; -+ -+ regmap_read(pll->clkr.regmap, pll->mode_reg, &mode); -+ enabled = (mode & enable_mask) == enable_mask; -+ -+ if (enabled) -+ clk_pll_disable(hw); -+ -+ regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l); -+ regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m); -+ regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n); -+ regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits); -+ -+ if (enabled) -+ clk_pll_enable(hw); -+ -+ return 0; -+} -+ - const struct clk_ops clk_pll_ops = { - .enable = clk_pll_enable, - .disable = clk_pll_disable, - .recalc_rate = clk_pll_recalc_rate, -+ .determine_rate = clk_pll_determine_rate, -+ .set_rate = clk_pll_set_rate, - }; - EXPORT_SYMBOL_GPL(clk_pll_ops); - ---- a/drivers/clk/qcom/clk-pll.h -+++ b/drivers/clk/qcom/clk-pll.h -@@ -18,6 +18,21 @@ - #include "clk-regmap.h" - - /** -+ * struct pll_freq_tbl - PLL frequency table -+ * @l: L value -+ * @m: M value -+ * @n: N value -+ * @ibits: internal values -+ */ -+struct pll_freq_tbl { -+ unsigned long freq; -+ u16 l; -+ u16 m; -+ u16 n; -+ u32 ibits; -+}; -+ -+/** - * struct clk_pll - phase locked loop (PLL) - * @l_reg: L register - * @m_reg: M register -@@ -26,6 +41,7 @@ - * @mode_reg: mode register - * @status_reg: status register - * @status_bit: ANDed with @status_reg to determine if PLL is enabled -+ * @freq_tbl: PLL frequency table - * @hw: handle between common and hardware-specific interfaces - */ - struct clk_pll { -@@ -36,6 +52,10 @@ struct clk_pll { - u32 mode_reg; - u32 status_reg; - u8 status_bit; -+ u8 post_div_width; -+ u8 post_div_shift; -+ -+ const struct pll_freq_tbl *freq_tbl; - - struct clk_regmap clkr; - }; diff --git a/target/linux/ipq806x/patches/0128-clk-qcom-Add-support-for-banked-MD-RCGs.patch b/target/linux/ipq806x/patches/0128-clk-qcom-Add-support-for-banked-MD-RCGs.patch deleted file mode 100644 index 38104b95d0..0000000000 --- a/target/linux/ipq806x/patches/0128-clk-qcom-Add-support-for-banked-MD-RCGs.patch +++ /dev/null @@ -1,308 +0,0 @@ -From 856324d2daa3246ac62d7920d6a274e1fa35bcf5 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Mon, 28 Apr 2014 15:59:16 -0700 -Subject: [PATCH 128/182] clk: qcom: Add support for banked MD RCGs - -The banked MD RCGs in global clock control have a different -register layout than the ones implemented in multimedia clock -control. Add support for these types of clocks so we can change -the rates of the UBI32 clocks. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/clk-rcg.c | 99 ++++++++++++++++++++------------------- - drivers/clk/qcom/clk-rcg.h | 5 +- - drivers/clk/qcom/mmcc-msm8960.c | 24 +++++++--- - 3 files changed, 73 insertions(+), 55 deletions(-) - ---- a/drivers/clk/qcom/clk-rcg.c -+++ b/drivers/clk/qcom/clk-rcg.c -@@ -67,16 +67,16 @@ static u8 clk_dyn_rcg_get_parent(struct - { - struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); - int num_parents = __clk_get_num_parents(hw->clk); -- u32 ns, ctl; -+ u32 ns, reg; - int bank; - int i; - struct src_sel *s; - -- regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); -- bank = reg_to_bank(rcg, ctl); -+ regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); -+ bank = reg_to_bank(rcg, reg); - s = &rcg->s[bank]; - -- regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); -+ regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns); - ns = ns_to_src(s, ns); - - for (i = 0; i < num_parents; i++) -@@ -192,90 +192,93 @@ static u32 mn_to_reg(struct mn *mn, u32 - - static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f) - { -- u32 ns, md, ctl, *regp; -+ u32 ns, md, reg; - int bank, new_bank; - struct mn *mn; - struct pre_div *p; - struct src_sel *s; - bool enabled; -- u32 md_reg; -- u32 bank_reg; -+ u32 md_reg, ns_reg; - bool banked_mn = !!rcg->mn[1].width; -+ bool banked_p = !!rcg->p[1].pre_div_width; - struct clk_hw *hw = &rcg->clkr.hw; - - enabled = __clk_is_enabled(hw->clk); - -- regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); -- regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); -- -- if (banked_mn) { -- regp = &ctl; -- bank_reg = rcg->clkr.enable_reg; -- } else { -- regp = &ns; -- bank_reg = rcg->ns_reg; -- } -- -- bank = reg_to_bank(rcg, *regp); -+ regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); -+ bank = reg_to_bank(rcg, reg); - new_bank = enabled ? !bank : bank; - -+ ns_reg = rcg->ns_reg[new_bank]; -+ regmap_read(rcg->clkr.regmap, ns_reg, &ns); -+ - if (banked_mn) { - mn = &rcg->mn[new_bank]; - md_reg = rcg->md_reg[new_bank]; - - ns |= BIT(mn->mnctr_reset_bit); -- regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); -+ regmap_write(rcg->clkr.regmap, ns_reg, ns); - - regmap_read(rcg->clkr.regmap, md_reg, &md); - md = mn_to_md(mn, f->m, f->n, md); - regmap_write(rcg->clkr.regmap, md_reg, md); - - ns = mn_to_ns(mn, f->m, f->n, ns); -- regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); -+ regmap_write(rcg->clkr.regmap, ns_reg, ns); - -- ctl = mn_to_reg(mn, f->m, f->n, ctl); -- regmap_write(rcg->clkr.regmap, rcg->clkr.enable_reg, ctl); -+ /* Two NS registers means mode control is in NS register */ -+ if (rcg->ns_reg[0] != rcg->ns_reg[1]) { -+ ns = mn_to_reg(mn, f->m, f->n, ns); -+ regmap_write(rcg->clkr.regmap, ns_reg, ns); -+ } else { -+ reg = mn_to_reg(mn, f->m, f->n, reg); -+ regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg); -+ } - - ns &= ~BIT(mn->mnctr_reset_bit); -- regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); -- } else { -+ regmap_write(rcg->clkr.regmap, ns_reg, ns); -+ } -+ -+ if (banked_p) { - p = &rcg->p[new_bank]; - ns = pre_div_to_ns(p, f->pre_div - 1, ns); - } - - s = &rcg->s[new_bank]; - ns = src_to_ns(s, s->parent_map[f->src], ns); -- regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); -+ regmap_write(rcg->clkr.regmap, ns_reg, ns); - - if (enabled) { -- *regp ^= BIT(rcg->mux_sel_bit); -- regmap_write(rcg->clkr.regmap, bank_reg, *regp); -+ regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); -+ reg ^= BIT(rcg->mux_sel_bit); -+ regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg); - } - } - - static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index) - { - struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); -- u32 ns, ctl, md, reg; -+ u32 ns, md, reg; - int bank; - struct freq_tbl f = { 0 }; - bool banked_mn = !!rcg->mn[1].width; -+ bool banked_p = !!rcg->p[1].pre_div_width; - -- regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); -- regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); -- reg = banked_mn ? ctl : ns; -- -+ regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); - bank = reg_to_bank(rcg, reg); - -+ regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns); -+ - if (banked_mn) { - regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); - f.m = md_to_m(&rcg->mn[bank], md); - f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m); -- } else { -- f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1; - } -- f.src = index; - -+ if (banked_p) -+ f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1; -+ -+ f.src = index; - configure_bank(rcg, &f); - - return 0; -@@ -336,28 +339,30 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *h - u32 m, n, pre_div, ns, md, mode, reg; - int bank; - struct mn *mn; -+ bool banked_p = !!rcg->p[1].pre_div_width; - bool banked_mn = !!rcg->mn[1].width; - -- regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); -- -- if (banked_mn) -- regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, ®); -- else -- reg = ns; -- -+ regmap_read(rcg->clkr.regmap, rcg->bank_reg, ®); - bank = reg_to_bank(rcg, reg); - -+ regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns); -+ m = n = pre_div = mode = 0; -+ - if (banked_mn) { - mn = &rcg->mn[bank]; - regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); - m = md_to_m(mn, md); - n = ns_m_to_n(mn, ns, m); -+ /* Two NS registers means mode control is in NS register */ -+ if (rcg->ns_reg[0] != rcg->ns_reg[1]) -+ reg = ns; - mode = reg_to_mnctr_mode(mn, reg); -- return calc_rate(parent_rate, m, n, mode, 0); -- } else { -- pre_div = ns_to_pre_div(&rcg->p[bank], ns); -- return calc_rate(parent_rate, 0, 0, 0, pre_div); - } -+ -+ if (banked_p) -+ pre_div = ns_to_pre_div(&rcg->p[bank], ns); -+ -+ return calc_rate(parent_rate, m, n, mode, pre_div); - } - - static const ---- a/drivers/clk/qcom/clk-rcg.h -+++ b/drivers/clk/qcom/clk-rcg.h -@@ -102,7 +102,7 @@ extern const struct clk_ops clk_rcg_ops; - * struct clk_dyn_rcg - root clock generator with glitch free mux - * - * @mux_sel_bit: bit to switch glitch free mux -- * @ns_reg: NS register -+ * @ns_reg: NS0 and NS1 register - * @md_reg: MD0 and MD1 register - * @mn: mn counter (banked) - * @s: source selector (banked) -@@ -112,8 +112,9 @@ extern const struct clk_ops clk_rcg_ops; - * - */ - struct clk_dyn_rcg { -- u32 ns_reg; -+ u32 ns_reg[2]; - u32 md_reg[2]; -+ u32 bank_reg; - - u8 mux_sel_bit; - ---- a/drivers/clk/qcom/mmcc-msm8960.c -+++ b/drivers/clk/qcom/mmcc-msm8960.c -@@ -728,9 +728,11 @@ static struct freq_tbl clk_tbl_gfx2d[] = - }; - - static struct clk_dyn_rcg gfx2d0_src = { -- .ns_reg = 0x0070, -+ .ns_reg[0] = 0x0070, -+ .ns_reg[1] = 0x0070, - .md_reg[0] = 0x0064, - .md_reg[1] = 0x0068, -+ .bank_reg = 0x0060, - .mn[0] = { - .mnctr_en_bit = 8, - .mnctr_reset_bit = 25, -@@ -786,9 +788,11 @@ static struct clk_branch gfx2d0_clk = { - }; - - static struct clk_dyn_rcg gfx2d1_src = { -- .ns_reg = 0x007c, -+ .ns_reg[0] = 0x007c, -+ .ns_reg[1] = 0x007c, - .md_reg[0] = 0x0078, - .md_reg[1] = 0x006c, -+ .bank_reg = 0x0074, - .mn[0] = { - .mnctr_en_bit = 8, - .mnctr_reset_bit = 25, -@@ -864,9 +868,11 @@ static struct freq_tbl clk_tbl_gfx3d[] = - }; - - static struct clk_dyn_rcg gfx3d_src = { -- .ns_reg = 0x008c, -+ .ns_reg[0] = 0x008c, -+ .ns_reg[1] = 0x008c, - .md_reg[0] = 0x0084, - .md_reg[1] = 0x0088, -+ .bank_reg = 0x0080, - .mn[0] = { - .mnctr_en_bit = 8, - .mnctr_reset_bit = 25, -@@ -1053,9 +1059,11 @@ static struct freq_tbl clk_tbl_mdp[] = { - }; - - static struct clk_dyn_rcg mdp_src = { -- .ns_reg = 0x00d0, -+ .ns_reg[0] = 0x00d0, -+ .ns_reg[1] = 0x00d0, - .md_reg[0] = 0x00c4, - .md_reg[1] = 0x00c8, -+ .bank_reg = 0x00c0, - .mn[0] = { - .mnctr_en_bit = 8, - .mnctr_reset_bit = 31, -@@ -1160,7 +1168,9 @@ static struct freq_tbl clk_tbl_rot[] = { - }; - - static struct clk_dyn_rcg rot_src = { -- .ns_reg = 0x00e8, -+ .ns_reg[0] = 0x00e8, -+ .ns_reg[1] = 0x00e8, -+ .bank_reg = 0x00e8, - .p[0] = { - .pre_div_shift = 22, - .pre_div_width = 4, -@@ -1357,9 +1367,11 @@ static struct freq_tbl clk_tbl_vcodec[] - }; - - static struct clk_dyn_rcg vcodec_src = { -- .ns_reg = 0x0100, -+ .ns_reg[0] = 0x0100, -+ .ns_reg[1] = 0x0100, - .md_reg[0] = 0x00fc, - .md_reg[1] = 0x0128, -+ .bank_reg = 0x00f8, - .mn[0] = { - .mnctr_en_bit = 5, - .mnctr_reset_bit = 31, diff --git a/target/linux/ipq806x/patches/0129-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch b/target/linux/ipq806x/patches/0129-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch deleted file mode 100644 index 8b8839ad04..0000000000 --- a/target/linux/ipq806x/patches/0129-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch +++ /dev/null @@ -1,860 +0,0 @@ -From 92fde23153240a6173645dabe4d99f4aa6570bb7 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Mon, 28 Apr 2014 16:01:03 -0700 -Subject: [PATCH 129/182] clk: qcom: Add support for NSS/GMAC clocks and - resets - -The NSS driver expects one virtual clock that actually represents -two clocks (one for each UBI32 core). Register the ubi32 core -clocks and also make a wrapper virtual clock called nss_core_clk -to be used by the driver. This will properly handle switching the -rates of both clocks at the same time like how the NSS driver -expects it. Also add the TCM clock and the NSS resets. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/gcc-ipq806x.c | 710 +++++++++++++++++++++++++- - include/dt-bindings/clock/qcom,gcc-ipq806x.h | 3 + - include/dt-bindings/reset/qcom,gcc-ipq806x.h | 43 ++ - 3 files changed, 755 insertions(+), 1 deletion(-) - ---- a/drivers/clk/qcom/gcc-ipq806x.c -+++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -32,6 +32,33 @@ - #include "clk-branch.h" - #include "reset.h" - -+static struct clk_pll pll0 = { -+ .l_reg = 0x30c4, -+ .m_reg = 0x30c8, -+ .n_reg = 0x30cc, -+ .config_reg = 0x30d4, -+ .mode_reg = 0x30c0, -+ .status_reg = 0x30d8, -+ .status_bit = 16, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "pll0", -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .ops = &clk_pll_ops, -+ }, -+}; -+ -+static struct clk_regmap pll0_vote = { -+ .enable_reg = 0x34c0, -+ .enable_mask = BIT(0), -+ .hw.init = &(struct clk_init_data){ -+ .name = "pll0_vote", -+ .parent_names = (const char *[]){ "pll0" }, -+ .num_parents = 1, -+ .ops = &clk_pll_vote_ops, -+ }, -+}; -+ - static struct clk_pll pll3 = { - .l_reg = 0x3164, - .m_reg = 0x3168, -@@ -102,11 +129,46 @@ static struct clk_regmap pll14_vote = { - }, - }; - -+#define NSS_PLL_RATE(f, _l, _m, _n, i) \ -+ { \ -+ .freq = f, \ -+ .l = _l, \ -+ .m = _m, \ -+ .n = _n, \ -+ .ibits = i, \ -+ } -+ -+static struct pll_freq_tbl pll18_freq_tbl[] = { -+ NSS_PLL_RATE(550000000, 44, 0, 1, 0x01495625), -+ NSS_PLL_RATE(733000000, 58, 16, 25, 0x014b5625), -+}; -+ -+static struct clk_pll pll18 = { -+ .l_reg = 0x31a4, -+ .m_reg = 0x31a8, -+ .n_reg = 0x31ac, -+ .config_reg = 0x31b4, -+ .mode_reg = 0x31a0, -+ .status_reg = 0x31b8, -+ .status_bit = 16, -+ .post_div_shift = 16, -+ .post_div_width = 1, -+ .freq_tbl = pll18_freq_tbl, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .name = "pll18", -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .ops = &clk_pll_ops, -+ }, -+}; -+ - #define P_PXO 0 - #define P_PLL8 1 - #define P_PLL3 1 - #define P_PLL0 2 - #define P_CXO 2 -+#define P_PLL14 3 -+#define P_PLL18 4 - - static const u8 gcc_pxo_pll8_map[] = { - [P_PXO] = 0, -@@ -157,6 +219,22 @@ static const char *gcc_pxo_pll8_pll0_map - "pll0", - }; - -+static const u8 gcc_pxo_pll8_pll14_pll18_pll0_map[] = { -+ [P_PXO] = 0, -+ [P_PLL8] = 4, -+ [P_PLL0] = 2, -+ [P_PLL14] = 5, -+ [P_PLL18] = 1, -+}; -+ -+static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = { -+ "pxo", -+ "pll8_vote", -+ "pll0_vote", -+ "pll14", -+ "pll18", -+}; -+ - static struct freq_tbl clk_tbl_gsbi_uart[] = { - { 1843200, P_PLL8, 2, 6, 625 }, - { 3686400, P_PLL8, 2, 12, 625 }, -@@ -2132,12 +2210,567 @@ static struct clk_branch usb_fs1_h_clk = - }, - }; - -+static const struct freq_tbl clk_tbl_gmac[] = { -+ { 133000000, P_PLL0, 1, 50, 301 }, -+ { } -+}; -+ -+static struct clk_dyn_rcg gmac_core1_src = { -+ .ns_reg[0] = 0x3cac, -+ .ns_reg[1] = 0x3cb0, -+ .md_reg[0] = 0x3ca4, -+ .md_reg[1] = 0x3ca8, -+ .bank_reg = 0x3ca0, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3ca0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core1_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core1_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 4, -+ .hwcg_reg = 0x3cb4, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3cb4, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core1_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core1_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg gmac_core2_src = { -+ .ns_reg[0] = 0x3ccc, -+ .ns_reg[1] = 0x3cd0, -+ .md_reg[0] = 0x3cc4, -+ .md_reg[1] = 0x3cc8, -+ .bank_reg = 0x3ca0, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3cc0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core2_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core2_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 5, -+ .hwcg_reg = 0x3cd4, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3cd4, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core2_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core2_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg gmac_core3_src = { -+ .ns_reg[0] = 0x3cec, -+ .ns_reg[1] = 0x3cf0, -+ .md_reg[0] = 0x3ce4, -+ .md_reg[1] = 0x3ce8, -+ .bank_reg = 0x3ce0, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3ce0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core3_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core3_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 6, -+ .hwcg_reg = 0x3cf4, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3cf4, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core3_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core3_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg gmac_core4_src = { -+ .ns_reg[0] = 0x3d0c, -+ .ns_reg[1] = 0x3d10, -+ .md_reg[0] = 0x3d04, -+ .md_reg[1] = 0x3d08, -+ .bank_reg = 0x3d00, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_gmac, -+ .clkr = { -+ .enable_reg = 0x3d00, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core4_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch gmac_core4_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 7, -+ .hwcg_reg = 0x3d14, -+ .hwcg_bit = 6, -+ .clkr = { -+ .enable_reg = 0x3d14, -+ .enable_mask = BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "gmac_core4_clk", -+ .parent_names = (const char *[]){ -+ "gmac_core4_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_nss_tcm[] = { -+ { 266000000, P_PLL0, 3, 0, 0 }, -+ { 400000000, P_PLL0, 2, 0, 0 }, -+ { } -+}; -+ -+static struct clk_dyn_rcg nss_tcm_src = { -+ .ns_reg[0] = 0x3dc4, -+ .ns_reg[1] = 0x3dc8, -+ .bank_reg = 0x3dc0, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 4, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_nss_tcm, -+ .clkr = { -+ .enable_reg = 0x3dc0, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "nss_tcm_src", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_tcm_clk = { -+ .halt_reg = 0x3c20, -+ .halt_bit = 14, -+ .clkr = { -+ .enable_reg = 0x3dd0, -+ .enable_mask = BIT(6) | BIT(4), -+ .hw.init = &(struct clk_init_data){ -+ .name = "nss_tcm_clk", -+ .parent_names = (const char *[]){ -+ "nss_tcm_src", -+ }, -+ .num_parents = 1, -+ .ops = &clk_branch_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+ }, -+}; -+ -+static const struct freq_tbl clk_tbl_nss[] = { -+ { 110000000, P_PLL18, 1, 1, 5 }, -+ { 275000000, P_PLL18, 2, 0, 0 }, -+ { 550000000, P_PLL18, 1, 0, 0 }, -+ { 733000000, P_PLL18, 1, 0, 0 }, -+ { } -+}; -+ -+static struct clk_dyn_rcg ubi32_core1_src_clk = { -+ .ns_reg[0] = 0x3d2c, -+ .ns_reg[1] = 0x3d30, -+ .md_reg[0] = 0x3d24, -+ .md_reg[1] = 0x3d28, -+ .bank_reg = 0x3d20, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_nss, -+ .clkr = { -+ .enable_reg = 0x3d20, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "ubi32_core1_src_clk", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, -+ }, -+ }, -+}; -+ -+static struct clk_dyn_rcg ubi32_core2_src_clk = { -+ .ns_reg[0] = 0x3d4c, -+ .ns_reg[1] = 0x3d50, -+ .md_reg[0] = 0x3d44, -+ .md_reg[1] = 0x3d48, -+ .bank_reg = 0x3d40, -+ .mn[0] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .mn[1] = { -+ .mnctr_en_bit = 8, -+ .mnctr_reset_bit = 7, -+ .mnctr_mode_shift = 5, -+ .n_val_shift = 16, -+ .m_val_shift = 16, -+ .width = 8, -+ }, -+ .s[0] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .s[1] = { -+ .src_sel_shift = 0, -+ .parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map, -+ }, -+ .p[0] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .p[1] = { -+ .pre_div_shift = 3, -+ .pre_div_width = 2, -+ }, -+ .mux_sel_bit = 0, -+ .freq_tbl = clk_tbl_nss, -+ .clkr = { -+ .enable_reg = 0x3d40, -+ .enable_mask = BIT(1), -+ .hw.init = &(struct clk_init_data){ -+ .name = "ubi32_core2_src_clk", -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .ops = &clk_dyn_rcg_ops, -+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, -+ }, -+ }, -+}; -+ -+static int nss_core_clk_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ int ret; -+ -+ ret = clk_dyn_rcg_ops.set_rate(&ubi32_core1_src_clk.clkr.hw, rate, -+ parent_rate); -+ if (ret) -+ return ret; -+ -+ return clk_dyn_rcg_ops.set_rate(&ubi32_core2_src_clk.clkr.hw, rate, -+ parent_rate); -+} -+ -+static int -+nss_core_clk_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate, u8 index) -+{ -+ int ret; -+ -+ ret = clk_dyn_rcg_ops.set_rate_and_parent( -+ &ubi32_core1_src_clk.clkr.hw, rate, parent_rate, index); -+ if (ret) -+ return ret; -+ -+ ret = clk_dyn_rcg_ops.set_rate_and_parent( -+ &ubi32_core2_src_clk.clkr.hw, rate, parent_rate, index); -+ return ret; -+} -+ -+static long nss_core_clk_determine_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *p_rate, struct clk **p) -+{ -+ return clk_dyn_rcg_ops.determine_rate(&ubi32_core1_src_clk.clkr.hw, -+ rate, p_rate, p); -+} -+ -+static unsigned long -+nss_core_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -+{ -+ return clk_dyn_rcg_ops.recalc_rate(&ubi32_core1_src_clk.clkr.hw, -+ parent_rate); -+} -+ -+static u8 nss_core_clk_get_parent(struct clk_hw *hw) -+{ -+ return clk_dyn_rcg_ops.get_parent(&ubi32_core1_src_clk.clkr.hw); -+} -+ -+static int nss_core_clk_set_parent(struct clk_hw *hw, u8 i) -+{ -+ int ret; -+ -+ ret = clk_dyn_rcg_ops.set_parent(&ubi32_core1_src_clk.clkr.hw, i); -+ if (ret) -+ return ret; -+ -+ return clk_dyn_rcg_ops.set_parent(&ubi32_core2_src_clk.clkr.hw, i); -+} -+ -+static struct clk *nss_core_clk_get_safe_parent(struct clk_hw *hw) -+{ -+ return clk_get_parent_by_index(hw->clk, -+ ubi32_core2_src_clk.s[0].parent_map[P_PLL8]); -+} -+ -+static const struct clk_ops clk_ops_nss_core = { -+ .set_rate = nss_core_clk_set_rate, -+ .set_rate_and_parent = nss_core_clk_set_rate_and_parent, -+ .determine_rate = nss_core_clk_determine_rate, -+ .recalc_rate = nss_core_clk_recalc_rate, -+ .get_parent = nss_core_clk_get_parent, -+ .set_parent = nss_core_clk_set_parent, -+ .get_safe_parent = nss_core_clk_get_safe_parent, -+}; -+ -+/* Virtual clock for nss core clocks */ -+static struct clk_regmap nss_core_clk = { -+ .hw.init = &(struct clk_init_data){ -+ .name = "nss_core_clk", -+ .ops = &clk_ops_nss_core, -+ .parent_names = gcc_pxo_pll8_pll14_pll18_pll0, -+ .num_parents = 5, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+}; -+ - static struct clk_regmap *gcc_ipq806x_clks[] = { -+ [PLL0] = &pll0.clkr, -+ [PLL0_VOTE] = &pll0_vote, - [PLL3] = &pll3.clkr, - [PLL8] = &pll8.clkr, - [PLL8_VOTE] = &pll8_vote, - [PLL14] = &pll14.clkr, - [PLL14_VOTE] = &pll14_vote, -+ [PLL18] = &pll18.clkr, - [GSBI1_UART_SRC] = &gsbi1_uart_src.clkr, - [GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr, - [GSBI2_UART_SRC] = &gsbi2_uart_src.clkr, -@@ -2232,6 +2865,19 @@ static struct clk_regmap *gcc_ipq806x_cl - [USB_FS1_XCVR_SRC] = &usb_fs1_xcvr_clk_src.clkr, - [USB_FS1_XCVR_CLK] = &usb_fs1_xcvr_clk.clkr, - [USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr, -+ [GMAC_CORE1_CLK_SRC] = &gmac_core1_src.clkr, -+ [GMAC_CORE1_CLK] = &gmac_core1_clk.clkr, -+ [GMAC_CORE2_CLK_SRC] = &gmac_core2_src.clkr, -+ [GMAC_CORE2_CLK] = &gmac_core2_clk.clkr, -+ [GMAC_CORE3_CLK_SRC] = &gmac_core3_src.clkr, -+ [GMAC_CORE3_CLK] = &gmac_core3_clk.clkr, -+ [GMAC_CORE4_CLK_SRC] = &gmac_core4_src.clkr, -+ [GMAC_CORE4_CLK] = &gmac_core4_clk.clkr, -+ [UBI32_CORE1_CLK_SRC] = &ubi32_core1_src_clk.clkr, -+ [UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr, -+ [NSSTCM_CLK_SRC] = &nss_tcm_src.clkr, -+ [NSSTCM_CLK] = &nss_tcm_clk.clkr, -+ [NSS_CORE_CLK] = &nss_core_clk, - }; - - static const struct qcom_reset_map gcc_ipq806x_resets[] = { -@@ -2350,6 +2996,48 @@ static const struct qcom_reset_map gcc_i - [USB30_1_PHY_RESET] = { 0x3b58, 0 }, - [NSSFB0_RESET] = { 0x3b60, 6 }, - [NSSFB1_RESET] = { 0x3b60, 7 }, -+ [UBI32_CORE1_CLKRST_CLAMP_RESET] = { 0x3d3c, 3}, -+ [UBI32_CORE1_CLAMP_RESET] = { 0x3d3c, 2 }, -+ [UBI32_CORE1_AHB_RESET] = { 0x3d3c, 1 }, -+ [UBI32_CORE1_AXI_RESET] = { 0x3d3c, 0 }, -+ [UBI32_CORE2_CLKRST_CLAMP_RESET] = { 0x3d5c, 3 }, -+ [UBI32_CORE2_CLAMP_RESET] = { 0x3d5c, 2 }, -+ [UBI32_CORE2_AHB_RESET] = { 0x3d5c, 1 }, -+ [UBI32_CORE2_AXI_RESET] = { 0x3d5c, 0 }, -+ [GMAC_CORE1_RESET] = { 0x3cbc, 0 }, -+ [GMAC_CORE2_RESET] = { 0x3cdc, 0 }, -+ [GMAC_CORE3_RESET] = { 0x3cfc, 0 }, -+ [GMAC_CORE4_RESET] = { 0x3d1c, 0 }, -+ [GMAC_AHB_RESET] = { 0x3e24, 0 }, -+ [NSS_CH0_RST_RX_CLK_N_RESET] = { 0x3b60, 0 }, -+ [NSS_CH0_RST_TX_CLK_N_RESET] = { 0x3b60, 1 }, -+ [NSS_CH0_RST_RX_125M_N_RESET] = { 0x3b60, 2 }, -+ [NSS_CH0_HW_RST_RX_125M_N_RESET] = { 0x3b60, 3 }, -+ [NSS_CH0_RST_TX_125M_N_RESET] = { 0x3b60, 4 }, -+ [NSS_CH1_RST_RX_CLK_N_RESET] = { 0x3b60, 5 }, -+ [NSS_CH1_RST_TX_CLK_N_RESET] = { 0x3b60, 6 }, -+ [NSS_CH1_RST_RX_125M_N_RESET] = { 0x3b60, 7 }, -+ [NSS_CH1_HW_RST_RX_125M_N_RESET] = { 0x3b60, 8 }, -+ [NSS_CH1_RST_TX_125M_N_RESET] = { 0x3b60, 9 }, -+ [NSS_CH2_RST_RX_CLK_N_RESET] = { 0x3b60, 10 }, -+ [NSS_CH2_RST_TX_CLK_N_RESET] = { 0x3b60, 11 }, -+ [NSS_CH2_RST_RX_125M_N_RESET] = { 0x3b60, 12 }, -+ [NSS_CH2_HW_RST_RX_125M_N_RESET] = { 0x3b60, 13 }, -+ [NSS_CH2_RST_TX_125M_N_RESET] = { 0x3b60, 14 }, -+ [NSS_CH3_RST_RX_CLK_N_RESET] = { 0x3b60, 15 }, -+ [NSS_CH3_RST_TX_CLK_N_RESET] = { 0x3b60, 16 }, -+ [NSS_CH3_RST_RX_125M_N_RESET] = { 0x3b60, 17 }, -+ [NSS_CH3_HW_RST_RX_125M_N_RESET] = { 0x3b60, 18 }, -+ [NSS_CH3_RST_TX_125M_N_RESET] = { 0x3b60, 19 }, -+ [NSS_RST_RX_250M_125M_N_RESET] = { 0x3b60, 20 }, -+ [NSS_RST_TX_250M_125M_N_RESET] = { 0x3b60, 21 }, -+ [NSS_QSGMII_TXPI_RST_N_RESET] = { 0x3b60, 22 }, -+ [NSS_QSGMII_CDR_RST_N_RESET] = { 0x3b60, 23 }, -+ [NSS_SGMII2_CDR_RST_N_RESET] = { 0x3b60, 24 }, -+ [NSS_SGMII3_CDR_RST_N_RESET] = { 0x3b60, 25 }, -+ [NSS_CAL_PRBS_RST_N_RESET] = { 0x3b60, 26 }, -+ [NSS_LCKDT_RST_N_RESET] = { 0x3b60, 27 }, -+ [NSS_SRDS_N_RESET] = { 0x3b60, 28 }, - }; - - static const struct regmap_config gcc_ipq806x_regmap_config = { -@@ -2378,6 +3066,8 @@ static int gcc_ipq806x_probe(struct plat - { - struct clk *clk; - struct device *dev = &pdev->dev; -+ struct regmap *regmap; -+ int ret; - - /* Temporary until RPM clocks supported */ - clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000); -@@ -2388,7 +3078,25 @@ static int gcc_ipq806x_probe(struct plat - if (IS_ERR(clk)) - return PTR_ERR(clk); - -- return qcom_cc_probe(pdev, &gcc_ipq806x_desc); -+ ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc); -+ if (ret) -+ return ret; -+ -+ regmap = dev_get_regmap(dev, NULL); -+ if (!regmap) -+ return -ENODEV; -+ -+ /* Setup PLL18 static bits */ -+ regmap_update_bits(regmap, 0x31a4, 0xffffffc0, 0x40000400); -+ regmap_write(regmap, 0x31b0, 0x3080); -+ -+ /* Set GMAC footswitch sleep/wakeup values */ -+ regmap_write(regmap, 0x3cb8, 8); -+ regmap_write(regmap, 0x3cd8, 8); -+ regmap_write(regmap, 0x3cf8, 8); -+ regmap_write(regmap, 0x3d18, 8); -+ -+ return 0; - } - - static int gcc_ipq806x_remove(struct platform_device *pdev) ---- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h -@@ -289,5 +289,8 @@ - #define UBI32_CORE2_CLK_SRC 277 - #define UBI32_CORE1_CLK 278 - #define UBI32_CORE2_CLK 279 -+#define NSSTCM_CLK_SRC 280 -+#define NSSTCM_CLK 281 -+#define NSS_CORE_CLK 282 /* Virtual */ - - #endif ---- a/include/dt-bindings/reset/qcom,gcc-ipq806x.h -+++ b/include/dt-bindings/reset/qcom,gcc-ipq806x.h -@@ -129,4 +129,47 @@ - #define USB30_1_PHY_RESET 112 - #define NSSFB0_RESET 113 - #define NSSFB1_RESET 114 -+#define UBI32_CORE1_CLKRST_CLAMP_RESET 115 -+#define UBI32_CORE1_CLAMP_RESET 116 -+#define UBI32_CORE1_AHB_RESET 117 -+#define UBI32_CORE1_AXI_RESET 118 -+#define UBI32_CORE2_CLKRST_CLAMP_RESET 119 -+#define UBI32_CORE2_CLAMP_RESET 120 -+#define UBI32_CORE2_AHB_RESET 121 -+#define UBI32_CORE2_AXI_RESET 122 -+#define GMAC_CORE1_RESET 123 -+#define GMAC_CORE2_RESET 124 -+#define GMAC_CORE3_RESET 125 -+#define GMAC_CORE4_RESET 126 -+#define GMAC_AHB_RESET 127 -+#define NSS_CH0_RST_RX_CLK_N_RESET 128 -+#define NSS_CH0_RST_TX_CLK_N_RESET 129 -+#define NSS_CH0_RST_RX_125M_N_RESET 130 -+#define NSS_CH0_HW_RST_RX_125M_N_RESET 131 -+#define NSS_CH0_RST_TX_125M_N_RESET 132 -+#define NSS_CH1_RST_RX_CLK_N_RESET 133 -+#define NSS_CH1_RST_TX_CLK_N_RESET 134 -+#define NSS_CH1_RST_RX_125M_N_RESET 135 -+#define NSS_CH1_HW_RST_RX_125M_N_RESET 136 -+#define NSS_CH1_RST_TX_125M_N_RESET 137 -+#define NSS_CH2_RST_RX_CLK_N_RESET 138 -+#define NSS_CH2_RST_TX_CLK_N_RESET 139 -+#define NSS_CH2_RST_RX_125M_N_RESET 140 -+#define NSS_CH2_HW_RST_RX_125M_N_RESET 141 -+#define NSS_CH2_RST_TX_125M_N_RESET 142 -+#define NSS_CH3_RST_RX_CLK_N_RESET 143 -+#define NSS_CH3_RST_TX_CLK_N_RESET 144 -+#define NSS_CH3_RST_RX_125M_N_RESET 145 -+#define NSS_CH3_HW_RST_RX_125M_N_RESET 146 -+#define NSS_CH3_RST_TX_125M_N_RESET 147 -+#define NSS_RST_RX_250M_125M_N_RESET 148 -+#define NSS_RST_TX_250M_125M_N_RESET 149 -+#define NSS_QSGMII_TXPI_RST_N_RESET 150 -+#define NSS_QSGMII_CDR_RST_N_RESET 151 -+#define NSS_SGMII2_CDR_RST_N_RESET 152 -+#define NSS_SGMII3_CDR_RST_N_RESET 153 -+#define NSS_CAL_PRBS_RST_N_RESET 154 -+#define NSS_LCKDT_RST_N_RESET 155 -+#define NSS_SRDS_N_RESET 156 -+ - #endif diff --git a/target/linux/ipq806x/patches/0130-ARM-qcom-Add-initial-IPQ8064-SoC-and-AP148-device-tr.patch b/target/linux/ipq806x/patches/0130-ARM-qcom-Add-initial-IPQ8064-SoC-and-AP148-device-tr.patch deleted file mode 100644 index 8fda0a17c4..0000000000 --- a/target/linux/ipq806x/patches/0130-ARM-qcom-Add-initial-IPQ8064-SoC-and-AP148-device-tr.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 1c6e51ffb10f5bf93a3018c7c1e04d7ed93f944e Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 7 Mar 2014 10:56:59 -0600 -Subject: [PATCH 130/182] ARM: qcom: Add initial IPQ8064 SoC and AP148 device - trees - -Add basic IPQ8064 SoC include device tree and support for basic booting on -the AP148 Reference board. - -Signed-off-by: Kumar Gala ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 25 +++++ - arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi | 1 + - arch/arm/boot/dts/qcom-ipq8064.dtsi | 176 ++++++++++++++++++++++++++++++ - arch/arm/mach-qcom/board.c | 2 + - 5 files changed, 205 insertions(+) - create mode 100644 arch/arm/boot/dts/qcom-ipq8064-ap148.dts - create mode 100644 arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi - create mode 100644 arch/arm/boot/dts/qcom-ipq8064.dtsi - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -235,6 +235,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \ - qcom-apq8064-ifc6410.dtb \ - qcom-apq8074-dragonboard.dtb \ - qcom-apq8084-mtp.dtb \ -+ qcom-ipq8064-ap148.dtb \ - qcom-msm8660-surf.dtb \ - qcom-msm8960-cdp.dtb - dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -0,0 +1,25 @@ -+#include "qcom-ipq8064-v1.0.dtsi" -+ -+/ { -+ model = "Qualcomm IPQ8064/AP148"; -+ compatible = "qcom,ipq8064-ap148", "qcom,ipq8064"; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ rsvd@41200000 { -+ reg = <0x41200000 0x300000>; -+ no-map; -+ }; -+ }; -+ -+ soc { -+ gsbi@16300000 { -+ qcom,mode = ; -+ status = "ok"; -+ serial@16340000 { -+ status = "ok"; -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-ipq8064-v1.0.dtsi -@@ -0,0 +1 @@ -+#include "qcom-ipq8064.dtsi" ---- /dev/null -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -0,0 +1,176 @@ -+/dts-v1/; -+ -+#include "skeleton.dtsi" -+#include -+#include -+ -+/ { -+ model = "Qualcomm IPQ8064"; -+ compatible = "qcom,ipq8064"; -+ interrupt-parent = <&intc>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; -+ device_type = "cpu"; -+ reg = <0>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc0>; -+ qcom,saw = <&saw0>; -+ }; -+ -+ cpu@1 { -+ compatible = "qcom,krait"; -+ enable-method = "qcom,kpss-acc-v1"; -+ device_type = "cpu"; -+ reg = <1>; -+ next-level-cache = <&L2>; -+ qcom,acc = <&acc1>; -+ qcom,saw = <&saw1>; -+ }; -+ -+ L2: l2-cache { -+ compatible = "cache"; -+ cache-level = <2>; -+ }; -+ }; -+ -+ cpu-pmu { -+ compatible = "qcom,krait-pmu"; -+ interrupts = <1 10 0x304>; -+ }; -+ -+ reserved-memory { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ nss@40000000 { -+ reg = <0x40000000 0x1000000>; -+ no-map; -+ }; -+ -+ smem@41000000 { -+ reg = <0x41000000 0x200000>; -+ no-map; -+ }; -+ }; -+ -+ soc: soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ compatible = "simple-bus"; -+ -+ qcom_pinmux: pinmux@800000 { -+ compatible = "qcom,ipq8064-pinctrl"; -+ reg = <0x800000 0x4000>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ interrupts = <0 32 0x4>; -+ }; -+ -+ intc: interrupt-controller@2000000 { -+ compatible = "qcom,msm-qgic2"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = <0x02000000 0x1000>, -+ <0x02002000 0x1000>; -+ }; -+ -+ timer@200a000 { -+ compatible = "qcom,kpss-timer", "qcom,msm-timer"; -+ interrupts = <1 1 0x301>, -+ <1 2 0x301>, -+ <1 3 0x301>; -+ reg = <0x0200a000 0x100>; -+ clock-frequency = <25000000>, -+ <32768>; -+ cpu-offset = <0x80000>; -+ }; -+ -+ acc0: clock-controller@2088000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02088000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ acc1: clock-controller@2098000 { -+ compatible = "qcom,kpss-acc-v1"; -+ reg = <0x02098000 0x1000>, <0x02008000 0x1000>; -+ }; -+ -+ saw0: regulator@2089000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02089000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ -+ saw1: regulator@2099000 { -+ compatible = "qcom,saw2"; -+ reg = <0x02099000 0x1000>, <0x02009000 0x1000>; -+ regulator; -+ }; -+ -+ gsbi2: gsbi@12480000 { -+ compatible = "qcom,gsbi-v1.0.0"; -+ reg = <0x12480000 0x100>; -+ clocks = <&gcc GSBI2_H_CLK>; -+ clock-names = "iface"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ status = "disabled"; -+ -+ serial@12490000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x12490000 0x1000>, -+ <0x12480000 0x1000>; -+ interrupts = <0 195 0x0>; -+ clocks = <&gcc GSBI2_UART_CLK>, <&gcc GSBI2_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ }; -+ -+ gsbi4: gsbi@16300000 { -+ compatible = "qcom,gsbi-v1.0.0"; -+ reg = <0x16300000 0x100>; -+ clocks = <&gcc GSBI4_H_CLK>; -+ clock-names = "iface"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ status = "disabled"; -+ -+ serial@16340000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x16340000 0x1000>, -+ <0x16300000 0x1000>; -+ interrupts = <0 152 0x0>; -+ clocks = <&gcc GSBI4_UART_CLK>, <&gcc GSBI4_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ }; -+ -+ qcom,ssbi@500000 { -+ compatible = "qcom,ssbi"; -+ reg = <0x00500000 0x1000>; -+ qcom,controller-type = "pmic-arbiter"; -+ }; -+ -+ gcc: clock-controller@900000 { -+ compatible = "qcom,gcc-ipq8064"; -+ reg = <0x00900000 0x4000>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; -+ }; -+}; ---- a/arch/arm/mach-qcom/board.c -+++ b/arch/arm/mach-qcom/board.c -@@ -18,6 +18,8 @@ static const char * const qcom_dt_match[ - "qcom,apq8064", - "qcom,apq8074-dragonboard", - "qcom,apq8084", -+ "qcom,ipq8062", -+ "qcom,ipq8064", - "qcom,msm8660-surf", - "qcom,msm8960-cdp", - NULL diff --git a/target/linux/ipq806x/patches/0131-ARM-qcom-config-Enable-IPQ806x-support.patch b/target/linux/ipq806x/patches/0131-ARM-qcom-config-Enable-IPQ806x-support.patch deleted file mode 100644 index 3a0e3ead2a..0000000000 --- a/target/linux/ipq806x/patches/0131-ARM-qcom-config-Enable-IPQ806x-support.patch +++ /dev/null @@ -1,20 +0,0 @@ -From df1564829c4abe206d354f7c1b745cc1e864f4bd Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 11 Apr 2014 14:18:29 -0500 -Subject: [PATCH 131/182] ARM: qcom: config: Enable IPQ806x support - -Signed-off-by: Kumar Gala ---- - arch/arm/configs/qcom_defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -133,6 +133,7 @@ CONFIG_QCOM_BAM_DMA=y - CONFIG_STAGING=y - CONFIG_QCOM_GSBI=y - CONFIG_COMMON_CLK_QCOM=y -+CONFIG_IPQ_GCC_806X=y - CONFIG_MSM_GCC_8660=y - CONFIG_MSM_MMCC_8960=y - CONFIG_MSM_MMCC_8974=y diff --git a/target/linux/ipq806x/patches/0132-XXX-Add-boot-support-for-u-boot.ipq-image.patch b/target/linux/ipq806x/patches/0132-XXX-Add-boot-support-for-u-boot.ipq-image.patch deleted file mode 100644 index c09c3a68f3..0000000000 --- a/target/linux/ipq806x/patches/0132-XXX-Add-boot-support-for-u-boot.ipq-image.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 776fff11c1bf57e564a386521e56c277287a568c Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 8 May 2014 13:40:16 -0500 -Subject: [PATCH 132/182] XXX: Add boot support for u-boot.ipq image - ---- - arch/arm/Makefile | 2 +- - arch/arm/boot/Makefile | 11 ++++++++++- - 2 files changed, 11 insertions(+), 2 deletions(-) - ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -302,7 +302,7 @@ archprepare: - # Convert bzImage to zImage - bzImage: zImage - --BOOT_TARGETS = zImage Image xipImage bootpImage uImage -+BOOT_TARGETS = zImage Image xipImage bootpImage uImage uImage.ipq Image.gz - INSTALL_TARGETS = zinstall uinstall install - - PHONY += bzImage $(BOOT_TARGETS) $(INSTALL_TARGETS) ---- a/arch/arm/boot/Makefile -+++ b/arch/arm/boot/Makefile -@@ -25,7 +25,7 @@ INITRD_PHYS := $(initrd_phys-y) - - export ZRELADDR INITRD_PHYS PARAMS_PHYS - --targets := Image zImage xipImage bootpImage uImage -+targets := Image zImage xipImage bootpImage uImage uImage.ipq Image.gz - - ifeq ($(CONFIG_XIP_KERNEL),y) - -@@ -80,6 +80,15 @@ $(obj)/uImage: $(obj)/zImage FORCE - $(call if_changed,uimage) - @$(kecho) ' Image $@ is ready' - -+$(obj)/uImage.ipq: $(obj)/Image.gz FORCE -+ @$(check_for_multiple_loadaddr) -+ $(call if_changed,uimage,gzip) -+ @$(kecho) ' Image $@ is ready' -+ -+$(obj)/Image.gz: $(obj)/Image FORCE -+ $(call if_changed,gzip) -+ @$(kecho) ' Image $@ is ready' -+ - $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE - $(Q)$(MAKE) $(build)=$(obj)/bootp $@ - @: diff --git a/target/linux/ipq806x/patches/0133-spi-qup-Remove-chip-select-function.patch b/target/linux/ipq806x/patches/0133-spi-qup-Remove-chip-select-function.patch deleted file mode 100644 index 14ae782b49..0000000000 --- a/target/linux/ipq806x/patches/0133-spi-qup-Remove-chip-select-function.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 9bc674f40f22596ef8c2ff6d7f9e53da0baa57e9 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 12 Jun 2014 14:34:10 -0500 -Subject: [PATCH 133/182] spi: qup: Remove chip select function - -This patch removes the chip select function. Chip select should instead be -supported using GPIOs, defining the DT entry "cs-gpios", and letting the SPI -core assert/deassert the chip select as it sees fit. - -Signed-off-by: Andy Gross ---- - .../devicetree/bindings/spi/qcom,spi-qup.txt | 6 ++++ - drivers/spi/spi-qup.c | 33 ++++---------------- - 2 files changed, 12 insertions(+), 27 deletions(-) - ---- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt -+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt -@@ -23,6 +23,12 @@ Optional properties: - - spi-max-frequency: Specifies maximum SPI clock frequency, - Units - Hz. Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt -+- num-cs: total number of chipselects -+- cs-gpios: should specify GPIOs used for chipselects. -+ The gpios will be referred to as reg = in the SPI child -+ nodes. If unspecified, a single SPI device without a chip -+ select can be used. -+ - - SPI slave nodes must be children of the SPI master node and can contain - properties described in Documentation/devicetree/bindings/spi/spi-bus.txt ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -424,31 +424,6 @@ static int spi_qup_io_config(struct spi_ - return 0; - } - --static void spi_qup_set_cs(struct spi_device *spi, bool enable) --{ -- struct spi_qup *controller = spi_master_get_devdata(spi->master); -- -- u32 iocontol, mask; -- -- iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL); -- -- /* Disable auto CS toggle and use manual */ -- iocontol &= ~SPI_IO_C_MX_CS_MODE; -- iocontol |= SPI_IO_C_FORCE_CS; -- -- iocontol &= ~SPI_IO_C_CS_SELECT_MASK; -- iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select); -- -- mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select; -- -- if (enable) -- iocontol |= mask; -- else -- iocontol &= ~mask; -- -- writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL); --} -- - static int spi_qup_transfer_one(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *xfer) -@@ -571,12 +546,16 @@ static int spi_qup_probe(struct platform - return -ENOMEM; - } - -+ /* use num-cs unless not present or out of range */ -+ if (of_property_read_u16(dev->of_node, "num-cs", -+ &master->num_chipselect) || -+ (master->num_chipselect > SPI_NUM_CHIPSELECTS)) -+ master->num_chipselect = SPI_NUM_CHIPSELECTS; -+ - master->bus_num = pdev->id; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; -- master->num_chipselect = SPI_NUM_CHIPSELECTS; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); - master->max_speed_hz = max_freq; -- master->set_cs = spi_qup_set_cs; - master->transfer_one = spi_qup_transfer_one; - master->dev.of_node = pdev->dev.of_node; - master->auto_runtime_pm = true; diff --git a/target/linux/ipq806x/patches/0134-spi-qup-Fix-order-of-spi_register_master.patch b/target/linux/ipq806x/patches/0134-spi-qup-Fix-order-of-spi_register_master.patch deleted file mode 100644 index 93afe28f15..0000000000 --- a/target/linux/ipq806x/patches/0134-spi-qup-Fix-order-of-spi_register_master.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a7357be131e30fd1fb987b2cb343bc81db487f96 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 12 Jun 2014 14:34:11 -0500 -Subject: [PATCH 134/182] spi: qup: Fix order of spi_register_master - -This patch moves the devm_spi_register_master below the initialization of the -runtime_pm. If done in the wrong order, the spi_register_master fails if any -probed slave devices issue SPI transactions. - -Signed-off-by: Andy Gross -Acked-by: Ivan T. Ivanov ---- - drivers/spi/spi-qup.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -619,16 +619,19 @@ static int spi_qup_probe(struct platform - if (ret) - goto error; - -- ret = devm_spi_register_master(dev, master); -- if (ret) -- goto error; -- - pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); - pm_runtime_use_autosuspend(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); -+ -+ ret = devm_spi_register_master(dev, master); -+ if (ret) -+ goto disable_pm; -+ - return 0; - -+disable_pm: -+ pm_runtime_disable(&pdev->dev); - error: - clk_disable_unprepare(cclk); - clk_disable_unprepare(iclk); diff --git a/target/linux/ipq806x/patches/0135-spi-qup-Add-support-for-v1.1.1.patch b/target/linux/ipq806x/patches/0135-spi-qup-Add-support-for-v1.1.1.patch deleted file mode 100644 index 86cce61322..0000000000 --- a/target/linux/ipq806x/patches/0135-spi-qup-Add-support-for-v1.1.1.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 8b9de04ef3aaa154f30baf1ac703a2d3b474ad4e Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 12 Jun 2014 14:34:12 -0500 -Subject: [PATCH 135/182] spi: qup: Add support for v1.1.1 - -This patch adds support for v1.1.1 of the SPI QUP controller. - -Signed-off-by: Andy Gross ---- - .../devicetree/bindings/spi/qcom,spi-qup.txt | 6 +++- - drivers/spi/spi-qup.c | 36 ++++++++++++-------- - 2 files changed, 27 insertions(+), 15 deletions(-) - ---- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt -+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt -@@ -7,7 +7,11 @@ SPI in master mode supports up to 50MHz, - data path from 4 bits to 32 bits and numerous protocol variants. - - Required properties: --- compatible: Should contain "qcom,spi-qup-v2.1.1" or "qcom,spi-qup-v2.2.1" -+- compatible: Should contain: -+ "qcom,spi-qup-v1.1.1" for 8660, 8960 and 8064. -+ "qcom,spi-qup-v2.1.1" for 8974 and later -+ "qcom,spi-qup-v2.2.1" for 8974 v2 and later. -+ - - reg: Should contain base register location and length - - interrupts: Interrupt number used by this controller - ---- a/drivers/spi/spi-qup.c -+++ b/drivers/spi/spi-qup.c -@@ -142,6 +142,7 @@ struct spi_qup { - int w_size; /* bytes per SPI word */ - int tx_bytes; - int rx_bytes; -+ int qup_v1; - }; - - -@@ -420,7 +421,9 @@ static int spi_qup_io_config(struct spi_ - config |= QUP_CONFIG_SPI_MODE; - writel_relaxed(config, controller->base + QUP_CONFIG); - -- writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK); -+ /* only write to OPERATIONAL_MASK when register is present */ -+ if (!controller->qup_v1) -+ writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK); - return 0; - } - -@@ -486,7 +489,7 @@ static int spi_qup_probe(struct platform - struct resource *res; - struct device *dev; - void __iomem *base; -- u32 data, max_freq, iomode; -+ u32 max_freq, iomode; - int ret, irq, size; - - dev = &pdev->dev; -@@ -529,15 +532,6 @@ static int spi_qup_probe(struct platform - return ret; - } - -- data = readl_relaxed(base + QUP_HW_VERSION); -- -- if (data < QUP_HW_VERSION_2_1_1) { -- clk_disable_unprepare(cclk); -- clk_disable_unprepare(iclk); -- dev_err(dev, "v.%08x is not supported\n", data); -- return -ENXIO; -- } -- - master = spi_alloc_master(dev, sizeof(struct spi_qup)); - if (!master) { - clk_disable_unprepare(cclk); -@@ -570,6 +564,10 @@ static int spi_qup_probe(struct platform - controller->cclk = cclk; - controller->irq = irq; - -+ /* set v1 flag if device is version 1 */ -+ if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1")) -+ controller->qup_v1 = 1; -+ - spin_lock_init(&controller->lock); - init_completion(&controller->done); - -@@ -593,8 +591,8 @@ static int spi_qup_probe(struct platform - size = QUP_IO_M_INPUT_FIFO_SIZE(iomode); - controller->in_fifo_sz = controller->in_blk_sz * (2 << size); - -- dev_info(dev, "v.%08x IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", -- data, controller->in_blk_sz, controller->in_fifo_sz, -+ dev_info(dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", -+ controller->in_blk_sz, controller->in_fifo_sz, - controller->out_blk_sz, controller->out_fifo_sz); - - writel_relaxed(1, base + QUP_SW_RESET); -@@ -607,10 +605,19 @@ static int spi_qup_probe(struct platform - - writel_relaxed(0, base + QUP_OPERATIONAL); - writel_relaxed(0, base + QUP_IO_M_MODES); -- writel_relaxed(0, base + QUP_OPERATIONAL_MASK); -+ -+ if (!controller->qup_v1) -+ writel_relaxed(0, base + QUP_OPERATIONAL_MASK); -+ - writel_relaxed(SPI_ERROR_CLK_UNDER_RUN | SPI_ERROR_CLK_OVER_RUN, - base + SPI_ERROR_FLAGS_EN); - -+ /* if earlier version of the QUP, disable INPUT_OVERRUN */ -+ if (controller->qup_v1) -+ writel_relaxed(QUP_ERROR_OUTPUT_OVER_RUN | -+ QUP_ERROR_INPUT_UNDER_RUN | QUP_ERROR_OUTPUT_UNDER_RUN, -+ base + QUP_ERROR_FLAGS_EN); -+ - writel_relaxed(0, base + SPI_CONFIG); - writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL); - -@@ -732,6 +739,7 @@ static int spi_qup_remove(struct platfor - } - - static struct of_device_id spi_qup_dt_match[] = { -+ { .compatible = "qcom,spi-qup-v1.1.1", }, - { .compatible = "qcom,spi-qup-v2.1.1", }, - { .compatible = "qcom,spi-qup-v2.2.1", }, - { } diff --git a/target/linux/ipq806x/patches/0136-ARM-ipq8064-ap148-Add-i2c-pinctrl-nodes.patch b/target/linux/ipq806x/patches/0136-ARM-ipq8064-ap148-Add-i2c-pinctrl-nodes.patch deleted file mode 100644 index 7e9776e57f..0000000000 --- a/target/linux/ipq806x/patches/0136-ARM-ipq8064-ap148-Add-i2c-pinctrl-nodes.patch +++ /dev/null @@ -1,86 +0,0 @@ -From e93b9480667cbd0e3a4276e8749279693fe239f4 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Wed, 14 May 2014 22:49:03 -0500 -Subject: [PATCH 136/182] ARM: ipq8064-ap148: Add i2c pinctrl nodes - -Signed-off-by: Andy Gross ---- - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 17 +++++++++++++++++ - arch/arm/boot/dts/qcom-ipq8064.dtsi | 27 +++++++++++++++++++++++++++ - 2 files changed, 44 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -14,12 +14,29 @@ - }; - - soc { -+ pinmux@800000 { -+ i2c4_pins: i2c4_pinmux { -+ pins = "gpio12", "gpio13"; -+ function = "gsbi4"; -+ bias-disable; -+ }; -+ }; -+ - gsbi@16300000 { - qcom,mode = ; - status = "ok"; - serial@16340000 { - status = "ok"; - }; -+ -+ i2c4: i2c@16380000 { -+ status = "ok"; -+ -+ clock-frequency = <200000>; -+ -+ pinctrl-0 = <&i2c4_pins>; -+ pinctrl-names = "default"; -+ }; - }; - }; - }; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -137,6 +137,20 @@ - clock-names = "core", "iface"; - status = "disabled"; - }; -+ -+ i2c@124a0000 { -+ compatible = "qcom,i2c-qup-v1.1.1"; -+ reg = <0x124a0000 0x1000>; -+ interrupts = <0 196 0>; -+ -+ clocks = <&gcc GSBI2_QUP_CLK>, <&gcc GSBI2_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ - }; - - gsbi4: gsbi@16300000 { -@@ -158,6 +172,19 @@ - clock-names = "core", "iface"; - status = "disabled"; - }; -+ -+ i2c@16380000 { -+ compatible = "qcom,i2c-qup-v1.1.1"; -+ reg = <0x16380000 0x1000>; -+ interrupts = <0 153 0>; -+ -+ clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; - }; - - qcom,ssbi@500000 { diff --git a/target/linux/ipq806x/patches/0137-ARM-qcom-ipq8064-ap148-Add-SPI-related-bindings.patch b/target/linux/ipq806x/patches/0137-ARM-qcom-ipq8064-ap148-Add-SPI-related-bindings.patch deleted file mode 100644 index f72446eb9e..0000000000 --- a/target/linux/ipq806x/patches/0137-ARM-qcom-ipq8064-ap148-Add-SPI-related-bindings.patch +++ /dev/null @@ -1,124 +0,0 @@ -From b9eaa80146abb09bcc7e6d8b33fca476453c839c Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Wed, 14 May 2014 22:01:16 -0500 -Subject: [PATCH 137/182] ARM: qcom-ipq8064-ap148: Add SPI related bindings - -Signed-off-by: Andy Gross ---- - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 42 ++++++++++++++++++++++++++ - arch/arm/boot/dts/qcom-ipq8064.dtsi | 47 ++++++++++++++++++++++++++++++ - 2 files changed, 89 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -20,6 +20,15 @@ - function = "gsbi4"; - bias-disable; - }; -+ -+ spi_pins: spi_pins { -+ mux { -+ pins = "gpio18", "gpio19", "gpio21"; -+ function = "gsbi5"; -+ drive-strength = <10>; -+ bias-none; -+ }; -+ }; - }; - - gsbi@16300000 { -@@ -38,5 +47,38 @@ - pinctrl-names = "default"; - }; - }; -+ -+ gsbi5: gsbi@1a200000 { -+ qcom,mode = ; -+ status = "ok"; -+ -+ spi4: spi@1a280000 { -+ status = "ok"; -+ spi-max-frequency = <50000000>; -+ -+ pinctrl-0 = <&spi_pins>; -+ pinctrl-names = "default"; -+ -+ cs-gpios = <&qcom_pinmux 20 0>; -+ -+ flash: m25p80@0 { -+ compatible = "s25fl256s1"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ spi-max-frequency = <50000000>; -+ reg = <0>; -+ -+ partition@0 { -+ label = "rootfs"; -+ reg = <0x0 0x1000000>; -+ }; -+ -+ partition@1 { -+ label = "scratch"; -+ reg = <0x1000000 0x1000000>; -+ }; -+ }; -+ }; -+ }; - }; - }; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -187,6 +187,53 @@ - }; - }; - -+ gsbi5: gsbi@1a200000 { -+ compatible = "qcom,gsbi-v1.0.0"; -+ reg = <0x1a200000 0x100>; -+ clocks = <&gcc GSBI5_H_CLK>; -+ clock-names = "iface"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ status = "disabled"; -+ -+ serial@1a240000 { -+ compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm"; -+ reg = <0x1a240000 0x1000>, -+ <0x1a200000 0x1000>; -+ interrupts = <0 154 0x0>; -+ clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ }; -+ -+ i2c@1a280000 { -+ compatible = "qcom,i2c-qup-v1.1.1"; -+ reg = <0x1a280000 0x1000>; -+ interrupts = <0 155 0>; -+ -+ clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ spi@1a280000 { -+ compatible = "qcom,spi-qup-v1.1.1"; -+ reg = <0x1a280000 0x1000>; -+ interrupts = <0 155 0>; -+ -+ clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>; -+ clock-names = "core", "iface"; -+ status = "disabled"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ }; -+ - qcom,ssbi@500000 { - compatible = "qcom,ssbi"; - reg = <0x00500000 0x1000>; diff --git a/target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch b/target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch deleted file mode 100644 index 8aaa766bcb..0000000000 --- a/target/linux/ipq806x/patches/0138-PCI-qcom-Add-support-for-pcie-controllers-on-IPQ8064.patch +++ /dev/null @@ -1,716 +0,0 @@ -From 98567c99b4dcd80fc9e5dd97229ebb9a7f6dab03 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 16 May 2014 11:53:23 -0500 -Subject: [PATCH 138/182] PCI: qcom: Add support for pcie controllers on - IPQ8064 - ---- - arch/arm/mach-qcom/Kconfig | 2 + - drivers/pci/host/Makefile | 1 + - drivers/pci/host/pci-qcom.c | 682 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 685 insertions(+) - create mode 100644 drivers/pci/host/pci-qcom.c - ---- a/arch/arm/mach-qcom/Kconfig -+++ b/arch/arm/mach-qcom/Kconfig -@@ -7,6 +7,8 @@ config ARCH_QCOM - select GENERIC_CLOCKEVENTS - select HAVE_SMP - select PINCTRL -+ select MIGHT_HAVE_PCI -+ select PCI_DOMAINS if PCI - select QCOM_SCM if SMP - help - Support for Qualcomm's devicetree based systems. ---- a/drivers/pci/host/Makefile -+++ b/drivers/pci/host/Makefile -@@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o - obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o - obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o - obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o -+obj-$(CONFIG_ARCH_QCOM) += pci-qcom.o ---- /dev/null -+++ b/drivers/pci/host/pci-qcom.c -@@ -0,0 +1,682 @@ -+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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. -+ */ -+ -+/* -+ * QCOM MSM PCIe controller driver. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Root Complex Port vendor/device IDs */ -+#define PCIE_VENDOR_ID_RCP 0x17cb -+#define PCIE_DEVICE_ID_RCP 0x0101 -+ -+#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b)) -+ -+#define PCIE20_PARF_PCS_DEEMPH 0x34 -+#define PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN1(x) __set(x, 21, 16) -+#define PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) __set(x, 13, 8) -+#define PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) __set(x, 5, 0) -+ -+#define PCIE20_PARF_PCS_SWING 0x38 -+#define PCIE20_PARF_PCS_SWING_TX_SWING_FULL(x) __set(x, 14, 8) -+#define PCIE20_PARF_PCS_SWING_TX_SWING_LOW(x) __set(x, 6, 0) -+ -+#define PCIE20_PARF_PHY_CTRL 0x40 -+#define PCIE20_PARF_PHY_CTRL_PHY_TX0_TERM_OFFST(x) __set(x, 20, 16) -+#define PCIE20_PARF_PHY_CTRL_PHY_LOS_LEVEL(x) __set(x, 12, 8) -+#define PCIE20_PARF_PHY_CTRL_PHY_RTUNE_REQ (1 << 4) -+#define PCIE20_PARF_PHY_CTRL_PHY_TEST_BURNIN (1 << 2) -+#define PCIE20_PARF_PHY_CTRL_PHY_TEST_BYPASS (1 << 1) -+#define PCIE20_PARF_PHY_CTRL_PHY_TEST_PWR_DOWN (1 << 0) -+ -+#define PCIE20_PARF_PHY_REFCLK 0x4C -+#define PCIE20_PARF_CONFIG_BITS 0x50 -+ -+#define PCIE20_ELBI_SYS_CTRL 0x04 -+#define PCIE20_ELBI_SYS_CTRL_LTSSM_EN 0x01 -+ -+#define PCIE20_CAP 0x70 -+#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10) -+ -+#define PCIE20_COMMAND_STATUS 0x04 -+#define PCIE20_BUSNUMBERS 0x18 -+#define PCIE20_MEMORY_BASE_LIMIT 0x20 -+ -+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818 -+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c -+#define PCIE20_PLR_IATU_VIEWPORT 0x900 -+#define PCIE20_PLR_IATU_CTRL1 0x904 -+#define PCIE20_PLR_IATU_CTRL2 0x908 -+#define PCIE20_PLR_IATU_LBAR 0x90C -+#define PCIE20_PLR_IATU_UBAR 0x910 -+#define PCIE20_PLR_IATU_LAR 0x914 -+#define PCIE20_PLR_IATU_LTAR 0x918 -+#define PCIE20_PLR_IATU_UTAR 0x91c -+ -+#define MSM_PCIE_DEV_CFG_ADDR 0x01000000 -+ -+#define RD 0 -+#define WR 1 -+ -+#define MAX_RC_NUM 3 -+#define PCIE_BUS_PRIV_DATA(pdev) \ -+ (((struct pci_sys_data *)pdev->bus->sysdata)->private_data) -+ -+/* PCIe TLP types that we are interested in */ -+#define PCI_CFG0_RDWR 0x4 -+#define PCI_CFG1_RDWR 0x5 -+ -+#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \ -+({ \ -+ unsigned long timeout = jiffies + usecs_to_jiffies(timeout_us); \ -+ might_sleep_if(timeout_us); \ -+ for (;;) { \ -+ (val) = readl(addr); \ -+ if (cond) \ -+ break; \ -+ if (timeout_us && time_after(jiffies, timeout)) { \ -+ (val) = readl(addr); \ -+ break; \ -+ } \ -+ if (sleep_us) \ -+ usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us); \ -+ } \ -+ (cond) ? 0 : -ETIMEDOUT; \ -+}) -+ -+struct qcom_pcie { -+ void __iomem *elbi_base; -+ void __iomem *parf_base; -+ void __iomem *dwc_base; -+ void __iomem *cfg_base; -+ int reset_gpio; -+ struct clk *iface_clk; -+ struct clk *bus_clk; -+ struct clk *phy_clk; -+ int irq_int[4]; -+ struct reset_control *axi_reset; -+ struct reset_control *ahb_reset; -+ struct reset_control *por_reset; -+ struct reset_control *pci_reset; -+ struct reset_control *phy_reset; -+ -+ struct resource conf; -+ struct resource io; -+ struct resource mem; -+}; -+ -+static int qcom_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); -+static int qcom_pcie_setup(int nr, struct pci_sys_data *sys); -+static int msm_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, -+ int size, u32 *val); -+static int msm_pcie_wr_conf(struct pci_bus *bus, u32 devfn, -+ int where, int size, u32 val); -+ -+static struct pci_ops qcom_pcie_ops = { -+ .read = msm_pcie_rd_conf, -+ .write = msm_pcie_wr_conf, -+}; -+ -+static struct hw_pci qcom_hw_pci[MAX_RC_NUM] = { -+ { -+#ifdef CONFIG_PCI_DOMAINS -+ .domain = 0, -+#endif -+ .ops = &qcom_pcie_ops, -+ .nr_controllers = 1, -+ .swizzle = pci_common_swizzle, -+ .setup = qcom_pcie_setup, -+ .map_irq = qcom_pcie_map_irq, -+ }, -+ { -+#ifdef CONFIG_PCI_DOMAINS -+ .domain = 1, -+#endif -+ .ops = &qcom_pcie_ops, -+ .nr_controllers = 1, -+ .swizzle = pci_common_swizzle, -+ .setup = qcom_pcie_setup, -+ .map_irq = qcom_pcie_map_irq, -+ }, -+ { -+#ifdef CONFIG_PCI_DOMAINS -+ .domain = 2, -+#endif -+ .ops = &qcom_pcie_ops, -+ .nr_controllers = 1, -+ .swizzle = pci_common_swizzle, -+ .setup = qcom_pcie_setup, -+ .map_irq = qcom_pcie_map_irq, -+ }, -+}; -+ -+static int nr_controllers; -+static DEFINE_SPINLOCK(qcom_hw_pci_lock); -+ -+static inline struct qcom_pcie *sys_to_pcie(struct pci_sys_data *sys) -+{ -+ return sys->private_data; -+} -+ -+inline int is_msm_pcie_rc(struct pci_bus *bus) -+{ -+ return (bus->number == 0); -+} -+ -+static int qcom_pcie_is_link_up(struct qcom_pcie *dev) -+{ -+ return readl_relaxed(dev->dwc_base + PCIE20_CAP_LINKCTRLSTATUS) & BIT(29); -+} -+ -+inline int msm_pcie_get_cfgtype(struct pci_bus *bus) -+{ -+ /* -+ * http://www.tldp.org/LDP/tlk/dd/pci.html -+ * Pass it onto the secondary bus interface unchanged if the -+ * bus number specified is greater than the secondary bus -+ * number and less than or equal to the subordinate bus -+ * number. -+ * -+ * Read/Write to the RC and Device/Switch connected to the RC -+ * are CFG0 type transactions. Rest have to be forwarded -+ * down stream as CFG1 transactions. -+ * -+ */ -+ if (bus->number == 0) -+ return PCI_CFG0_RDWR; -+ -+ return PCI_CFG0_RDWR; -+} -+ -+void msm_pcie_config_cfgtype(struct pci_bus *bus, u32 devfn) -+{ -+ uint32_t bdf, cfgtype; -+ struct qcom_pcie *dev = sys_to_pcie(bus->sysdata); -+ -+ cfgtype = msm_pcie_get_cfgtype(bus); -+ -+ if (cfgtype == PCI_CFG0_RDWR) { -+ bdf = MSM_PCIE_DEV_CFG_ADDR; -+ } else { -+ /* -+ * iATU Lower Target Address Register -+ * Bits Description -+ * *-1:0 Forms bits [*:0] of the -+ * start address of the new -+ * address of the translated -+ * region. The start address -+ * must be aligned to a -+ * CX_ATU_MIN_REGION_SIZE kB -+ * boundary, so these bits are -+ * always 0. A write to this -+ * location is ignored by the -+ * PCIe core. -+ * 31:*1 Forms bits [31:*] of the of -+ * the new address of the -+ * translated region. -+ * -+ * * is log2(CX_ATU_MIN_REGION_SIZE) -+ */ -+ bdf = (((bus->number & 0xff) << 24) & 0xff000000) | -+ (((devfn & 0xff) << 16) & 0x00ff0000); -+ } -+ -+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_VIEWPORT); -+ wmb(); -+ -+ /* Program Bdf Address */ -+ writel_relaxed(bdf, dev->dwc_base + PCIE20_PLR_IATU_LTAR); -+ wmb(); -+ -+ /* Write Config Request Type */ -+ writel_relaxed(cfgtype, dev->dwc_base + PCIE20_PLR_IATU_CTRL1); -+ wmb(); -+} -+ -+static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper, -+ int where, int size, u32 *val) -+{ -+ uint32_t word_offset, byte_offset, mask; -+ uint32_t rd_val, wr_val; -+ struct qcom_pcie *dev = sys_to_pcie(bus->sysdata); -+ void __iomem *config_base; -+ int rc; -+ -+ rc = is_msm_pcie_rc(bus); -+ -+ /* -+ * For downstream bus, make sure link is up -+ */ -+ if (rc && (devfn != 0)) { -+ *val = ~0; -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ } else if ((!rc) && (!qcom_pcie_is_link_up(dev))) { -+ *val = ~0; -+ return PCIBIOS_DEVICE_NOT_FOUND; -+ } -+ -+ msm_pcie_config_cfgtype(bus, devfn); -+ -+ word_offset = where & ~0x3; -+ byte_offset = where & 0x3; -+ mask = (~0 >> (8 * (4 - size))) << (8 * byte_offset); -+ -+ config_base = (rc) ? dev->dwc_base : dev->cfg_base; -+ rd_val = readl_relaxed(config_base + word_offset); -+ -+ if (oper == RD) { -+ *val = ((rd_val & mask) >> (8 * byte_offset)); -+ } else { -+ wr_val = (rd_val & ~mask) | -+ ((*val << (8 * byte_offset)) & mask); -+ writel_relaxed(wr_val, config_base + word_offset); -+ wmb(); /* ensure config data is written to hardware register */ -+ } -+ -+ return 0; -+} -+ -+static int msm_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, -+ int size, u32 *val) -+{ -+ return msm_pcie_oper_conf(bus, devfn, RD, where, size, val); -+} -+ -+static int msm_pcie_wr_conf(struct pci_bus *bus, u32 devfn, -+ int where, int size, u32 val) -+{ -+ /* -+ *Attempt to reset secondary bus is causing PCIE core to reset. -+ *Disable secondary bus reset functionality. -+ */ -+ if ((bus->number == 0) && (where == PCI_BRIDGE_CONTROL) && -+ (val & PCI_BRIDGE_CTL_BUS_RESET)) { -+ pr_info("PCIE secondary bus reset not supported\n"); -+ val &= ~PCI_BRIDGE_CTL_BUS_RESET; -+ } -+ -+ return msm_pcie_oper_conf(bus, devfn, WR, where, size, &val); -+} -+ -+static int qcom_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ struct qcom_pcie *pcie_dev = PCIE_BUS_PRIV_DATA(dev); -+ -+ return pcie_dev->irq_int[pin-1]; -+} -+ -+static int qcom_pcie_setup(int nr, struct pci_sys_data *sys) -+{ -+ struct qcom_pcie *qcom_pcie = sys->private_data; -+ -+ /* -+ * specify linux PCI framework to allocate device memory (BARs) -+ * from msm_pcie_dev.dev_mem_res resource. -+ */ -+ sys->mem_offset = 0; -+ sys->io_offset = 0; -+ -+ pci_add_resource(&sys->resources, &qcom_pcie->mem); -+ pci_add_resource(&sys->resources, &qcom_pcie->io); -+ -+ return 1; -+} -+ -+static inline void qcom_elbi_writel_relaxed(struct qcom_pcie *pcie, u32 val, u32 reg) -+{ -+ writel_relaxed(val, pcie->elbi_base + reg); -+} -+ -+static inline u32 qcom_elbi_readl_relaxed(struct qcom_pcie *pcie, u32 reg) -+{ -+ return readl_relaxed(pcie->elbi_base + reg); -+} -+ -+static inline void qcom_parf_writel_relaxed(struct qcom_pcie *pcie, u32 val, u32 reg) -+{ -+ writel_relaxed(val, pcie->parf_base + reg); -+} -+ -+static inline u32 qcom_parf_readl_relaxed(struct qcom_pcie *pcie, u32 reg) -+{ -+ return readl_relaxed(pcie->parf_base + reg); -+} -+ -+static void msm_pcie_write_mask(void __iomem *addr, -+ uint32_t clear_mask, uint32_t set_mask) -+{ -+ uint32_t val; -+ -+ val = (readl_relaxed(addr) & ~clear_mask) | set_mask; -+ writel_relaxed(val, addr); -+ wmb(); /* ensure data is written to hardware register */ -+} -+ -+static void qcom_pcie_config_controller(struct qcom_pcie *dev) -+{ -+ /* -+ * program and enable address translation region 0 (device config -+ * address space); region type config; -+ * axi config address range to device config address range -+ */ -+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_VIEWPORT); -+ /* ensure that hardware locks the region before programming it */ -+ wmb(); -+ -+ writel_relaxed(4, dev->dwc_base + PCIE20_PLR_IATU_CTRL1); -+ writel_relaxed(BIT(31), dev->dwc_base + PCIE20_PLR_IATU_CTRL2); -+ writel_relaxed(dev->conf.start, dev->dwc_base + PCIE20_PLR_IATU_LBAR); -+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UBAR); -+ writel_relaxed(dev->conf.end, dev->dwc_base + PCIE20_PLR_IATU_LAR); -+ writel_relaxed(MSM_PCIE_DEV_CFG_ADDR, -+ dev->dwc_base + PCIE20_PLR_IATU_LTAR); -+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UTAR); -+ /* ensure that hardware registers the configuration */ -+ wmb(); -+ -+ /* -+ * program and enable address translation region 2 (device resource -+ * address space); region type memory; -+ * axi device bar address range to device bar address range -+ */ -+ writel_relaxed(2, dev->dwc_base + PCIE20_PLR_IATU_VIEWPORT); -+ /* ensure that hardware locks the region before programming it */ -+ wmb(); -+ -+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_CTRL1); -+ writel_relaxed(BIT(31), dev->dwc_base + PCIE20_PLR_IATU_CTRL2); -+ writel_relaxed(dev->mem.start, dev->dwc_base + PCIE20_PLR_IATU_LBAR); -+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UBAR); -+ writel_relaxed(dev->mem.end, dev->dwc_base + PCIE20_PLR_IATU_LAR); -+ writel_relaxed(dev->mem.start, -+ dev->dwc_base + PCIE20_PLR_IATU_LTAR); -+ writel_relaxed(0, dev->dwc_base + PCIE20_PLR_IATU_UTAR); -+ /* ensure that hardware registers the configuration */ -+ wmb(); -+ -+ /* 1K PCIE buffer setting */ -+ writel_relaxed(0x3, dev->dwc_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); -+ writel_relaxed(0x1, dev->dwc_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); -+ /* ensure that hardware registers the configuration */ -+ wmb(); -+} -+ -+static int qcom_pcie_probe(struct platform_device *pdev) -+{ -+ unsigned long flags; -+ struct qcom_pcie *qcom_pcie; -+ struct device_node *np = pdev->dev.of_node; -+ struct resource *elbi_base, *parf_base, *dwc_base; -+ struct hw_pci *hw; -+ struct of_pci_range range; -+ struct of_pci_range_parser parser; -+ int ret, i; -+ u32 val; -+ -+ qcom_pcie = devm_kzalloc(&pdev->dev, sizeof(*qcom_pcie), GFP_KERNEL); -+ if (!qcom_pcie) { -+ dev_err(&pdev->dev, "no memory for qcom_pcie\n"); -+ return -ENOMEM; -+ } -+ -+ elbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); -+ qcom_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, elbi_base); -+ if (IS_ERR(qcom_pcie->elbi_base)) { -+ dev_err(&pdev->dev, "Failed to ioremap elbi space\n"); -+ return PTR_ERR(qcom_pcie->elbi_base); -+ } -+ -+ parf_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); -+ qcom_pcie->parf_base = devm_ioremap_resource(&pdev->dev, parf_base); -+ if (IS_ERR(qcom_pcie->parf_base)) { -+ dev_err(&pdev->dev, "Failed to ioremap parf space\n"); -+ return PTR_ERR(qcom_pcie->parf_base); -+ } -+ -+ dwc_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base"); -+ qcom_pcie->dwc_base = devm_ioremap_resource(&pdev->dev, dwc_base); -+ if (IS_ERR(qcom_pcie->dwc_base)) { -+ dev_err(&pdev->dev, "Failed to ioremap dwc_base space\n"); -+ return PTR_ERR(qcom_pcie->dwc_base); -+ } -+ -+ if (of_pci_range_parser_init(&parser, np)) { -+ dev_err(&pdev->dev, "missing ranges property\n"); -+ return -EINVAL; -+ } -+ -+ /* Get the I/O and memory ranges from DT */ -+ for_each_of_pci_range(&parser, &range) { -+ switch (range.pci_space & 0x3) { -+ case 0: /* cfg */ -+ of_pci_range_to_resource(&range, np, &qcom_pcie->conf); -+ qcom_pcie->conf.flags = IORESOURCE_MEM; -+ break; -+ case 1: /* io */ -+ of_pci_range_to_resource(&range, np, &qcom_pcie->io); -+ break; -+ default: /* mem */ -+ of_pci_range_to_resource(&range, np, &qcom_pcie->mem); -+ break; -+ } -+ } -+ -+ qcom_pcie->cfg_base = devm_ioremap_resource(&pdev->dev, &qcom_pcie->conf); -+ if (IS_ERR(qcom_pcie->cfg_base)) { -+ dev_err(&pdev->dev, "Failed to ioremap PCIe cfg space\n"); -+ return PTR_ERR(qcom_pcie->cfg_base); -+ } -+ -+ qcom_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); -+ if (!gpio_is_valid(qcom_pcie->reset_gpio)) { -+ dev_err(&pdev->dev, "pcie reset gpio is not valid\n"); -+ return -EINVAL; -+ } -+ -+ ret = devm_gpio_request_one(&pdev->dev, qcom_pcie->reset_gpio, -+ GPIOF_DIR_OUT, "pcie_reset"); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to request pcie reset gpio\n"); -+ return ret; -+ } -+ -+ qcom_pcie->iface_clk = devm_clk_get(&pdev->dev, "iface"); -+ if (IS_ERR(qcom_pcie->iface_clk)) { -+ dev_err(&pdev->dev, "Failed to get pcie iface clock\n"); -+ return PTR_ERR(qcom_pcie->iface_clk); -+ } -+ -+ qcom_pcie->phy_clk = devm_clk_get(&pdev->dev, "phy"); -+ if (IS_ERR(qcom_pcie->phy_clk)) { -+ dev_err(&pdev->dev, "Failed to get pcie phy clock\n"); -+ return PTR_ERR(qcom_pcie->phy_clk); -+ } -+ -+ qcom_pcie->bus_clk = devm_clk_get(&pdev->dev, "core"); -+ if (IS_ERR(qcom_pcie->bus_clk)) { -+ dev_err(&pdev->dev, "Failed to get pcie core clock\n"); -+ return PTR_ERR(qcom_pcie->bus_clk); -+ } -+ -+ qcom_pcie->axi_reset = devm_reset_control_get(&pdev->dev, "axi"); -+ if (IS_ERR(qcom_pcie->axi_reset)) { -+ dev_err(&pdev->dev, "Failed to get axi reset\n"); -+ return PTR_ERR(qcom_pcie->axi_reset); -+ } -+ -+ qcom_pcie->ahb_reset = devm_reset_control_get(&pdev->dev, "ahb"); -+ if (IS_ERR(qcom_pcie->ahb_reset)) { -+ dev_err(&pdev->dev, "Failed to get ahb reset\n"); -+ return PTR_ERR(qcom_pcie->ahb_reset); -+ } -+ -+ qcom_pcie->por_reset = devm_reset_control_get(&pdev->dev, "por"); -+ if (IS_ERR(qcom_pcie->por_reset)) { -+ dev_err(&pdev->dev, "Failed to get por reset\n"); -+ return PTR_ERR(qcom_pcie->por_reset); -+ } -+ -+ qcom_pcie->pci_reset = devm_reset_control_get(&pdev->dev, "pci"); -+ if (IS_ERR(qcom_pcie->pci_reset)) { -+ dev_err(&pdev->dev, "Failed to get pci reset\n"); -+ return PTR_ERR(qcom_pcie->pci_reset); -+ } -+ -+ qcom_pcie->phy_reset = devm_reset_control_get(&pdev->dev, "phy"); -+ if (IS_ERR(qcom_pcie->phy_reset)) { -+ dev_err(&pdev->dev, "Failed to get phy reset\n"); -+ return PTR_ERR(qcom_pcie->phy_reset); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ qcom_pcie->irq_int[i] = platform_get_irq(pdev, i+1); -+ if (qcom_pcie->irq_int[i] < 0) { -+ dev_err(&pdev->dev, "failed to get irq resource\n"); -+ return qcom_pcie->irq_int[i]; -+ } -+ } -+ -+ gpio_set_value(qcom_pcie->reset_gpio, 0); -+ usleep_range(10000, 15000); -+ -+ /* assert PCIe PARF reset while powering the core */ -+ reset_control_assert(qcom_pcie->ahb_reset); -+ -+ /* enable clocks */ -+ ret = clk_prepare_enable(qcom_pcie->iface_clk); -+ if (ret) -+ return ret; -+ ret = clk_prepare_enable(qcom_pcie->phy_clk); -+ if (ret) -+ return ret; -+ ret = clk_prepare_enable(qcom_pcie->bus_clk); -+ if (ret) -+ return ret; -+ -+ /* -+ * de-assert PCIe PARF reset; -+ * wait 1us before accessing PARF registers -+ */ -+ reset_control_deassert(qcom_pcie->ahb_reset); -+ udelay(1); -+ -+ /* enable PCIe clocks and resets */ -+ msm_pcie_write_mask(qcom_pcie->parf_base + PCIE20_PARF_PHY_CTRL, BIT(0), 0); -+ -+ /* Set Tx Termination Offset */ -+ val = qcom_parf_readl_relaxed(qcom_pcie, PCIE20_PARF_PHY_CTRL); -+ val |= PCIE20_PARF_PHY_CTRL_PHY_TX0_TERM_OFFST(7); -+ qcom_parf_writel_relaxed(qcom_pcie, val, PCIE20_PARF_PHY_CTRL); -+ -+ /* PARF programming */ -+ qcom_parf_writel_relaxed(qcom_pcie, PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) | -+ PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) | -+ PCIE20_PARF_PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22), -+ PCIE20_PARF_PCS_DEEMPH); -+ qcom_parf_writel_relaxed(qcom_pcie, PCIE20_PARF_PCS_SWING_TX_SWING_FULL(0x78) | -+ PCIE20_PARF_PCS_SWING_TX_SWING_LOW(0x78), -+ PCIE20_PARF_PCS_SWING); -+ qcom_parf_writel_relaxed(qcom_pcie, (4<<24), PCIE20_PARF_CONFIG_BITS); -+ /* ensure that hardware registers the PARF configuration */ -+ wmb(); -+ -+ /* enable reference clock */ -+ msm_pcie_write_mask(qcom_pcie->parf_base + PCIE20_PARF_PHY_REFCLK, BIT(12), BIT(16)); -+ -+ /* ensure that access is enabled before proceeding */ -+ wmb(); -+ -+ /* de-assert PICe PHY, Core, POR and AXI clk domain resets */ -+ reset_control_deassert(qcom_pcie->phy_reset); -+ reset_control_deassert(qcom_pcie->pci_reset); -+ reset_control_deassert(qcom_pcie->por_reset); -+ reset_control_deassert(qcom_pcie->axi_reset); -+ -+ /* wait 150ms for clock acquisition */ -+ usleep_range(10000, 15000); -+ -+ /* de-assert PCIe reset link to bring EP out of reset */ -+ gpio_set_value(qcom_pcie->reset_gpio, 1 - 0); -+ usleep_range(10000, 15000); -+ -+ /* enable link training */ -+ val = qcom_elbi_readl_relaxed(qcom_pcie, PCIE20_ELBI_SYS_CTRL); -+ val |= PCIE20_ELBI_SYS_CTRL_LTSSM_EN; -+ qcom_elbi_writel_relaxed(qcom_pcie, val, PCIE20_ELBI_SYS_CTRL); -+ wmb(); -+ -+ /* poll for link to come up for upto 100ms */ -+ ret = readl_poll_timeout( -+ (qcom_pcie->dwc_base + PCIE20_CAP_LINKCTRLSTATUS), -+ val, (val & BIT(29)), 10000, 100000); -+ -+ printk("link initialized %d\n", ret); -+ -+ qcom_pcie_config_controller(qcom_pcie); -+ -+ platform_set_drvdata(pdev, qcom_pcie); -+ -+ spin_lock_irqsave(&qcom_hw_pci_lock, flags); -+ qcom_hw_pci[nr_controllers].private_data = (void **)&qcom_pcie; -+ hw = &qcom_hw_pci[nr_controllers]; -+ nr_controllers++; -+ spin_unlock_irqrestore(&qcom_hw_pci_lock, flags); -+ -+ pci_common_init(hw); -+ -+ return 0; -+} -+ -+static int __exit qcom_pcie_remove(struct platform_device *pdev) -+{ -+ struct qcom_pcie *qcom_pcie = platform_get_drvdata(pdev); -+ -+ return 0; -+} -+ -+static struct of_device_id qcom_pcie_match[] = { -+ { .compatible = "qcom,pcie-ipq8064", }, -+ {} -+}; -+ -+static struct platform_driver qcom_pcie_driver = { -+ .probe = qcom_pcie_probe, -+ .remove = qcom_pcie_remove, -+ .driver = { -+ .name = "qcom_pcie", -+ .owner = THIS_MODULE, -+ .of_match_table = qcom_pcie_match, -+ }, -+}; -+ -+static int qcom_pcie_init(void) -+{ -+ return platform_driver_register(&qcom_pcie_driver); -+} -+subsys_initcall(qcom_pcie_init); -+ -+/* RC do not represent the right class; set it to PCI_CLASS_BRIDGE_PCI */ -+static void msm_pcie_fixup_early(struct pci_dev *dev) -+{ -+ if (dev->hdr_type == 1) -+ dev->class = (dev->class & 0xff) | (PCI_CLASS_BRIDGE_PCI << 8); -+} -+DECLARE_PCI_FIXUP_EARLY(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP, msm_pcie_fixup_early); diff --git a/target/linux/ipq806x/patches/0139-ARM-dts-msm-Add-PCIe-related-nodes-for-IPQ8064-AP148.patch b/target/linux/ipq806x/patches/0139-ARM-dts-msm-Add-PCIe-related-nodes-for-IPQ8064-AP148.patch deleted file mode 100644 index 1fd205256d..0000000000 --- a/target/linux/ipq806x/patches/0139-ARM-dts-msm-Add-PCIe-related-nodes-for-IPQ8064-AP148.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 7c6525a0d5cf88f9244187fbe8ee293fa4ee43c1 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Mon, 12 May 2014 19:36:23 -0500 -Subject: [PATCH 139/182] ARM: dts: msm: Add PCIe related nodes for - IPQ8064/AP148 - ---- - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 38 ++++++++++++ - arch/arm/boot/dts/qcom-ipq8064.dtsi | 93 ++++++++++++++++++++++++++++++ - 2 files changed, 131 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -21,6 +21,22 @@ - bias-disable; - }; - -+ pcie1_pins: pcie1_pinmux { -+ mux { -+ pins = "gpio3"; -+ drive-strength = <2>; -+ bias-disable; -+ }; -+ }; -+ -+ pcie2_pins: pcie2_pinmux { -+ mux { -+ pins = "gpio48"; -+ drive-strength = <2>; -+ bias-disable; -+ }; -+ }; -+ - spi_pins: spi_pins { - mux { - pins = "gpio18", "gpio19", "gpio21"; -@@ -80,5 +96,27 @@ - }; - }; - }; -+ -+ pci@1b500000 { -+ status = "ok"; -+ reset-gpio = <&qcom_pinmux 3 0>; -+ pinctrl-0 = <&pcie1_pins>; -+ pinctrl-names = "default"; -+ -+ ranges = <0x00000000 0 0x00000000 0x0ff00000 0 0x00100000 /* configuration space */ -+ 0x81000000 0 0 0x0fe00000 0 0x00100000 /* downstream I/O */ -+ 0x82000000 0 0x00000000 0x08000000 0 0x07e00000>; /* non-prefetchable memory */ -+ }; -+ -+ pci@1b700000 { -+ status = "ok"; -+ reset-gpio = <&qcom_pinmux 48 0>; -+ pinctrl-0 = <&pcie2_pins>; -+ pinctrl-names = "default"; -+ -+ ranges = <0x00000000 0 0x00000000 0x31f00000 0 0x00100000 /* configuration space */ -+ 0x81000000 0 0 0x31e00000 0 0x00100000 /* downstream I/O */ -+ 0x82000000 0 0x00000000 0x2e000000 0 0x03e00000>; /* non-prefetchable memory */ -+ }; - }; - }; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -2,6 +2,7 @@ - - #include "skeleton.dtsi" - #include -+#include - #include - - / { -@@ -246,5 +247,97 @@ - #clock-cells = <1>; - #reset-cells = <1>; - }; -+ -+ pci@1b500000 { -+ compatible = "qcom,pcie-ipq8064"; -+ reg = <0x1b500000 0x1000 -+ 0x1b502000 0x80 -+ 0x1b600000 0x100 -+ >; -+ reg-names = "base", "elbi", "parf"; -+ -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ interrupts = <0 35 0x0 -+ 0 36 0x0 -+ 0 37 0x0 -+ 0 38 0x0 -+ 0 39 0x0>; -+ resets = <&gcc PCIE_ACLK_RESET>, -+ <&gcc PCIE_HCLK_RESET>, -+ <&gcc PCIE_POR_RESET>, -+ <&gcc PCIE_PCI_RESET>, -+ <&gcc PCIE_PHY_RESET>; -+ reset-names = "axi", "ahb", "por", "pci", "phy"; -+ -+ clocks = <&gcc PCIE_A_CLK>, -+ <&gcc PCIE_H_CLK>, -+ <&gcc PCIE_PHY_CLK>; -+ clock-names = "core", "iface", "phy"; -+ status = "disabled"; -+ }; -+ -+ pci@1b700000 { -+ compatible = "qcom,pcie-ipq8064"; -+ reg = <0x1b700000 0x1000 -+ 0x1b702000 0x80 -+ 0x1b800000 0x100 -+ >; -+ reg-names = "base", "elbi", "parf"; -+ -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ -+ interrupts = <0 57 0x0 -+ 0 58 0x0 -+ 0 59 0x0 -+ 0 60 0x0 -+ 0 61 0x0>; -+ resets = <&gcc PCIE_1_ACLK_RESET>, -+ <&gcc PCIE_1_HCLK_RESET>, -+ <&gcc PCIE_1_POR_RESET>, -+ <&gcc PCIE_1_PCI_RESET>, -+ <&gcc PCIE_1_PHY_RESET>; -+ reset-names = "axi", "ahb", "por", "pci", "phy"; -+ -+ clocks = <&gcc PCIE_1_A_CLK>, -+ <&gcc PCIE_1_H_CLK>, -+ <&gcc PCIE_1_PHY_CLK>; -+ clock-names = "core", "iface", "phy"; -+ status = "disabled"; -+ }; -+ -+ pci@1b900000 { -+ compatible = "qcom,pcie-ipq8064"; -+ reg = <0x1b900000 0x1000 -+ 0x1b902000 0x80 -+ 0x1ba00000 0x100 -+ >; -+ reg-names = "base", "elbi", "parf"; -+ -+ #address-cells = <3>; -+ #size-cells = <2>; -+ device_type = "pci"; -+ -+ interrupts = <0 71 0x0 -+ 0 72 0x0 -+ 0 73 0x0 -+ 0 74 0x0 -+ 0 75 0x0>; -+ resets = <&gcc PCIE_2_ACLK_RESET>, -+ <&gcc PCIE_2_HCLK_RESET>, -+ <&gcc PCIE_2_POR_RESET>, -+ <&gcc PCIE_2_PCI_RESET>, -+ <&gcc PCIE_2_PHY_RESET>; -+ reset-names = "axi", "ahb", "por", "pci", "phy"; -+ -+ clocks = <&gcc PCIE_2_A_CLK>, -+ <&gcc PCIE_2_H_CLK>, -+ <&gcc PCIE_2_PHY_CLK>; -+ clock-names = "core", "iface", "phy"; -+ status = "disabled"; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0140-ARM-qcom-config-Enable-PCI-support-for-IPQ806x.patch b/target/linux/ipq806x/patches/0140-ARM-qcom-config-Enable-PCI-support-for-IPQ806x.patch deleted file mode 100644 index 14a5db48ba..0000000000 --- a/target/linux/ipq806x/patches/0140-ARM-qcom-config-Enable-PCI-support-for-IPQ806x.patch +++ /dev/null @@ -1,28 +0,0 @@ -From a7e90802be401083098511e72866a0f824c10e15 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 16 May 2014 16:54:48 -0500 -Subject: [PATCH 140/182] ARM: qcom: config: Enable PCI support for IPQ806x - ---- - arch/arm/configs/qcom_defconfig | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -21,6 +21,8 @@ CONFIG_ARCH_QCOM=y - CONFIG_ARCH_MSM8X60=y - CONFIG_ARCH_MSM8960=y - CONFIG_ARCH_MSM8974=y -+CONFIG_PCI=y -+CONFIG_PCI_MSI=y - CONFIG_SMP=y - CONFIG_PREEMPT=y - CONFIG_AEABI=y -@@ -83,6 +85,7 @@ CONFIG_INPUT_MISC=y - CONFIG_INPUT_UINPUT=y - CONFIG_SERIO_LIBPS2=y - # CONFIG_LEGACY_PTYS is not set -+CONFIG_SERIAL_8250=y - CONFIG_SERIAL_MSM=y - CONFIG_SERIAL_MSM_CONSOLE=y - CONFIG_HW_RANDOM=y diff --git a/target/linux/ipq806x/patches/0141-ahci-platform-Bump-max-number-of-clocks-to-5.patch b/target/linux/ipq806x/patches/0141-ahci-platform-Bump-max-number-of-clocks-to-5.patch deleted file mode 100644 index 2f5adcaf41..0000000000 --- a/target/linux/ipq806x/patches/0141-ahci-platform-Bump-max-number-of-clocks-to-5.patch +++ /dev/null @@ -1,23 +0,0 @@ -From fd475809eefc0870515d0b04815e2bbae67be906 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 6 Jun 2014 12:09:01 -0500 -Subject: [PATCH 141/182] ahci-platform: Bump max number of clocks to 5 - -Qualcomm IPQ806x SoCs with SATA controllers need 5 clocks to be enabled. - -Signed-off-by: Kumar Gala ---- - drivers/ata/ahci.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/ata/ahci.h -+++ b/drivers/ata/ahci.h -@@ -53,7 +53,7 @@ - - enum { - AHCI_MAX_PORTS = 32, -- AHCI_MAX_CLKS = 3, -+ AHCI_MAX_CLKS = 5, - AHCI_MAX_SG = 168, /* hardware max is 64K */ - AHCI_DMA_BOUNDARY = 0xffffffff, - AHCI_MAX_CMDS = 32, diff --git a/target/linux/ipq806x/patches/0142-ata-Add-Qualcomm-ARM-SoC-AHCI-SATA-host-controller-d.patch b/target/linux/ipq806x/patches/0142-ata-Add-Qualcomm-ARM-SoC-AHCI-SATA-host-controller-d.patch deleted file mode 100644 index 5db5d9d69b..0000000000 --- a/target/linux/ipq806x/patches/0142-ata-Add-Qualcomm-ARM-SoC-AHCI-SATA-host-controller-d.patch +++ /dev/null @@ -1,136 +0,0 @@ -From c5ea64dcf7b5d45e402e78b9f291d521669b7b80 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Fri, 30 May 2014 15:35:40 -0500 -Subject: [PATCH 142/182] ata: Add Qualcomm ARM SoC AHCI SATA host controller - driver - -Add support for the Qualcomm AHCI SATA controller that exists on several -SoC and specifically the IPQ806x family of chips. The IPQ806x SATA support -requires the associated IPQ806x SATA PHY Driver to be enabled as well. - -Signed-off-by: Kumar Gala ---- - drivers/ata/Kconfig | 10 ++++++ - drivers/ata/Makefile | 1 + - drivers/ata/ahci_qcom.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 97 insertions(+) - create mode 100644 drivers/ata/ahci_qcom.c - ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -122,6 +122,16 @@ config AHCI_IMX - - If unsure, say N. - -+config AHCI_QCOM -+ tristate "Qualcomm AHCI SATA support" -+ depends on ARCH_QCOM -+ help -+ This option enables support for AHCI SATA controller -+ integrated into Qualcomm ARM SoC chipsets. For more -+ information please refer to http://www.qualcomm.com/chipsets. -+ -+ If unsure, say N. -+ - config SATA_FSL - tristate "Freescale 3.0Gbps SATA support" - depends on FSL_SOC ---- a/drivers/ata/Makefile -+++ b/drivers/ata/Makefile -@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o - obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o - obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o - obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o -+obj-$(CONFIG_AHCI_QCOM) += ahci_qcom.o libahci.o libahci_platform.o - - # SFF w/ custom DMA - obj-$(CONFIG_PDC_ADMA) += pdc_adma.o ---- /dev/null -+++ b/drivers/ata/ahci_qcom.c -@@ -0,0 +1,86 @@ -+/* -+ * Qualcomm ARM SoC AHCI SATA platform driver -+ * -+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov -+ * -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include "ahci.h" -+ -+static const struct ata_port_info qcom_ahci_port_info = { -+ .flags = AHCI_FLAG_COMMON, -+ .pio_mask = ATA_PIO4, -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &ahci_platform_ops, -+}; -+ -+static int qcom_ahci_probe(struct platform_device *pdev) -+{ -+ struct ahci_host_priv *hpriv; -+ struct clk *rxoob_clk; -+ int rc; -+ -+ hpriv = ahci_platform_get_resources(pdev); -+ if (IS_ERR(hpriv)) -+ return PTR_ERR(hpriv); -+ -+ /* Try and set the rxoob clk to 100Mhz */ -+ rxoob_clk = of_clk_get_by_name(pdev->dev.of_node, "rxoob"); -+ if (IS_ERR(rxoob_clk)) -+ return PTR_ERR(rxoob_clk); -+ -+ rc = clk_set_rate(rxoob_clk, 100000000); -+ if (rc) -+ return rc; -+ -+ rc = ahci_platform_enable_resources(hpriv); -+ if (rc) -+ return rc; -+ -+ rc = ahci_platform_init_host(pdev, hpriv, &qcom_ahci_port_info, 0, 0); -+ if (rc) -+ goto disable_resources; -+ -+ return 0; -+disable_resources: -+ ahci_platform_disable_resources(hpriv); -+ return rc; -+} -+ -+static const struct of_device_id qcom_ahci_of_match[] = { -+ { .compatible = "qcom,msm-ahci", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, qcom_ahci_of_match); -+ -+static struct platform_driver qcom_ahci_driver = { -+ .probe = qcom_ahci_probe, -+ .remove = ata_platform_remove_one, -+ .driver = { -+ .name = "qcom_ahci_qcom", -+ .owner = THIS_MODULE, -+ .of_match_table = qcom_ahci_of_match, -+ }, -+}; -+module_platform_driver(qcom_ahci_driver); -+ -+MODULE_DESCRIPTION("Qualcomm AHCI SATA platform driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("ahci:qcom"); diff --git a/target/linux/ipq806x/patches/0143-ata-qcom-Add-device-tree-bindings-information.patch b/target/linux/ipq806x/patches/0143-ata-qcom-Add-device-tree-bindings-information.patch deleted file mode 100644 index 01ca7336ee..0000000000 --- a/target/linux/ipq806x/patches/0143-ata-qcom-Add-device-tree-bindings-information.patch +++ /dev/null @@ -1,57 +0,0 @@ -From dd280a4cf6b826144f74d3fc4285633f1c337a1d Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 12 Jun 2014 11:28:47 -0500 -Subject: [PATCH 143/182] ata: qcom: Add device tree bindings information - -Add device tree binding for Qualcomm AHCI SATA controller and specifically -the sata controller on the IPQ806x family of SoCs. - -Signed-off-by: Kumar Gala ---- - .../devicetree/bindings/ata/qcom-sata.txt | 40 ++++++++++++++++++++ - 1 file changed, 40 insertions(+) - create mode 100644 Documentation/devicetree/bindings/ata/qcom-sata.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/ata/qcom-sata.txt -@@ -0,0 +1,40 @@ -+* Qualcomm AHCI SATA Controller -+ -+SATA nodes are defined to describe on-chip Serial ATA controllers. -+Each SATA controller should have its own node. -+ -+Required properties: -+- compatible : compatible list, contains "qcom,msm-ahci" -+- interrupts : -+- reg : -+- phys : Must contain exactly one entry as specified -+ in phy-bindings.txt -+- phy-names : Must be "sata-phy" -+ -+Required properties for "qcom,ipq806x-ahci" compatible: -+- clocks : Must contain an entry for each entry in clock-names. -+- clock-names : Shall be: -+ "slave_iface" - Fabric port AHB clock for SATA -+ "iface" - AHB clock -+ "core" - core clock -+ "rxoob" - RX out-of-band clock -+ "pmalive" - Power Module Alive clock -+ -+Example: -+ sata@29000000 { -+ compatible = "qcom,ipq806x-ahci", "qcom,msm-ahci"; -+ reg = <0x29000000 0x180>; -+ -+ interrupts = <0 209 0x0>; -+ -+ clocks = <&gcc SFAB_SATA_S_H_CLK>, -+ <&gcc SATA_H_CLK>, -+ <&gcc SATA_A_CLK>, -+ <&gcc SATA_RXOOB_CLK>, -+ <&gcc SATA_PMALIVE_CLK>; -+ clock-names = "slave_iface", "iface", "core", -+ "rxoob", "pmalive"; -+ -+ phys = <&sata_phy>; -+ phy-names = "sata-phy"; -+ }; diff --git a/target/linux/ipq806x/patches/0144-phy-qcom-Add-driver-for-QCOM-IPQ806x-SATA-PHY.patch b/target/linux/ipq806x/patches/0144-phy-qcom-Add-driver-for-QCOM-IPQ806x-SATA-PHY.patch deleted file mode 100644 index 9a5457df6c..0000000000 --- a/target/linux/ipq806x/patches/0144-phy-qcom-Add-driver-for-QCOM-IPQ806x-SATA-PHY.patch +++ /dev/null @@ -1,251 +0,0 @@ -From 7554dfbbec255e4cd5dd4445841c28c48fd4a855 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Tue, 3 Jun 2014 11:59:09 -0500 -Subject: [PATCH 144/182] phy: qcom: Add driver for QCOM IPQ806x SATA PHY - -Add a PHY driver for uses with AHCI based SATA controller driver on the -IPQ806x family of SoCs. - -Signed-off-by: Kumar Gala ---- - drivers/phy/Kconfig | 7 ++ - drivers/phy/Makefile | 1 + - drivers/phy/phy-qcom-ipq806x-sata.c | 211 +++++++++++++++++++++++++++++++++++ - 3 files changed, 219 insertions(+) - create mode 100644 drivers/phy/phy-qcom-ipq806x-sata.c - ---- a/drivers/phy/Kconfig -+++ b/drivers/phy/Kconfig -@@ -65,4 +65,11 @@ config BCM_KONA_USB2_PHY - help - Enable this to support the Broadcom Kona USB 2.0 PHY. - -+config PHY_QCOM_IPQ806X_SATA -+ tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" -+ depends on ARCH_QCOM -+ depends on HAS_IOMEM -+ depends on OF -+ select GENERIC_PHY -+ - endmenu ---- a/drivers/phy/Makefile -+++ b/drivers/phy/Makefile -@@ -9,3 +9,4 @@ obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += p - obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o - obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o - obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o -+obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o ---- /dev/null -+++ b/drivers/phy/phy-qcom-ipq806x-sata.c -@@ -0,0 +1,211 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct qcom_ipq806x_sata_phy { -+ void __iomem *mmio; -+ struct clk *cfg_clk; -+}; -+ -+#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b)) -+ -+#define SATA_PHY_P0_PARAM0 0x200 -+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x) __set(x, 17, 12) -+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK GENMASK(17, 12) -+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x) __set(x, 11, 6) -+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK GENMASK(11, 6) -+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x) __set(x, 5, 0) -+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK GENMASK(5, 0) -+ -+#define SATA_PHY_P0_PARAM1 0x204 -+#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x) __set(x, 31, 21) -+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x) __set(x, 20, 14) -+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK GENMASK(20, 14) -+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x) __set(x, 13, 7) -+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK GENMASK(13, 7) -+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x) __set(x, 6, 0) -+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK GENMASK(6, 0) -+ -+#define SATA_PHY_P0_PARAM2 0x208 -+#define SATA_PHY_P0_PARAM2_RX_EQ(x) __set(x, 20, 18) -+#define SATA_PHY_P0_PARAM2_RX_EQ_MASK GENMASK(20, 18) -+ -+#define SATA_PHY_P0_PARAM3 0x20C -+#define SATA_PHY_SSC_EN 0x8 -+#define SATA_PHY_P0_PARAM4 0x210 -+#define SATA_PHY_REF_SSP_EN 0x2 -+#define SATA_PHY_RESET 0x1 -+ -+static inline void qcom_ipq806x_sata_delay_us(unsigned int delay) -+{ -+ /* sleep for max. 50us more to combine processor wakeups */ -+ usleep_range(delay, delay + 50); -+} -+ -+static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy) -+{ -+ struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy); -+ u32 reg; -+ -+ /* Setting SSC_EN to 1 */ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3); -+ reg = reg | SATA_PHY_SSC_EN; -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3); -+ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) & -+ ~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK | -+ SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK | -+ SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK); -+ reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf); -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0); -+ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) & -+ ~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK | -+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK | -+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK); -+ reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) | -+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) | -+ SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55); -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1); -+ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) & -+ ~SATA_PHY_P0_PARAM2_RX_EQ_MASK; -+ reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3); -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2); -+ -+ /* Setting PHY_RESET to 1 */ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); -+ reg = reg | SATA_PHY_RESET; -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); -+ -+ /* Setting REF_SSP_EN to 1 */ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); -+ reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET; -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); -+ mb(); -+ qcom_ipq806x_sata_delay_us(20); -+ -+ /* Clearing PHY_RESET to 0 */ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); -+ reg = reg & ~SATA_PHY_RESET; -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); -+ -+ return 0; -+} -+ -+static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy) -+{ -+ struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy); -+ u32 reg; -+ -+ /* Setting PHY_RESET to 1 */ -+ reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4); -+ reg = reg | SATA_PHY_RESET; -+ writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4); -+ -+ return 0; -+} -+ -+static struct phy_ops qcom_ipq806x_sata_phy_ops = { -+ .init = qcom_ipq806x_sata_phy_init, -+ .exit = qcom_ipq806x_sata_phy_exit, -+ .owner = THIS_MODULE, -+}; -+ -+static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev) -+{ -+ struct qcom_ipq806x_sata_phy *phy; -+ struct device *dev = &pdev->dev; -+ struct resource *res; -+ struct phy_provider *phy_provider; -+ struct phy *generic_phy; -+ int ret; -+ -+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); -+ if (!phy) { -+ dev_err(dev, "%s: failed to allocate phy\n", __func__); -+ return -ENOMEM; -+ } -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ phy->mmio = devm_ioremap_resource(dev, res); -+ if (IS_ERR(phy->mmio)) -+ return PTR_ERR(phy->mmio); -+ -+ generic_phy = devm_phy_create(dev, &qcom_ipq806x_sata_phy_ops, NULL); -+ if (IS_ERR(generic_phy)) { -+ dev_err(dev, "%s: failed to create phy\n", __func__); -+ return PTR_ERR(generic_phy); -+ } -+ -+ phy_set_drvdata(generic_phy, phy); -+ -+ phy->cfg_clk = devm_clk_get(dev, "cfg"); -+ if (IS_ERR(phy->cfg_clk)) { -+ dev_err(dev, "Failed to get sata cfg clock\n"); -+ return PTR_ERR(phy->cfg_clk); -+ } -+ -+ ret = clk_prepare_enable(phy->cfg_clk); -+ if (ret) -+ return ret; -+ -+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); -+ if (IS_ERR(phy_provider)) { -+ clk_disable_unprepare(phy->cfg_clk); -+ dev_err(dev, "%s: failed to register phy\n", __func__); -+ return PTR_ERR(phy_provider); -+ } -+ -+ return 0; -+} -+ -+static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev) -+{ -+ struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev); -+ -+ clk_disable_unprepare(phy->cfg_clk); -+ -+ return 0; -+} -+ -+static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = { -+ { .compatible = "qcom,ipq806x-sata-phy" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match); -+ -+static struct platform_driver qcom_ipq806x_sata_phy_driver = { -+ .probe = qcom_ipq806x_sata_phy_probe, -+ .remove = qcom_ipq806x_sata_phy_remove, -+ .driver = { -+ .name = "qcom-ipq806x-sata-phy", -+ .owner = THIS_MODULE, -+ .of_match_table = qcom_ipq806x_sata_phy_of_match, -+ } -+}; -+module_platform_driver(qcom_ipq806x_sata_phy_driver); -+ -+MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0145-phy-qcom-Add-device-tree-bindings-information.patch b/target/linux/ipq806x/patches/0145-phy-qcom-Add-device-tree-bindings-information.patch deleted file mode 100644 index bd5e5d4fb3..0000000000 --- a/target/linux/ipq806x/patches/0145-phy-qcom-Add-device-tree-bindings-information.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 37258bc8fe832e4c681593a864686f627f6d3455 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Tue, 10 Jun 2014 13:09:01 -0500 -Subject: [PATCH 145/182] phy: qcom: Add device tree bindings information - -Add binding spec for Qualcomm SoC PHYs, starting with the SATA PHY on -the IPQ806x family of SoCs. - -Signed-off-by: Kumar Gala ---- - Documentation/devicetree/bindings/phy/qcom-phy.txt | 23 ++++++++++++++++++++ - 1 file changed, 23 insertions(+) - create mode 100644 Documentation/devicetree/bindings/phy/qcom-phy.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/phy/qcom-phy.txt -@@ -0,0 +1,23 @@ -+Qualcomm IPQ806x SATA PHY Controller -+------------------------------------ -+ -+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers. -+Each SATA PHY controller should have its own node. -+ -+Required properties: -+- compatible: compatible list, contains "qcom,ipq806x-sata-phy" -+- reg: offset and length of the SATA PHY register set; -+- #phy-cells: must be zero -+- clocks: must be exactly one entry -+- clock-names: must be "cfg" -+ -+Example: -+ sata_phy: sata-phy@1b400000 { -+ compatible = "qcom,ipq806x-sata-phy"; -+ reg = <0x1b400000 0x200>; -+ -+ clocks = <&gcc SATA_PHY_CFG_CLK>; -+ clock-names = "cfg"; -+ -+ #phy-cells = <0>; -+ }; diff --git a/target/linux/ipq806x/patches/0146-ARM-dts-qcom-Add-SATA-support-for-IPQ8064-and-AP148-.patch b/target/linux/ipq806x/patches/0146-ARM-dts-qcom-Add-SATA-support-for-IPQ8064-and-AP148-.patch deleted file mode 100644 index da124c74d1..0000000000 --- a/target/linux/ipq806x/patches/0146-ARM-dts-qcom-Add-SATA-support-for-IPQ8064-and-AP148-.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 6992cf3e8900d042a845eafc11e7841f32fec0a6 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Thu, 12 Jun 2014 10:56:54 -0500 -Subject: [PATCH 146/182] ARM: dts: qcom: Add SATA support for IPQ8064 and - AP148 board - ---- - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 8 ++++++++ - arch/arm/boot/dts/qcom-ipq8064.dtsi | 30 ++++++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -118,5 +118,13 @@ - 0x81000000 0 0 0x31e00000 0 0x00100000 /* downstream I/O */ - 0x82000000 0 0x00000000 0x2e000000 0 0x03e00000>; /* non-prefetchable memory */ - }; -+ -+ sata-phy@1b400000 { -+ status = "ok"; -+ }; -+ -+ sata@29000000 { -+ status = "ok"; -+ }; - }; - }; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -339,5 +339,35 @@ - clock-names = "core", "iface", "phy"; - status = "disabled"; - }; -+ -+ sata_phy: sata-phy@1b400000 { -+ compatible = "qcom,ipq806x-sata-phy"; -+ reg = <0x1b400000 0x200>; -+ -+ clocks = <&gcc SATA_PHY_CFG_CLK>; -+ clock-names = "cfg"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ sata@29000000 { -+ compatible = "qcom,ipq806x-ahci", "qcom,msm-ahci"; -+ reg = <0x29000000 0x180>; -+ -+ interrupts = <0 209 0x0>; -+ -+ clocks = <&gcc SFAB_SATA_S_H_CLK>, -+ <&gcc SATA_H_CLK>, -+ <&gcc SATA_A_CLK>, -+ <&gcc SATA_RXOOB_CLK>, -+ <&gcc SATA_PMALIVE_CLK>; -+ clock-names = "slave_face", "iface", "core", -+ "rxoob", "pmalive"; -+ -+ phys = <&sata_phy>; -+ phy-names = "sata-phy"; -+ status = "disabled"; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0147-ARM-qcom-Enable-SATA-SATA-PHY-drivers-in-defconfig.patch b/target/linux/ipq806x/patches/0147-ARM-qcom-Enable-SATA-SATA-PHY-drivers-in-defconfig.patch deleted file mode 100644 index 7465f56e4f..0000000000 --- a/target/linux/ipq806x/patches/0147-ARM-qcom-Enable-SATA-SATA-PHY-drivers-in-defconfig.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 54a945eca8381fa8cda03b20eda3b2f23a88d289 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Tue, 3 Jun 2014 10:36:41 -0500 -Subject: [PATCH 147/182] ARM: qcom: Enable SATA/SATA-PHY drivers in defconfig - ---- - arch/arm/configs/qcom_defconfig | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -57,7 +57,6 @@ CONFIG_MTD_BLOCK=y - CONFIG_MTD_M25P80=y - CONFIG_BLK_DEV_LOOP=y - CONFIG_BLK_DEV_RAM=y --CONFIG_SCSI=y - CONFIG_SCSI_TGT=y - CONFIG_BLK_DEV_SD=y - CONFIG_CHR_DEV_SG=y -@@ -66,6 +65,8 @@ CONFIG_SCSI_MULTI_LUN=y - CONFIG_SCSI_CONSTANTS=y - CONFIG_SCSI_LOGGING=y - CONFIG_SCSI_SCAN_ASYNC=y -+CONFIG_ATA=y -+CONFIG_AHCI_QCOM=y - CONFIG_NETDEVICES=y - CONFIG_DUMMY=y - CONFIG_MDIO_BITBANG=y -@@ -141,7 +142,7 @@ CONFIG_MSM_GCC_8660=y - CONFIG_MSM_MMCC_8960=y - CONFIG_MSM_MMCC_8974=y - CONFIG_MSM_IOMMU=y --CONFIG_GENERIC_PHY=y -+CONFIG_PHY_QCOM_IPQ806X_SATA=y - CONFIG_EXT2_FS=y - CONFIG_EXT2_FS_XATTR=y - CONFIG_EXT3_FS=y diff --git a/target/linux/ipq806x/patches/0148-ARM-qcom-enable-default-CPU_IDLE-to-get-wfi-support-.patch b/target/linux/ipq806x/patches/0148-ARM-qcom-enable-default-CPU_IDLE-to-get-wfi-support-.patch deleted file mode 100644 index c68a23b2fe..0000000000 --- a/target/linux/ipq806x/patches/0148-ARM-qcom-enable-default-CPU_IDLE-to-get-wfi-support-.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 8c9156c67c3e3e37812bb0e4d24263be0e564881 Mon Sep 17 00:00:00 2001 -From: Kumar Gala -Date: Mon, 16 Jun 2014 14:40:29 -0500 -Subject: [PATCH 148/182] ARM: qcom: enable default CPU_IDLE to get wfi - support on IPQ806x - -Signed-off-by: Kumar Gala ---- - arch/arm/configs/qcom_defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -31,6 +31,7 @@ CONFIG_HIGHPTE=y - CONFIG_CLEANCACHE=y - CONFIG_ARM_APPENDED_DTB=y - CONFIG_ARM_ATAG_DTB_COMPAT=y -+CONFIG_CPU_IDLE=y - CONFIG_VFP=y - CONFIG_NEON=y - # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set diff --git a/target/linux/ipq806x/patches/0149-pinctrl-qcom-Add-BUS_HOLD-Keeper-bias.patch b/target/linux/ipq806x/patches/0149-pinctrl-qcom-Add-BUS_HOLD-Keeper-bias.patch deleted file mode 100644 index 8b2e18ab84..0000000000 --- a/target/linux/ipq806x/patches/0149-pinctrl-qcom-Add-BUS_HOLD-Keeper-bias.patch +++ /dev/null @@ -1,50 +0,0 @@ -From b1325bfad3ad0e543ce90a6b08d74500dc96f4b9 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 16 Jun 2014 16:52:55 -0500 -Subject: [PATCH 149/182] pinctrl: qcom: Add BUS_HOLD/Keeper bias - -This patch adds the bus_hold bias option for pins. - -Signed-off-by: Andy Gross ---- - drivers/pinctrl/pinctrl-msm.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/pinctrl/pinctrl-msm.c -+++ b/drivers/pinctrl/pinctrl-msm.c -@@ -207,6 +207,7 @@ static int msm_config_reg(struct msm_pin - case PIN_CONFIG_BIAS_DISABLE: - case PIN_CONFIG_BIAS_PULL_DOWN: - case PIN_CONFIG_BIAS_PULL_UP: -+ case PIN_CONFIG_BIAS_BUS_HOLD: - *bit = g->pull_bit; - *mask = 3; - break; -@@ -243,6 +244,7 @@ static int msm_config_set(struct pinctrl - - #define MSM_NO_PULL 0 - #define MSM_PULL_DOWN 1 -+#define MSM_KEEPER 2 - #define MSM_PULL_UP 3 - - static unsigned msm_regval_to_drive(u32 val) -@@ -280,6 +282,9 @@ static int msm_config_group_get(struct p - case PIN_CONFIG_BIAS_PULL_DOWN: - arg = arg == MSM_PULL_DOWN; - break; -+ case PIN_CONFIG_BIAS_BUS_HOLD: -+ arg = arg == MSM_KEEPER; -+ break; - case PIN_CONFIG_BIAS_PULL_UP: - arg = arg == MSM_PULL_UP; - break; -@@ -339,6 +344,9 @@ static int msm_config_group_set(struct p - case PIN_CONFIG_BIAS_PULL_DOWN: - arg = MSM_PULL_DOWN; - break; -+ case PIN_CONFIG_BIAS_BUS_HOLD: -+ arg = MSM_KEEPER; -+ break; - case PIN_CONFIG_BIAS_PULL_UP: - arg = MSM_PULL_UP; - break; diff --git a/target/linux/ipq806x/patches/0150-mtd-nand-Add-Qualcomm-NAND-controller.patch b/target/linux/ipq806x/patches/0150-mtd-nand-Add-Qualcomm-NAND-controller.patch deleted file mode 100644 index f19045ed73..0000000000 --- a/target/linux/ipq806x/patches/0150-mtd-nand-Add-Qualcomm-NAND-controller.patch +++ /dev/null @@ -1,8784 +0,0 @@ -From d2981ca1343b837fc574c4e46806d041b258720d Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 16 Jun 2014 17:13:22 -0500 -Subject: [PATCH 150/182] mtd: nand: Add Qualcomm NAND controller - -This patch adds the Qualcomm NAND controller and required infrastructure. - -Signed-off-by: Andy Gross ---- - drivers/mtd/nand/Kconfig | 18 + - drivers/mtd/nand/Makefile | 2 + - drivers/mtd/nand/qcom_adm_dma.c | 797 +++++ - drivers/mtd/nand/qcom_adm_dma.h | 268 ++ - drivers/mtd/nand/qcom_nand.c | 7455 +++++++++++++++++++++++++++++++++++++++ - drivers/mtd/nand/qcom_nand.h | 196 + - 6 files changed, 8736 insertions(+) - create mode 100644 drivers/mtd/nand/qcom_adm_dma.c - create mode 100644 drivers/mtd/nand/qcom_adm_dma.h - create mode 100644 drivers/mtd/nand/qcom_nand.c - create mode 100644 drivers/mtd/nand/qcom_nand.h - ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -510,4 +510,22 @@ config MTD_NAND_XWAY - Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached - to the External Bus Unit (EBU). - -+config MTD_QCOM_DMA -+ tristate "QCMO NAND DMA Support" -+ depends on ARCH_QCOM && MTD_QCOM_NAND -+ default n -+ help -+ DMA support for QCOM NAND -+ -+config MTD_QCOM_NAND -+ tristate "QCOM NAND Device Support" -+ depends on MTD && ARCH_QCOM -+ select CRC16 -+ select BITREVERSE -+ select MTD_NAND_IDS -+ select MTD_QCOM_DMA -+ default y -+ help -+ Support for some NAND chips connected to the QCOM NAND controller. -+ - endif # MTD_NAND ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -49,5 +49,7 @@ obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740 - obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ - obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o - obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ -+obj-$(CONFIG_MTD_QCOM_NAND) += qcom_nand.o -+obj-$(CONFIG_MTD_QCOM_DMA) += qcom_adm_dma.o - - nand-objs := nand_base.o nand_bbt.o ---- /dev/null -+++ b/drivers/mtd/nand/qcom_adm_dma.c -@@ -0,0 +1,797 @@ -+/* * Copyright (c) 2012 The Linux Foundation. All rights reserved.* */ -+/* linux/arch/arm/mach-msm/dma.c -+ * -+ * Copyright (C) 2007 Google, Inc. -+ * Copyright (c) 2008-2010, 2012 The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "qcom_adm_dma.h" -+ -+#define MODULE_NAME "msm_dmov" -+ -+#define MSM_DMOV_CHANNEL_COUNT 16 -+#define MSM_DMOV_CRCI_COUNT 16 -+ -+enum { -+ CLK_DIS, -+ CLK_TO_BE_DIS, -+ CLK_EN -+}; -+ -+struct msm_dmov_ci_conf { -+ int start; -+ int end; -+ int burst; -+}; -+ -+struct msm_dmov_crci_conf { -+ int sd; -+ int blk_size; -+}; -+ -+struct msm_dmov_chan_conf { -+ int sd; -+ int block; -+ int priority; -+}; -+ -+struct msm_dmov_conf { -+ void *base; -+ struct msm_dmov_crci_conf *crci_conf; -+ struct msm_dmov_chan_conf *chan_conf; -+ int channel_active; -+ int sd; -+ size_t sd_size; -+ struct list_head staged_commands[MSM_DMOV_CHANNEL_COUNT]; -+ struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; -+ struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; -+ struct mutex lock; -+ spinlock_t list_lock; -+ unsigned int irq; -+ struct clk *clk; -+ struct clk *pclk; -+ struct clk *ebiclk; -+ unsigned int clk_ctl; -+ struct delayed_work work; -+ struct workqueue_struct *cmd_wq; -+ -+ struct reset_control *adm_reset; -+ struct reset_control *pbus_reset; -+ struct reset_control *c0_reset; -+ struct reset_control *c1_reset; -+ struct reset_control *c2_reset; -+ -+}; -+ -+static void msm_dmov_clock_work(struct work_struct *); -+ -+#define DMOV_CRCI_DEFAULT_CONF { .sd = 0, .blk_size = 0 } -+#define DMOV_CRCI_CONF(secd, blk) { .sd = secd, .blk_size = blk } -+ -+static struct msm_dmov_crci_conf adm_crci_conf[] = { -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_CONF(0, 1), -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+ DMOV_CRCI_DEFAULT_CONF, -+}; -+ -+#define DMOV_CHANNEL_DEFAULT_CONF { .sd = 0, .block = 0, .priority = 1 } -+ -+static struct msm_dmov_chan_conf adm_chan_conf[] = { -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+ DMOV_CHANNEL_DEFAULT_CONF, -+}; -+ -+#define DMOV_IRQ_TO_ADM(irq) 0 -+ -+static struct msm_dmov_conf dmov_conf[] = { -+ { -+ .crci_conf = adm_crci_conf, -+ .chan_conf = adm_chan_conf, -+ .lock = __MUTEX_INITIALIZER(dmov_conf[0].lock), -+ .list_lock = __SPIN_LOCK_UNLOCKED(dmov_list_lock), -+ .clk_ctl = CLK_EN, -+ .work = __DELAYED_WORK_INITIALIZER(dmov_conf[0].work, -+ msm_dmov_clock_work,0), -+ } -+}; -+ -+#define MSM_DMOV_ID_COUNT (MSM_DMOV_CHANNEL_COUNT * ARRAY_SIZE(dmov_conf)) -+#define DMOV_REG(name, adm) ((name) + (dmov_conf[adm].base) +\ -+ (dmov_conf[adm].sd * dmov_conf[adm].sd_size)) -+#define DMOV_ID_TO_ADM(id) ((id) / MSM_DMOV_CHANNEL_COUNT) -+#define DMOV_ID_TO_CHAN(id) ((id) % MSM_DMOV_CHANNEL_COUNT) -+#define DMOV_CHAN_ADM_TO_ID(ch, adm) ((ch) + (adm) * MSM_DMOV_CHANNEL_COUNT) -+ -+enum { -+ MSM_DMOV_PRINT_ERRORS = 1, -+ MSM_DMOV_PRINT_IO = 2, -+ MSM_DMOV_PRINT_FLOW = 4 -+}; -+ -+unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS; -+ -+#define MSM_DMOV_DPRINTF(mask, format, args...) \ -+ do { \ -+ if ((mask) & msm_dmov_print_mask) \ -+ printk(KERN_ERR format, args); \ -+ } while (0) -+#define PRINT_ERROR(format, args...) \ -+ MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_ERRORS, format, args); -+#define PRINT_IO(format, args...) \ -+ MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_IO, format, args); -+#define PRINT_FLOW(format, args...) \ -+ MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args); -+ -+static int msm_dmov_clk_on(int adm) -+{ -+ int ret; -+ -+return 0; -+ ret = clk_prepare_enable(dmov_conf[adm].clk); -+ if (ret) -+ return ret; -+ if (dmov_conf[adm].pclk) { -+ ret = clk_prepare_enable(dmov_conf[adm].pclk); -+ if (ret) { -+ clk_disable_unprepare(dmov_conf[adm].clk); -+ return ret; -+ } -+ } -+ if (dmov_conf[adm].ebiclk) { -+ ret = clk_prepare_enable(dmov_conf[adm].ebiclk); -+ if (ret) { -+ if (dmov_conf[adm].pclk) -+ clk_disable_unprepare(dmov_conf[adm].pclk); -+ clk_disable_unprepare(dmov_conf[adm].clk); -+ } -+ } -+ return ret; -+} -+ -+static void msm_dmov_clk_off(int adm) -+{ -+#if 0 -+ if (dmov_conf[adm].ebiclk) -+ clk_disable_unprepare(dmov_conf[adm].ebiclk); -+ if (dmov_conf[adm].pclk) -+ clk_disable_unprepare(dmov_conf[adm].pclk); -+ clk_disable_unprepare(dmov_conf[adm].clk); -+#endif -+} -+ -+static void msm_dmov_clock_work(struct work_struct *work) -+{ -+ struct msm_dmov_conf *conf = -+ container_of(to_delayed_work(work), struct msm_dmov_conf, work); -+ int adm = DMOV_IRQ_TO_ADM(conf->irq); -+ mutex_lock(&conf->lock); -+ if (conf->clk_ctl == CLK_TO_BE_DIS) { -+ BUG_ON(conf->channel_active); -+ msm_dmov_clk_off(adm); -+ conf->clk_ctl = CLK_DIS; -+ } -+ mutex_unlock(&conf->lock); -+} -+ -+enum { -+ NOFLUSH = 0, -+ GRACEFUL, -+ NONGRACEFUL, -+}; -+ -+/* Caller must hold the list lock */ -+static struct msm_dmov_cmd *start_ready_cmd(unsigned ch, int adm) -+{ -+ struct msm_dmov_cmd *cmd; -+ -+ if (list_empty(&dmov_conf[adm].ready_commands[ch])) { -+ return NULL; -+ } -+ -+ cmd = list_entry(dmov_conf[adm].ready_commands[ch].next, typeof(*cmd), -+ list); -+ list_del(&cmd->list); -+ if (cmd->exec_func) -+ cmd->exec_func(cmd); -+ list_add_tail(&cmd->list, &dmov_conf[adm].active_commands[ch]); -+ if (!dmov_conf[adm].channel_active) { -+ enable_irq(dmov_conf[adm].irq); -+ } -+ dmov_conf[adm].channel_active |= BIT(ch); -+ PRINT_IO("msm dmov enqueue command, %x, ch %d\n", cmd->cmdptr, ch); -+ writel_relaxed(cmd->cmdptr, DMOV_REG(DMOV_CMD_PTR(ch), adm)); -+ -+ return cmd; -+} -+ -+static void msm_dmov_enqueue_cmd_ext_work(struct work_struct *work) -+{ -+ struct msm_dmov_cmd *cmd = -+ container_of(work, struct msm_dmov_cmd, work); -+ unsigned id = cmd->id; -+ unsigned status; -+ unsigned long flags; -+ int adm = DMOV_ID_TO_ADM(id); -+ int ch = DMOV_ID_TO_CHAN(id); -+ -+ mutex_lock(&dmov_conf[adm].lock); -+ if (dmov_conf[adm].clk_ctl == CLK_DIS) { -+ status = msm_dmov_clk_on(adm); -+ if (status != 0) -+ goto error; -+ } -+ dmov_conf[adm].clk_ctl = CLK_EN; -+ -+ spin_lock_irqsave(&dmov_conf[adm].list_lock, flags); -+ -+ cmd = list_entry(dmov_conf[adm].staged_commands[ch].next, typeof(*cmd), -+ list); -+ list_del(&cmd->list); -+ list_add_tail(&cmd->list, &dmov_conf[adm].ready_commands[ch]); -+ status = readl_relaxed(DMOV_REG(DMOV_STATUS(ch), adm)); -+ if (status & DMOV_STATUS_CMD_PTR_RDY) { -+ PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", -+ id, status); -+ cmd = start_ready_cmd(ch, adm); -+ /* -+ * We added something to the ready list, and still hold the -+ * list lock. Thus, no need to check for cmd == NULL -+ */ -+ if (cmd->toflush) { -+ int flush = (cmd->toflush == GRACEFUL) ? 1 << 31 : 0; -+ writel_relaxed(flush, DMOV_REG(DMOV_FLUSH0(ch), adm)); -+ } -+ } else { -+ cmd->toflush = 0; -+ if (list_empty(&dmov_conf[adm].active_commands[ch]) && -+ !list_empty(&dmov_conf[adm].ready_commands[ch])) -+ PRINT_ERROR("msm_dmov_enqueue_cmd_ext(%d), stalled, " -+ "status %x\n", id, status); -+ PRINT_IO("msm_dmov_enqueue_cmd(%d), enqueue command, status " -+ "%x\n", id, status); -+ } -+ if (!dmov_conf[adm].channel_active) { -+ dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS; -+ schedule_delayed_work(&dmov_conf[adm].work, (HZ/10)); -+ } -+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags); -+error: -+ mutex_unlock(&dmov_conf[adm].lock); -+} -+ -+static void __msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd) -+{ -+ int adm = DMOV_ID_TO_ADM(id); -+ int ch = DMOV_ID_TO_CHAN(id); -+ unsigned long flags; -+ cmd->id = id; -+ cmd->toflush = 0; -+ -+ spin_lock_irqsave(&dmov_conf[adm].list_lock, flags); -+ list_add_tail(&cmd->list, &dmov_conf[adm].staged_commands[ch]); -+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags); -+ -+ queue_work(dmov_conf[adm].cmd_wq, &cmd->work); -+} -+ -+void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd) -+{ -+ INIT_WORK(&cmd->work, msm_dmov_enqueue_cmd_ext_work); -+ __msm_dmov_enqueue_cmd_ext(id, cmd); -+} -+EXPORT_SYMBOL(msm_dmov_enqueue_cmd_ext); -+ -+void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) -+{ -+ /* Disable callback function (for backwards compatibility) */ -+ cmd->exec_func = NULL; -+ INIT_WORK(&cmd->work, msm_dmov_enqueue_cmd_ext_work); -+ __msm_dmov_enqueue_cmd_ext(id, cmd); -+} -+EXPORT_SYMBOL(msm_dmov_enqueue_cmd); -+ -+void msm_dmov_flush(unsigned int id, int graceful) -+{ -+ unsigned long irq_flags; -+ int ch = DMOV_ID_TO_CHAN(id); -+ int adm = DMOV_ID_TO_ADM(id); -+ int flush = graceful ? DMOV_FLUSH_TYPE : 0; -+ struct msm_dmov_cmd *cmd; -+ -+ spin_lock_irqsave(&dmov_conf[adm].list_lock, irq_flags); -+ /* XXX not checking if flush cmd sent already */ -+ if (!list_empty(&dmov_conf[adm].active_commands[ch])) { -+ PRINT_IO("msm_dmov_flush(%d), send flush cmd\n", id); -+ writel_relaxed(flush, DMOV_REG(DMOV_FLUSH0(ch), adm)); -+ } -+ list_for_each_entry(cmd, &dmov_conf[adm].staged_commands[ch], list) -+ cmd->toflush = graceful ? GRACEFUL : NONGRACEFUL; -+ /* spin_unlock_irqrestore has the necessary barrier */ -+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, irq_flags); -+} -+EXPORT_SYMBOL(msm_dmov_flush); -+ -+struct msm_dmov_exec_cmdptr_cmd { -+ struct msm_dmov_cmd dmov_cmd; -+ struct completion complete; -+ unsigned id; -+ unsigned int result; -+ struct msm_dmov_errdata err; -+}; -+ -+static void -+dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd, -+ unsigned int result, -+ struct msm_dmov_errdata *err) -+{ -+ struct msm_dmov_exec_cmdptr_cmd *cmd = container_of(_cmd, struct msm_dmov_exec_cmdptr_cmd, dmov_cmd); -+ cmd->result = result; -+ if (result != 0x80000002 && err) -+ memcpy(&cmd->err, err, sizeof(struct msm_dmov_errdata)); -+ -+ complete(&cmd->complete); -+} -+ -+int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) -+{ -+ struct msm_dmov_exec_cmdptr_cmd cmd; -+ -+ PRINT_FLOW("dmov_exec_cmdptr(%d, %x)\n", id, cmdptr); -+ -+ cmd.dmov_cmd.cmdptr = cmdptr; -+ cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func; -+ cmd.dmov_cmd.exec_func = NULL; -+ cmd.id = id; -+ cmd.result = 0; -+ INIT_WORK_ONSTACK(&cmd.dmov_cmd.work, msm_dmov_enqueue_cmd_ext_work); -+ init_completion(&cmd.complete); -+ -+ __msm_dmov_enqueue_cmd_ext(id, &cmd.dmov_cmd); -+ wait_for_completion_timeout(&cmd.complete, msecs_to_jiffies(1000)); -+ -+ if (cmd.result != 0x80000002) { -+ PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result); -+ PRINT_ERROR("dmov_exec_cmdptr(%d): flush: %x %x %x %x\n", -+ id, cmd.err.flush[0], cmd.err.flush[1], cmd.err.flush[2], cmd.err.flush[3]); -+ return -EIO; -+ } -+ PRINT_FLOW("dmov_exec_cmdptr(%d, %x) done\n", id, cmdptr); -+ return 0; -+} -+EXPORT_SYMBOL(msm_dmov_exec_cmd); -+ -+static void fill_errdata(struct msm_dmov_errdata *errdata, int ch, int adm) -+{ -+ errdata->flush[0] = readl_relaxed(DMOV_REG(DMOV_FLUSH0(ch), adm)); -+ errdata->flush[1] = readl_relaxed(DMOV_REG(DMOV_FLUSH1(ch), adm)); -+ errdata->flush[2] = 0; -+ errdata->flush[3] = readl_relaxed(DMOV_REG(DMOV_FLUSH3(ch), adm)); -+ errdata->flush[4] = readl_relaxed(DMOV_REG(DMOV_FLUSH4(ch), adm)); -+ errdata->flush[5] = readl_relaxed(DMOV_REG(DMOV_FLUSH5(ch), adm)); -+} -+ -+static irqreturn_t msm_dmov_isr(int irq, void *dev_id) -+{ -+ unsigned int int_status; -+ unsigned int mask; -+ unsigned int id; -+ unsigned int ch; -+ unsigned long irq_flags; -+ unsigned int ch_status; -+ unsigned int ch_result; -+ unsigned int valid = 0; -+ struct msm_dmov_cmd *cmd; -+ int adm = DMOV_IRQ_TO_ADM(irq); -+ -+ mutex_lock(&dmov_conf[adm].lock); -+ /* read and clear isr */ -+ int_status = readl_relaxed(DMOV_REG(DMOV_ISR, adm)); -+ PRINT_FLOW("msm_datamover_irq_handler: DMOV_ISR %x\n", int_status); -+ -+ spin_lock_irqsave(&dmov_conf[adm].list_lock, irq_flags); -+ while (int_status) { -+ mask = int_status & -int_status; -+ ch = fls(mask) - 1; -+ id = DMOV_CHAN_ADM_TO_ID(ch, adm); -+ PRINT_FLOW("msm_datamover_irq_handler %08x %08x id %d\n", int_status, mask, id); -+ int_status &= ~mask; -+ ch_status = readl_relaxed(DMOV_REG(DMOV_STATUS(ch), adm)); -+ if (!(ch_status & DMOV_STATUS_RSLT_VALID)) { -+ PRINT_FLOW("msm_datamover_irq_handler id %d, " -+ "result not valid %x\n", id, ch_status); -+ continue; -+ } -+ do { -+ valid = 1; -+ ch_result = readl_relaxed(DMOV_REG(DMOV_RSLT(ch), adm)); -+ if (list_empty(&dmov_conf[adm].active_commands[ch])) { -+ PRINT_ERROR("msm_datamover_irq_handler id %d, got result " -+ "with no active command, status %x, result %x\n", -+ id, ch_status, ch_result); -+ cmd = NULL; -+ } else { -+ cmd = list_entry(dmov_conf[adm]. -+ active_commands[ch].next, typeof(*cmd), -+ list); -+ } -+ PRINT_FLOW("msm_datamover_irq_handler id %d, status %x, result %x\n", id, ch_status, ch_result); -+ if (ch_result & DMOV_RSLT_DONE) { -+ PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", -+ id, ch_status); -+ PRINT_IO("msm_datamover_irq_handler id %d, got result " -+ "for %p, result %x\n", id, cmd, ch_result); -+ if (cmd) { -+ list_del(&cmd->list); -+ cmd->complete_func(cmd, ch_result, NULL); -+ } -+ } -+ if (ch_result & DMOV_RSLT_FLUSH) { -+ struct msm_dmov_errdata errdata; -+ -+ fill_errdata(&errdata, ch, adm); -+ PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); -+ PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]); -+ if (cmd) { -+ list_del(&cmd->list); -+ cmd->complete_func(cmd, ch_result, &errdata); -+ } -+ } -+ if (ch_result & DMOV_RSLT_ERROR) { -+ struct msm_dmov_errdata errdata; -+ -+ fill_errdata(&errdata, ch, adm); -+ -+ PRINT_ERROR("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); -+ PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]); -+ if (cmd) { -+ list_del(&cmd->list); -+ cmd->complete_func(cmd, ch_result, &errdata); -+ } -+ /* this does not seem to work, once we get an error */ -+ /* the datamover will no longer accept commands */ -+ writel_relaxed(0, DMOV_REG(DMOV_FLUSH0(ch), -+ adm)); -+ } -+ rmb(); -+ ch_status = readl_relaxed(DMOV_REG(DMOV_STATUS(ch), -+ adm)); -+ PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); -+ if (ch_status & DMOV_STATUS_CMD_PTR_RDY) -+ start_ready_cmd(ch, adm); -+ } while (ch_status & DMOV_STATUS_RSLT_VALID); -+ if (list_empty(&dmov_conf[adm].active_commands[ch]) && -+ list_empty(&dmov_conf[adm].ready_commands[ch])) -+ dmov_conf[adm].channel_active &= ~(1U << ch); -+ PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); -+ } -+ spin_unlock_irqrestore(&dmov_conf[adm].list_lock, irq_flags); -+ -+ if (!dmov_conf[adm].channel_active && valid) { -+ disable_irq_nosync(dmov_conf[adm].irq); -+ dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS; -+ schedule_delayed_work(&dmov_conf[adm].work, (HZ/10)); -+ } -+ -+ mutex_unlock(&dmov_conf[adm].lock); -+ -+ return valid ? IRQ_HANDLED : IRQ_NONE; -+} -+ -+static int msm_dmov_suspend_late(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ int adm = (pdev->id >= 0) ? pdev->id : 0; -+ mutex_lock(&dmov_conf[adm].lock); -+ if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS) { -+ BUG_ON(dmov_conf[adm].channel_active); -+ msm_dmov_clk_off(adm); -+ dmov_conf[adm].clk_ctl = CLK_DIS; -+ } -+ mutex_unlock(&dmov_conf[adm].lock); -+ return 0; -+} -+ -+static int msm_dmov_runtime_suspend(struct device *dev) -+{ -+ dev_dbg(dev, "pm_runtime: suspending...\n"); -+ return 0; -+} -+ -+static int msm_dmov_runtime_resume(struct device *dev) -+{ -+ dev_dbg(dev, "pm_runtime: resuming...\n"); -+ return 0; -+} -+ -+static int msm_dmov_runtime_idle(struct device *dev) -+{ -+ dev_dbg(dev, "pm_runtime: idling...\n"); -+ return 0; -+} -+ -+static struct dev_pm_ops msm_dmov_dev_pm_ops = { -+ .runtime_suspend = msm_dmov_runtime_suspend, -+ .runtime_resume = msm_dmov_runtime_resume, -+ .runtime_idle = msm_dmov_runtime_idle, -+ .suspend = msm_dmov_suspend_late, -+}; -+ -+static int msm_dmov_init_clocks(struct platform_device *pdev) -+{ -+ int adm = (pdev->id >= 0) ? pdev->id : 0; -+ int ret; -+ -+ dmov_conf[adm].clk = devm_clk_get(&pdev->dev, "core_clk"); -+ if (IS_ERR(dmov_conf[adm].clk)) { -+ printk(KERN_ERR "%s: Error getting adm_clk\n", __func__); -+ dmov_conf[adm].clk = NULL; -+ return -ENOENT; -+ } -+ -+ dmov_conf[adm].pclk = devm_clk_get(&pdev->dev, "iface_clk"); -+ if (IS_ERR(dmov_conf[adm].pclk)) { -+ dmov_conf[adm].pclk = NULL; -+ /* pclk not present on all SoCs, don't bail on failure */ -+ } -+ -+ dmov_conf[adm].ebiclk = devm_clk_get(&pdev->dev, "mem_clk"); -+ if (IS_ERR(dmov_conf[adm].ebiclk)) { -+ dmov_conf[adm].ebiclk = NULL; -+ /* ebiclk not present on all SoCs, don't bail on failure */ -+ } else { -+ ret = clk_set_rate(dmov_conf[adm].ebiclk, 27000000); -+ if (ret) -+ return -ENOENT; -+ } -+ -+ return 0; -+} -+ -+static void config_datamover(int adm) -+{ -+ int i; -+ -+ /* Reset the ADM */ -+ reset_control_assert(dmov_conf[adm].adm_reset); -+ reset_control_assert(dmov_conf[adm].c0_reset); -+ reset_control_assert(dmov_conf[adm].c1_reset); -+ reset_control_assert(dmov_conf[adm].c2_reset); -+ -+ reset_control_deassert(dmov_conf[adm].c2_reset); -+ reset_control_deassert(dmov_conf[adm].c1_reset); -+ reset_control_deassert(dmov_conf[adm].c0_reset); -+ reset_control_deassert(dmov_conf[adm].adm_reset); -+ -+ for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) { -+ struct msm_dmov_chan_conf *chan_conf = -+ dmov_conf[adm].chan_conf; -+ unsigned conf; -+ /* Only configure scorpion channels */ -+ if (chan_conf[i].sd <= 1) { -+ conf = readl_relaxed(DMOV_REG(DMOV_CONF(i), adm)); -+ conf |= DMOV_CONF_MPU_DISABLE | -+ DMOV_CONF_PERM_MPU_CONF | -+ DMOV_CONF_FLUSH_RSLT_EN | -+ DMOV_CONF_FORCE_RSLT_EN | -+ DMOV_CONF_IRQ_EN | -+ DMOV_CONF_PRIORITY(chan_conf[i].priority); -+ -+ conf &= ~DMOV_CONF_SD(7); -+ conf |= DMOV_CONF_SD(chan_conf[i].sd); -+ writel_relaxed(conf, DMOV_REG(DMOV_CONF(i), adm)); -+ } -+ } -+ -+ for (i = 0; i < MSM_DMOV_CRCI_COUNT; i++) { -+ writel_relaxed(DMOV_CRCI_CTL_RST, -+ DMOV_REG(DMOV_CRCI_CTL(i), adm)); -+ } -+ -+ /* NAND CRCI Enable */ -+ writel_relaxed(0, DMOV_REG(DMOV_CRCI_CTL(DMOV_NAND_CRCI_DATA), adm)); -+ writel_relaxed(0, DMOV_REG(DMOV_CRCI_CTL(DMOV_NAND_CRCI_CMD), adm)); -+ -+ /* GSBI5 CRCI Enable */ -+ writel_relaxed(0, DMOV_REG(DMOV_CRCI_CTL(DMOV_SPI_GSBI5_RX_CRCI), adm)); -+ writel_relaxed(0, DMOV_REG(DMOV_CRCI_CTL(DMOV_SPI_GSBI5_TX_CRCI), adm)); -+ -+ writel_relaxed(DMOV_CI_CONF_RANGE_START(0x40) | /* EBI1 */ -+ DMOV_CI_CONF_RANGE_END(0xb0) | -+ DMOV_CI_CONF_MAX_BURST(0x8), -+ DMOV_REG(DMOV_CI_CONF(0), adm)); -+ -+ writel_relaxed(DMOV_CI_CONF_RANGE_START(0x2a) | /* IMEM */ -+ DMOV_CI_CONF_RANGE_END(0x2c) | -+ DMOV_CI_CONF_MAX_BURST(0x8), -+ DMOV_REG(DMOV_CI_CONF(1), adm)); -+ -+ writel_relaxed(DMOV_CI_CONF_RANGE_START(0x12) | /* CPSS/SPS */ -+ DMOV_CI_CONF_RANGE_END(0x28) | -+ DMOV_CI_CONF_MAX_BURST(0x8), -+ DMOV_REG(DMOV_CI_CONF(2), adm)); -+ -+ writel_relaxed(DMOV_HI_GP_CTL_CORE_CLK_LP_EN | /* will disable LP */ -+ DMOV_HI_GP_CTL_LP_CNT(0xf), -+ DMOV_REG(DMOV_HI_GP_CTL, adm)); -+ -+} -+ -+static int msm_dmov_probe(struct platform_device *pdev) -+{ -+ -+ int adm = (pdev->id >= 0) ? pdev->id : 0; -+ int i; -+ int ret; -+ struct resource *irqres = -+ platform_get_resource(pdev, IORESOURCE_IRQ, 0); -+ struct resource *mres = -+ platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ -+ dmov_conf[adm].sd=0; -+ dmov_conf[adm].sd_size=0x800; -+ -+ dmov_conf[adm].irq = irqres->start; -+ -+ dmov_conf[adm].base = devm_ioremap_resource(&pdev->dev, mres); -+ if (!dmov_conf[adm].base) -+ return -ENOMEM; -+ -+ dmov_conf[adm].cmd_wq = alloc_ordered_workqueue("dmov%d_wq", 0, adm); -+ if (!dmov_conf[adm].cmd_wq) { -+ PRINT_ERROR("Couldn't allocate ADM%d workqueue.\n", adm); -+ return -ENOMEM; -+ } -+ -+ /* get resets */ -+ dmov_conf[adm].adm_reset = devm_reset_control_get(&pdev->dev, "adm"); -+ if (IS_ERR(dmov_conf[adm].adm_reset)) { -+ dev_err(&pdev->dev, "failed to get adm reset\n"); -+ ret = PTR_ERR(dmov_conf[adm].adm_reset); -+ goto out_wq; -+ } -+ -+ dmov_conf[adm].pbus_reset = devm_reset_control_get(&pdev->dev, "pbus"); -+ if (IS_ERR(dmov_conf[adm].pbus_reset)) { -+ dev_err(&pdev->dev, "failed to get pbus reset\n"); -+ ret = PTR_ERR(dmov_conf[adm].pbus_reset); -+ goto out_wq; -+ } -+ -+ dmov_conf[adm].c0_reset = devm_reset_control_get(&pdev->dev, "c0"); -+ if (IS_ERR(dmov_conf[adm].c0_reset)) { -+ dev_err(&pdev->dev, "failed to get c0 reset\n"); -+ ret = PTR_ERR(dmov_conf[adm].c0_reset); -+ goto out_wq; -+ } -+ -+ dmov_conf[adm].c1_reset = devm_reset_control_get(&pdev->dev, "c1"); -+ if (IS_ERR(dmov_conf[adm].c1_reset)) { -+ dev_err(&pdev->dev, "failed to get c1 reset\n"); -+ ret = PTR_ERR(dmov_conf[adm].c1_reset); -+ goto out_wq; -+ } -+ -+ dmov_conf[adm].c2_reset = devm_reset_control_get(&pdev->dev, "c2"); -+ if (IS_ERR(dmov_conf[adm].c2_reset)) { -+ dev_err(&pdev->dev, "failed to get c2 reset\n"); -+ ret = PTR_ERR(dmov_conf[adm].c2_reset); -+ goto out_wq; -+ } -+ -+ ret = devm_request_threaded_irq(&pdev->dev, dmov_conf[adm].irq, NULL, -+ msm_dmov_isr, IRQF_ONESHOT, "msmdatamover", NULL); -+ -+ if (ret) { -+ PRINT_ERROR("Requesting ADM%d irq %d failed\n", adm, -+ dmov_conf[adm].irq); -+ goto out_wq; -+ } -+ -+ disable_irq(dmov_conf[adm].irq); -+ ret = msm_dmov_init_clocks(pdev); -+ if (ret) { -+ PRINT_ERROR("Requesting ADM%d clocks failed\n", adm); -+ goto out_wq; -+ } -+ clk_prepare_enable(dmov_conf[adm].clk); -+ clk_prepare_enable(dmov_conf[adm].pclk); -+ -+// ret = msm_dmov_clk_on(adm); -+// if (ret) { -+// PRINT_ERROR("Enabling ADM%d clocks failed\n", adm); -+// goto out_wq; -+// } -+ -+ config_datamover(adm); -+ for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) { -+ INIT_LIST_HEAD(&dmov_conf[adm].staged_commands[i]); -+ INIT_LIST_HEAD(&dmov_conf[adm].ready_commands[i]); -+ INIT_LIST_HEAD(&dmov_conf[adm].active_commands[i]); -+ -+ writel_relaxed(DMOV_RSLT_CONF_IRQ_EN -+ | DMOV_RSLT_CONF_FORCE_FLUSH_RSLT, -+ DMOV_REG(DMOV_RSLT_CONF(i), adm)); -+ } -+ wmb(); -+// msm_dmov_clk_off(adm); -+ return ret; -+out_wq: -+ destroy_workqueue(dmov_conf[adm].cmd_wq); -+ return ret; -+} -+ -+#ifdef CONFIG_OF -+static const struct of_device_id adm_of_match[] = { -+ { .compatible = "qcom,adm", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, adm_of_match); -+#endif -+ -+static struct platform_driver msm_dmov_driver = { -+ .probe = msm_dmov_probe, -+ .driver = { -+ .name = MODULE_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = adm_of_match, -+ .pm = &msm_dmov_dev_pm_ops, -+ }, -+}; -+ -+/* static int __init */ -+static int __init msm_init_datamover(void) -+{ -+ int ret; -+ ret = platform_driver_register(&msm_dmov_driver); -+ if (ret) -+ return ret; -+ return 0; -+} -+arch_initcall(msm_init_datamover); ---- /dev/null -+++ b/drivers/mtd/nand/qcom_adm_dma.h -@@ -0,0 +1,268 @@ -+/* * Copyright (c) 2012 The Linux Foundation. All rights reserved.* */ -+/* linux/include/asm-arm/arch-msm/dma.h -+ * -+ * Copyright (C) 2007 Google, Inc. -+ * Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#ifndef __ASM_ARCH_MSM_DMA_H -+#define __ASM_ARCH_MSM_DMA_H -+#include -+ -+struct msm_dmov_errdata { -+ uint32_t flush[6]; -+}; -+ -+struct msm_dmov_cmd { -+ struct list_head list; -+ unsigned int cmdptr; -+ void (*complete_func)(struct msm_dmov_cmd *cmd, -+ unsigned int result, -+ struct msm_dmov_errdata *err); -+ void (*exec_func)(struct msm_dmov_cmd *cmd); -+ struct work_struct work; -+ unsigned id; /* For internal use */ -+ void *user; /* Pointer for caller's reference */ -+ u8 toflush; -+}; -+ -+struct msm_dmov_pdata { -+ int sd; -+ size_t sd_size; -+}; -+ -+void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); -+void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd); -+void msm_dmov_flush(unsigned int id, int graceful); -+int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr); -+ -+#define DMOV_CRCIS_PER_CONF 10 -+ -+#define DMOV_ADDR(off, ch) ((off) + ((ch) << 2)) -+ -+#define DMOV_CMD_PTR(ch) DMOV_ADDR(0x000, ch) -+#define DMOV_CMD_LIST (0 << 29) /* does not work */ -+#define DMOV_CMD_PTR_LIST (1 << 29) /* works */ -+#define DMOV_CMD_INPUT_CFG (2 << 29) /* untested */ -+#define DMOV_CMD_OUTPUT_CFG (3 << 29) /* untested */ -+#define DMOV_CMD_ADDR(addr) ((addr) >> 3) -+ -+#define DMOV_RSLT(ch) DMOV_ADDR(0x040, ch) -+#define DMOV_RSLT_VALID (1 << 31) /* 0 == host has empties result fifo */ -+#define DMOV_RSLT_ERROR (1 << 3) -+#define DMOV_RSLT_FLUSH (1 << 2) -+#define DMOV_RSLT_DONE (1 << 1) /* top pointer done */ -+#define DMOV_RSLT_USER (1 << 0) /* command with FR force result */ -+ -+#define DMOV_FLUSH0(ch) DMOV_ADDR(0x080, ch) -+#define DMOV_FLUSH1(ch) DMOV_ADDR(0x0C0, ch) -+#define DMOV_FLUSH2(ch) DMOV_ADDR(0x100, ch) -+#define DMOV_FLUSH3(ch) DMOV_ADDR(0x140, ch) -+#define DMOV_FLUSH4(ch) DMOV_ADDR(0x180, ch) -+#define DMOV_FLUSH5(ch) DMOV_ADDR(0x1C0, ch) -+#define DMOV_FLUSH_TYPE (1 << 31) -+ -+#define DMOV_STATUS(ch) DMOV_ADDR(0x200, ch) -+#define DMOV_STATUS_RSLT_COUNT(n) (((n) >> 29)) -+#define DMOV_STATUS_CMD_COUNT(n) (((n) >> 27) & 3) -+#define DMOV_STATUS_RSLT_VALID (1 << 1) -+#define DMOV_STATUS_CMD_PTR_RDY (1 << 0) -+ -+#define DMOV_CONF(ch) DMOV_ADDR(0x240, ch) -+#define DMOV_CONF_SD(sd) (((sd & 4) << 11) | ((sd & 3) << 4)) -+#define DMOV_CONF_OTHER_CH_BLK_MASK(m) ((m << 0x10) & 0xffff0000) -+#define DMOV_CONF_SHADOW_EN (1 << 12) -+#define DMOV_CONF_MPU_DISABLE (1 << 11) -+#define DMOV_CONF_PERM_MPU_CONF (1 << 9) -+#define DMOV_CONF_FLUSH_RSLT_EN (1 << 8) -+#define DMOV_CONF_IRQ_EN (1 << 6) -+#define DMOV_CONF_FORCE_RSLT_EN (1 << 7) -+#define DMOV_CONF_PRIORITY(n) (n << 0) -+ -+#define DMOV_DBG_ERR(ci) DMOV_ADDR(0x280, ci) -+ -+#define DMOV_RSLT_CONF(ch) DMOV_ADDR(0x300, ch) -+#define DMOV_RSLT_CONF_FORCE_TOP_PTR_RSLT (1 << 2) -+#define DMOV_RSLT_CONF_FORCE_FLUSH_RSLT (1 << 1) -+#define DMOV_RSLT_CONF_IRQ_EN (1 << 0) -+ -+#define DMOV_ISR DMOV_ADDR(0x380, 0) -+ -+#define DMOV_CI_CONF(ci) DMOV_ADDR(0x390, ci) -+#define DMOV_CI_CONF_RANGE_END(n) ((n) << 24) -+#define DMOV_CI_CONF_RANGE_START(n) ((n) << 16) -+#define DMOV_CI_CONF_MAX_BURST(n) ((n) << 0) -+ -+#define DMOV_CI_DBG_ERR(ci) DMOV_ADDR(0x3B0, ci) -+ -+#define DMOV_CRCI_CONF0 DMOV_ADDR(0x3D0, 0) -+#define DMOV_CRCI_CONF0_CRCI9_SD (2 << 0x1b) -+ -+#define DMOV_CRCI_CONF1 DMOV_ADDR(0x3D4, 0) -+#define DMOV_CRCI_CONF0_SD(crci, sd) (sd << (crci*3)) -+#define DMOV_CRCI_CONF1_SD(crci, sd) (sd << ((crci-DMOV_CRCIS_PER_CONF)*3)) -+ -+#define DMOV_HI_GP_CTL DMOV_ADDR(0x3D8, 0) -+#define DMOV_HI_GP_CTL_CORE_CLK_LP_EN (1 << 12) -+#define DMOV_HI_GP_CTL_LP_CNT(x) (((x) & 0xf) << 8) -+#define DMOV_HI_GP_CTL_CI3_CLK_LP_EN (1 << 7) -+#define DMOV_HI_GP_CTL_CI2_CLK_LP_EN (1 << 6) -+#define DMOV_HI_GP_CTL_CI1_CLK_LP_EN (1 << 5) -+#define DMOV_HI_GP_CTL_CI0_CLK_LP_EN (1 << 4) -+ -+#define DMOV_CRCI_CTL(crci) DMOV_ADDR(0x400, crci) -+#define DMOV_CRCI_CTL_BLK_SZ(n) ((n) << 0) -+#define DMOV_CRCI_CTL_RST (1 << 17) -+#define DMOV_CRCI_MUX (1 << 18) -+ -+/* channel assignments */ -+ -+/* -+ * Format of CRCI numbers: crci number + (muxsel << 4) -+ */ -+ -+#define DMOV_GP_CHAN 9 -+ -+#define DMOV_CE_IN_CHAN 0 -+#define DMOV_CE_IN_CRCI 2 -+ -+#define DMOV_CE_OUT_CHAN 1 -+#define DMOV_CE_OUT_CRCI 3 -+ -+#define DMOV_TSIF_CHAN 2 -+#define DMOV_TSIF_CRCI 11 -+ -+#define DMOV_HSUART_GSBI6_TX_CHAN 7 -+#define DMOV_HSUART_GSBI6_TX_CRCI 6 -+ -+#define DMOV_HSUART_GSBI6_RX_CHAN 8 -+#define DMOV_HSUART_GSBI6_RX_CRCI 11 -+ -+#define DMOV_HSUART_GSBI8_TX_CHAN 7 -+#define DMOV_HSUART_GSBI8_TX_CRCI 10 -+ -+#define DMOV_HSUART_GSBI8_RX_CHAN 8 -+#define DMOV_HSUART_GSBI8_RX_CRCI 9 -+ -+#define DMOV_HSUART_GSBI9_TX_CHAN 4 -+#define DMOV_HSUART_GSBI9_TX_CRCI 13 -+ -+#define DMOV_HSUART_GSBI9_RX_CHAN 3 -+#define DMOV_HSUART_GSBI9_RX_CRCI 12 -+ -+#define DMOV_NAND_CHAN 3 -+#define DMOV_NAND_CRCI_CMD 15 -+#define DMOV_NAND_CRCI_DATA 3 -+ -+#define DMOV_SPI_GSBI5_RX_CRCI 9 -+#define DMOV_SPI_GSBI5_TX_CRCI 10 -+#define DMOV_SPI_GSBI5_RX_CHAN 6 -+#define DMOV_SPI_GSBI5_TX_CHAN 5 -+ -+/* channels for APQ8064 */ -+#define DMOV8064_CE_IN_CHAN 0 -+#define DMOV8064_CE_IN_CRCI 14 -+ -+#define DMOV8064_CE_OUT_CHAN 1 -+#define DMOV8064_CE_OUT_CRCI 15 -+ -+#define DMOV8064_TSIF_CHAN 2 -+#define DMOV8064_TSIF_CRCI 1 -+ -+/* channels for APQ8064 SGLTE*/ -+#define DMOV_APQ8064_HSUART_GSBI4_TX_CHAN 11 -+#define DMOV_APQ8064_HSUART_GSBI4_TX_CRCI 8 -+ -+#define DMOV_APQ8064_HSUART_GSBI4_RX_CHAN 10 -+#define DMOV_APQ8064_HSUART_GSBI4_RX_CRCI 7 -+ -+/* channels for MPQ8064 */ -+#define DMOV_MPQ8064_HSUART_GSBI6_TX_CHAN 7 -+#define DMOV_MPQ8064_HSUART_GSBI6_TX_CRCI 6 -+ -+#define DMOV_MPQ8064_HSUART_GSBI6_RX_CHAN 6 -+#define DMOV_MPQ8064_HSUART_GSBI6_RX_CRCI 11 -+ -+#define DMOV_IPQ806X_HSUART_GSBI6_TX_CHAN DMOV_MPQ8064_HSUART_GSBI6_TX_CHAN -+#define DMOV_IPQ806X_HSUART_GSBI6_TX_CRCI DMOV_MPQ8064_HSUART_GSBI6_TX_CRCI -+ -+#define DMOV_IPQ806X_HSUART_GSBI6_RX_CHAN DMOV_MPQ8064_HSUART_GSBI6_RX_CHAN -+#define DMOV_IPQ806X_HSUART_GSBI6_RX_CRCI DMOV_MPQ8064_HSUART_GSBI6_RX_CRCI -+ -+/* no client rate control ifc (eg, ram) */ -+#define DMOV_NONE_CRCI 0 -+ -+ -+/* If the CMD_PTR register has CMD_PTR_LIST selected, the data mover -+ * is going to walk a list of 32bit pointers as described below. Each -+ * pointer points to a *array* of dmov_s, etc structs. The last pointer -+ * in the list is marked with CMD_PTR_LP. The last struct in each array -+ * is marked with CMD_LC (see below). -+ */ -+#define CMD_PTR_ADDR(addr) ((addr) >> 3) -+#define CMD_PTR_LP (1 << 31) /* last pointer */ -+#define CMD_PTR_PT (3 << 29) /* ? */ -+ -+/* Single Item Mode */ -+typedef struct { -+ unsigned cmd; -+ unsigned src; -+ unsigned dst; -+ unsigned len; -+} dmov_s; -+ -+/* Scatter/Gather Mode */ -+typedef struct { -+ unsigned cmd; -+ unsigned src_dscr; -+ unsigned dst_dscr; -+ unsigned _reserved; -+} dmov_sg; -+ -+/* Box mode */ -+typedef struct { -+ uint32_t cmd; -+ uint32_t src_row_addr; -+ uint32_t dst_row_addr; -+ uint32_t src_dst_len; -+ uint32_t num_rows; -+ uint32_t row_offset; -+} dmov_box; -+ -+/* bits for the cmd field of the above structures */ -+ -+#define CMD_LC (1 << 31) /* last command */ -+#define CMD_FR (1 << 22) /* force result -- does not work? */ -+#define CMD_OCU (1 << 21) /* other channel unblock */ -+#define CMD_OCB (1 << 20) /* other channel block */ -+#define CMD_TCB (1 << 19) /* ? */ -+#define CMD_DAH (1 << 18) /* destination address hold -- does not work?*/ -+#define CMD_SAH (1 << 17) /* source address hold -- does not work? */ -+ -+#define CMD_MODE_SINGLE (0 << 0) /* dmov_s structure used */ -+#define CMD_MODE_SG (1 << 0) /* untested */ -+#define CMD_MODE_IND_SG (2 << 0) /* untested */ -+#define CMD_MODE_BOX (3 << 0) /* untested */ -+ -+#define CMD_DST_SWAP_BYTES (1 << 14) /* exchange each byte n with byte n+1 */ -+#define CMD_DST_SWAP_SHORTS (1 << 15) /* exchange each short n with short n+1 */ -+#define CMD_DST_SWAP_WORDS (1 << 16) /* exchange each word n with word n+1 */ -+ -+#define CMD_SRC_SWAP_BYTES (1 << 11) /* exchange each byte n with byte n+1 */ -+#define CMD_SRC_SWAP_SHORTS (1 << 12) /* exchange each short n with short n+1 */ -+#define CMD_SRC_SWAP_WORDS (1 << 13) /* exchange each word n with word n+1 */ -+ -+#define CMD_DST_CRCI(n) (((n) & 15) << 7) -+#define CMD_SRC_CRCI(n) (((n) & 15) << 3) -+ -+#endif ---- /dev/null -+++ b/drivers/mtd/nand/qcom_nand.c -@@ -0,0 +1,7455 @@ -+/* -+ * Copyright (C) 2007 Google, Inc. -+ * Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "qcom_adm_dma.h" -+ -+#include "qcom_nand.h" -+unsigned long msm_nand_phys = 0; -+unsigned long msm_nandc01_phys = 0; -+unsigned long msm_nandc10_phys = 0; -+unsigned long msm_nandc11_phys = 0; -+unsigned long ebi2_register_base = 0; -+static uint32_t dual_nand_ctlr_present; -+static uint32_t interleave_enable; -+static uint32_t enable_bch_ecc; -+static uint32_t boot_layout; -+ -+ -+#define MSM_NAND_DMA_BUFFER_SIZE SZ_8K -+#define MSM_NAND_DMA_BUFFER_SLOTS \ -+ (MSM_NAND_DMA_BUFFER_SIZE / (sizeof(((atomic_t *)0)->counter) * 8)) -+ -+#define MSM_NAND_CFG0_RAW_ONFI_IDENTIFIER 0x88000800 -+#define MSM_NAND_CFG0_RAW_ONFI_PARAM_INFO 0x88040000 -+#define MSM_NAND_CFG1_RAW_ONFI_IDENTIFIER 0x0005045d -+#define MSM_NAND_CFG1_RAW_ONFI_PARAM_INFO 0x0005045d -+ -+#define ONFI_IDENTIFIER_LENGTH 0x0004 -+#define ONFI_PARAM_INFO_LENGTH 0x0200 -+#define ONFI_PARAM_PAGE_LENGTH 0x0100 -+ -+#define ONFI_PARAMETER_PAGE_SIGNATURE 0x49464E4F -+ -+#define FLASH_READ_ONFI_IDENTIFIER_COMMAND 0x90 -+#define FLASH_READ_ONFI_IDENTIFIER_ADDRESS 0x20 -+#define FLASH_READ_ONFI_PARAMETERS_COMMAND 0xEC -+#define FLASH_READ_ONFI_PARAMETERS_ADDRESS 0x00 -+ -+#define UD_SIZE_BYTES_MASK (0x3FF << 9) -+#define SPARE_SIZE_BYTES_MASK (0xF << 23) -+#define ECC_NUM_DATA_BYTES_MASK (0x3FF << 16) -+ -+#define VERBOSE 0 -+ -+struct msm_nand_chip { -+ struct device *dev; -+ wait_queue_head_t wait_queue; -+ atomic_t dma_buffer_busy; -+ unsigned dma_channel; -+ uint8_t *dma_buffer; -+ dma_addr_t dma_addr; -+ unsigned CFG0, CFG1, CFG0_RAW, CFG1_RAW; -+ uint32_t ecc_buf_cfg; -+ uint32_t ecc_bch_cfg; -+ uint32_t ecc_parity_bytes; -+ unsigned cw_size; -+ unsigned int uncorrectable_bit_mask; -+ unsigned int num_err_mask; -+}; -+ -+#define CFG1_WIDE_FLASH (1U << 1) -+ -+/* TODO: move datamover code out */ -+ -+#define SRC_CRCI_NAND_CMD CMD_SRC_CRCI(DMOV_NAND_CRCI_CMD) -+#define DST_CRCI_NAND_CMD CMD_DST_CRCI(DMOV_NAND_CRCI_CMD) -+#define SRC_CRCI_NAND_DATA CMD_SRC_CRCI(DMOV_NAND_CRCI_DATA) -+#define DST_CRCI_NAND_DATA CMD_DST_CRCI(DMOV_NAND_CRCI_DATA) -+ -+#define msm_virt_to_dma(chip, vaddr) \ -+ ((chip)->dma_addr + \ -+ ((uint8_t *)(vaddr) - (chip)->dma_buffer)) -+ -+/** -+ * msm_nand_oob_64 - oob info for 2KB page -+ */ -+static struct nand_ecclayout msm_nand_oob_64 = { -+ .eccbytes = 40, -+ .eccpos = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, -+ }, -+ .oobavail = 16, -+ .oobfree = { -+ {30, 16}, -+ } -+}; -+ -+/** -+ * msm_nand_oob_128 - oob info for 4KB page -+ */ -+static struct nand_ecclayout msm_nand_oob_128 = { -+ .eccbytes = 80, -+ .eccpos = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, -+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, -+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, -+ }, -+ .oobavail = 32, -+ .oobfree = { -+ {70, 32}, -+ } -+}; -+ -+/** -+ * msm_nand_oob_224 - oob info for 4KB page 8Bit interface -+ */ -+static struct nand_ecclayout msm_nand_oob_224_x8 = { -+ .eccbytes = 104, -+ .eccpos = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, -+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, -+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, -+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, -+ }, -+ .oobavail = 32, -+ .oobfree = { -+ {91, 32}, -+ } -+}; -+ -+/** -+ * msm_nand_oob_224 - oob info for 4KB page 16Bit interface -+ */ -+static struct nand_ecclayout msm_nand_oob_224_x16 = { -+ .eccbytes = 112, -+ .eccpos = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -+ 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, -+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, -+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, -+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, -+ }, -+ .oobavail = 32, -+ .oobfree = { -+ {98, 32}, -+ } -+}; -+ -+/** -+ * msm_nand_oob_256 - oob info for 8KB page -+ */ -+static struct nand_ecclayout msm_nand_oob_256 = { -+ .eccbytes = 160, -+ .eccpos = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, -+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, -+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -+ 90, 91, 92, 93, 94, 96, 97, 98 , 99, 100, -+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, -+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, -+ 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, -+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, -+ 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, -+ 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, -+ }, -+ .oobavail = 64, -+ .oobfree = { -+ {151, 64}, -+ } -+}; -+ -+/** -+ * msm_onenand_oob_64 - oob info for large (2KB) page -+ */ -+static struct nand_ecclayout msm_onenand_oob_64 = { -+ .eccbytes = 20, -+ .eccpos = { -+ 8, 9, 10, 11, 12, -+ 24, 25, 26, 27, 28, -+ 40, 41, 42, 43, 44, -+ 56, 57, 58, 59, 60, -+ }, -+ .oobavail = 20, -+ .oobfree = { -+ {2, 3}, {14, 2}, {18, 3}, {30, 2}, -+ {34, 3}, {46, 2}, {50, 3}, {62, 2} -+ } -+}; -+ -+static void *msm_nand_get_dma_buffer(struct msm_nand_chip *chip, size_t size) -+{ -+ unsigned int bitmask, free_bitmask, old_bitmask; -+ unsigned int need_mask, current_need_mask; -+ int free_index; -+ -+ need_mask = (1UL << DIV_ROUND_UP(size, MSM_NAND_DMA_BUFFER_SLOTS)) - 1; -+ bitmask = atomic_read(&chip->dma_buffer_busy); -+ free_bitmask = ~bitmask; -+ while (free_bitmask) { -+ free_index = __ffs(free_bitmask); -+ current_need_mask = need_mask << free_index; -+ -+ if (size + free_index * MSM_NAND_DMA_BUFFER_SLOTS >= -+ MSM_NAND_DMA_BUFFER_SIZE) -+ return NULL; -+ -+ if ((bitmask & current_need_mask) == 0) { -+ old_bitmask = -+ atomic_cmpxchg(&chip->dma_buffer_busy, -+ bitmask, -+ bitmask | current_need_mask); -+ if (old_bitmask == bitmask) -+ return chip->dma_buffer + -+ free_index * MSM_NAND_DMA_BUFFER_SLOTS; -+ free_bitmask = 0; /* force return */ -+ } -+ /* current free range was too small, clear all free bits */ -+ /* below the top busy bit within current_need_mask */ -+ free_bitmask &= -+ ~(~0U >> (32 - fls(bitmask & current_need_mask))); -+ } -+ -+ return NULL; -+} -+ -+static void msm_nand_release_dma_buffer(struct msm_nand_chip *chip, -+ void *buffer, size_t size) -+{ -+ int index; -+ unsigned int used_mask; -+ -+ used_mask = (1UL << DIV_ROUND_UP(size, MSM_NAND_DMA_BUFFER_SLOTS)) - 1; -+ index = ((uint8_t *)buffer - chip->dma_buffer) / -+ MSM_NAND_DMA_BUFFER_SLOTS; -+ atomic_sub(used_mask << index, &chip->dma_buffer_busy); -+ -+ wake_up(&chip->wait_queue); -+} -+ -+ -+unsigned flash_rd_reg(struct msm_nand_chip *chip, unsigned addr) -+{ -+ struct { -+ dmov_s cmd; -+ unsigned cmdptr; -+ unsigned data; -+ } *dma_buffer; -+ unsigned rv; -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer( -+ chip, sizeof(*dma_buffer)))); -+ -+ dma_buffer->cmd.cmd = CMD_LC | CMD_OCB | CMD_OCU; -+ dma_buffer->cmd.src = addr; -+ dma_buffer->cmd.dst = msm_virt_to_dma(chip, &dma_buffer->data); -+ dma_buffer->cmd.len = 4; -+ -+ dma_buffer->cmdptr = -+ (msm_virt_to_dma(chip, &dma_buffer->cmd) >> 3) | CMD_PTR_LP; -+ dma_buffer->data = 0xeeeeeeee; -+ -+ mb(); -+ msm_dmov_exec_cmd( -+ chip->dma_channel, DMOV_CMD_PTR_LIST | -+ DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ rv = dma_buffer->data; -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ return rv; -+} -+ -+void flash_wr_reg(struct msm_nand_chip *chip, unsigned addr, unsigned val) -+{ -+ struct { -+ dmov_s cmd; -+ unsigned cmdptr; -+ unsigned data; -+ } *dma_buffer; -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer( -+ chip, sizeof(*dma_buffer)))); -+ -+ dma_buffer->cmd.cmd = CMD_LC | CMD_OCB | CMD_OCU; -+ dma_buffer->cmd.src = msm_virt_to_dma(chip, &dma_buffer->data); -+ dma_buffer->cmd.dst = addr; -+ dma_buffer->cmd.len = 4; -+ -+ dma_buffer->cmdptr = -+ (msm_virt_to_dma(chip, &dma_buffer->cmd) >> 3) | CMD_PTR_LP; -+ dma_buffer->data = val; -+ -+ mb(); -+ msm_dmov_exec_cmd( -+ chip->dma_channel, DMOV_CMD_PTR_LIST | -+ DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+} -+ -+/* -+ * Allocates a bounce buffer, and stores the buffer address in -+ * variable pointed to by bounce_buf. bounce_buf should point to a -+ * stack variable, to avoid SMP issues. -+ */ -+static int msm_nand_alloc_bounce(void *addr, size_t size, -+ enum dma_data_direction dir, -+ uint8_t **bounce_buf) -+{ -+ if (bounce_buf == NULL) { -+ printk(KERN_ERR "not allocating bounce buffer\n"); -+ return -EINVAL; -+ } -+ -+ *bounce_buf = kmalloc(size, GFP_KERNEL | GFP_NOFS | GFP_DMA); -+ if (*bounce_buf == NULL) { -+ printk(KERN_ERR "error alloc bounce buffer %zu\n", size); -+ return -ENOMEM; -+ } -+ -+ if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) -+ memcpy(*bounce_buf, addr, size); -+ -+ return 0; -+} -+ -+/* -+ * Maps the user buffer for DMA. If the buffer is vmalloced and the -+ * buffer crosses a page boundary, then we kmalloc a bounce buffer and -+ * copy the data into it. The bounce buffer is stored in the variable -+ * pointed to by bounce_buf, for freeing up later on. The bounce_buf -+ * should point to a stack variable, to avoid SMP issues. -+ */ -+static dma_addr_t -+msm_nand_dma_map(struct device *dev, void *addr, size_t size, -+ enum dma_data_direction dir, uint8_t **bounce_buf) -+{ -+ int ret; -+ struct page *page; -+ unsigned long offset = (unsigned long)addr & ~PAGE_MASK; -+ -+ if (virt_addr_valid(addr)) { -+ page = virt_to_page(addr); -+ } else { -+ if (size + offset > PAGE_SIZE) { -+ ret = msm_nand_alloc_bounce(addr, size, dir, bounce_buf); -+ if (ret < 0) -+ return DMA_ERROR_CODE; -+ -+ offset = (unsigned long)*bounce_buf & ~PAGE_MASK; -+ page = virt_to_page(*bounce_buf); -+ } else { -+ page = vmalloc_to_page(addr); -+ } -+ } -+ -+ return dma_map_page(dev, page, offset, size, dir); -+} -+ -+static void msm_nand_dma_unmap(struct device *dev, dma_addr_t addr, size_t size, -+ enum dma_data_direction dir, -+ void *orig_buf, void *bounce_buf) -+{ -+ dma_unmap_page(dev, addr, size, dir); -+ -+ if (bounce_buf != NULL) { -+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) -+ memcpy(orig_buf, bounce_buf, size); -+ -+ kfree(bounce_buf); -+ } -+} -+ -+uint32_t flash_read_id(struct msm_nand_chip *chip) -+{ -+ struct { -+ dmov_s cmd[9]; -+ unsigned cmdptr; -+ unsigned data[7]; -+ } *dma_buffer; -+ uint32_t rv; -+ dmov_s *cmd; -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ dma_buffer->data[0] = 0 | 4; -+ dma_buffer->data[1] = MSM_NAND_CMD_FETCH_ID; -+ dma_buffer->data[2] = 1; -+ dma_buffer->data[3] = 0xeeeeeeee; -+ dma_buffer->data[4] = 0xeeeeeeee; -+ dma_buffer->data[5] = flash_rd_reg(chip, MSM_NAND_SFLASHC_BURST_CFG); -+ dma_buffer->data[6] = 0x00000000; -+ BUILD_BUG_ON(6 != ARRAY_SIZE(dma_buffer->data) - 1); -+ -+ cmd = dma_buffer->cmd; -+ -+ cmd->cmd = 0 | CMD_OCB; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data[6]); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data[6]); -+ cmd->dst = MSM_NAND_ADDR0; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data[6]); -+ cmd->dst = MSM_NAND_ADDR1; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data[0]); -+ cmd->dst = MSM_NAND_FLASH_CHIP_SELECT; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data[1]); -+ cmd->dst = MSM_NAND_FLASH_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data[2]); -+ cmd->dst = MSM_NAND_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_FLASH_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data[3]); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_READ_ID; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data[4]); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = CMD_OCU | CMD_LC; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data[5]); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ BUILD_BUG_ON(8 != ARRAY_SIZE(dma_buffer->cmd) - 1); -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3 -+ ) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST | -+ DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ pr_info("status: %x\n", dma_buffer->data[3]); -+ pr_info("nandid: %x maker %02x device %02x\n", -+ dma_buffer->data[4], dma_buffer->data[4] & 0xff, -+ (dma_buffer->data[4] >> 8) & 0xff); -+ rv = dma_buffer->data[4]; -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ return rv; -+} -+ -+struct flash_identification { -+ uint32_t flash_id; -+ uint32_t density; -+ uint32_t widebus; -+ uint32_t pagesize; -+ uint32_t blksize; -+ uint32_t oobsize; -+ uint32_t ecc_correctability; -+} supported_flash; -+ -+uint16_t flash_onfi_crc_check(uint8_t *buffer, uint16_t count) -+{ -+ int i; -+ uint16_t result; -+ -+ for (i = 0; i < count; i++) -+ buffer[i] = bitrev8(buffer[i]); -+ -+ result = bitrev16(crc16(bitrev16(0x4f4e), buffer, count)); -+ -+ for (i = 0; i < count; i++) -+ buffer[i] = bitrev8(buffer[i]); -+ -+ return result; -+} -+ -+static void flash_reset(struct msm_nand_chip *chip) -+{ -+ struct { -+ dmov_s cmd[6]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t exec; -+ uint32_t flash_status; -+ uint32_t sflash_bcfg_orig; -+ uint32_t sflash_bcfg_mod; -+ uint32_t chip_select; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ dma_addr_t dma_cmd; -+ dma_addr_t dma_cmdptr; -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ dma_buffer->data.sflash_bcfg_orig -+ = flash_rd_reg(chip, MSM_NAND_SFLASHC_BURST_CFG); -+ dma_buffer->data.sflash_bcfg_mod = 0x00000000; -+ dma_buffer->data.chip_select = 4; -+ dma_buffer->data.cmd = MSM_NAND_CMD_RESET; -+ dma_buffer->data.exec = 1; -+ dma_buffer->data.flash_status = 0xeeeeeeee; -+ -+ cmd = dma_buffer->cmd; -+ -+ /* Put the Nand ctlr in Async mode and disable SFlash ctlr */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sflash_bcfg_mod); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.chip_select); -+ cmd->dst = MSM_NAND_FLASH_CHIP_SELECT; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready, & write Reset command */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = MSM_NAND_FLASH_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = MSM_NAND_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_FLASH_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.flash_status); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Restore the SFLASH_BURST_CONFIG register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sflash_bcfg_orig); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ BUILD_BUG_ON(6 != ARRAY_SIZE(dma_buffer->cmd)); -+ -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_cmd = msm_virt_to_dma(chip, dma_buffer->cmd); -+ dma_buffer->cmdptr = (dma_cmd >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ dma_cmdptr = msm_virt_to_dma(chip, &dma_buffer->cmdptr); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(dma_cmdptr)); -+ mb(); -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+} -+ -+uint32_t flash_onfi_probe(struct msm_nand_chip *chip) -+{ -+ -+ -+ struct onfi_param_page { -+ uint32_t parameter_page_signature; -+ uint16_t revision_number; -+ uint16_t features_supported; -+ uint16_t optional_commands_supported; -+ uint8_t reserved0[22]; -+ uint8_t device_manufacturer[12]; -+ uint8_t device_model[20]; -+ uint8_t jedec_manufacturer_id; -+ uint16_t date_code; -+ uint8_t reserved1[13]; -+ uint32_t number_of_data_bytes_per_page; -+ uint16_t number_of_spare_bytes_per_page; -+ uint32_t number_of_data_bytes_per_partial_page; -+ uint16_t number_of_spare_bytes_per_partial_page; -+ uint32_t number_of_pages_per_block; -+ uint32_t number_of_blocks_per_logical_unit; -+ uint8_t number_of_logical_units; -+ uint8_t number_of_address_cycles; -+ uint8_t number_of_bits_per_cell; -+ uint16_t maximum_bad_blocks_per_logical_unit; -+ uint16_t block_endurance; -+ uint8_t guaranteed_valid_begin_blocks; -+ uint16_t guaranteed_valid_begin_blocks_endurance; -+ uint8_t number_of_programs_per_page; -+ uint8_t partial_program_attributes; -+ uint8_t number_of_bits_ecc_correctability; -+ uint8_t number_of_interleaved_address_bits; -+ uint8_t interleaved_operation_attributes; -+ uint8_t reserved2[13]; -+ uint8_t io_pin_capacitance; -+ uint16_t timing_mode_support; -+ uint16_t program_cache_timing_mode_support; -+ uint16_t maximum_page_programming_time; -+ uint16_t maximum_block_erase_time; -+ uint16_t maximum_page_read_time; -+ uint16_t maximum_change_column_setup_time; -+ uint8_t reserved3[23]; -+ uint16_t vendor_specific_revision_number; -+ uint8_t vendor_specific[88]; -+ uint16_t integrity_crc; -+ -+ } __attribute__((__packed__)); -+ -+ struct onfi_param_page *onfi_param_page_ptr; -+ uint8_t *onfi_identifier_buf = NULL; -+ uint8_t *onfi_param_info_buf = NULL; -+ -+ struct { -+ dmov_s cmd[12]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t exec; -+ uint32_t flash_status; -+ uint32_t devcmd1_orig; -+ uint32_t devcmdvld_orig; -+ uint32_t devcmd1_mod; -+ uint32_t devcmdvld_mod; -+ uint32_t sflash_bcfg_orig; -+ uint32_t sflash_bcfg_mod; -+ uint32_t chip_select; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ unsigned page_address = 0; -+ int err = 0; -+ dma_addr_t dma_addr_param_info = 0; -+ dma_addr_t dma_addr_identifier = 0; -+ unsigned cmd_set_count = 2; -+ unsigned crc_chk_count = 0; -+ -+ /*if (msm_nand_data.nr_parts) { -+ page_address = ((msm_nand_data.parts[0]).offset << 6); -+ } else { -+ pr_err("flash_onfi_probe: " -+ "No partition info available\n"); -+ err = -EIO; -+ return err; -+ }*/ -+ -+ wait_event(chip->wait_queue, (onfi_identifier_buf = -+ msm_nand_get_dma_buffer(chip, ONFI_IDENTIFIER_LENGTH))); -+ dma_addr_identifier = msm_virt_to_dma(chip, onfi_identifier_buf); -+ -+ wait_event(chip->wait_queue, (onfi_param_info_buf = -+ msm_nand_get_dma_buffer(chip, ONFI_PARAM_INFO_LENGTH))); -+ dma_addr_param_info = msm_virt_to_dma(chip, onfi_param_info_buf); -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ dma_buffer->data.sflash_bcfg_orig = flash_rd_reg -+ (chip, MSM_NAND_SFLASHC_BURST_CFG); -+ dma_buffer->data.devcmd1_orig = flash_rd_reg(chip, MSM_NAND_DEV_CMD1); -+ dma_buffer->data.devcmdvld_orig = flash_rd_reg(chip, -+ MSM_NAND_DEV_CMD_VLD); -+ dma_buffer->data.chip_select = 4; -+ -+ while (cmd_set_count-- > 0) { -+ cmd = dma_buffer->cmd; -+ -+ dma_buffer->data.devcmd1_mod = (dma_buffer->data.devcmd1_orig & -+ 0xFFFFFF00) | (cmd_set_count -+ ? FLASH_READ_ONFI_IDENTIFIER_COMMAND -+ : FLASH_READ_ONFI_PARAMETERS_COMMAND); -+ dma_buffer->data.cmd = MSM_NAND_CMD_PAGE_READ; -+ dma_buffer->data.addr0 = (page_address << 16) | (cmd_set_count -+ ? FLASH_READ_ONFI_IDENTIFIER_ADDRESS -+ : FLASH_READ_ONFI_PARAMETERS_ADDRESS); -+ dma_buffer->data.addr1 = (page_address >> 16) & 0xFF; -+ dma_buffer->data.cfg0 = (cmd_set_count -+ ? MSM_NAND_CFG0_RAW_ONFI_IDENTIFIER -+ : MSM_NAND_CFG0_RAW_ONFI_PARAM_INFO); -+ dma_buffer->data.cfg1 = (cmd_set_count -+ ? MSM_NAND_CFG1_RAW_ONFI_IDENTIFIER -+ : MSM_NAND_CFG1_RAW_ONFI_PARAM_INFO); -+ dma_buffer->data.sflash_bcfg_mod = 0x00000000; -+ dma_buffer->data.devcmdvld_mod = (dma_buffer-> -+ data.devcmdvld_orig & 0xFFFFFFFE); -+ dma_buffer->data.exec = 1; -+ dma_buffer->data.flash_status = 0xeeeeeeee; -+ -+ /* Put the Nand ctlr in Async mode and disable SFlash ctlr */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sflash_bcfg_mod); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.chip_select); -+ cmd->dst = MSM_NAND_FLASH_CHIP_SELECT; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready, & write CMD,ADDR0,ADDR1,CHIPSEL regs */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = MSM_NAND_FLASH_CMD; -+ cmd->len = 12; -+ cmd++; -+ -+ /* Configure the CFG0 and CFG1 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = MSM_NAND_DEV0_CFG0; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Configure the DEV_CMD_VLD register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.devcmdvld_mod); -+ cmd->dst = MSM_NAND_DEV_CMD_VLD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Configure the DEV_CMD1 register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.devcmd1_mod); -+ cmd->dst = MSM_NAND_DEV_CMD1; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.exec); -+ cmd->dst = MSM_NAND_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the two status registers */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_FLASH_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.flash_status); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read data block - valid only if status says success */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_FLASH_BUFFER; -+ cmd->dst = (cmd_set_count ? dma_addr_identifier : -+ dma_addr_param_info); -+ cmd->len = (cmd_set_count ? ONFI_IDENTIFIER_LENGTH : -+ ONFI_PARAM_INFO_LENGTH); -+ cmd++; -+ -+ /* Restore the DEV_CMD1 register */ -+ cmd->cmd = 0 ; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.devcmd1_orig); -+ cmd->dst = MSM_NAND_DEV_CMD1; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Restore the DEV_CMD_VLD register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.devcmdvld_orig); -+ cmd->dst = MSM_NAND_DEV_CMD_VLD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Restore the SFLASH_BURST_CONFIG register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sflash_bcfg_orig); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ BUILD_BUG_ON(12 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) -+ >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* Check for errors, protection violations etc */ -+ if (dma_buffer->data.flash_status & 0x110) { -+ pr_info("MPU/OP error (0x%x) during " -+ "ONFI probe\n", -+ dma_buffer->data.flash_status); -+ err = -EIO; -+ break; -+ } -+ -+ if (cmd_set_count) { -+ onfi_param_page_ptr = (struct onfi_param_page *) -+ (&(onfi_identifier_buf[0])); -+ if (onfi_param_page_ptr->parameter_page_signature != -+ ONFI_PARAMETER_PAGE_SIGNATURE) { -+ pr_info("ONFI probe : Found a non" -+ "ONFI Compliant device \n"); -+ err = -EIO; -+ break; -+ } -+ } else { -+ for (crc_chk_count = 0; crc_chk_count < -+ ONFI_PARAM_INFO_LENGTH -+ / ONFI_PARAM_PAGE_LENGTH; -+ crc_chk_count++) { -+ onfi_param_page_ptr = -+ (struct onfi_param_page *) -+ (&(onfi_param_info_buf -+ [ONFI_PARAM_PAGE_LENGTH * -+ crc_chk_count])); -+ if (flash_onfi_crc_check( -+ (uint8_t *)onfi_param_page_ptr, -+ ONFI_PARAM_PAGE_LENGTH - 2) == -+ onfi_param_page_ptr->integrity_crc) { -+ break; -+ } -+ } -+ if (crc_chk_count >= ONFI_PARAM_INFO_LENGTH -+ / ONFI_PARAM_PAGE_LENGTH) { -+ pr_info("ONFI probe : CRC Check " -+ "failed on ONFI Parameter " -+ "data \n"); -+ err = -EIO; -+ break; -+ } else { -+ supported_flash.flash_id = -+ flash_read_id(chip); -+ supported_flash.widebus = -+ onfi_param_page_ptr-> -+ features_supported & 0x01; -+ supported_flash.pagesize = -+ onfi_param_page_ptr-> -+ number_of_data_bytes_per_page; -+ supported_flash.blksize = -+ onfi_param_page_ptr-> -+ number_of_pages_per_block * -+ supported_flash.pagesize; -+ supported_flash.oobsize = -+ onfi_param_page_ptr-> -+ number_of_spare_bytes_per_page; -+ supported_flash.density = -+ onfi_param_page_ptr-> -+ number_of_blocks_per_logical_unit -+ * supported_flash.blksize; -+ supported_flash.ecc_correctability = -+ onfi_param_page_ptr-> -+ number_of_bits_ecc_correctability; -+ -+ pr_info("ONFI probe : Found an ONFI " -+ "compliant device %s\n", -+ onfi_param_page_ptr->device_model); -+ -+ /* Temporary hack for MT29F4G08ABC device. -+ * Since the device is not properly adhering -+ * to ONFi specification it is reporting -+ * as 16 bit device though it is 8 bit device!!! -+ */ -+ if (!strncmp(onfi_param_page_ptr->device_model, -+ "MT29F4G08ABC", 12)) -+ supported_flash.widebus = 0; -+ } -+ } -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ msm_nand_release_dma_buffer(chip, onfi_param_info_buf, -+ ONFI_PARAM_INFO_LENGTH); -+ msm_nand_release_dma_buffer(chip, onfi_identifier_buf, -+ ONFI_IDENTIFIER_LENGTH); -+ -+ return err; -+} -+ -+static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, -+ struct mtd_oob_ops *ops) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[8 * 5 + 2]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t chipsel; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t eccbchcfg; -+ uint32_t exec; -+ uint32_t ecccfg; -+ struct { -+ uint32_t flash_status; -+ uint32_t buffer_status; -+ } result[8]; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ unsigned n; -+ unsigned page = 0; -+ uint32_t oob_len; -+ uint32_t sectordatasize; -+ uint32_t sectoroobsize; -+ int err, pageerr, rawerr; -+ dma_addr_t data_dma_addr = 0; -+ dma_addr_t oob_dma_addr = 0; -+ dma_addr_t data_dma_addr_curr = 0; -+ dma_addr_t oob_dma_addr_curr = 0; -+ uint8_t *dat_bounce_buf = NULL; -+ uint8_t *oob_bounce_buf = NULL; -+ uint32_t oob_col = 0; -+ unsigned page_count; -+ unsigned pages_read = 0; -+ unsigned start_sector = 0; -+ uint32_t ecc_errors; -+ uint32_t total_ecc_errors = 0; -+ unsigned cwperpage; -+#if VERBOSE -+ pr_info("=================================================" -+ "================\n"); -+ pr_info("%s:\nfrom 0x%llx mode %d\ndatbuf 0x%p datlen 0x%x" -+ "\noobbuf 0x%p ooblen 0x%x\n", -+ __func__, from, ops->mode, ops->datbuf, ops->len, -+ ops->oobbuf, ops->ooblen); -+#endif -+ -+ if (mtd->writesize == 2048) -+ page = from >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = from >> 12; -+ -+ oob_len = ops->ooblen; -+ cwperpage = (mtd->writesize >> 9); -+ -+ if (from & (mtd->writesize - 1)) { -+ pr_err("%s: unsupported from, 0x%llx\n", -+ __func__, from); -+ return -EINVAL; -+ } -+ if (ops->mode != MTD_OPS_RAW) { -+ if (ops->datbuf != NULL && (ops->len % mtd->writesize) != 0) { -+ /* when ops->datbuf is NULL, ops->len can be ooblen */ -+ pr_err("%s: unsupported ops->len, %d\n", -+ __func__, ops->len); -+ return -EINVAL; -+ } -+ } else { -+ if (ops->datbuf != NULL && -+ (ops->len % (mtd->writesize + mtd->oobsize)) != 0) { -+ pr_err("%s: unsupported ops->len," -+ " %d for MTD_OPS_RAW\n", __func__, ops->len); -+ return -EINVAL; -+ } -+ } -+ -+ if (ops->mode != MTD_OPS_RAW && ops->ooblen != 0 && ops->ooboffs != 0) { -+ pr_err("%s: unsupported ops->ooboffs, %d\n", -+ __func__, ops->ooboffs); -+ return -EINVAL; -+ } -+ -+ if (ops->oobbuf && !ops->datbuf && ops->mode == MTD_OPS_AUTO_OOB) -+ start_sector = cwperpage - 1; -+ -+ if (ops->oobbuf && !ops->datbuf) { -+ page_count = ops->ooblen / ((ops->mode == MTD_OPS_AUTO_OOB) ? -+ mtd->oobavail : mtd->oobsize); -+ if ((page_count == 0) && (ops->ooblen)) -+ page_count = 1; -+ } else if (ops->mode != MTD_OPS_RAW) -+ page_count = ops->len / mtd->writesize; -+ else -+ page_count = ops->len / (mtd->writesize + mtd->oobsize); -+ -+ if (ops->datbuf) { -+ data_dma_addr_curr = data_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->datbuf, ops->len, -+ DMA_FROM_DEVICE, &dat_bounce_buf); -+ if (dma_mapping_error(chip->dev, data_dma_addr)) { -+ pr_err("msm_nand_read_oob: failed to get dma addr " -+ "for %p\n", ops->datbuf); -+ return -EIO; -+ } -+ } -+ if (ops->oobbuf) { -+ memset(ops->oobbuf, 0xff, ops->ooblen); -+ oob_dma_addr_curr = oob_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->oobbuf, -+ ops->ooblen, DMA_BIDIRECTIONAL, -+ &oob_bounce_buf); -+ if (dma_mapping_error(chip->dev, oob_dma_addr)) { -+ pr_err("msm_nand_read_oob: failed to get dma addr " -+ "for %p\n", ops->oobbuf); -+ err = -EIO; -+ goto err_dma_map_oobbuf_failed; -+ } -+ } -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer( -+ chip, sizeof(*dma_buffer)))); -+ -+ oob_col = start_sector * chip->cw_size; -+ if (chip->CFG1 & CFG1_WIDE_FLASH) -+ oob_col >>= 1; -+ -+ err = 0; -+ while (page_count-- > 0) { -+ cmd = dma_buffer->cmd; -+ -+ /* CMD / ADDR0 / ADDR1 / CHIPSEL program values */ -+ if (ops->mode != MTD_OPS_RAW) { -+ dma_buffer->data.cmd = MSM_NAND_CMD_PAGE_READ_ECC; -+ dma_buffer->data.cfg0 = -+ (chip->CFG0 & ~(7U << 6)) -+ | (((cwperpage-1) - start_sector) << 6); -+ dma_buffer->data.cfg1 = chip->CFG1; -+ if (enable_bch_ecc) -+ dma_buffer->data.eccbchcfg = chip->ecc_bch_cfg; -+ } else { -+ dma_buffer->data.cmd = MSM_NAND_CMD_PAGE_READ; -+ dma_buffer->data.cfg0 = (chip->CFG0_RAW -+ & ~(7U << 6)) | ((cwperpage-1) << 6); -+ dma_buffer->data.cfg1 = chip->CFG1_RAW | -+ (chip->CFG1 & CFG1_WIDE_FLASH); -+ } -+ -+ dma_buffer->data.addr0 = (page << 16) | oob_col; -+ dma_buffer->data.addr1 = (page >> 16) & 0xff; -+ /* chipsel_0 + enable DM interface */ -+ dma_buffer->data.chipsel = 0 | 4; -+ -+ -+ /* GO bit for the EXEC register */ -+ dma_buffer->data.exec = 1; -+ -+ -+ BUILD_BUG_ON(8 != ARRAY_SIZE(dma_buffer->data.result)); -+ -+ for (n = start_sector; n < cwperpage; n++) { -+ /* flash + buffer status return words */ -+ dma_buffer->data.result[n].flash_status = 0xeeeeeeee; -+ dma_buffer->data.result[n].buffer_status = 0xeeeeeeee; -+ -+ /* block on cmd ready, then -+ * write CMD / ADDR0 / ADDR1 / CHIPSEL -+ * regs in a burst -+ */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = MSM_NAND_FLASH_CMD; -+ if (n == start_sector) -+ cmd->len = 16; -+ else -+ cmd->len = 4; -+ cmd++; -+ -+ if (n == start_sector) { -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = MSM_NAND_DEV0_CFG0; -+ if (enable_bch_ecc) -+ cmd->len = 12; -+ else -+ cmd->len = 8; -+ cmd++; -+ -+ dma_buffer->data.ecccfg = chip->ecc_buf_cfg; -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.ecccfg); -+ cmd->dst = MSM_NAND_EBI2_ECC_BUF_CFG; -+ cmd->len = 4; -+ cmd++; -+ } -+ -+ /* kick the execute register */ -+ cmd->cmd = 0; -+ cmd->src = -+ msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = MSM_NAND_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* block on data ready, then -+ * read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_FLASH_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.result[n]); -+ /* MSM_NAND_FLASH_STATUS + MSM_NAND_BUFFER_STATUS */ -+ cmd->len = 8; -+ cmd++; -+ -+ /* read data block -+ * (only valid if status says success) -+ */ -+ if (ops->datbuf) { -+ if (ops->mode != MTD_OPS_RAW) { -+ if (!boot_layout) -+ sectordatasize = (n < (cwperpage - 1)) -+ ? 516 : (512 - ((cwperpage - 1) << 2)); -+ else -+ sectordatasize = 512; -+ } else { -+ sectordatasize = chip->cw_size; -+ } -+ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_FLASH_BUFFER; -+ cmd->dst = data_dma_addr_curr; -+ data_dma_addr_curr += sectordatasize; -+ cmd->len = sectordatasize; -+ cmd++; -+ } -+ -+ if (ops->oobbuf && (n == (cwperpage - 1) -+ || ops->mode != MTD_OPS_AUTO_OOB)) { -+ cmd->cmd = 0; -+ if (n == (cwperpage - 1)) { -+ cmd->src = MSM_NAND_FLASH_BUFFER + -+ (512 - ((cwperpage - 1) << 2)); -+ sectoroobsize = (cwperpage << 2); -+ if (ops->mode != MTD_OPS_AUTO_OOB) -+ sectoroobsize += -+ chip->ecc_parity_bytes; -+ } else { -+ cmd->src = MSM_NAND_FLASH_BUFFER + 516; -+ sectoroobsize = chip->ecc_parity_bytes; -+ } -+ -+ cmd->dst = oob_dma_addr_curr; -+ if (sectoroobsize < oob_len) -+ cmd->len = sectoroobsize; -+ else -+ cmd->len = oob_len; -+ oob_dma_addr_curr += cmd->len; -+ oob_len -= cmd->len; -+ if (cmd->len > 0) -+ cmd++; -+ } -+ } -+ -+ BUILD_BUG_ON(8 * 5 + 2 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = -+ (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) -+ | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* if any of the writes failed (0x10), or there -+ * was a protection violation (0x100), we lose -+ */ -+ pageerr = rawerr = 0; -+ for (n = start_sector; n < cwperpage; n++) { -+ if (dma_buffer->data.result[n].flash_status & 0x110) { -+ rawerr = -EIO; -+ break; -+ } -+ } -+ if (rawerr) { -+ if (ops->datbuf && ops->mode != MTD_OPS_RAW) { -+ uint8_t *datbuf = ops->datbuf + -+ pages_read * mtd->writesize; -+ -+ dma_sync_single_for_cpu(chip->dev, -+ data_dma_addr_curr-mtd->writesize, -+ mtd->writesize, DMA_BIDIRECTIONAL); -+ -+ for (n = 0; n < mtd->writesize; n++) { -+ /* empty blocks read 0x54 at -+ * these offsets -+ */ -+ if ((n % 516 == 3 || n % 516 == 175) -+ && datbuf[n] == 0x54) -+ datbuf[n] = 0xff; -+ if (datbuf[n] != 0xff) { -+ pageerr = rawerr; -+ break; -+ } -+ } -+ -+ dma_sync_single_for_device(chip->dev, -+ data_dma_addr_curr-mtd->writesize, -+ mtd->writesize, DMA_BIDIRECTIONAL); -+ -+ } -+ if (ops->oobbuf) { -+ dma_sync_single_for_cpu(chip->dev, -+ oob_dma_addr_curr - (ops->ooblen - oob_len), -+ ops->ooblen - oob_len, DMA_BIDIRECTIONAL); -+ -+ for (n = 0; n < ops->ooblen; n++) { -+ if (ops->oobbuf[n] != 0xff) { -+ pageerr = rawerr; -+ break; -+ } -+ } -+ -+ dma_sync_single_for_device(chip->dev, -+ oob_dma_addr_curr - (ops->ooblen - oob_len), -+ ops->ooblen - oob_len, DMA_BIDIRECTIONAL); -+ } -+ } -+ if (pageerr) { -+ for (n = start_sector; n < cwperpage; n++) { -+ if (dma_buffer->data.result[n].buffer_status & -+ chip->uncorrectable_bit_mask) { -+ /* not thread safe */ -+ mtd->ecc_stats.failed++; -+ pageerr = -EBADMSG; -+ break; -+ } -+ } -+ } -+ if (!rawerr) { /* check for corretable errors */ -+ for (n = start_sector; n < cwperpage; n++) { -+ ecc_errors = -+ (dma_buffer->data.result[n].buffer_status -+ & chip->num_err_mask); -+ if (ecc_errors) { -+ total_ecc_errors += ecc_errors; -+ /* not thread safe */ -+ mtd->ecc_stats.corrected += ecc_errors; -+ if (ecc_errors > 1) -+ pageerr = -EUCLEAN; -+ } -+ } -+ } -+ if (pageerr && (pageerr != -EUCLEAN || err == 0)) -+ err = pageerr; -+ -+#if VERBOSE -+ if (rawerr && !pageerr) { -+ pr_err("msm_nand_read_oob %llx %x %x empty page\n", -+ (loff_t)page * mtd->writesize, ops->len, -+ ops->ooblen); -+ } else { -+ for (n = start_sector; n < cwperpage; n++) -+ pr_info("flash_status[%d] = %x,\ -+ buffr_status[%d] = %x\n", -+ n, dma_buffer->data.result[n].flash_status, -+ n, dma_buffer->data.result[n].buffer_status); -+ } -+#endif -+ if (err && err != -EUCLEAN && err != -EBADMSG) -+ break; -+ pages_read++; -+ page++; -+ } -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ if (ops->oobbuf) { -+ msm_nand_dma_unmap(chip->dev, oob_dma_addr, -+ ops->ooblen, DMA_FROM_DEVICE, -+ ops->oobbuf, oob_bounce_buf); -+ } -+err_dma_map_oobbuf_failed: -+ if (ops->datbuf) { -+ msm_nand_dma_unmap(chip->dev, data_dma_addr, -+ ops->len, DMA_BIDIRECTIONAL, -+ ops->datbuf, dat_bounce_buf); -+ } -+ -+ if (ops->mode != MTD_OPS_RAW) -+ ops->retlen = mtd->writesize * pages_read; -+ else -+ ops->retlen = (mtd->writesize + mtd->oobsize) * -+ pages_read; -+ ops->oobretlen = ops->ooblen - oob_len; -+ if (err) -+ pr_err("msm_nand_read_oob %llx %x %x failed %d, corrected %d\n", -+ from, ops->datbuf ? ops->len : 0, ops->ooblen, err, -+ total_ecc_errors); -+#if VERBOSE -+ pr_info("\n%s: ret %d, retlen %d oobretlen %d\n", -+ __func__, err, ops->retlen, ops->oobretlen); -+ -+ pr_info("===================================================" -+ "==============\n"); -+#endif -+ return err; -+} -+ -+static int msm_nand_read_oob_dualnandc(struct mtd_info *mtd, loff_t from, -+ struct mtd_oob_ops *ops) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[16 * 6 + 20]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t nandc01_addr0; -+ uint32_t nandc10_addr0; -+ uint32_t nandc11_addr1; -+ uint32_t chipsel_cs0; -+ uint32_t chipsel_cs1; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t eccbchcfg; -+ uint32_t exec; -+ uint32_t ecccfg; -+ uint32_t ebi2_chip_select_cfg0; -+ uint32_t adm_mux_data_ack_req_nc01; -+ uint32_t adm_mux_cmd_ack_req_nc01; -+ uint32_t adm_mux_data_ack_req_nc10; -+ uint32_t adm_mux_cmd_ack_req_nc10; -+ uint32_t adm_default_mux; -+ uint32_t default_ebi2_chip_select_cfg0; -+ uint32_t nc10_flash_dev_cmd_vld; -+ uint32_t nc10_flash_dev_cmd1; -+ uint32_t nc10_flash_dev_cmd_vld_default; -+ uint32_t nc10_flash_dev_cmd1_default; -+ struct { -+ uint32_t flash_status; -+ uint32_t buffer_status; -+ } result[16]; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ unsigned n; -+ unsigned page = 0; -+ uint32_t oob_len; -+ uint32_t sectordatasize; -+ uint32_t sectoroobsize; -+ int err, pageerr, rawerr; -+ dma_addr_t data_dma_addr = 0; -+ dma_addr_t oob_dma_addr = 0; -+ dma_addr_t data_dma_addr_curr = 0; -+ dma_addr_t oob_dma_addr_curr = 0; -+ uint32_t oob_col = 0; -+ unsigned page_count; -+ unsigned pages_read = 0; -+ unsigned start_sector = 0; -+ uint32_t ecc_errors; -+ uint32_t total_ecc_errors = 0; -+ unsigned cwperpage; -+ unsigned cw_offset = chip->cw_size; -+#if VERBOSE -+ pr_info("=================================================" -+ "============\n"); -+ pr_info("%s:\nfrom 0x%llx mode %d\ndatbuf 0x%p datlen 0x%x" -+ "\noobbuf 0x%p ooblen 0x%x\n\n", -+ __func__, from, ops->mode, ops->datbuf, -+ ops->len, ops->oobbuf, ops->ooblen); -+#endif -+ -+ if (mtd->writesize == 2048) -+ page = from >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = from >> 12; -+ -+ if (interleave_enable) -+ page = (from >> 1) >> 12; -+ -+ oob_len = ops->ooblen; -+ cwperpage = (mtd->writesize >> 9); -+ -+ if (from & (mtd->writesize - 1)) { -+ pr_err("%s: unsupported from, 0x%llx\n", -+ __func__, from); -+ return -EINVAL; -+ } -+ if (ops->mode != MTD_OPS_RAW) { -+ if (ops->datbuf != NULL && (ops->len % mtd->writesize) != 0) { -+ pr_err("%s: unsupported ops->len, %d\n", -+ __func__, ops->len); -+ return -EINVAL; -+ } -+ } else { -+ if (ops->datbuf != NULL && -+ (ops->len % (mtd->writesize + mtd->oobsize)) != 0) { -+ pr_err("%s: unsupported ops->len," -+ " %d for MTD_OPS_RAW\n", __func__, ops->len); -+ return -EINVAL; -+ } -+ } -+ -+ if (ops->mode != MTD_OPS_RAW && ops->ooblen != 0 && ops->ooboffs != 0) { -+ pr_err("%s: unsupported ops->ooboffs, %d\n", -+ __func__, ops->ooboffs); -+ return -EINVAL; -+ } -+ -+ if (ops->oobbuf && !ops->datbuf && ops->mode == MTD_OPS_AUTO_OOB) -+ start_sector = cwperpage - 1; -+ -+ if (ops->oobbuf && !ops->datbuf) { -+ page_count = ops->ooblen / ((ops->mode == MTD_OPS_AUTO_OOB) ? -+ mtd->oobavail : mtd->oobsize); -+ if ((page_count == 0) && (ops->ooblen)) -+ page_count = 1; -+ } else if (ops->mode != MTD_OPS_RAW) -+ page_count = ops->len / mtd->writesize; -+ else -+ page_count = ops->len / (mtd->writesize + mtd->oobsize); -+ -+ if (ops->datbuf) { -+ data_dma_addr_curr = data_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->datbuf, ops->len, -+ DMA_FROM_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, data_dma_addr)) { -+ pr_err("msm_nand_read_oob_dualnandc: " -+ "failed to get dma addr for %p\n", -+ ops->datbuf); -+ return -EIO; -+ } -+ } -+ if (ops->oobbuf) { -+ memset(ops->oobbuf, 0xff, ops->ooblen); -+ oob_dma_addr_curr = oob_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->oobbuf, -+ ops->ooblen, DMA_BIDIRECTIONAL, NULL); -+ if (dma_mapping_error(chip->dev, oob_dma_addr)) { -+ pr_err("msm_nand_read_oob_dualnandc: " -+ "failed to get dma addr for %p\n", -+ ops->oobbuf); -+ err = -EIO; -+ goto err_dma_map_oobbuf_failed; -+ } -+ } -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer( -+ chip, sizeof(*dma_buffer)))); -+ -+ oob_col = start_sector * chip->cw_size; -+ if (chip->CFG1 & CFG1_WIDE_FLASH) { -+ oob_col >>= 1; -+ cw_offset >>= 1; -+ } -+ -+ err = 0; -+ while (page_count-- > 0) { -+ cmd = dma_buffer->cmd; -+ -+ if (ops->mode != MTD_OPS_RAW) { -+ dma_buffer->data.cmd = MSM_NAND_CMD_PAGE_READ_ECC; -+ if (start_sector == (cwperpage - 1)) { -+ dma_buffer->data.cfg0 = (chip->CFG0 & -+ ~(7U << 6)); -+ } else { -+ dma_buffer->data.cfg0 = (chip->CFG0 & -+ ~(7U << 6)) -+ | (((cwperpage >> 1)-1) << 6); -+ } -+ dma_buffer->data.cfg1 = chip->CFG1; -+ if (enable_bch_ecc) -+ dma_buffer->data.eccbchcfg = chip->ecc_bch_cfg; -+ } else { -+ dma_buffer->data.cmd = MSM_NAND_CMD_PAGE_READ; -+ dma_buffer->data.cfg0 = ((chip->CFG0_RAW & -+ ~(7U << 6)) | ((((cwperpage >> 1)-1) << 6))); -+ dma_buffer->data.cfg1 = chip->CFG1_RAW | -+ (chip->CFG1 & CFG1_WIDE_FLASH); -+ } -+ -+ if (!interleave_enable) { -+ if (start_sector == (cwperpage - 1)) { -+ dma_buffer->data.nandc10_addr0 = -+ (page << 16) | oob_col; -+ dma_buffer->data.nc10_flash_dev_cmd_vld = 0xD; -+ dma_buffer->data.nc10_flash_dev_cmd1 = -+ 0xF00F3000; -+ } else { -+ dma_buffer->data.nandc01_addr0 = page << 16; -+ /* NC10 ADDR0 points to the next code word */ -+ dma_buffer->data.nandc10_addr0 = (page << 16) | -+ cw_offset; -+ dma_buffer->data.nc10_flash_dev_cmd_vld = 0x1D; -+ dma_buffer->data.nc10_flash_dev_cmd1 = -+ 0xF00FE005; -+ } -+ } else { -+ dma_buffer->data.nandc01_addr0 = -+ dma_buffer->data.nandc10_addr0 = -+ (page << 16) | oob_col; -+ } -+ /* ADDR1 */ -+ dma_buffer->data.nandc11_addr1 = (page >> 16) & 0xff; -+ -+ dma_buffer->data.adm_mux_data_ack_req_nc01 = 0x00000A3C; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc01 = 0x0000053C; -+ dma_buffer->data.adm_mux_data_ack_req_nc10 = 0x00000F28; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc10 = 0x00000F14; -+ dma_buffer->data.adm_default_mux = 0x00000FC0; -+ dma_buffer->data.nc10_flash_dev_cmd_vld_default = 0x1D; -+ dma_buffer->data.nc10_flash_dev_cmd1_default = 0xF00F3000; -+ -+ dma_buffer->data.ebi2_chip_select_cfg0 = 0x00000805; -+ dma_buffer->data.default_ebi2_chip_select_cfg0 = 0x00000801; -+ -+ /* chipsel_0 + enable DM interface */ -+ dma_buffer->data.chipsel_cs0 = (1<<4) | 4; -+ /* chipsel_1 + enable DM interface */ -+ dma_buffer->data.chipsel_cs1 = (1<<4) | 5; -+ -+ /* GO bit for the EXEC register */ -+ dma_buffer->data.exec = 1; -+ -+ BUILD_BUG_ON(16 != ARRAY_SIZE(dma_buffer->data.result)); -+ -+ for (n = start_sector; n < cwperpage; n++) { -+ /* flash + buffer status return words */ -+ dma_buffer->data.result[n].flash_status = 0xeeeeeeee; -+ dma_buffer->data.result[n].buffer_status = 0xeeeeeeee; -+ -+ if (n == start_sector) { -+ if (!interleave_enable) { -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.nc10_flash_dev_cmd_vld); -+ cmd->dst = NC10(MSM_NAND_DEV_CMD_VLD); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nc10_flash_dev_cmd1); -+ cmd->dst = NC10(MSM_NAND_DEV_CMD1); -+ cmd->len = 4; -+ cmd++; -+ -+ /* NC01, NC10 --> ADDR1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc11_addr1); -+ cmd->dst = NC11(MSM_NAND_ADDR1); -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = NC11(MSM_NAND_DEV0_CFG0); -+ if (enable_bch_ecc) -+ cmd->len = 12; -+ else -+ cmd->len = 8; -+ cmd++; -+ } else { -+ /* enable CS0 & CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ -+ /* NC01, NC10 --> ADDR1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc11_addr1); -+ cmd->dst = NC11(MSM_NAND_ADDR1); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Enable CS0 for NC01 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.chipsel_cs0); -+ cmd->dst = -+ NC01(MSM_NAND_FLASH_CHIP_SELECT); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Enable CS1 for NC10 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.chipsel_cs1); -+ cmd->dst = -+ NC10(MSM_NAND_FLASH_CHIP_SELECT); -+ cmd->len = 4; -+ cmd++; -+ -+ /* config DEV0_CFG0 & CFG1 for CS0 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = NC01(MSM_NAND_DEV0_CFG0); -+ cmd->len = 8; -+ cmd++; -+ -+ /* config DEV1_CFG0 & CFG1 for CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = NC10(MSM_NAND_DEV1_CFG0); -+ cmd->len = 8; -+ cmd++; -+ } -+ -+ dma_buffer->data.ecccfg = chip->ecc_buf_cfg; -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.ecccfg); -+ cmd->dst = NC11(MSM_NAND_EBI2_ECC_BUF_CFG); -+ cmd->len = 4; -+ cmd++; -+ -+ /* if 'only' the last code word */ -+ if (n == cwperpage - 1) { -+ /* MASK CMD ACK/REQ --> NC01 (0x53C)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_cmd_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* CMD */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cmd); -+ cmd->dst = NC10(MSM_NAND_FLASH_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* NC10 --> ADDR0 ( 0x0 ) */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc10_addr0); -+ cmd->dst = NC10(MSM_NAND_ADDR0); -+ cmd->len = 4; -+ cmd++; -+ -+ /* kick the execute reg for NC10 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.exec); -+ cmd->dst = NC10(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_data_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* block on data ready from NC10, then -+ * read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC10(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.result[n]); -+ /* MSM_NAND_FLASH_STATUS + -+ * MSM_NAND_BUFFER_STATUS -+ */ -+ cmd->len = 8; -+ cmd++; -+ } else { -+ /* NC01 --> ADDR0 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc01_addr0); -+ cmd->dst = NC01(MSM_NAND_ADDR0); -+ cmd->len = 4; -+ cmd++; -+ -+ /* NC10 --> ADDR1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc10_addr0); -+ cmd->dst = NC10(MSM_NAND_ADDR0); -+ cmd->len = 4; -+ cmd++; -+ -+ /* MASK CMD ACK/REQ --> NC10 (0xF14)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_cmd_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* CMD */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cmd); -+ cmd->dst = NC01(MSM_NAND_FLASH_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* kick the execute register for NC01*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.exec); -+ cmd->dst = NC01(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ } -+ } -+ -+ /* read data block -+ * (only valid if status says success) -+ */ -+ if (ops->datbuf || (ops->oobbuf && -+ ops->mode != MTD_OPS_AUTO_OOB)) { -+ if (ops->mode != MTD_OPS_RAW) -+ sectordatasize = (n < (cwperpage - 1)) -+ ? 516 : (512 - ((cwperpage - 1) << 2)); -+ else -+ sectordatasize = chip->cw_size; -+ -+ if (n % 2 == 0) { -+ /* MASK DATA ACK/REQ --> NC10 (0xF28)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_data_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* block on data ready from NC01, then -+ * read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC01(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.result[n]); -+ /* MSM_NAND_FLASH_STATUS + -+ * MSM_NAND_BUFFER_STATUS -+ */ -+ cmd->len = 8; -+ cmd++; -+ -+ /* MASK CMD ACK/REQ --> NC01 (0x53C)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_cmd_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* CMD */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cmd); -+ cmd->dst = NC10(MSM_NAND_FLASH_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* kick the execute register for NC10 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.exec); -+ cmd->dst = NC10(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read only when there is data -+ * buffer -+ */ -+ if (ops->datbuf) { -+ cmd->cmd = 0; -+ cmd->src = -+ NC01(MSM_NAND_FLASH_BUFFER); -+ cmd->dst = data_dma_addr_curr; -+ data_dma_addr_curr += -+ sectordatasize; -+ cmd->len = sectordatasize; -+ cmd++; -+ } -+ } else { -+ /* MASK DATA ACK/REQ --> -+ * NC01 (0xA3C) -+ */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_data_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* block on data ready from NC10 -+ * then read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = -+ NC10(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.result[n]); -+ /* MSM_NAND_FLASH_STATUS + -+ * MSM_NAND_BUFFER_STATUS -+ */ -+ cmd->len = 8; -+ cmd++; -+ if (n != cwperpage - 1) { -+ /* MASK CMD ACK/REQ --> -+ * NC10 (0xF14) -+ */ -+ cmd->cmd = 0; -+ cmd->src = -+ msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_cmd_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* CMD */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cmd); -+ cmd->dst = -+ NC01(MSM_NAND_FLASH_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* EXEC */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.exec); -+ cmd->dst = -+ NC01(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ } -+ -+ /* Read only when there is data -+ * buffer -+ */ -+ if (ops->datbuf) { -+ cmd->cmd = 0; -+ cmd->src = -+ NC10(MSM_NAND_FLASH_BUFFER); -+ cmd->dst = data_dma_addr_curr; -+ data_dma_addr_curr += -+ sectordatasize; -+ cmd->len = sectordatasize; -+ cmd++; -+ } -+ } -+ } -+ -+ if (ops->oobbuf && (n == (cwperpage - 1) -+ || ops->mode != MTD_OPS_AUTO_OOB)) { -+ cmd->cmd = 0; -+ if (n == (cwperpage - 1)) { -+ /* Use NC10 for reading the -+ * last codeword!!! -+ */ -+ cmd->src = NC10(MSM_NAND_FLASH_BUFFER) + -+ (512 - ((cwperpage - 1) << 2)); -+ sectoroobsize = (cwperpage << 2); -+ if (ops->mode != MTD_OPS_AUTO_OOB) -+ sectoroobsize += -+ chip->ecc_parity_bytes; -+ } else { -+ if (n % 2 == 0) -+ cmd->src = -+ NC01(MSM_NAND_FLASH_BUFFER) -+ + 516; -+ else -+ cmd->src = -+ NC10(MSM_NAND_FLASH_BUFFER) -+ + 516; -+ sectoroobsize = chip->ecc_parity_bytes; -+ } -+ cmd->dst = oob_dma_addr_curr; -+ if (sectoroobsize < oob_len) -+ cmd->len = sectoroobsize; -+ else -+ cmd->len = oob_len; -+ oob_dma_addr_curr += cmd->len; -+ oob_len -= cmd->len; -+ if (cmd->len > 0) -+ cmd++; -+ } -+ } -+ /* ADM --> Default mux state (0xFC0) */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_default_mux); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ if (!interleave_enable) { -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nc10_flash_dev_cmd_vld_default); -+ cmd->dst = NC10(MSM_NAND_DEV_CMD_VLD); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nc10_flash_dev_cmd1_default); -+ cmd->dst = NC10(MSM_NAND_DEV_CMD1); -+ cmd->len = 4; -+ cmd++; -+ } else { -+ /* disable CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.default_ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ } -+ -+ BUILD_BUG_ON(16 * 6 + 20 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = -+ (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) -+ | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* if any of the writes failed (0x10), or there -+ * was a protection violation (0x100), we lose -+ */ -+ pageerr = rawerr = 0; -+ for (n = start_sector; n < cwperpage; n++) { -+ if (dma_buffer->data.result[n].flash_status & 0x110) { -+ rawerr = -EIO; -+ break; -+ } -+ } -+ if (rawerr) { -+ if (ops->datbuf && ops->mode != MTD_OPS_RAW) { -+ uint8_t *datbuf = ops->datbuf + -+ pages_read * mtd->writesize; -+ -+ dma_sync_single_for_cpu(chip->dev, -+ data_dma_addr_curr-mtd->writesize, -+ mtd->writesize, DMA_BIDIRECTIONAL); -+ -+ for (n = 0; n < mtd->writesize; n++) { -+ /* empty blocks read 0x54 at -+ * these offsets -+ */ -+ if ((n % 516 == 3 || n % 516 == 175) -+ && datbuf[n] == 0x54) -+ datbuf[n] = 0xff; -+ if (datbuf[n] != 0xff) { -+ pageerr = rawerr; -+ break; -+ } -+ } -+ -+ dma_sync_single_for_device(chip->dev, -+ data_dma_addr_curr-mtd->writesize, -+ mtd->writesize, DMA_BIDIRECTIONAL); -+ -+ } -+ if (ops->oobbuf) { -+ dma_sync_single_for_cpu(chip->dev, -+ oob_dma_addr_curr - (ops->ooblen - oob_len), -+ ops->ooblen - oob_len, DMA_BIDIRECTIONAL); -+ -+ for (n = 0; n < ops->ooblen; n++) { -+ if (ops->oobbuf[n] != 0xff) { -+ pageerr = rawerr; -+ break; -+ } -+ } -+ -+ dma_sync_single_for_device(chip->dev, -+ oob_dma_addr_curr - (ops->ooblen - oob_len), -+ ops->ooblen - oob_len, DMA_BIDIRECTIONAL); -+ } -+ } -+ if (pageerr) { -+ for (n = start_sector; n < cwperpage; n++) { -+ if (dma_buffer->data.result[n].buffer_status -+ & chip->uncorrectable_bit_mask) { -+ /* not thread safe */ -+ mtd->ecc_stats.failed++; -+ pageerr = -EBADMSG; -+ break; -+ } -+ } -+ } -+ if (!rawerr) { /* check for corretable errors */ -+ for (n = start_sector; n < cwperpage; n++) { -+ ecc_errors = dma_buffer->data. -+ result[n].buffer_status -+ & chip->num_err_mask; -+ if (ecc_errors) { -+ total_ecc_errors += ecc_errors; -+ /* not thread safe */ -+ mtd->ecc_stats.corrected += ecc_errors; -+ if (ecc_errors > 1) -+ pageerr = -EUCLEAN; -+ } -+ } -+ } -+ if (pageerr && (pageerr != -EUCLEAN || err == 0)) -+ err = pageerr; -+ -+#if VERBOSE -+ if (rawerr && !pageerr) { -+ pr_err("msm_nand_read_oob_dualnandc " -+ "%llx %x %x empty page\n", -+ (loff_t)page * mtd->writesize, ops->len, -+ ops->ooblen); -+ } else { -+ for (n = start_sector; n < cwperpage; n++) { -+ if (n%2) { -+ pr_info("NC10: flash_status[%d] = %x, " -+ "buffr_status[%d] = %x\n", -+ n, dma_buffer-> -+ data.result[n].flash_status, -+ n, dma_buffer-> -+ data.result[n].buffer_status); -+ } else { -+ pr_info("NC01: flash_status[%d] = %x, " -+ "buffr_status[%d] = %x\n", -+ n, dma_buffer-> -+ data.result[n].flash_status, -+ n, dma_buffer-> -+ data.result[n].buffer_status); -+ } -+ } -+ } -+#endif -+ if (err && err != -EUCLEAN && err != -EBADMSG) -+ break; -+ pages_read++; -+ page++; -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ if (ops->oobbuf) { -+ dma_unmap_page(chip->dev, oob_dma_addr, -+ ops->ooblen, DMA_FROM_DEVICE); -+ } -+err_dma_map_oobbuf_failed: -+ if (ops->datbuf) { -+ dma_unmap_page(chip->dev, data_dma_addr, -+ ops->len, DMA_BIDIRECTIONAL); -+ } -+ -+ if (ops->mode != MTD_OPS_RAW) -+ ops->retlen = mtd->writesize * pages_read; -+ else -+ ops->retlen = (mtd->writesize + mtd->oobsize) * -+ pages_read; -+ ops->oobretlen = ops->ooblen - oob_len; -+ if (err) -+ pr_err("msm_nand_read_oob_dualnandc " -+ "%llx %x %x failed %d, corrected %d\n", -+ from, ops->datbuf ? ops->len : 0, ops->ooblen, err, -+ total_ecc_errors); -+#if VERBOSE -+ pr_info("\n%s: ret %d, retlen %d oobretlen %d\n", -+ __func__, err, ops->retlen, ops->oobretlen); -+ -+ pr_info("===================================================" -+ "==========\n"); -+#endif -+ return err; -+} -+ -+static int -+msm_nand_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ int ret; -+ struct mtd_ecc_stats stats; -+ struct mtd_oob_ops ops; -+ int (*read_oob)(struct mtd_info *, loff_t, struct mtd_oob_ops *); -+ -+ if (!dual_nand_ctlr_present) -+ read_oob = msm_nand_read_oob; -+ else -+ read_oob = msm_nand_read_oob_dualnandc; -+ -+ ops.mode = MTD_OPS_PLACE_OOB; -+ ops.retlen = 0; -+ ops.ooblen = 0; -+ ops.oobbuf = NULL; -+ ret = 0; -+ *retlen = 0; -+ stats = mtd->ecc_stats; -+ -+ if ((from & (mtd->writesize - 1)) == 0 && len == mtd->writesize) { -+ /* reading a page on page boundary */ -+ ops.len = len; -+ ops.datbuf = buf; -+ ret = read_oob(mtd, from, &ops); -+ *retlen = ops.retlen; -+ } else if (len > 0) { -+ /* reading any size on any offset. partial page is supported */ -+ u8 *bounce_buf; -+ loff_t aligned_from; -+ loff_t offset; -+ size_t actual_len; -+ -+ bounce_buf = kmalloc(mtd->writesize, GFP_KERNEL); -+ if (!bounce_buf) { -+ pr_err("%s: could not allocate memory\n", __func__); -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ops.len = mtd->writesize; -+ offset = from & (mtd->writesize - 1); -+ aligned_from = from - offset; -+ -+ for (;;) { -+ int no_copy; -+ -+ actual_len = mtd->writesize - offset; -+ if (actual_len > len) -+ actual_len = len; -+ -+ no_copy = (offset == 0 && actual_len == mtd->writesize); -+ ops.datbuf = (no_copy) ? buf : bounce_buf; -+ -+ /* -+ * MTD API requires that all the pages are to -+ * be read even if uncorrectable or -+ * correctable ECC errors occur. -+ */ -+ ret = read_oob(mtd, aligned_from, &ops); -+ if (ret == -EBADMSG || ret == -EUCLEAN) -+ ret = 0; -+ -+ if (ret < 0) -+ break; -+ -+ if (!no_copy) -+ memcpy(buf, bounce_buf + offset, actual_len); -+ -+ len -= actual_len; -+ *retlen += actual_len; -+ if (len == 0) -+ break; -+ -+ buf += actual_len; -+ offset = 0; -+ aligned_from += mtd->writesize; -+ } -+ -+ kfree(bounce_buf); -+ } -+ -+out: -+ if (ret) -+ return ret; -+ -+ if (mtd->ecc_stats.failed - stats.failed) -+ return -EBADMSG; -+ -+ if (mtd->ecc_stats.corrected - stats.corrected) -+ return -EUCLEAN; -+ -+ return 0; -+} -+ -+static int -+msm_nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ struct { -+ dmov_s cmd[8 * 7 + 2]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t chipsel; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t eccbchcfg; -+ uint32_t exec; -+ uint32_t ecccfg; -+ uint32_t clrfstatus; -+ uint32_t clrrstatus; -+ uint32_t flash_status[8]; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ unsigned n; -+ unsigned page = 0; -+ uint32_t oob_len; -+ uint32_t sectordatawritesize; -+ int err = 0; -+ dma_addr_t data_dma_addr = 0; -+ dma_addr_t oob_dma_addr = 0; -+ dma_addr_t data_dma_addr_curr = 0; -+ dma_addr_t oob_dma_addr_curr = 0; -+ uint8_t *dat_bounce_buf = NULL; -+ uint8_t *oob_bounce_buf = NULL; -+ unsigned page_count; -+ unsigned pages_written = 0; -+ unsigned cwperpage; -+#if VERBOSE -+ pr_info("=================================================" -+ "================\n"); -+ pr_info("%s:\nto 0x%llx mode %d\ndatbuf 0x%p datlen 0x%x" -+ "\noobbuf 0x%p ooblen 0x%x\n", -+ __func__, to, ops->mode, ops->datbuf, ops->len, -+ ops->oobbuf, ops->ooblen); -+#endif -+ -+ if (mtd->writesize == 2048) -+ page = to >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = to >> 12; -+ -+ oob_len = ops->ooblen; -+ cwperpage = (mtd->writesize >> 9); -+ -+ if (to & (mtd->writesize - 1)) { -+ pr_err("%s: unsupported to, 0x%llx\n", __func__, to); -+ return -EINVAL; -+ } -+ -+ if (ops->mode != MTD_OPS_RAW) { -+ if (ops->ooblen != 0 && ops->mode != MTD_OPS_AUTO_OOB) { -+ pr_err("%s: unsupported ops->mode,%d\n", -+ __func__, ops->mode); -+ return -EINVAL; -+ } -+ if ((ops->len % mtd->writesize) != 0) { -+ pr_err("%s: unsupported ops->len, %d\n", -+ __func__, ops->len); -+ return -EINVAL; -+ } -+ } else { -+ if ((ops->len % (mtd->writesize + mtd->oobsize)) != 0) { -+ pr_err("%s: unsupported ops->len, " -+ "%d for MTD_OPS_RAW mode\n", -+ __func__, ops->len); -+ return -EINVAL; -+ } -+ } -+ -+ if (ops->datbuf == NULL) { -+ pr_err("%s: unsupported ops->datbuf == NULL\n", __func__); -+ return -EINVAL; -+ } -+ if (ops->mode != MTD_OPS_RAW && ops->ooblen != 0 && ops->ooboffs != 0) { -+ pr_err("%s: unsupported ops->ooboffs, %d\n", -+ __func__, ops->ooboffs); -+ return -EINVAL; -+ } -+ -+ if (ops->datbuf) { -+ data_dma_addr_curr = data_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->datbuf, -+ ops->len, DMA_TO_DEVICE, -+ &dat_bounce_buf); -+ if (dma_mapping_error(chip->dev, data_dma_addr)) { -+ pr_err("msm_nand_write_oob: failed to get dma addr " -+ "for %p\n", ops->datbuf); -+ return -EIO; -+ } -+ } -+ if (ops->oobbuf) { -+ oob_dma_addr_curr = oob_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->oobbuf, -+ ops->ooblen, DMA_TO_DEVICE, -+ &oob_bounce_buf); -+ if (dma_mapping_error(chip->dev, oob_dma_addr)) { -+ pr_err("msm_nand_write_oob: failed to get dma addr " -+ "for %p\n", ops->oobbuf); -+ err = -EIO; -+ goto err_dma_map_oobbuf_failed; -+ } -+ } -+ if (ops->mode != MTD_OPS_RAW) -+ page_count = ops->len / mtd->writesize; -+ else -+ page_count = ops->len / (mtd->writesize + mtd->oobsize); -+ -+ wait_event(chip->wait_queue, (dma_buffer = -+ msm_nand_get_dma_buffer(chip, sizeof(*dma_buffer)))); -+ -+ while (page_count-- > 0) { -+ cmd = dma_buffer->cmd; -+ -+ if (ops->mode != MTD_OPS_RAW) { -+ dma_buffer->data.cfg0 = chip->CFG0; -+ dma_buffer->data.cfg1 = chip->CFG1; -+ if (enable_bch_ecc) -+ dma_buffer->data.eccbchcfg = chip->ecc_bch_cfg; -+ } else { -+ dma_buffer->data.cfg0 = (chip->CFG0_RAW & -+ ~(7U << 6)) | ((cwperpage-1) << 6); -+ dma_buffer->data.cfg1 = chip->CFG1_RAW | -+ (chip->CFG1 & CFG1_WIDE_FLASH); -+ } -+ -+ /* CMD / ADDR0 / ADDR1 / CHIPSEL program values */ -+ dma_buffer->data.cmd = MSM_NAND_CMD_PRG_PAGE; -+ dma_buffer->data.addr0 = page << 16; -+ dma_buffer->data.addr1 = (page >> 16) & 0xff; -+ /* chipsel_0 + enable DM interface */ -+ dma_buffer->data.chipsel = 0 | 4; -+ -+ -+ /* GO bit for the EXEC register */ -+ dma_buffer->data.exec = 1; -+ dma_buffer->data.clrfstatus = 0x00000020; -+ dma_buffer->data.clrrstatus = 0x000000C0; -+ -+ BUILD_BUG_ON(8 != ARRAY_SIZE(dma_buffer->data.flash_status)); -+ -+ for (n = 0; n < cwperpage ; n++) { -+ /* status return words */ -+ dma_buffer->data.flash_status[n] = 0xeeeeeeee; -+ /* block on cmd ready, then -+ * write CMD / ADDR0 / ADDR1 / CHIPSEL regs in a burst -+ */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = -+ msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = MSM_NAND_FLASH_CMD; -+ if (n == 0) -+ cmd->len = 16; -+ else -+ cmd->len = 4; -+ cmd++; -+ -+ if (n == 0) { -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = MSM_NAND_DEV0_CFG0; -+ if (enable_bch_ecc) -+ cmd->len = 12; -+ else -+ cmd->len = 8; -+ cmd++; -+ -+ dma_buffer->data.ecccfg = chip->ecc_buf_cfg; -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.ecccfg); -+ cmd->dst = MSM_NAND_EBI2_ECC_BUF_CFG; -+ cmd->len = 4; -+ cmd++; -+ } -+ -+ /* write data block */ -+ if (ops->mode != MTD_OPS_RAW) { -+ if (!boot_layout) -+ sectordatawritesize = (n < (cwperpage - 1)) ? -+ 516 : (512 - ((cwperpage - 1) << 2)); -+ else -+ sectordatawritesize = 512; -+ } else { -+ sectordatawritesize = chip->cw_size; -+ } -+ -+ cmd->cmd = 0; -+ cmd->src = data_dma_addr_curr; -+ data_dma_addr_curr += sectordatawritesize; -+ cmd->dst = MSM_NAND_FLASH_BUFFER; -+ cmd->len = sectordatawritesize; -+ cmd++; -+ -+ if (ops->oobbuf) { -+ if (n == (cwperpage - 1)) { -+ cmd->cmd = 0; -+ cmd->src = oob_dma_addr_curr; -+ cmd->dst = MSM_NAND_FLASH_BUFFER + -+ (512 - ((cwperpage - 1) << 2)); -+ if ((cwperpage << 2) < oob_len) -+ cmd->len = (cwperpage << 2); -+ else -+ cmd->len = oob_len; -+ oob_dma_addr_curr += cmd->len; -+ oob_len -= cmd->len; -+ if (cmd->len > 0) -+ cmd++; -+ } -+ if (ops->mode != MTD_OPS_AUTO_OOB) { -+ /* skip ecc bytes in oobbuf */ -+ if (oob_len < chip->ecc_parity_bytes) { -+ oob_dma_addr_curr += -+ chip->ecc_parity_bytes; -+ oob_len -= -+ chip->ecc_parity_bytes; -+ } else { -+ oob_dma_addr_curr += oob_len; -+ oob_len = 0; -+ } -+ } -+ } -+ -+ /* kick the execute register */ -+ cmd->cmd = 0; -+ cmd->src = -+ msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = MSM_NAND_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* block on data ready, then -+ * read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_FLASH_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.flash_status[n]); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.clrfstatus); -+ cmd->dst = MSM_NAND_FLASH_STATUS; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.clrrstatus); -+ cmd->dst = MSM_NAND_READ_STATUS; -+ cmd->len = 4; -+ cmd++; -+ -+ } -+ -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ BUILD_BUG_ON(8 * 7 + 2 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmdptr = -+ (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) | -+ CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR( -+ msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* if any of the writes failed (0x10), or there was a -+ * protection violation (0x100), or the program success -+ * bit (0x80) is unset, we lose -+ */ -+ err = 0; -+ for (n = 0; n < cwperpage; n++) { -+ if (dma_buffer->data.flash_status[n] & 0x110) { -+ err = -EIO; -+ break; -+ } -+ if (!(dma_buffer->data.flash_status[n] & 0x80)) { -+ err = -EIO; -+ break; -+ } -+ } -+ -+#if VERBOSE -+ for (n = 0; n < cwperpage; n++) -+ pr_info("write pg %d: flash_status[%d] = %x\n", page, -+ n, dma_buffer->data.flash_status[n]); -+ -+#endif -+ if (err) -+ break; -+ pages_written++; -+ page++; -+ } -+ if (ops->mode != MTD_OPS_RAW) -+ ops->retlen = mtd->writesize * pages_written; -+ else -+ ops->retlen = (mtd->writesize + mtd->oobsize) * pages_written; -+ -+ ops->oobretlen = ops->ooblen - oob_len; -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ if (ops->oobbuf) { -+ msm_nand_dma_unmap(chip->dev, oob_dma_addr, -+ ops->ooblen, DMA_TO_DEVICE, -+ ops->oobbuf, oob_bounce_buf); -+ } -+err_dma_map_oobbuf_failed: -+ if (ops->datbuf) { -+ msm_nand_dma_unmap(chip->dev, data_dma_addr, ops->len, -+ DMA_TO_DEVICE, ops->datbuf, -+ dat_bounce_buf); -+ } -+ if (err) -+ pr_err("msm_nand_write_oob %llx %x %x failed %d\n", -+ to, ops->len, ops->ooblen, err); -+ -+#if VERBOSE -+ pr_info("\n%s: ret %d, retlen %d oobretlen %d\n", -+ __func__, err, ops->retlen, ops->oobretlen); -+ -+ pr_info("===================================================" -+ "==============\n"); -+#endif -+ return err; -+} -+ -+static int -+msm_nand_write_oob_dualnandc(struct mtd_info *mtd, loff_t to, -+ struct mtd_oob_ops *ops) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ struct { -+ dmov_s cmd[16 * 6 + 18]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t nandc01_addr0; -+ uint32_t nandc10_addr0; -+ uint32_t nandc11_addr1; -+ uint32_t chipsel_cs0; -+ uint32_t chipsel_cs1; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t eccbchcfg; -+ uint32_t exec; -+ uint32_t ecccfg; -+ uint32_t cfg0_nc01; -+ uint32_t ebi2_chip_select_cfg0; -+ uint32_t adm_mux_data_ack_req_nc01; -+ uint32_t adm_mux_cmd_ack_req_nc01; -+ uint32_t adm_mux_data_ack_req_nc10; -+ uint32_t adm_mux_cmd_ack_req_nc10; -+ uint32_t adm_default_mux; -+ uint32_t default_ebi2_chip_select_cfg0; -+ uint32_t nc01_flash_dev_cmd_vld; -+ uint32_t nc10_flash_dev_cmd0; -+ uint32_t nc01_flash_dev_cmd_vld_default; -+ uint32_t nc10_flash_dev_cmd0_default; -+ uint32_t flash_status[16]; -+ uint32_t clrfstatus; -+ uint32_t clrrstatus; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ unsigned n; -+ unsigned page = 0; -+ uint32_t oob_len; -+ uint32_t sectordatawritesize; -+ int err = 0; -+ dma_addr_t data_dma_addr = 0; -+ dma_addr_t oob_dma_addr = 0; -+ dma_addr_t data_dma_addr_curr = 0; -+ dma_addr_t oob_dma_addr_curr = 0; -+ unsigned page_count; -+ unsigned pages_written = 0; -+ unsigned cwperpage; -+ unsigned cw_offset = chip->cw_size; -+#if VERBOSE -+ pr_info("=================================================" -+ "============\n"); -+ pr_info("%s:\nto 0x%llx mode %d\ndatbuf 0x%p datlen 0x%x" -+ "\noobbuf 0x%p ooblen 0x%x\n\n", -+ __func__, to, ops->mode, ops->datbuf, ops->len, -+ ops->oobbuf, ops->ooblen); -+#endif -+ -+ if (mtd->writesize == 2048) -+ page = to >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = to >> 12; -+ -+ if (interleave_enable) -+ page = (to >> 1) >> 12; -+ -+ oob_len = ops->ooblen; -+ cwperpage = (mtd->writesize >> 9); -+ -+ if (to & (mtd->writesize - 1)) { -+ pr_err("%s: unsupported to, 0x%llx\n", __func__, to); -+ return -EINVAL; -+ } -+ -+ if (ops->mode != MTD_OPS_RAW) { -+ if (ops->ooblen != 0 && ops->mode != MTD_OPS_AUTO_OOB) { -+ pr_err("%s: unsupported ops->mode,%d\n", -+ __func__, ops->mode); -+ return -EINVAL; -+ } -+ if ((ops->len % mtd->writesize) != 0) { -+ pr_err("%s: unsupported ops->len, %d\n", -+ __func__, ops->len); -+ return -EINVAL; -+ } -+ } else { -+ if ((ops->len % (mtd->writesize + mtd->oobsize)) != 0) { -+ pr_err("%s: unsupported ops->len, " -+ "%d for MTD_OPS_RAW mode\n", -+ __func__, ops->len); -+ return -EINVAL; -+ } -+ } -+ -+ if (ops->datbuf == NULL) { -+ pr_err("%s: unsupported ops->datbuf == NULL\n", __func__); -+ return -EINVAL; -+ } -+ -+ if (ops->mode != MTD_OPS_RAW && ops->ooblen != 0 && ops->ooboffs != 0) { -+ pr_err("%s: unsupported ops->ooboffs, %d\n", -+ __func__, ops->ooboffs); -+ return -EINVAL; -+ } -+ -+ if (ops->datbuf) { -+ data_dma_addr_curr = data_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->datbuf, -+ ops->len, DMA_TO_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, data_dma_addr)) { -+ pr_err("msm_nand_write_oob_dualnandc:" -+ "failed to get dma addr " -+ "for %p\n", ops->datbuf); -+ return -EIO; -+ } -+ } -+ if (ops->oobbuf) { -+ oob_dma_addr_curr = oob_dma_addr = -+ msm_nand_dma_map(chip->dev, ops->oobbuf, -+ ops->ooblen, DMA_TO_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, oob_dma_addr)) { -+ pr_err("msm_nand_write_oob_dualnandc:" -+ "failed to get dma addr " -+ "for %p\n", ops->oobbuf); -+ err = -EIO; -+ goto err_dma_map_oobbuf_failed; -+ } -+ } -+ if (ops->mode != MTD_OPS_RAW) -+ page_count = ops->len / mtd->writesize; -+ else -+ page_count = ops->len / (mtd->writesize + mtd->oobsize); -+ -+ wait_event(chip->wait_queue, (dma_buffer = -+ msm_nand_get_dma_buffer(chip, sizeof(*dma_buffer)))); -+ -+ if (chip->CFG1 & CFG1_WIDE_FLASH) -+ cw_offset >>= 1; -+ -+ dma_buffer->data.ebi2_chip_select_cfg0 = 0x00000805; -+ dma_buffer->data.adm_mux_data_ack_req_nc01 = 0x00000A3C; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc01 = 0x0000053C; -+ dma_buffer->data.adm_mux_data_ack_req_nc10 = 0x00000F28; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc10 = 0x00000F14; -+ dma_buffer->data.adm_default_mux = 0x00000FC0; -+ dma_buffer->data.default_ebi2_chip_select_cfg0 = 0x00000801; -+ dma_buffer->data.nc01_flash_dev_cmd_vld = 0x9; -+ dma_buffer->data.nc10_flash_dev_cmd0 = 0x1085D060; -+ dma_buffer->data.nc01_flash_dev_cmd_vld_default = 0x1D; -+ dma_buffer->data.nc10_flash_dev_cmd0_default = 0x1080D060; -+ dma_buffer->data.clrfstatus = 0x00000020; -+ dma_buffer->data.clrrstatus = 0x000000C0; -+ -+ while (page_count-- > 0) { -+ cmd = dma_buffer->cmd; -+ -+ if (ops->mode != MTD_OPS_RAW) { -+ dma_buffer->data.cfg0 = ((chip->CFG0 & ~(7U << 6)) -+ & ~(1 << 4)) | ((((cwperpage >> 1)-1)) << 6); -+ dma_buffer->data.cfg1 = chip->CFG1; -+ if (enable_bch_ecc) -+ dma_buffer->data.eccbchcfg = chip->ecc_bch_cfg; -+ } else { -+ dma_buffer->data.cfg0 = ((chip->CFG0_RAW & -+ ~(7U << 6)) & ~(1 << 4)) | (((cwperpage >> 1)-1) << 6); -+ dma_buffer->data.cfg1 = chip->CFG1_RAW | -+ (chip->CFG1 & CFG1_WIDE_FLASH); -+ } -+ -+ /* Disables the automatic issuing of the read -+ * status command for first NAND controller. -+ */ -+ if (!interleave_enable) -+ dma_buffer->data.cfg0_nc01 = dma_buffer->data.cfg0 -+ | (1 << 4); -+ else -+ dma_buffer->data.cfg0 |= (1 << 4); -+ -+ dma_buffer->data.cmd = MSM_NAND_CMD_PRG_PAGE; -+ dma_buffer->data.chipsel_cs0 = (1<<4) | 4; -+ dma_buffer->data.chipsel_cs1 = (1<<4) | 5; -+ -+ /* GO bit for the EXEC register */ -+ dma_buffer->data.exec = 1; -+ -+ if (!interleave_enable) { -+ dma_buffer->data.nandc01_addr0 = (page << 16) | 0x0; -+ /* NC10 ADDR0 points to the next code word */ -+ dma_buffer->data.nandc10_addr0 = -+ (page << 16) | cw_offset; -+ } else { -+ dma_buffer->data.nandc01_addr0 = -+ dma_buffer->data.nandc10_addr0 = (page << 16) | 0x0; -+ } -+ /* ADDR1 */ -+ dma_buffer->data.nandc11_addr1 = (page >> 16) & 0xff; -+ -+ BUILD_BUG_ON(16 != ARRAY_SIZE(dma_buffer->data.flash_status)); -+ -+ for (n = 0; n < cwperpage; n++) { -+ /* status return words */ -+ dma_buffer->data.flash_status[n] = 0xeeeeeeee; -+ -+ if (n == 0) { -+ if (!interleave_enable) { -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.nc01_flash_dev_cmd_vld); -+ cmd->dst = NC01(MSM_NAND_DEV_CMD_VLD); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nc10_flash_dev_cmd0); -+ cmd->dst = NC10(MSM_NAND_DEV_CMD0); -+ cmd->len = 4; -+ cmd++; -+ -+ /* common settings for both NC01 & NC10 -+ * NC01, NC10 --> ADDR1 / CHIPSEL -+ */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc11_addr1); -+ cmd->dst = NC11(MSM_NAND_ADDR1); -+ cmd->len = 8; -+ cmd++; -+ -+ /* Disables the automatic issue of the -+ * read status command after the write -+ * operation. -+ */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0_nc01); -+ cmd->dst = NC01(MSM_NAND_DEV0_CFG0); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = NC10(MSM_NAND_DEV0_CFG0); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg1); -+ cmd->dst = NC11(MSM_NAND_DEV0_CFG1); -+ if (enable_bch_ecc) -+ cmd->len = 8; -+ else -+ cmd->len = 4; -+ cmd++; -+ } else { -+ /* enable CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ -+ /* NC11 --> ADDR1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc11_addr1); -+ cmd->dst = NC11(MSM_NAND_ADDR1); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Enable CS0 for NC01 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.chipsel_cs0); -+ cmd->dst = -+ NC01(MSM_NAND_FLASH_CHIP_SELECT); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Enable CS1 for NC10 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.chipsel_cs1); -+ cmd->dst = -+ NC10(MSM_NAND_FLASH_CHIP_SELECT); -+ cmd->len = 4; -+ cmd++; -+ -+ /* config DEV0_CFG0 & CFG1 for CS0 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = NC01(MSM_NAND_DEV0_CFG0); -+ cmd->len = 8; -+ cmd++; -+ -+ /* config DEV1_CFG0 & CFG1 for CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cfg0); -+ cmd->dst = NC10(MSM_NAND_DEV1_CFG0); -+ cmd->len = 8; -+ cmd++; -+ } -+ -+ dma_buffer->data.ecccfg = chip->ecc_buf_cfg; -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.ecccfg); -+ cmd->dst = NC11(MSM_NAND_EBI2_ECC_BUF_CFG); -+ cmd->len = 4; -+ cmd++; -+ -+ /* NC01 --> ADDR0 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc01_addr0); -+ cmd->dst = NC01(MSM_NAND_ADDR0); -+ cmd->len = 4; -+ cmd++; -+ -+ /* NC10 --> ADDR0 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nandc10_addr0); -+ cmd->dst = NC10(MSM_NAND_ADDR0); -+ cmd->len = 4; -+ cmd++; -+ } -+ -+ if (n % 2 == 0) { -+ /* MASK CMD ACK/REQ --> NC10 (0xF14)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_cmd_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* CMD */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cmd); -+ cmd->dst = NC01(MSM_NAND_FLASH_CMD); -+ cmd->len = 4; -+ cmd++; -+ } else { -+ /* MASK CMD ACK/REQ --> NC01 (0x53C)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_cmd_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* CMD */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.cmd); -+ cmd->dst = NC10(MSM_NAND_FLASH_CMD); -+ cmd->len = 4; -+ cmd++; -+ } -+ -+ if (ops->mode != MTD_OPS_RAW) -+ sectordatawritesize = (n < (cwperpage - 1)) ? -+ 516 : (512 - ((cwperpage - 1) << 2)); -+ else -+ sectordatawritesize = chip->cw_size; -+ -+ cmd->cmd = 0; -+ cmd->src = data_dma_addr_curr; -+ data_dma_addr_curr += sectordatawritesize; -+ -+ if (n % 2 == 0) -+ cmd->dst = NC01(MSM_NAND_FLASH_BUFFER); -+ else -+ cmd->dst = NC10(MSM_NAND_FLASH_BUFFER); -+ cmd->len = sectordatawritesize; -+ cmd++; -+ -+ if (ops->oobbuf) { -+ if (n == (cwperpage - 1)) { -+ cmd->cmd = 0; -+ cmd->src = oob_dma_addr_curr; -+ cmd->dst = NC10(MSM_NAND_FLASH_BUFFER) + -+ (512 - ((cwperpage - 1) << 2)); -+ if ((cwperpage << 2) < oob_len) -+ cmd->len = (cwperpage << 2); -+ else -+ cmd->len = oob_len; -+ oob_dma_addr_curr += cmd->len; -+ oob_len -= cmd->len; -+ if (cmd->len > 0) -+ cmd++; -+ } -+ if (ops->mode != MTD_OPS_AUTO_OOB) { -+ /* skip ecc bytes in oobbuf */ -+ if (oob_len < chip->ecc_parity_bytes) { -+ oob_dma_addr_curr += -+ chip->ecc_parity_bytes; -+ oob_len -= -+ chip->ecc_parity_bytes; -+ } else { -+ oob_dma_addr_curr += oob_len; -+ oob_len = 0; -+ } -+ } -+ } -+ -+ if (n % 2 == 0) { -+ if (n != 0) { -+ /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer-> -+ data.adm_mux_data_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* block on data ready from NC10, then -+ * read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC10(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.flash_status[n-1]); -+ cmd->len = 4; -+ cmd++; -+ } -+ /* kick the NC01 execute register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.exec); -+ cmd->dst = NC01(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ } else { -+ /* MASK DATA ACK/REQ --> NC10 (0xF28)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_data_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* block on data ready from NC01, then -+ * read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC01(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.flash_status[n-1]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* kick the execute register */ -+ cmd->cmd = 0; -+ cmd->src = -+ msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = NC10(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ } -+ } -+ -+ /* MASK DATA ACK/REQ --> NC01 (0xA3C)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_data_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* we should process outstanding request */ -+ /* block on data ready, then -+ * read the status register -+ */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC10(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.flash_status[n-1]); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.clrfstatus); -+ cmd->dst = NC11(MSM_NAND_FLASH_STATUS); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.clrrstatus); -+ cmd->dst = NC11(MSM_NAND_READ_STATUS); -+ cmd->len = 4; -+ cmd++; -+ -+ /* MASK DATA ACK/REQ --> NC01 (0xFC0)*/ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_default_mux); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ if (!interleave_enable) { -+ /* setting to defalut values back */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nc01_flash_dev_cmd_vld_default); -+ cmd->dst = NC01(MSM_NAND_DEV_CMD_VLD); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.nc10_flash_dev_cmd0_default); -+ cmd->dst = NC10(MSM_NAND_DEV_CMD0); -+ cmd->len = 4; -+ cmd++; -+ } else { -+ /* disable CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.default_ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ } -+ -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ BUILD_BUG_ON(16 * 6 + 18 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmdptr = -+ ((msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) | CMD_PTR_LP); -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR( -+ msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* if any of the writes failed (0x10), or there was a -+ * protection violation (0x100), or the program success -+ * bit (0x80) is unset, we lose -+ */ -+ err = 0; -+ for (n = 0; n < cwperpage; n++) { -+ if (dma_buffer->data.flash_status[n] & 0x110) { -+ err = -EIO; -+ break; -+ } -+ if (!(dma_buffer->data.flash_status[n] & 0x80)) { -+ err = -EIO; -+ break; -+ } -+ } -+ /* check for flash status busy for the last codeword */ -+ if (!interleave_enable) -+ if (!(dma_buffer->data.flash_status[cwperpage - 1] -+ & 0x20)) { -+ err = -EIO; -+ break; -+ } -+#if VERBOSE -+ for (n = 0; n < cwperpage; n++) { -+ if (n%2) { -+ pr_info("NC10: write pg %d: flash_status[%d] = %x\n", -+ page, n, dma_buffer->data.flash_status[n]); -+ } else { -+ pr_info("NC01: write pg %d: flash_status[%d] = %x\n", -+ page, n, dma_buffer->data.flash_status[n]); -+ } -+ } -+#endif -+ if (err) -+ break; -+ pages_written++; -+ page++; -+ } -+ if (ops->mode != MTD_OPS_RAW) -+ ops->retlen = mtd->writesize * pages_written; -+ else -+ ops->retlen = (mtd->writesize + mtd->oobsize) * pages_written; -+ -+ ops->oobretlen = ops->ooblen - oob_len; -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ if (ops->oobbuf) -+ dma_unmap_page(chip->dev, oob_dma_addr, -+ ops->ooblen, DMA_TO_DEVICE); -+err_dma_map_oobbuf_failed: -+ if (ops->datbuf) -+ dma_unmap_page(chip->dev, data_dma_addr, ops->len, -+ DMA_TO_DEVICE); -+ if (err) -+ pr_err("msm_nand_write_oob_dualnandc %llx %x %x failed %d\n", -+ to, ops->len, ops->ooblen, err); -+ -+#if VERBOSE -+ pr_info("\n%s: ret %d, retlen %d oobretlen %d\n", -+ __func__, err, ops->retlen, ops->oobretlen); -+ -+ pr_info("===================================================" -+ "==========\n"); -+#endif -+ return err; -+} -+ -+static int msm_nand_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ int ret; -+ struct mtd_oob_ops ops; -+ int (*write_oob)(struct mtd_info *, loff_t, struct mtd_oob_ops *); -+ -+ if (!dual_nand_ctlr_present) -+ write_oob = msm_nand_write_oob; -+ else -+ write_oob = msm_nand_write_oob_dualnandc; -+ -+ ops.mode = MTD_OPS_PLACE_OOB; -+ ops.retlen = 0; -+ ops.ooblen = 0; -+ ops.oobbuf = NULL; -+ ret = 0; -+ *retlen = 0; -+ -+ if (!virt_addr_valid(buf) && -+ ((to | len) & (mtd->writesize - 1)) == 0 && -+ ((unsigned long) buf & ~PAGE_MASK) + len > PAGE_SIZE) { -+ /* -+ * Handle writing of large size write buffer in vmalloc -+ * address space that does not fit in an MMU page. -+ * The destination address must be on page boundary, -+ * and the size must be multiple of NAND page size. -+ * Writing partial page is not supported. -+ */ -+ ops.len = mtd->writesize; -+ -+ for (;;) { -+ ops.datbuf = (uint8_t *) buf; -+ -+ ret = write_oob(mtd, to, &ops); -+ if (ret < 0) -+ break; -+ -+ len -= mtd->writesize; -+ *retlen += mtd->writesize; -+ if (len == 0) -+ break; -+ -+ buf += mtd->writesize; -+ to += mtd->writesize; -+ } -+ } else { -+ ops.len = len; -+ ops.datbuf = (uint8_t *) buf; -+ ret = write_oob(mtd, to, &ops); -+ *retlen = ops.retlen; -+ } -+ -+ return ret; -+} -+ -+static int -+msm_nand_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ int err; -+ struct msm_nand_chip *chip = mtd->priv; -+ struct { -+ dmov_s cmd[6]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t chipsel; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t exec; -+ uint32_t flash_status; -+ uint32_t clrfstatus; -+ uint32_t clrrstatus; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ unsigned page = 0; -+ -+ if (mtd->writesize == 2048) -+ page = instr->addr >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = instr->addr >> 12; -+ -+ if (instr->addr & (mtd->erasesize - 1)) { -+ pr_err("%s: unsupported erase address, 0x%llx\n", -+ __func__, instr->addr); -+ return -EINVAL; -+ } -+ if (instr->len != mtd->erasesize) { -+ pr_err("%s: unsupported erase len, %lld\n", -+ __func__, instr->len); -+ return -EINVAL; -+ } -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer( -+ chip, sizeof(*dma_buffer)))); -+ -+ cmd = dma_buffer->cmd; -+ -+ dma_buffer->data.cmd = MSM_NAND_CMD_BLOCK_ERASE; -+ dma_buffer->data.addr0 = page; -+ dma_buffer->data.addr1 = 0; -+ dma_buffer->data.chipsel = 0 | 4; -+ dma_buffer->data.exec = 1; -+ dma_buffer->data.flash_status = 0xeeeeeeee; -+ dma_buffer->data.cfg0 = chip->CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */ -+ dma_buffer->data.cfg1 = chip->CFG1; -+ dma_buffer->data.clrfstatus = 0x00000020; -+ dma_buffer->data.clrrstatus = 0x000000C0; -+ -+ cmd->cmd = DST_CRCI_NAND_CMD | CMD_OCB; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = MSM_NAND_FLASH_CMD; -+ cmd->len = 16; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cfg0); -+ cmd->dst = MSM_NAND_DEV0_CFG0; -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = MSM_NAND_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_FLASH_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.flash_status); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.clrfstatus); -+ cmd->dst = MSM_NAND_FLASH_STATUS; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = CMD_OCU | CMD_LC; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.clrrstatus); -+ cmd->dst = MSM_NAND_READ_STATUS; -+ cmd->len = 4; -+ cmd++; -+ -+ BUILD_BUG_ON(5 != ARRAY_SIZE(dma_buffer->cmd) - 1); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmdptr = -+ (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd( -+ chip->dma_channel, DMOV_CMD_PTR_LIST | -+ DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* we fail if there was an operation error, a mpu error, or the -+ * erase success bit was not set. -+ */ -+ -+ if (dma_buffer->data.flash_status & 0x110 || -+ !(dma_buffer->data.flash_status & 0x80)) -+ err = -EIO; -+ else -+ err = 0; -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ if (err) { -+ pr_err("%s: erase failed, 0x%llx\n", __func__, instr->addr); -+ instr->fail_addr = instr->addr; -+ instr->state = MTD_ERASE_FAILED; -+ } else { -+ instr->state = MTD_ERASE_DONE; -+ instr->fail_addr = 0xffffffff; -+ mtd_erase_callback(instr); -+ } -+ return err; -+} -+ -+static int -+msm_nand_erase_dualnandc(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ int err; -+ struct msm_nand_chip *chip = mtd->priv; -+ struct { -+ dmov_s cmd[18]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t chipsel_cs0; -+ uint32_t chipsel_cs1; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t exec; -+ uint32_t ecccfg; -+ uint32_t ebi2_chip_select_cfg0; -+ uint32_t adm_mux_data_ack_req_nc01; -+ uint32_t adm_mux_cmd_ack_req_nc01; -+ uint32_t adm_mux_data_ack_req_nc10; -+ uint32_t adm_mux_cmd_ack_req_nc10; -+ uint32_t adm_default_mux; -+ uint32_t default_ebi2_chip_select_cfg0; -+ uint32_t nc01_flash_dev_cmd0; -+ uint32_t nc01_flash_dev_cmd0_default; -+ uint32_t flash_status[2]; -+ uint32_t clrfstatus; -+ uint32_t clrrstatus; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ unsigned page = 0; -+ -+ if (mtd->writesize == 2048) -+ page = instr->addr >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = instr->addr >> 12; -+ -+ if (mtd->writesize == 8192) -+ page = (instr->addr >> 1) >> 12; -+ -+ if (instr->addr & (mtd->erasesize - 1)) { -+ pr_err("%s: unsupported erase address, 0x%llx\n", -+ __func__, instr->addr); -+ return -EINVAL; -+ } -+ if (instr->len != mtd->erasesize) { -+ pr_err("%s: unsupported erase len, %lld\n", -+ __func__, instr->len); -+ return -EINVAL; -+ } -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer( -+ chip, sizeof(*dma_buffer)))); -+ -+ cmd = dma_buffer->cmd; -+ -+ dma_buffer->data.cmd = MSM_NAND_CMD_BLOCK_ERASE; -+ dma_buffer->data.addr0 = page; -+ dma_buffer->data.addr1 = 0; -+ dma_buffer->data.chipsel_cs0 = (1<<4) | 4; -+ dma_buffer->data.chipsel_cs1 = (1<<4) | 5; -+ dma_buffer->data.exec = 1; -+ dma_buffer->data.flash_status[0] = 0xeeeeeeee; -+ dma_buffer->data.flash_status[1] = 0xeeeeeeee; -+ dma_buffer->data.cfg0 = chip->CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */ -+ dma_buffer->data.cfg1 = chip->CFG1; -+ dma_buffer->data.clrfstatus = 0x00000020; -+ dma_buffer->data.clrrstatus = 0x000000C0; -+ -+ dma_buffer->data.ebi2_chip_select_cfg0 = 0x00000805; -+ dma_buffer->data.adm_mux_data_ack_req_nc01 = 0x00000A3C; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc01 = 0x0000053C; -+ dma_buffer->data.adm_mux_data_ack_req_nc10 = 0x00000F28; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc10 = 0x00000F14; -+ dma_buffer->data.adm_default_mux = 0x00000FC0; -+ dma_buffer->data.default_ebi2_chip_select_cfg0 = 0x00000801; -+ -+ /* enable CS1 */ -+ cmd->cmd = 0 | CMD_OCB; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ -+ /* erase CS0 block now !!! */ -+ /* 0xF14 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_cmd_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = NC01(MSM_NAND_FLASH_CMD); -+ cmd->len = 16; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cfg0); -+ cmd->dst = NC01(MSM_NAND_DEV0_CFG0); -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = NC01(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* 0xF28 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_data_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC01(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.flash_status[0]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* erase CS1 block now !!! */ -+ /* 0x53C */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_cmd_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = NC10(MSM_NAND_FLASH_CMD); -+ cmd->len = 12; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.chipsel_cs1); -+ cmd->dst = NC10(MSM_NAND_FLASH_CHIP_SELECT); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cfg0); -+ cmd->dst = NC10(MSM_NAND_DEV1_CFG0); -+ cmd->len = 8; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = NC10(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* 0xA3C */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_data_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC10(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.flash_status[1]); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.clrfstatus); -+ cmd->dst = NC11(MSM_NAND_FLASH_STATUS); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.clrrstatus); -+ cmd->dst = NC11(MSM_NAND_READ_STATUS); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_default_mux); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* disable CS1 */ -+ cmd->cmd = CMD_OCU | CMD_LC; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.default_ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ -+ BUILD_BUG_ON(17 != ARRAY_SIZE(dma_buffer->cmd) - 1); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ -+ dma_buffer->cmdptr = -+ (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd( -+ chip->dma_channel, DMOV_CMD_PTR_LIST | -+ DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* we fail if there was an operation error, a mpu error, or the -+ * erase success bit was not set. -+ */ -+ -+ if (dma_buffer->data.flash_status[0] & 0x110 || -+ !(dma_buffer->data.flash_status[0] & 0x80) || -+ dma_buffer->data.flash_status[1] & 0x110 || -+ !(dma_buffer->data.flash_status[1] & 0x80)) -+ err = -EIO; -+ else -+ err = 0; -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ if (err) { -+ pr_err("%s: erase failed, 0x%llx\n", __func__, instr->addr); -+ instr->fail_addr = instr->addr; -+ instr->state = MTD_ERASE_FAILED; -+ } else { -+ instr->state = MTD_ERASE_DONE; -+ instr->fail_addr = 0xffffffff; -+ mtd_erase_callback(instr); -+ } -+ return err; -+} -+ -+static int -+msm_nand_block_isbad(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ int ret; -+ struct { -+ dmov_s cmd[5]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t chipsel; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t eccbchcfg; -+ uint32_t exec; -+ uint32_t ecccfg; -+ struct { -+ uint32_t flash_status; -+ uint32_t buffer_status; -+ } result; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ uint8_t *buf; -+ unsigned page = 0; -+ unsigned cwperpage; -+ -+ if (mtd->writesize == 2048) -+ page = ofs >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = ofs >> 12; -+ -+ cwperpage = (mtd->writesize >> 9); -+ -+ /* Check for invalid offset */ -+ if (ofs > mtd->size) -+ return -EINVAL; -+ if (ofs & (mtd->erasesize - 1)) { -+ pr_err("%s: unsupported block address, 0x%x\n", -+ __func__, (uint32_t)ofs); -+ return -EINVAL; -+ } -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer(chip , -+ sizeof(*dma_buffer) + 4))); -+ buf = (uint8_t *)dma_buffer + sizeof(*dma_buffer); -+ -+ /* Read 4 bytes starting from the bad block marker location -+ * in the last code word of the page -+ */ -+ -+ cmd = dma_buffer->cmd; -+ -+ dma_buffer->data.cmd = MSM_NAND_CMD_PAGE_READ; -+ dma_buffer->data.cfg0 = chip->CFG0_RAW & ~(7U << 6); -+ dma_buffer->data.cfg1 = chip->CFG1_RAW | -+ (chip->CFG1 & CFG1_WIDE_FLASH); -+ if (enable_bch_ecc) -+ dma_buffer->data.eccbchcfg = chip->ecc_bch_cfg; -+ -+ if (chip->CFG1 & CFG1_WIDE_FLASH) -+ dma_buffer->data.addr0 = (page << 16) | -+ ((chip->cw_size * (cwperpage-1)) >> 1); -+ else -+ dma_buffer->data.addr0 = (page << 16) | -+ (chip->cw_size * (cwperpage-1)); -+ -+ dma_buffer->data.addr1 = (page >> 16) & 0xff; -+ dma_buffer->data.chipsel = 0 | 4; -+ -+ dma_buffer->data.exec = 1; -+ -+ dma_buffer->data.result.flash_status = 0xeeeeeeee; -+ dma_buffer->data.result.buffer_status = 0xeeeeeeee; -+ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = MSM_NAND_FLASH_CMD; -+ cmd->len = 16; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cfg0); -+ cmd->dst = MSM_NAND_DEV0_CFG0; -+ if (enable_bch_ecc) -+ cmd->len = 12; -+ else -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = MSM_NAND_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_FLASH_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.result); -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_FLASH_BUFFER + -+ (mtd->writesize - (chip->cw_size * (cwperpage-1))); -+ cmd->dst = msm_virt_to_dma(chip, buf); -+ cmd->len = 4; -+ cmd++; -+ -+ BUILD_BUG_ON(5 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, -+ dma_buffer->cmd) >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST | -+ DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ ret = 0; -+ if (dma_buffer->data.result.flash_status & 0x110) -+ ret = -EIO; -+ -+ if (!ret) { -+ /* Check for bad block marker byte */ -+ if (chip->CFG1 & CFG1_WIDE_FLASH) { -+ if (buf[0] != 0xFF || buf[1] != 0xFF) -+ ret = 1; -+ } else { -+ if (buf[0] != 0xFF) -+ ret = 1; -+ } -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer) + 4); -+ return ret; -+} -+ -+static int -+msm_nand_block_isbad_dualnandc(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ int ret; -+ struct { -+ dmov_s cmd[18]; -+ unsigned cmdptr; -+ struct { -+ uint32_t cmd; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t chipsel_cs0; -+ uint32_t chipsel_cs1; -+ uint32_t cfg0; -+ uint32_t cfg1; -+ uint32_t exec; -+ uint32_t ecccfg; -+ uint32_t ebi2_chip_select_cfg0; -+ uint32_t adm_mux_data_ack_req_nc01; -+ uint32_t adm_mux_cmd_ack_req_nc01; -+ uint32_t adm_mux_data_ack_req_nc10; -+ uint32_t adm_mux_cmd_ack_req_nc10; -+ uint32_t adm_default_mux; -+ uint32_t default_ebi2_chip_select_cfg0; -+ struct { -+ uint32_t flash_status; -+ uint32_t buffer_status; -+ } result[2]; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ uint8_t *buf01; -+ uint8_t *buf10; -+ unsigned page = 0; -+ unsigned cwperpage; -+ -+ if (mtd->writesize == 2048) -+ page = ofs >> 11; -+ -+ if (mtd->writesize == 4096) -+ page = ofs >> 12; -+ -+ if (mtd->writesize == 8192) -+ page = (ofs >> 1) >> 12; -+ -+ cwperpage = ((mtd->writesize >> 1) >> 9); -+ -+ /* Check for invalid offset */ -+ if (ofs > mtd->size) -+ return -EINVAL; -+ if (ofs & (mtd->erasesize - 1)) { -+ pr_err("%s: unsupported block address, 0x%x\n", -+ __func__, (uint32_t)ofs); -+ return -EINVAL; -+ } -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer(chip , -+ sizeof(*dma_buffer) + 8))); -+ buf01 = (uint8_t *)dma_buffer + sizeof(*dma_buffer); -+ buf10 = buf01 + 4; -+ -+ /* Read 4 bytes starting from the bad block marker location -+ * in the last code word of the page -+ */ -+ cmd = dma_buffer->cmd; -+ -+ dma_buffer->data.cmd = MSM_NAND_CMD_PAGE_READ; -+ dma_buffer->data.cfg0 = chip->CFG0_RAW & ~(7U << 6); -+ dma_buffer->data.cfg1 = chip->CFG1_RAW | -+ (chip->CFG1 & CFG1_WIDE_FLASH); -+ -+ if (chip->CFG1 & CFG1_WIDE_FLASH) -+ dma_buffer->data.addr0 = (page << 16) | -+ ((528*(cwperpage-1)) >> 1); -+ else -+ dma_buffer->data.addr0 = (page << 16) | -+ (528*(cwperpage-1)); -+ -+ dma_buffer->data.addr1 = (page >> 16) & 0xff; -+ dma_buffer->data.chipsel_cs0 = (1<<4) | 4; -+ dma_buffer->data.chipsel_cs1 = (1<<4) | 5; -+ -+ dma_buffer->data.exec = 1; -+ -+ dma_buffer->data.result[0].flash_status = 0xeeeeeeee; -+ dma_buffer->data.result[0].buffer_status = 0xeeeeeeee; -+ dma_buffer->data.result[1].flash_status = 0xeeeeeeee; -+ dma_buffer->data.result[1].buffer_status = 0xeeeeeeee; -+ -+ dma_buffer->data.ebi2_chip_select_cfg0 = 0x00000805; -+ dma_buffer->data.adm_mux_data_ack_req_nc01 = 0x00000A3C; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc01 = 0x0000053C; -+ dma_buffer->data.adm_mux_data_ack_req_nc10 = 0x00000F28; -+ dma_buffer->data.adm_mux_cmd_ack_req_nc10 = 0x00000F14; -+ dma_buffer->data.adm_default_mux = 0x00000FC0; -+ dma_buffer->data.default_ebi2_chip_select_cfg0 = 0x00000801; -+ -+ /* Reading last code word from NC01 */ -+ /* enable CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ -+ /* 0xF14 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_cmd_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = NC01(MSM_NAND_FLASH_CMD); -+ cmd->len = 16; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cfg0); -+ cmd->dst = NC01(MSM_NAND_DEV0_CFG0); -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = NC01(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* 0xF28 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_data_ack_req_nc10); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC01(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.result[0]); -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = NC01(MSM_NAND_FLASH_BUFFER) + ((mtd->writesize >> 1) - -+ (528*(cwperpage-1))); -+ cmd->dst = msm_virt_to_dma(chip, buf01); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Reading last code word from NC10 */ -+ /* 0x53C */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_cmd_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = NC10(MSM_NAND_FLASH_CMD); -+ cmd->len = 12; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.chipsel_cs1); -+ cmd->dst = NC10(MSM_NAND_FLASH_CHIP_SELECT); -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cfg0); -+ cmd->dst = NC10(MSM_NAND_DEV1_CFG0); -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = NC10(MSM_NAND_EXEC_CMD); -+ cmd->len = 4; -+ cmd++; -+ -+ /* A3C */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_mux_data_ack_req_nc01); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = NC10(MSM_NAND_FLASH_STATUS); -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.result[1]); -+ cmd->len = 8; -+ cmd++; -+ -+ cmd->cmd = 0; -+ cmd->src = NC10(MSM_NAND_FLASH_BUFFER) + ((mtd->writesize >> 1) - -+ (528*(cwperpage-1))); -+ cmd->dst = msm_virt_to_dma(chip, buf10); -+ cmd->len = 4; -+ cmd++; -+ -+ /* FC0 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.adm_default_mux); -+ cmd->dst = EBI2_NAND_ADM_MUX; -+ cmd->len = 4; -+ cmd++; -+ -+ /* disble CS1 */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.ebi2_chip_select_cfg0); -+ cmd->dst = EBI2_CHIP_SELECT_CFG0; -+ cmd->len = 4; -+ cmd++; -+ -+ BUILD_BUG_ON(18 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, -+ dma_buffer->cmd) >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST | -+ DMOV_CMD_ADDR(msm_virt_to_dma(chip, &dma_buffer->cmdptr))); -+ mb(); -+ -+ ret = 0; -+ if ((dma_buffer->data.result[0].flash_status & 0x110) || -+ (dma_buffer->data.result[1].flash_status & 0x110)) -+ ret = -EIO; -+ -+ if (!ret) { -+ /* Check for bad block marker byte for NC01 & NC10 */ -+ if (chip->CFG1 & CFG1_WIDE_FLASH) { -+ if ((buf01[0] != 0xFF || buf01[1] != 0xFF) || -+ (buf10[0] != 0xFF || buf10[1] != 0xFF)) -+ ret = 1; -+ } else { -+ if (buf01[0] != 0xFF || buf10[0] != 0xFF) -+ ret = 1; -+ } -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer) + 8); -+ return ret; -+} -+ -+static int -+msm_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct mtd_oob_ops ops; -+ int ret; -+ uint8_t *buf; -+ -+ /* Check for invalid offset */ -+ if (ofs > mtd->size) -+ return -EINVAL; -+ if (ofs & (mtd->erasesize - 1)) { -+ pr_err("%s: unsupported block address, 0x%x\n", -+ __func__, (uint32_t)ofs); -+ return -EINVAL; -+ } -+ -+ /* -+ Write all 0s to the first page -+ This will set the BB marker to 0 -+ */ -+ buf = page_address(ZERO_PAGE()); -+ -+ ops.mode = MTD_OPS_RAW; -+ ops.len = mtd->writesize + mtd->oobsize; -+ ops.retlen = 0; -+ ops.ooblen = 0; -+ ops.datbuf = buf; -+ ops.oobbuf = NULL; -+ if (!interleave_enable) -+ ret = msm_nand_write_oob(mtd, ofs, &ops); -+ else -+ ret = msm_nand_write_oob_dualnandc(mtd, ofs, &ops); -+ -+ return ret; -+} -+ -+/** -+ * msm_nand_suspend - [MTD Interface] Suspend the msm_nand flash -+ * @param mtd MTD device structure -+ */ -+static int msm_nand_suspend(struct mtd_info *mtd) -+{ -+ return 0; -+} -+ -+/** -+ * msm_nand_resume - [MTD Interface] Resume the msm_nand flash -+ * @param mtd MTD device structure -+ */ -+static void msm_nand_resume(struct mtd_info *mtd) -+{ -+} -+ -+struct onenand_information { -+ uint16_t manufacturer_id; -+ uint16_t device_id; -+ uint16_t version_id; -+ uint16_t data_buf_size; -+ uint16_t boot_buf_size; -+ uint16_t num_of_buffers; -+ uint16_t technology; -+}; -+ -+static struct onenand_information onenand_info; -+static uint32_t nand_sfcmd_mode; -+ -+uint32_t flash_onenand_probe(struct msm_nand_chip *chip) -+{ -+ struct { -+ dmov_s cmd[7]; -+ unsigned cmdptr; -+ struct { -+ uint32_t bcfg; -+ uint32_t cmd; -+ uint32_t exec; -+ uint32_t status; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t addr2; -+ uint32_t addr3; -+ uint32_t addr4; -+ uint32_t addr5; -+ uint32_t addr6; -+ uint32_t data0; -+ uint32_t data1; -+ uint32_t data2; -+ uint32_t data3; -+ uint32_t data4; -+ uint32_t data5; -+ uint32_t data6; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ int err = 0; -+ uint32_t initialsflashcmd = 0; -+ -+ initialsflashcmd = flash_rd_reg(chip, MSM_NAND_SFLASHC_CMD); -+ -+ if ((initialsflashcmd & 0x10) == 0x10) -+ nand_sfcmd_mode = MSM_NAND_SFCMD_ASYNC; -+ else -+ nand_sfcmd_mode = MSM_NAND_SFCMD_BURST; -+ -+ printk(KERN_INFO "SFLASHC Async Mode bit: %x \n", nand_sfcmd_mode); -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ cmd = dma_buffer->cmd; -+ -+ dma_buffer->data.bcfg = SFLASH_BCFG | -+ (nand_sfcmd_mode ? 0 : (1 << 24)); -+ dma_buffer->data.cmd = SFLASH_PREPCMD(7, 0, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGRD); -+ dma_buffer->data.exec = 1; -+ dma_buffer->data.status = CLEAN_DATA_32; -+ dma_buffer->data.addr0 = (ONENAND_DEVICE_ID << 16) | -+ (ONENAND_MANUFACTURER_ID); -+ dma_buffer->data.addr1 = (ONENAND_DATA_BUFFER_SIZE << 16) | -+ (ONENAND_VERSION_ID); -+ dma_buffer->data.addr2 = (ONENAND_AMOUNT_OF_BUFFERS << 16) | -+ (ONENAND_BOOT_BUFFER_SIZE); -+ dma_buffer->data.addr3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_TECHNOLOGY << 0); -+ dma_buffer->data.data0 = CLEAN_DATA_32; -+ dma_buffer->data.data1 = CLEAN_DATA_32; -+ dma_buffer->data.data2 = CLEAN_DATA_32; -+ dma_buffer->data.data3 = CLEAN_DATA_32; -+ -+ /* Enable and configure the SFlash controller */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.bcfg); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.cmd); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Configure the ADDR0 and ADDR1 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr0); -+ cmd->dst = MSM_NAND_ADDR0; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Configure the ADDR2 and ADDR3 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr2); -+ cmd->dst = MSM_NAND_ADDR2; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.exec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the two status registers */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.status); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read data registers - valid only if status says success */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_GENP_REG0; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data0); -+ cmd->len = 16; -+ cmd++; -+ -+ BUILD_BUG_ON(7 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) -+ >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST -+ | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ /* Check for errors, protection violations etc */ -+ if (dma_buffer->data.status & 0x110) { -+ pr_info("%s: MPU/OP error" -+ "(0x%x) during Onenand probe\n", -+ __func__, dma_buffer->data.status); -+ err = -EIO; -+ } else { -+ -+ onenand_info.manufacturer_id = -+ (dma_buffer->data.data0 >> 0) & 0x0000FFFF; -+ onenand_info.device_id = -+ (dma_buffer->data.data0 >> 16) & 0x0000FFFF; -+ onenand_info.version_id = -+ (dma_buffer->data.data1 >> 0) & 0x0000FFFF; -+ onenand_info.data_buf_size = -+ (dma_buffer->data.data1 >> 16) & 0x0000FFFF; -+ onenand_info.boot_buf_size = -+ (dma_buffer->data.data2 >> 0) & 0x0000FFFF; -+ onenand_info.num_of_buffers = -+ (dma_buffer->data.data2 >> 16) & 0x0000FFFF; -+ onenand_info.technology = -+ (dma_buffer->data.data3 >> 0) & 0x0000FFFF; -+ -+ -+ pr_info("=======================================" -+ "==========================\n"); -+ -+ pr_info("%s: manufacturer_id = 0x%x\n" -+ , __func__, onenand_info.manufacturer_id); -+ pr_info("%s: device_id = 0x%x\n" -+ , __func__, onenand_info.device_id); -+ pr_info("%s: version_id = 0x%x\n" -+ , __func__, onenand_info.version_id); -+ pr_info("%s: data_buf_size = 0x%x\n" -+ , __func__, onenand_info.data_buf_size); -+ pr_info("%s: boot_buf_size = 0x%x\n" -+ , __func__, onenand_info.boot_buf_size); -+ pr_info("%s: num_of_buffers = 0x%x\n" -+ , __func__, onenand_info.num_of_buffers); -+ pr_info("%s: technology = 0x%x\n" -+ , __func__, onenand_info.technology); -+ -+ pr_info("=======================================" -+ "==========================\n"); -+ -+ if ((onenand_info.manufacturer_id != 0x00EC) -+ || ((onenand_info.device_id & 0x0040) != 0x0040) -+ || (onenand_info.data_buf_size != 0x0800) -+ || (onenand_info.boot_buf_size != 0x0200) -+ || (onenand_info.num_of_buffers != 0x0201) -+ || (onenand_info.technology != 0)) { -+ -+ pr_info("%s: Detected an unsupported device\n" -+ , __func__); -+ err = -EIO; -+ } -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ return err; -+} -+ -+int msm_onenand_read_oob(struct mtd_info *mtd, -+ loff_t from, struct mtd_oob_ops *ops) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[53]; -+ unsigned cmdptr; -+ struct { -+ uint32_t sfbcfg; -+ uint32_t sfcmd[9]; -+ uint32_t sfexec; -+ uint32_t sfstat[9]; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t addr2; -+ uint32_t addr3; -+ uint32_t addr4; -+ uint32_t addr5; -+ uint32_t addr6; -+ uint32_t data0; -+ uint32_t data1; -+ uint32_t data2; -+ uint32_t data3; -+ uint32_t data4; -+ uint32_t data5; -+ uint32_t data6; -+ uint32_t macro[5]; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ int err = 0; -+ int i; -+ dma_addr_t data_dma_addr = 0; -+ dma_addr_t oob_dma_addr = 0; -+ dma_addr_t data_dma_addr_curr = 0; -+ dma_addr_t oob_dma_addr_curr = 0; -+ -+ loff_t from_curr = 0; -+ unsigned page_count; -+ unsigned pages_read = 0; -+ -+ uint16_t onenand_startaddr1; -+ uint16_t onenand_startaddr8; -+ uint16_t onenand_startaddr2; -+ uint16_t onenand_startbuffer; -+ uint16_t onenand_sysconfig1; -+ uint16_t controller_status; -+ uint16_t interrupt_status; -+ uint16_t ecc_status; -+#if VERBOSE -+ pr_info("=================================================" -+ "================\n"); -+ pr_info("%s: from 0x%llx mode %d \ndatbuf 0x%p datlen 0x%x" -+ "\noobbuf 0x%p ooblen 0x%x\n", -+ __func__, from, ops->mode, ops->datbuf, ops->len, -+ ops->oobbuf, ops->ooblen); -+#endif -+ if (!mtd) { -+ pr_err("%s: invalid mtd pointer, 0x%x\n", __func__, -+ (uint32_t)mtd); -+ return -EINVAL; -+ } -+ if (from & (mtd->writesize - 1)) { -+ pr_err("%s: unsupported from, 0x%llx\n", __func__, -+ from); -+ return -EINVAL; -+ } -+ -+ if ((ops->mode != MTD_OPS_PLACE_OOB) && (ops->mode != MTD_OPS_AUTO_OOB) && -+ (ops->mode != MTD_OPS_RAW)) { -+ pr_err("%s: unsupported ops->mode, %d\n", __func__, -+ ops->mode); -+ return -EINVAL; -+ } -+ -+ if (((ops->datbuf == NULL) || (ops->len == 0)) && -+ ((ops->oobbuf == NULL) || (ops->ooblen == 0))) { -+ pr_err("%s: incorrect ops fields - nothing to do\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if ((ops->datbuf != NULL) && (ops->len == 0)) { -+ pr_err("%s: data buffer passed but length 0\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if ((ops->oobbuf != NULL) && (ops->ooblen == 0)) { -+ pr_err("%s: oob buffer passed but length 0\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if (ops->mode != MTD_OPS_RAW) { -+ if (ops->datbuf != NULL && (ops->len % mtd->writesize) != 0) { -+ /* when ops->datbuf is NULL, ops->len can be ooblen */ -+ pr_err("%s: unsupported ops->len, %d\n", __func__, -+ ops->len); -+ return -EINVAL; -+ } -+ } else { -+ if (ops->datbuf != NULL && -+ (ops->len % (mtd->writesize + mtd->oobsize)) != 0) { -+ pr_err("%s: unsupported ops->len," -+ " %d for MTD_OPS_RAW\n", __func__, ops->len); -+ return -EINVAL; -+ } -+ } -+ -+ if ((ops->mode == MTD_OPS_RAW) && (ops->oobbuf)) { -+ pr_err("%s: unsupported operation, oobbuf pointer " -+ "passed in for RAW mode, %x\n", __func__, -+ (uint32_t)ops->oobbuf); -+ return -EINVAL; -+ } -+ -+ if (ops->oobbuf && !ops->datbuf) { -+ page_count = ops->ooblen / ((ops->mode == MTD_OPS_AUTO_OOB) ? -+ mtd->oobavail : mtd->oobsize); -+ if ((page_count == 0) && (ops->ooblen)) -+ page_count = 1; -+ } else if (ops->mode != MTD_OPS_RAW) -+ page_count = ops->len / mtd->writesize; -+ else -+ page_count = ops->len / (mtd->writesize + mtd->oobsize); -+ -+ if ((ops->mode == MTD_OPS_PLACE_OOB) && (ops->oobbuf != NULL)) { -+ if (page_count * mtd->oobsize > ops->ooblen) { -+ pr_err("%s: unsupported ops->ooblen for " -+ "PLACE, %d\n", __func__, ops->ooblen); -+ return -EINVAL; -+ } -+ } -+ -+ if ((ops->mode == MTD_OPS_PLACE_OOB) && (ops->ooblen != 0) && -+ (ops->ooboffs != 0)) { -+ pr_err("%s: unsupported ops->ooboffs, %d\n", __func__, -+ ops->ooboffs); -+ return -EINVAL; -+ } -+ -+ if (ops->datbuf) { -+ memset(ops->datbuf, 0x55, ops->len); -+ data_dma_addr_curr = data_dma_addr = msm_nand_dma_map(chip->dev, -+ ops->datbuf, ops->len, DMA_FROM_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, data_dma_addr)) { -+ pr_err("%s: failed to get dma addr for %p\n", -+ __func__, ops->datbuf); -+ return -EIO; -+ } -+ } -+ if (ops->oobbuf) { -+ memset(ops->oobbuf, 0x55, ops->ooblen); -+ oob_dma_addr_curr = oob_dma_addr = msm_nand_dma_map(chip->dev, -+ ops->oobbuf, ops->ooblen, DMA_FROM_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, oob_dma_addr)) { -+ pr_err("%s: failed to get dma addr for %p\n", -+ __func__, ops->oobbuf); -+ err = -EIO; -+ goto err_dma_map_oobbuf_failed; -+ } -+ } -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ from_curr = from; -+ -+ while (page_count-- > 0) { -+ -+ cmd = dma_buffer->cmd; -+ -+ if ((onenand_info.device_id & ONENAND_DEVICE_IS_DDP) -+ && (from_curr >= (mtd->size>>1))) { /* DDP Device */ -+ onenand_startaddr1 = DEVICE_FLASHCORE_1 | -+ (((uint32_t)(from_curr-(mtd->size>>1)) -+ / mtd->erasesize)); -+ onenand_startaddr2 = DEVICE_BUFFERRAM_1; -+ } else { -+ onenand_startaddr1 = DEVICE_FLASHCORE_0 | -+ ((uint32_t)from_curr / mtd->erasesize) ; -+ onenand_startaddr2 = DEVICE_BUFFERRAM_0; -+ } -+ -+ onenand_startaddr8 = (((uint32_t)from_curr & -+ (mtd->erasesize - 1)) / mtd->writesize) << 2; -+ onenand_startbuffer = DATARAM0_0 << 8; -+ onenand_sysconfig1 = (ops->mode == MTD_OPS_RAW) ? -+ ONENAND_SYSCFG1_ECCDIS(nand_sfcmd_mode) : -+ ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode); -+ -+ dma_buffer->data.sfbcfg = SFLASH_BCFG | -+ (nand_sfcmd_mode ? 0 : (1 << 24)); -+ dma_buffer->data.sfcmd[0] = SFLASH_PREPCMD(7, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfcmd[1] = SFLASH_PREPCMD(0, 0, 32, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_INTHI); -+ dma_buffer->data.sfcmd[2] = SFLASH_PREPCMD(3, 7, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGRD); -+ dma_buffer->data.sfcmd[3] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATRD); -+ dma_buffer->data.sfcmd[4] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATRD); -+ dma_buffer->data.sfcmd[5] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATRD); -+ dma_buffer->data.sfcmd[6] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATRD); -+ dma_buffer->data.sfcmd[7] = SFLASH_PREPCMD(32, 0, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATRD); -+ dma_buffer->data.sfcmd[8] = SFLASH_PREPCMD(4, 10, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfexec = 1; -+ dma_buffer->data.sfstat[0] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[1] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[2] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[3] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[4] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[5] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[6] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[7] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[8] = CLEAN_DATA_32; -+ dma_buffer->data.addr0 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr1 = (ONENAND_START_ADDRESS_8 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.addr2 = (ONENAND_START_BUFFER << 16) | -+ (ONENAND_START_ADDRESS_2); -+ dma_buffer->data.addr3 = (ONENAND_ECC_STATUS << 16) | -+ (ONENAND_COMMAND); -+ dma_buffer->data.addr4 = (ONENAND_CONTROLLER_STATUS << 16) | -+ (ONENAND_INTERRUPT_STATUS); -+ dma_buffer->data.addr5 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr6 = (ONENAND_START_ADDRESS_3 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.data0 = (ONENAND_CLRINTR << 16) | -+ (onenand_sysconfig1); -+ dma_buffer->data.data1 = (onenand_startaddr8 << 16) | -+ (onenand_startaddr1); -+ dma_buffer->data.data2 = (onenand_startbuffer << 16) | -+ (onenand_startaddr2); -+ dma_buffer->data.data3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_CMDLOADSPARE); -+ dma_buffer->data.data4 = (CLEAN_DATA_16 << 16) | -+ (CLEAN_DATA_16); -+ dma_buffer->data.data5 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data6 = (ONENAND_STARTADDR3_RES << 16) | -+ (ONENAND_STARTADDR1_RES); -+ dma_buffer->data.macro[0] = 0x0200; -+ dma_buffer->data.macro[1] = 0x0300; -+ dma_buffer->data.macro[2] = 0x0400; -+ dma_buffer->data.macro[3] = 0x0500; -+ dma_buffer->data.macro[4] = 0x8010; -+ -+ /*************************************************************/ -+ /* Write necessary address registers in the onenand device */ -+ /*************************************************************/ -+ -+ /* Enable and configure the SFlash controller */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfbcfg); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[0]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the ADDR0 and ADDR1 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr0); -+ cmd->dst = MSM_NAND_ADDR0; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr2); -+ cmd->dst = MSM_NAND_ADDR2; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the ADDR6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr6); -+ cmd->dst = MSM_NAND_ADDR6; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the GENP0, GENP1, GENP2, GENP3 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data0); -+ cmd->dst = MSM_NAND_GENP_REG0; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the FLASH_DEV_CMD4,5,6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->dst = MSM_NAND_DEV_CMD4; -+ cmd->len = 12; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[0]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Wait for the interrupt from the Onenand device controller */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[1]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[1]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Read necessary status registers from the onenand device */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[2]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[2]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the GENP3 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_GENP_REG3; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data3); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the DEVCMD4 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_DEV_CMD4; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Read the data ram area from the onenand buffer ram */ -+ /*************************************************************/ -+ -+ if (ops->datbuf) { -+ -+ dma_buffer->data.data3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_CMDLOAD); -+ -+ for (i = 0; i < 4; i++) { -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfcmd[3+i]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the MACRO1 register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.macro[i]); -+ cmd->dst = MSM_NAND_MACRO1_REG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data rdy, & read status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfstat[3+i]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Transfer nand ctlr buf contents to usr buf */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_FLASH_BUFFER; -+ cmd->dst = data_dma_addr_curr; -+ cmd->len = 512; -+ data_dma_addr_curr += 512; -+ cmd++; -+ } -+ } -+ -+ if ((ops->oobbuf) || (ops->mode == MTD_OPS_RAW)) { -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfcmd[7]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the MACRO1 register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.macro[4]); -+ cmd->dst = MSM_NAND_MACRO1_REG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfstat[7]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Transfer nand ctlr buffer contents into usr buf */ -+ if (ops->mode == MTD_OPS_AUTO_OOB) { -+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_FLASH_BUFFER + -+ mtd->ecclayout->oobfree[i].offset; -+ cmd->dst = oob_dma_addr_curr; -+ cmd->len = -+ mtd->ecclayout->oobfree[i].length; -+ oob_dma_addr_curr += -+ mtd->ecclayout->oobfree[i].length; -+ cmd++; -+ } -+ } -+ if (ops->mode == MTD_OPS_PLACE_OOB) { -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_FLASH_BUFFER; -+ cmd->dst = oob_dma_addr_curr; -+ cmd->len = mtd->oobsize; -+ oob_dma_addr_curr += mtd->oobsize; -+ cmd++; -+ } -+ if (ops->mode == MTD_OPS_RAW) { -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_FLASH_BUFFER; -+ cmd->dst = data_dma_addr_curr; -+ cmd->len = mtd->oobsize; -+ data_dma_addr_curr += mtd->oobsize; -+ cmd++; -+ } -+ } -+ -+ /*************************************************************/ -+ /* Restore the necessary registers to proper values */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[8]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[8]); -+ cmd->len = 4; -+ cmd++; -+ -+ -+ BUILD_BUG_ON(53 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) -+ >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ ecc_status = (dma_buffer->data.data3 >> 16) & -+ 0x0000FFFF; -+ interrupt_status = (dma_buffer->data.data4 >> 0) & -+ 0x0000FFFF; -+ controller_status = (dma_buffer->data.data4 >> 16) & -+ 0x0000FFFF; -+ -+#if VERBOSE -+ pr_info("\n%s: sflash status %x %x %x %x %x %x %x" -+ "%x %x\n", __func__, -+ dma_buffer->data.sfstat[0], -+ dma_buffer->data.sfstat[1], -+ dma_buffer->data.sfstat[2], -+ dma_buffer->data.sfstat[3], -+ dma_buffer->data.sfstat[4], -+ dma_buffer->data.sfstat[5], -+ dma_buffer->data.sfstat[6], -+ dma_buffer->data.sfstat[7], -+ dma_buffer->data.sfstat[8]); -+ -+ pr_info("%s: controller_status = %x\n", __func__, -+ controller_status); -+ pr_info("%s: interrupt_status = %x\n", __func__, -+ interrupt_status); -+ pr_info("%s: ecc_status = %x\n", __func__, -+ ecc_status); -+#endif -+ /* Check for errors, protection violations etc */ -+ if ((controller_status != 0) -+ || (dma_buffer->data.sfstat[0] & 0x110) -+ || (dma_buffer->data.sfstat[1] & 0x110) -+ || (dma_buffer->data.sfstat[2] & 0x110) -+ || (dma_buffer->data.sfstat[8] & 0x110) -+ || ((dma_buffer->data.sfstat[3] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[4] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[5] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[6] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[7] & 0x110) && -+ ((ops->oobbuf) -+ || (ops->mode == MTD_OPS_RAW)))) { -+ pr_info("%s: ECC/MPU/OP error\n", __func__); -+ err = -EIO; -+ } -+ -+ if (err) -+ break; -+ pages_read++; -+ from_curr += mtd->writesize; -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ if (ops->oobbuf) { -+ dma_unmap_page(chip->dev, oob_dma_addr, ops->ooblen, -+ DMA_FROM_DEVICE); -+ } -+err_dma_map_oobbuf_failed: -+ if (ops->datbuf) { -+ dma_unmap_page(chip->dev, data_dma_addr, ops->len, -+ DMA_FROM_DEVICE); -+ } -+ -+ if (err) { -+ pr_err("%s: %llx %x %x failed\n", __func__, from_curr, -+ ops->datbuf ? ops->len : 0, ops->ooblen); -+ } else { -+ ops->retlen = ops->oobretlen = 0; -+ if (ops->datbuf != NULL) { -+ if (ops->mode != MTD_OPS_RAW) -+ ops->retlen = mtd->writesize * pages_read; -+ else -+ ops->retlen = (mtd->writesize + mtd->oobsize) -+ * pages_read; -+ } -+ if (ops->oobbuf != NULL) { -+ if (ops->mode == MTD_OPS_AUTO_OOB) -+ ops->oobretlen = mtd->oobavail * pages_read; -+ else -+ ops->oobretlen = mtd->oobsize * pages_read; -+ } -+ } -+ -+#if VERBOSE -+ pr_info("\n%s: ret %d, retlen %d oobretlen %d\n", -+ __func__, err, ops->retlen, ops->oobretlen); -+ -+ pr_info("===================================================" -+ "==============\n"); -+#endif -+ return err; -+} -+ -+int msm_onenand_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ int ret; -+ struct mtd_oob_ops ops; -+ -+ ops.mode = MTD_OPS_PLACE_OOB; -+ ops.datbuf = buf; -+ ops.len = len; -+ ops.retlen = 0; -+ ops.oobbuf = NULL; -+ ops.ooblen = 0; -+ ops.oobretlen = 0; -+ ret = msm_onenand_read_oob(mtd, from, &ops); -+ *retlen = ops.retlen; -+ -+ return ret; -+} -+ -+static int msm_onenand_write_oob(struct mtd_info *mtd, loff_t to, -+ struct mtd_oob_ops *ops) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[53]; -+ unsigned cmdptr; -+ struct { -+ uint32_t sfbcfg; -+ uint32_t sfcmd[10]; -+ uint32_t sfexec; -+ uint32_t sfstat[10]; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t addr2; -+ uint32_t addr3; -+ uint32_t addr4; -+ uint32_t addr5; -+ uint32_t addr6; -+ uint32_t data0; -+ uint32_t data1; -+ uint32_t data2; -+ uint32_t data3; -+ uint32_t data4; -+ uint32_t data5; -+ uint32_t data6; -+ uint32_t macro[5]; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ int err = 0; -+ int i, j, k; -+ dma_addr_t data_dma_addr = 0; -+ dma_addr_t oob_dma_addr = 0; -+ dma_addr_t init_dma_addr = 0; -+ dma_addr_t data_dma_addr_curr = 0; -+ dma_addr_t oob_dma_addr_curr = 0; -+ uint8_t *init_spare_bytes; -+ -+ loff_t to_curr = 0; -+ unsigned page_count; -+ unsigned pages_written = 0; -+ -+ uint16_t onenand_startaddr1; -+ uint16_t onenand_startaddr8; -+ uint16_t onenand_startaddr2; -+ uint16_t onenand_startbuffer; -+ uint16_t onenand_sysconfig1; -+ -+ uint16_t controller_status; -+ uint16_t interrupt_status; -+ uint16_t ecc_status; -+ -+#if VERBOSE -+ pr_info("=================================================" -+ "================\n"); -+ pr_info("%s: to 0x%llx mode %d \ndatbuf 0x%p datlen 0x%x" -+ "\noobbuf 0x%p ooblen 0x%x\n", -+ __func__, to, ops->mode, ops->datbuf, ops->len, -+ ops->oobbuf, ops->ooblen); -+#endif -+ if (!mtd) { -+ pr_err("%s: invalid mtd pointer, 0x%x\n", __func__, -+ (uint32_t)mtd); -+ return -EINVAL; -+ } -+ if (to & (mtd->writesize - 1)) { -+ pr_err("%s: unsupported to, 0x%llx\n", __func__, to); -+ return -EINVAL; -+ } -+ -+ if ((ops->mode != MTD_OPS_PLACE_OOB) && (ops->mode != MTD_OPS_AUTO_OOB) && -+ (ops->mode != MTD_OPS_RAW)) { -+ pr_err("%s: unsupported ops->mode, %d\n", __func__, -+ ops->mode); -+ return -EINVAL; -+ } -+ -+ if (((ops->datbuf == NULL) || (ops->len == 0)) && -+ ((ops->oobbuf == NULL) || (ops->ooblen == 0))) { -+ pr_err("%s: incorrect ops fields - nothing to do\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if ((ops->datbuf != NULL) && (ops->len == 0)) { -+ pr_err("%s: data buffer passed but length 0\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if ((ops->oobbuf != NULL) && (ops->ooblen == 0)) { -+ pr_err("%s: oob buffer passed but length 0\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if (ops->mode != MTD_OPS_RAW) { -+ if (ops->datbuf != NULL && (ops->len % mtd->writesize) != 0) { -+ /* when ops->datbuf is NULL, ops->len can be ooblen */ -+ pr_err("%s: unsupported ops->len, %d\n", __func__, -+ ops->len); -+ return -EINVAL; -+ } -+ } else { -+ if (ops->datbuf != NULL && -+ (ops->len % (mtd->writesize + mtd->oobsize)) != 0) { -+ pr_err("%s: unsupported ops->len," -+ " %d for MTD_OPS_RAW\n", __func__, ops->len); -+ return -EINVAL; -+ } -+ } -+ -+ if ((ops->mode == MTD_OPS_RAW) && (ops->oobbuf)) { -+ pr_err("%s: unsupported operation, oobbuf pointer " -+ "passed in for RAW mode, %x\n", __func__, -+ (uint32_t)ops->oobbuf); -+ return -EINVAL; -+ } -+ -+ if (ops->oobbuf && !ops->datbuf) { -+ page_count = ops->ooblen / ((ops->mode == MTD_OPS_AUTO_OOB) ? -+ mtd->oobavail : mtd->oobsize); -+ if ((page_count == 0) && (ops->ooblen)) -+ page_count = 1; -+ } else if (ops->mode != MTD_OPS_RAW) -+ page_count = ops->len / mtd->writesize; -+ else -+ page_count = ops->len / (mtd->writesize + mtd->oobsize); -+ -+ if ((ops->mode == MTD_OPS_AUTO_OOB) && (ops->oobbuf != NULL)) { -+ if (page_count > 1) { -+ pr_err("%s: unsupported ops->ooblen for" -+ "AUTO, %d\n", __func__, ops->ooblen); -+ return -EINVAL; -+ } -+ } -+ -+ if ((ops->mode == MTD_OPS_PLACE_OOB) && (ops->oobbuf != NULL)) { -+ if (page_count * mtd->oobsize > ops->ooblen) { -+ pr_err("%s: unsupported ops->ooblen for" -+ "PLACE, %d\n", __func__, ops->ooblen); -+ return -EINVAL; -+ } -+ } -+ -+ if ((ops->mode == MTD_OPS_PLACE_OOB) && (ops->ooblen != 0) && -+ (ops->ooboffs != 0)) { -+ pr_err("%s: unsupported ops->ooboffs, %d\n", -+ __func__, ops->ooboffs); -+ return -EINVAL; -+ } -+ -+ init_spare_bytes = kmalloc(64, GFP_KERNEL); -+ if (!init_spare_bytes) { -+ pr_err("%s: failed to alloc init_spare_bytes buffer\n", -+ __func__); -+ return -ENOMEM; -+ } -+ for (i = 0; i < 64; i++) -+ init_spare_bytes[i] = 0xFF; -+ -+ if ((ops->oobbuf) && (ops->mode == MTD_OPS_AUTO_OOB)) { -+ for (i = 0, k = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) -+ for (j = 0; j < mtd->ecclayout->oobfree[i].length; -+ j++) { -+ init_spare_bytes[j + -+ mtd->ecclayout->oobfree[i].offset] -+ = (ops->oobbuf)[k]; -+ k++; -+ } -+ } -+ -+ if (ops->datbuf) { -+ data_dma_addr_curr = data_dma_addr = msm_nand_dma_map(chip->dev, -+ ops->datbuf, ops->len, DMA_TO_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, data_dma_addr)) { -+ pr_err("%s: failed to get dma addr for %p\n", -+ __func__, ops->datbuf); -+ return -EIO; -+ } -+ } -+ if (ops->oobbuf) { -+ oob_dma_addr_curr = oob_dma_addr = msm_nand_dma_map(chip->dev, -+ ops->oobbuf, ops->ooblen, DMA_TO_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, oob_dma_addr)) { -+ pr_err("%s: failed to get dma addr for %p\n", -+ __func__, ops->oobbuf); -+ err = -EIO; -+ goto err_dma_map_oobbuf_failed; -+ } -+ } -+ -+ init_dma_addr = msm_nand_dma_map(chip->dev, init_spare_bytes, 64, -+ DMA_TO_DEVICE, NULL); -+ if (dma_mapping_error(chip->dev, init_dma_addr)) { -+ pr_err("%s: failed to get dma addr for %p\n", -+ __func__, init_spare_bytes); -+ err = -EIO; -+ goto err_dma_map_initbuf_failed; -+ } -+ -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ to_curr = to; -+ -+ while (page_count-- > 0) { -+ cmd = dma_buffer->cmd; -+ -+ if ((onenand_info.device_id & ONENAND_DEVICE_IS_DDP) -+ && (to_curr >= (mtd->size>>1))) { /* DDP Device */ -+ onenand_startaddr1 = DEVICE_FLASHCORE_1 | -+ (((uint32_t)(to_curr-(mtd->size>>1)) -+ / mtd->erasesize)); -+ onenand_startaddr2 = DEVICE_BUFFERRAM_1; -+ } else { -+ onenand_startaddr1 = DEVICE_FLASHCORE_0 | -+ ((uint32_t)to_curr / mtd->erasesize) ; -+ onenand_startaddr2 = DEVICE_BUFFERRAM_0; -+ } -+ -+ onenand_startaddr8 = (((uint32_t)to_curr & -+ (mtd->erasesize - 1)) / mtd->writesize) << 2; -+ onenand_startbuffer = DATARAM0_0 << 8; -+ onenand_sysconfig1 = (ops->mode == MTD_OPS_RAW) ? -+ ONENAND_SYSCFG1_ECCDIS(nand_sfcmd_mode) : -+ ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode); -+ -+ dma_buffer->data.sfbcfg = SFLASH_BCFG | -+ (nand_sfcmd_mode ? 0 : (1 << 24)); -+ dma_buffer->data.sfcmd[0] = SFLASH_PREPCMD(6, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfcmd[1] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATWR); -+ dma_buffer->data.sfcmd[2] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATWR); -+ dma_buffer->data.sfcmd[3] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATWR); -+ dma_buffer->data.sfcmd[4] = SFLASH_PREPCMD(256, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATWR); -+ dma_buffer->data.sfcmd[5] = SFLASH_PREPCMD(32, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_DATWR); -+ dma_buffer->data.sfcmd[6] = SFLASH_PREPCMD(1, 6, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfcmd[7] = SFLASH_PREPCMD(0, 0, 32, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_INTHI); -+ dma_buffer->data.sfcmd[8] = SFLASH_PREPCMD(3, 7, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGRD); -+ dma_buffer->data.sfcmd[9] = SFLASH_PREPCMD(4, 10, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfexec = 1; -+ dma_buffer->data.sfstat[0] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[1] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[2] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[3] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[4] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[5] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[6] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[7] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[8] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[9] = CLEAN_DATA_32; -+ dma_buffer->data.addr0 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr1 = (ONENAND_START_ADDRESS_8 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.addr2 = (ONENAND_START_BUFFER << 16) | -+ (ONENAND_START_ADDRESS_2); -+ dma_buffer->data.addr3 = (ONENAND_ECC_STATUS << 16) | -+ (ONENAND_COMMAND); -+ dma_buffer->data.addr4 = (ONENAND_CONTROLLER_STATUS << 16) | -+ (ONENAND_INTERRUPT_STATUS); -+ dma_buffer->data.addr5 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr6 = (ONENAND_START_ADDRESS_3 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.data0 = (ONENAND_CLRINTR << 16) | -+ (onenand_sysconfig1); -+ dma_buffer->data.data1 = (onenand_startaddr8 << 16) | -+ (onenand_startaddr1); -+ dma_buffer->data.data2 = (onenand_startbuffer << 16) | -+ (onenand_startaddr2); -+ dma_buffer->data.data3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_CMDPROGSPARE); -+ dma_buffer->data.data4 = (CLEAN_DATA_16 << 16) | -+ (CLEAN_DATA_16); -+ dma_buffer->data.data5 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data6 = (ONENAND_STARTADDR3_RES << 16) | -+ (ONENAND_STARTADDR1_RES); -+ dma_buffer->data.macro[0] = 0x0200; -+ dma_buffer->data.macro[1] = 0x0300; -+ dma_buffer->data.macro[2] = 0x0400; -+ dma_buffer->data.macro[3] = 0x0500; -+ dma_buffer->data.macro[4] = 0x8010; -+ -+ -+ /*************************************************************/ -+ /* Write necessary address registers in the onenand device */ -+ /*************************************************************/ -+ -+ /* Enable and configure the SFlash controller */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfbcfg); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[0]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the ADDR0 and ADDR1 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr0); -+ cmd->dst = MSM_NAND_ADDR0; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr2); -+ cmd->dst = MSM_NAND_ADDR2; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the ADDR6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr6); -+ cmd->dst = MSM_NAND_ADDR6; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the GENP0, GENP1, GENP2, GENP3 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data0); -+ cmd->dst = MSM_NAND_GENP_REG0; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the FLASH_DEV_CMD4,5,6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->dst = MSM_NAND_DEV_CMD4; -+ cmd->len = 12; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[0]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Write the data ram area in the onenand buffer ram */ -+ /*************************************************************/ -+ -+ if (ops->datbuf) { -+ dma_buffer->data.data3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_CMDPROG); -+ -+ for (i = 0; i < 4; i++) { -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfcmd[1+i]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Trnsfr usr buf contents to nand ctlr buf */ -+ cmd->cmd = 0; -+ cmd->src = data_dma_addr_curr; -+ cmd->dst = MSM_NAND_FLASH_BUFFER; -+ cmd->len = 512; -+ data_dma_addr_curr += 512; -+ cmd++; -+ -+ /* Write the MACRO1 register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.macro[i]); -+ cmd->dst = MSM_NAND_MACRO1_REG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data rdy, & read status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, -+ &dma_buffer->data.sfstat[1+i]); -+ cmd->len = 4; -+ cmd++; -+ -+ } -+ } -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[5]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ if ((ops->oobbuf) || (ops->mode == MTD_OPS_RAW)) { -+ -+ /* Transfer user buf contents into nand ctlr buffer */ -+ if (ops->mode == MTD_OPS_AUTO_OOB) { -+ cmd->cmd = 0; -+ cmd->src = init_dma_addr; -+ cmd->dst = MSM_NAND_FLASH_BUFFER; -+ cmd->len = mtd->oobsize; -+ cmd++; -+ } -+ if (ops->mode == MTD_OPS_PLACE_OOB) { -+ cmd->cmd = 0; -+ cmd->src = oob_dma_addr_curr; -+ cmd->dst = MSM_NAND_FLASH_BUFFER; -+ cmd->len = mtd->oobsize; -+ oob_dma_addr_curr += mtd->oobsize; -+ cmd++; -+ } -+ if (ops->mode == MTD_OPS_RAW) { -+ cmd->cmd = 0; -+ cmd->src = data_dma_addr_curr; -+ cmd->dst = MSM_NAND_FLASH_BUFFER; -+ cmd->len = mtd->oobsize; -+ data_dma_addr_curr += mtd->oobsize; -+ cmd++; -+ } -+ } else { -+ cmd->cmd = 0; -+ cmd->src = init_dma_addr; -+ cmd->dst = MSM_NAND_FLASH_BUFFER; -+ cmd->len = mtd->oobsize; -+ cmd++; -+ } -+ -+ /* Write the MACRO1 register */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.macro[4]); -+ cmd->dst = MSM_NAND_MACRO1_REG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[5]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*********************************************************/ -+ /* Issuing write command */ -+ /*********************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[6]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[6]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Wait for the interrupt from the Onenand device controller */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[7]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[7]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Read necessary status registers from the onenand device */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[8]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[8]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the GENP3 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_GENP_REG3; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data3); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the DEVCMD4 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_DEV_CMD4; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Restore the necessary registers to proper values */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[9]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[9]); -+ cmd->len = 4; -+ cmd++; -+ -+ -+ BUILD_BUG_ON(53 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) -+ >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ ecc_status = (dma_buffer->data.data3 >> 16) & 0x0000FFFF; -+ interrupt_status = (dma_buffer->data.data4 >> 0)&0x0000FFFF; -+ controller_status = (dma_buffer->data.data4 >> 16)&0x0000FFFF; -+ -+#if VERBOSE -+ pr_info("\n%s: sflash status %x %x %x %x %x %x %x" -+ " %x %x %x\n", __func__, -+ dma_buffer->data.sfstat[0], -+ dma_buffer->data.sfstat[1], -+ dma_buffer->data.sfstat[2], -+ dma_buffer->data.sfstat[3], -+ dma_buffer->data.sfstat[4], -+ dma_buffer->data.sfstat[5], -+ dma_buffer->data.sfstat[6], -+ dma_buffer->data.sfstat[7], -+ dma_buffer->data.sfstat[8], -+ dma_buffer->data.sfstat[9]); -+ -+ pr_info("%s: controller_status = %x\n", __func__, -+ controller_status); -+ pr_info("%s: interrupt_status = %x\n", __func__, -+ interrupt_status); -+ pr_info("%s: ecc_status = %x\n", __func__, -+ ecc_status); -+#endif -+ /* Check for errors, protection violations etc */ -+ if ((controller_status != 0) -+ || (dma_buffer->data.sfstat[0] & 0x110) -+ || (dma_buffer->data.sfstat[6] & 0x110) -+ || (dma_buffer->data.sfstat[7] & 0x110) -+ || (dma_buffer->data.sfstat[8] & 0x110) -+ || (dma_buffer->data.sfstat[9] & 0x110) -+ || ((dma_buffer->data.sfstat[1] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[2] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[3] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[4] & 0x110) && -+ (ops->datbuf)) -+ || ((dma_buffer->data.sfstat[5] & 0x110) && -+ ((ops->oobbuf) -+ || (ops->mode == MTD_OPS_RAW)))) { -+ pr_info("%s: ECC/MPU/OP error\n", __func__); -+ err = -EIO; -+ } -+ -+ if (err) -+ break; -+ pages_written++; -+ to_curr += mtd->writesize; -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ dma_unmap_page(chip->dev, init_dma_addr, 64, DMA_TO_DEVICE); -+ -+err_dma_map_initbuf_failed: -+ if (ops->oobbuf) { -+ dma_unmap_page(chip->dev, oob_dma_addr, ops->ooblen, -+ DMA_TO_DEVICE); -+ } -+err_dma_map_oobbuf_failed: -+ if (ops->datbuf) { -+ dma_unmap_page(chip->dev, data_dma_addr, ops->len, -+ DMA_TO_DEVICE); -+ } -+ -+ if (err) { -+ pr_err("%s: %llx %x %x failed\n", __func__, to_curr, -+ ops->datbuf ? ops->len : 0, ops->ooblen); -+ } else { -+ ops->retlen = ops->oobretlen = 0; -+ if (ops->datbuf != NULL) { -+ if (ops->mode != MTD_OPS_RAW) -+ ops->retlen = mtd->writesize * pages_written; -+ else -+ ops->retlen = (mtd->writesize + mtd->oobsize) -+ * pages_written; -+ } -+ if (ops->oobbuf != NULL) { -+ if (ops->mode == MTD_OPS_AUTO_OOB) -+ ops->oobretlen = mtd->oobavail * pages_written; -+ else -+ ops->oobretlen = mtd->oobsize * pages_written; -+ } -+ } -+ -+#if VERBOSE -+ pr_info("\n%s: ret %d, retlen %d oobretlen %d\n", -+ __func__, err, ops->retlen, ops->oobretlen); -+ -+ pr_info("=================================================" -+ "================\n"); -+#endif -+ kfree(init_spare_bytes); -+ return err; -+} -+ -+static int msm_onenand_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ int ret; -+ struct mtd_oob_ops ops; -+ -+ ops.mode = MTD_OPS_PLACE_OOB; -+ ops.datbuf = (uint8_t *)buf; -+ ops.len = len; -+ ops.retlen = 0; -+ ops.oobbuf = NULL; -+ ops.ooblen = 0; -+ ops.oobretlen = 0; -+ ret = msm_onenand_write_oob(mtd, to, &ops); -+ *retlen = ops.retlen; -+ -+ return ret; -+} -+ -+static int msm_onenand_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[20]; -+ unsigned cmdptr; -+ struct { -+ uint32_t sfbcfg; -+ uint32_t sfcmd[4]; -+ uint32_t sfexec; -+ uint32_t sfstat[4]; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t addr2; -+ uint32_t addr3; -+ uint32_t addr4; -+ uint32_t addr5; -+ uint32_t addr6; -+ uint32_t data0; -+ uint32_t data1; -+ uint32_t data2; -+ uint32_t data3; -+ uint32_t data4; -+ uint32_t data5; -+ uint32_t data6; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ int err = 0; -+ -+ uint16_t onenand_startaddr1; -+ uint16_t onenand_startaddr8; -+ uint16_t onenand_startaddr2; -+ uint16_t onenand_startbuffer; -+ -+ uint16_t controller_status; -+ uint16_t interrupt_status; -+ uint16_t ecc_status; -+ -+ uint64_t temp; -+ -+#if VERBOSE -+ pr_info("=================================================" -+ "================\n"); -+ pr_info("%s: addr 0x%llx len 0x%llx\n", -+ __func__, instr->addr, instr->len); -+#endif -+ if (instr->addr & (mtd->erasesize - 1)) { -+ pr_err("%s: Unsupported erase address, 0x%llx\n", -+ __func__, instr->addr); -+ return -EINVAL; -+ } -+ if (instr->len != mtd->erasesize) { -+ pr_err("%s: Unsupported erase len, %lld\n", -+ __func__, instr->len); -+ return -EINVAL; -+ } -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ cmd = dma_buffer->cmd; -+ -+ temp = instr->addr; -+ -+ if ((onenand_info.device_id & ONENAND_DEVICE_IS_DDP) -+ && (temp >= (mtd->size>>1))) { /* DDP Device */ -+ onenand_startaddr1 = DEVICE_FLASHCORE_1 | -+ (((uint32_t)(temp-(mtd->size>>1)) -+ / mtd->erasesize)); -+ onenand_startaddr2 = DEVICE_BUFFERRAM_1; -+ } else { -+ onenand_startaddr1 = DEVICE_FLASHCORE_0 | -+ ((uint32_t)temp / mtd->erasesize) ; -+ onenand_startaddr2 = DEVICE_BUFFERRAM_0; -+ } -+ -+ onenand_startaddr8 = 0x0000; -+ onenand_startbuffer = DATARAM0_0 << 8; -+ -+ dma_buffer->data.sfbcfg = SFLASH_BCFG | -+ (nand_sfcmd_mode ? 0 : (1 << 24)); -+ dma_buffer->data.sfcmd[0] = SFLASH_PREPCMD(7, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfcmd[1] = SFLASH_PREPCMD(0, 0, 32, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_INTHI); -+ dma_buffer->data.sfcmd[2] = SFLASH_PREPCMD(3, 7, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGRD); -+ dma_buffer->data.sfcmd[3] = SFLASH_PREPCMD(4, 10, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfexec = 1; -+ dma_buffer->data.sfstat[0] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[1] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[2] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[3] = CLEAN_DATA_32; -+ dma_buffer->data.addr0 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr1 = (ONENAND_START_ADDRESS_8 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.addr2 = (ONENAND_START_BUFFER << 16) | -+ (ONENAND_START_ADDRESS_2); -+ dma_buffer->data.addr3 = (ONENAND_ECC_STATUS << 16) | -+ (ONENAND_COMMAND); -+ dma_buffer->data.addr4 = (ONENAND_CONTROLLER_STATUS << 16) | -+ (ONENAND_INTERRUPT_STATUS); -+ dma_buffer->data.addr5 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr6 = (ONENAND_START_ADDRESS_3 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.data0 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data1 = (onenand_startaddr8 << 16) | -+ (onenand_startaddr1); -+ dma_buffer->data.data2 = (onenand_startbuffer << 16) | -+ (onenand_startaddr2); -+ dma_buffer->data.data3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_CMDERAS); -+ dma_buffer->data.data4 = (CLEAN_DATA_16 << 16) | -+ (CLEAN_DATA_16); -+ dma_buffer->data.data5 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data6 = (ONENAND_STARTADDR3_RES << 16) | -+ (ONENAND_STARTADDR1_RES); -+ -+ /***************************************************************/ -+ /* Write the necessary address registers in the onenand device */ -+ /***************************************************************/ -+ -+ /* Enable and configure the SFlash controller */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfbcfg); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[0]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the ADDR0 and ADDR1 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr0); -+ cmd->dst = MSM_NAND_ADDR0; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr2); -+ cmd->dst = MSM_NAND_ADDR2; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the ADDR6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr6); -+ cmd->dst = MSM_NAND_ADDR6; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data0); -+ cmd->dst = MSM_NAND_GENP_REG0; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the FLASH_DEV_CMD4,5,6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->dst = MSM_NAND_DEV_CMD4; -+ cmd->len = 12; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[0]); -+ cmd->len = 4; -+ cmd++; -+ -+ /***************************************************************/ -+ /* Wait for the interrupt from the Onenand device controller */ -+ /***************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[1]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[1]); -+ cmd->len = 4; -+ cmd++; -+ -+ /***************************************************************/ -+ /* Read the necessary status registers from the onenand device */ -+ /***************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[2]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[2]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the GENP3 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_GENP_REG3; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data3); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the DEVCMD4 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_DEV_CMD4; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->len = 4; -+ cmd++; -+ -+ /***************************************************************/ -+ /* Restore the necessary registers to proper values */ -+ /***************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[3]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[3]); -+ cmd->len = 4; -+ cmd++; -+ -+ -+ BUILD_BUG_ON(20 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) -+ >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST -+ | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ ecc_status = (dma_buffer->data.data3 >> 16) & 0x0000FFFF; -+ interrupt_status = (dma_buffer->data.data4 >> 0) & 0x0000FFFF; -+ controller_status = (dma_buffer->data.data4 >> 16) & 0x0000FFFF; -+ -+#if VERBOSE -+ pr_info("\n%s: sflash status %x %x %x %x\n", __func__, -+ dma_buffer->data.sfstat[0], -+ dma_buffer->data.sfstat[1], -+ dma_buffer->data.sfstat[2], -+ dma_buffer->data.sfstat[3]); -+ -+ pr_info("%s: controller_status = %x\n", __func__, -+ controller_status); -+ pr_info("%s: interrupt_status = %x\n", __func__, -+ interrupt_status); -+ pr_info("%s: ecc_status = %x\n", __func__, -+ ecc_status); -+#endif -+ /* Check for errors, protection violations etc */ -+ if ((controller_status != 0) -+ || (dma_buffer->data.sfstat[0] & 0x110) -+ || (dma_buffer->data.sfstat[1] & 0x110) -+ || (dma_buffer->data.sfstat[2] & 0x110) -+ || (dma_buffer->data.sfstat[3] & 0x110)) { -+ pr_err("%s: ECC/MPU/OP error\n", __func__); -+ err = -EIO; -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+ if (err) { -+ pr_err("%s: Erase failed, 0x%llx\n", __func__, -+ instr->addr); -+ instr->fail_addr = instr->addr; -+ instr->state = MTD_ERASE_FAILED; -+ } else { -+ instr->state = MTD_ERASE_DONE; -+ instr->fail_addr = 0xffffffff; -+ mtd_erase_callback(instr); -+ } -+ -+#if VERBOSE -+ pr_info("\n%s: ret %d\n", __func__, err); -+ pr_info("====================================================" -+ "=============\n"); -+#endif -+ return err; -+} -+ -+static int msm_onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct mtd_oob_ops ops; -+ int rval, i; -+ int ret = 0; -+ uint8_t *buffer; -+ uint8_t *oobptr; -+ -+ if ((ofs > mtd->size) || (ofs & (mtd->erasesize - 1))) { -+ pr_err("%s: unsupported block address, 0x%x\n", -+ __func__, (uint32_t)ofs); -+ return -EINVAL; -+ } -+ -+ buffer = kmalloc(2112, GFP_KERNEL|GFP_DMA); -+ if (buffer == 0) { -+ pr_err("%s: Could not kmalloc for buffer\n", -+ __func__); -+ return -ENOMEM; -+ } -+ -+ memset(buffer, 0x00, 2112); -+ oobptr = &(buffer[2048]); -+ -+ ops.mode = MTD_OPS_RAW; -+ ops.len = 2112; -+ ops.retlen = 0; -+ ops.ooblen = 0; -+ ops.oobretlen = 0; -+ ops.ooboffs = 0; -+ ops.datbuf = buffer; -+ ops.oobbuf = NULL; -+ -+ for (i = 0; i < 2; i++) { -+ ofs = ofs + i*mtd->writesize; -+ rval = msm_onenand_read_oob(mtd, ofs, &ops); -+ if (rval) { -+ pr_err("%s: Error in reading bad blk info\n", -+ __func__); -+ ret = rval; -+ break; -+ } -+ if ((oobptr[0] != 0xFF) || (oobptr[1] != 0xFF) || -+ (oobptr[16] != 0xFF) || (oobptr[17] != 0xFF) || -+ (oobptr[32] != 0xFF) || (oobptr[33] != 0xFF) || -+ (oobptr[48] != 0xFF) || (oobptr[49] != 0xFF) -+ ) { -+ ret = 1; -+ break; -+ } -+ } -+ -+ kfree(buffer); -+ -+#if VERBOSE -+ if (ret == 1) -+ pr_info("%s : Block containing 0x%x is bad\n", -+ __func__, (unsigned int)ofs); -+#endif -+ return ret; -+} -+ -+static int msm_onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct mtd_oob_ops ops; -+ int rval, i; -+ int ret = 0; -+ uint8_t *buffer; -+ -+ if ((ofs > mtd->size) || (ofs & (mtd->erasesize - 1))) { -+ pr_err("%s: unsupported block address, 0x%x\n", -+ __func__, (uint32_t)ofs); -+ return -EINVAL; -+ } -+ -+ buffer = page_address(ZERO_PAGE()); -+ -+ ops.mode = MTD_OPS_RAW; -+ ops.len = 2112; -+ ops.retlen = 0; -+ ops.ooblen = 0; -+ ops.oobretlen = 0; -+ ops.ooboffs = 0; -+ ops.datbuf = buffer; -+ ops.oobbuf = NULL; -+ -+ for (i = 0; i < 2; i++) { -+ ofs = ofs + i*mtd->writesize; -+ rval = msm_onenand_write_oob(mtd, ofs, &ops); -+ if (rval) { -+ pr_err("%s: Error in writing bad blk info\n", -+ __func__); -+ ret = rval; -+ break; -+ } -+ } -+ -+ return ret; -+} -+ -+static int msm_onenand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[20]; -+ unsigned cmdptr; -+ struct { -+ uint32_t sfbcfg; -+ uint32_t sfcmd[4]; -+ uint32_t sfexec; -+ uint32_t sfstat[4]; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t addr2; -+ uint32_t addr3; -+ uint32_t addr4; -+ uint32_t addr5; -+ uint32_t addr6; -+ uint32_t data0; -+ uint32_t data1; -+ uint32_t data2; -+ uint32_t data3; -+ uint32_t data4; -+ uint32_t data5; -+ uint32_t data6; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ int err = 0; -+ -+ uint16_t onenand_startaddr1; -+ uint16_t onenand_startaddr8; -+ uint16_t onenand_startaddr2; -+ uint16_t onenand_startblock; -+ -+ uint16_t controller_status; -+ uint16_t interrupt_status; -+ uint16_t write_prot_status; -+ -+ uint64_t start_ofs; -+ -+#if VERBOSE -+ pr_info("====================================================" -+ "=============\n"); -+ pr_info("%s: ofs 0x%llx len %lld\n", __func__, ofs, len); -+#endif -+ /* 'ofs' & 'len' should align to block size */ -+ if (ofs&(mtd->erasesize - 1)) { -+ pr_err("%s: Unsupported ofs address, 0x%llx\n", -+ __func__, ofs); -+ return -EINVAL; -+ } -+ -+ if (len&(mtd->erasesize - 1)) { -+ pr_err("%s: Unsupported len, %lld\n", -+ __func__, len); -+ return -EINVAL; -+ } -+ -+ if (ofs+len > mtd->size) { -+ pr_err("%s: Maximum chip size exceeded\n", __func__); -+ return -EINVAL; -+ } -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ for (start_ofs = ofs; ofs < start_ofs+len; ofs = ofs+mtd->erasesize) { -+#if VERBOSE -+ pr_info("%s: ofs 0x%llx len %lld\n", __func__, ofs, len); -+#endif -+ -+ cmd = dma_buffer->cmd; -+ if ((onenand_info.device_id & ONENAND_DEVICE_IS_DDP) -+ && (ofs >= (mtd->size>>1))) { /* DDP Device */ -+ onenand_startaddr1 = DEVICE_FLASHCORE_1 | -+ (((uint32_t)(ofs - (mtd->size>>1)) -+ / mtd->erasesize)); -+ onenand_startaddr2 = DEVICE_BUFFERRAM_1; -+ onenand_startblock = ((uint32_t)(ofs - (mtd->size>>1)) -+ / mtd->erasesize); -+ } else { -+ onenand_startaddr1 = DEVICE_FLASHCORE_0 | -+ ((uint32_t)ofs / mtd->erasesize) ; -+ onenand_startaddr2 = DEVICE_BUFFERRAM_0; -+ onenand_startblock = ((uint32_t)ofs -+ / mtd->erasesize); -+ } -+ -+ onenand_startaddr8 = 0x0000; -+ dma_buffer->data.sfbcfg = SFLASH_BCFG | -+ (nand_sfcmd_mode ? 0 : (1 << 24)); -+ dma_buffer->data.sfcmd[0] = SFLASH_PREPCMD(7, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfcmd[1] = SFLASH_PREPCMD(0, 0, 32, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_INTHI); -+ dma_buffer->data.sfcmd[2] = SFLASH_PREPCMD(3, 7, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGRD); -+ dma_buffer->data.sfcmd[3] = SFLASH_PREPCMD(4, 10, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfexec = 1; -+ dma_buffer->data.sfstat[0] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[1] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[2] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[3] = CLEAN_DATA_32; -+ dma_buffer->data.addr0 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr1 = (ONENAND_START_ADDRESS_8 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.addr2 = (ONENAND_START_BLOCK_ADDRESS << 16) | -+ (ONENAND_START_ADDRESS_2); -+ dma_buffer->data.addr3 = (ONENAND_WRITE_PROT_STATUS << 16) | -+ (ONENAND_COMMAND); -+ dma_buffer->data.addr4 = (ONENAND_CONTROLLER_STATUS << 16) | -+ (ONENAND_INTERRUPT_STATUS); -+ dma_buffer->data.addr5 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr6 = (ONENAND_START_ADDRESS_3 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.data0 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data1 = (onenand_startaddr8 << 16) | -+ (onenand_startaddr1); -+ dma_buffer->data.data2 = (onenand_startblock << 16) | -+ (onenand_startaddr2); -+ dma_buffer->data.data3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_CMD_UNLOCK); -+ dma_buffer->data.data4 = (CLEAN_DATA_16 << 16) | -+ (CLEAN_DATA_16); -+ dma_buffer->data.data5 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data6 = (ONENAND_STARTADDR3_RES << 16) | -+ (ONENAND_STARTADDR1_RES); -+ -+ /*************************************************************/ -+ /* Write the necessary address reg in the onenand device */ -+ /*************************************************************/ -+ -+ /* Enable and configure the SFlash controller */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfbcfg); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[0]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the ADDR0 and ADDR1 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr0); -+ cmd->dst = MSM_NAND_ADDR0; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr2); -+ cmd->dst = MSM_NAND_ADDR2; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the ADDR6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr6); -+ cmd->dst = MSM_NAND_ADDR6; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data0); -+ cmd->dst = MSM_NAND_GENP_REG0; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the FLASH_DEV_CMD4,5,6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->dst = MSM_NAND_DEV_CMD4; -+ cmd->len = 12; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[0]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Wait for the interrupt from the Onenand device controller */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[1]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[1]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*********************************************************/ -+ /* Read the necessary status reg from the onenand device */ -+ /*********************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[2]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[2]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the GENP3 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_GENP_REG3; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data3); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the DEVCMD4 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_DEV_CMD4; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->len = 4; -+ cmd++; -+ -+ /************************************************************/ -+ /* Restore the necessary registers to proper values */ -+ /************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[3]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[3]); -+ cmd->len = 4; -+ cmd++; -+ -+ -+ BUILD_BUG_ON(20 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) -+ >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ write_prot_status = (dma_buffer->data.data3 >> 16) & 0x0000FFFF; -+ interrupt_status = (dma_buffer->data.data4 >> 0) & 0x0000FFFF; -+ controller_status = (dma_buffer->data.data4 >> 16) & 0x0000FFFF; -+ -+#if VERBOSE -+ pr_info("\n%s: sflash status %x %x %x %x\n", __func__, -+ dma_buffer->data.sfstat[0], -+ dma_buffer->data.sfstat[1], -+ dma_buffer->data.sfstat[2], -+ dma_buffer->data.sfstat[3]); -+ -+ pr_info("%s: controller_status = %x\n", __func__, -+ controller_status); -+ pr_info("%s: interrupt_status = %x\n", __func__, -+ interrupt_status); -+ pr_info("%s: write_prot_status = %x\n", __func__, -+ write_prot_status); -+#endif -+ /* Check for errors, protection violations etc */ -+ if ((controller_status != 0) -+ || (dma_buffer->data.sfstat[0] & 0x110) -+ || (dma_buffer->data.sfstat[1] & 0x110) -+ || (dma_buffer->data.sfstat[2] & 0x110) -+ || (dma_buffer->data.sfstat[3] & 0x110)) { -+ pr_err("%s: ECC/MPU/OP error\n", __func__); -+ err = -EIO; -+ } -+ -+ if (!(write_prot_status & ONENAND_WP_US)) { -+ pr_err("%s: Unexpected status ofs = 0x%llx," -+ "wp_status = %x\n", -+ __func__, ofs, write_prot_status); -+ err = -EIO; -+ } -+ -+ if (err) -+ break; -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+#if VERBOSE -+ pr_info("\n%s: ret %d\n", __func__, err); -+ pr_info("====================================================" -+ "=============\n"); -+#endif -+ return err; -+} -+ -+static int msm_onenand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[20]; -+ unsigned cmdptr; -+ struct { -+ uint32_t sfbcfg; -+ uint32_t sfcmd[4]; -+ uint32_t sfexec; -+ uint32_t sfstat[4]; -+ uint32_t addr0; -+ uint32_t addr1; -+ uint32_t addr2; -+ uint32_t addr3; -+ uint32_t addr4; -+ uint32_t addr5; -+ uint32_t addr6; -+ uint32_t data0; -+ uint32_t data1; -+ uint32_t data2; -+ uint32_t data3; -+ uint32_t data4; -+ uint32_t data5; -+ uint32_t data6; -+ } data; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ int err = 0; -+ -+ uint16_t onenand_startaddr1; -+ uint16_t onenand_startaddr8; -+ uint16_t onenand_startaddr2; -+ uint16_t onenand_startblock; -+ -+ uint16_t controller_status; -+ uint16_t interrupt_status; -+ uint16_t write_prot_status; -+ -+ uint64_t start_ofs; -+ -+#if VERBOSE -+ pr_info("====================================================" -+ "=============\n"); -+ pr_info("%s: ofs 0x%llx len %lld\n", __func__, ofs, len); -+#endif -+ /* 'ofs' & 'len' should align to block size */ -+ if (ofs&(mtd->erasesize - 1)) { -+ pr_err("%s: Unsupported ofs address, 0x%llx\n", -+ __func__, ofs); -+ return -EINVAL; -+ } -+ -+ if (len&(mtd->erasesize - 1)) { -+ pr_err("%s: Unsupported len, %lld\n", -+ __func__, len); -+ return -EINVAL; -+ } -+ -+ if (ofs+len > mtd->size) { -+ pr_err("%s: Maximum chip size exceeded\n", __func__); -+ return -EINVAL; -+ } -+ -+ wait_event(chip->wait_queue, (dma_buffer = msm_nand_get_dma_buffer -+ (chip, sizeof(*dma_buffer)))); -+ -+ for (start_ofs = ofs; ofs < start_ofs+len; ofs = ofs+mtd->erasesize) { -+#if VERBOSE -+ pr_info("%s: ofs 0x%llx len %lld\n", __func__, ofs, len); -+#endif -+ -+ cmd = dma_buffer->cmd; -+ if ((onenand_info.device_id & ONENAND_DEVICE_IS_DDP) -+ && (ofs >= (mtd->size>>1))) { /* DDP Device */ -+ onenand_startaddr1 = DEVICE_FLASHCORE_1 | -+ (((uint32_t)(ofs - (mtd->size>>1)) -+ / mtd->erasesize)); -+ onenand_startaddr2 = DEVICE_BUFFERRAM_1; -+ onenand_startblock = ((uint32_t)(ofs - (mtd->size>>1)) -+ / mtd->erasesize); -+ } else { -+ onenand_startaddr1 = DEVICE_FLASHCORE_0 | -+ ((uint32_t)ofs / mtd->erasesize) ; -+ onenand_startaddr2 = DEVICE_BUFFERRAM_0; -+ onenand_startblock = ((uint32_t)ofs -+ / mtd->erasesize); -+ } -+ -+ onenand_startaddr8 = 0x0000; -+ dma_buffer->data.sfbcfg = SFLASH_BCFG | -+ (nand_sfcmd_mode ? 0 : (1 << 24)); -+ dma_buffer->data.sfcmd[0] = SFLASH_PREPCMD(7, 0, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfcmd[1] = SFLASH_PREPCMD(0, 0, 32, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_INTHI); -+ dma_buffer->data.sfcmd[2] = SFLASH_PREPCMD(3, 7, 0, -+ MSM_NAND_SFCMD_DATXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGRD); -+ dma_buffer->data.sfcmd[3] = SFLASH_PREPCMD(4, 10, 0, -+ MSM_NAND_SFCMD_CMDXS, -+ nand_sfcmd_mode, -+ MSM_NAND_SFCMD_REGWR); -+ dma_buffer->data.sfexec = 1; -+ dma_buffer->data.sfstat[0] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[1] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[2] = CLEAN_DATA_32; -+ dma_buffer->data.sfstat[3] = CLEAN_DATA_32; -+ dma_buffer->data.addr0 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr1 = (ONENAND_START_ADDRESS_8 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.addr2 = (ONENAND_START_BLOCK_ADDRESS << 16) | -+ (ONENAND_START_ADDRESS_2); -+ dma_buffer->data.addr3 = (ONENAND_WRITE_PROT_STATUS << 16) | -+ (ONENAND_COMMAND); -+ dma_buffer->data.addr4 = (ONENAND_CONTROLLER_STATUS << 16) | -+ (ONENAND_INTERRUPT_STATUS); -+ dma_buffer->data.addr5 = (ONENAND_INTERRUPT_STATUS << 16) | -+ (ONENAND_SYSTEM_CONFIG_1); -+ dma_buffer->data.addr6 = (ONENAND_START_ADDRESS_3 << 16) | -+ (ONENAND_START_ADDRESS_1); -+ dma_buffer->data.data0 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data1 = (onenand_startaddr8 << 16) | -+ (onenand_startaddr1); -+ dma_buffer->data.data2 = (onenand_startblock << 16) | -+ (onenand_startaddr2); -+ dma_buffer->data.data3 = (CLEAN_DATA_16 << 16) | -+ (ONENAND_CMD_LOCK); -+ dma_buffer->data.data4 = (CLEAN_DATA_16 << 16) | -+ (CLEAN_DATA_16); -+ dma_buffer->data.data5 = (ONENAND_CLRINTR << 16) | -+ (ONENAND_SYSCFG1_ECCENA(nand_sfcmd_mode)); -+ dma_buffer->data.data6 = (ONENAND_STARTADDR3_RES << 16) | -+ (ONENAND_STARTADDR1_RES); -+ -+ /*************************************************************/ -+ /* Write the necessary address reg in the onenand device */ -+ /*************************************************************/ -+ -+ /* Enable and configure the SFlash controller */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfbcfg); -+ cmd->dst = MSM_NAND_SFLASHC_BURST_CFG; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[0]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the ADDR0 and ADDR1 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr0); -+ cmd->dst = MSM_NAND_ADDR0; -+ cmd->len = 8; -+ cmd++; -+ -+ /* Write the ADDR2 ADDR3 ADDR4 ADDR5 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr2); -+ cmd->dst = MSM_NAND_ADDR2; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the ADDR6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.addr6); -+ cmd->dst = MSM_NAND_ADDR6; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Write the GENP0, GENP1, GENP2, GENP3, GENP4 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data0); -+ cmd->dst = MSM_NAND_GENP_REG0; -+ cmd->len = 16; -+ cmd++; -+ -+ /* Write the FLASH_DEV_CMD4,5,6 registers */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->dst = MSM_NAND_DEV_CMD4; -+ cmd->len = 12; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[0]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*************************************************************/ -+ /* Wait for the interrupt from the Onenand device controller */ -+ /*************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[1]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[1]); -+ cmd->len = 4; -+ cmd++; -+ -+ /*********************************************************/ -+ /* Read the necessary status reg from the onenand device */ -+ /*********************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[2]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[2]); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the GENP3 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_GENP_REG3; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data3); -+ cmd->len = 4; -+ cmd++; -+ -+ /* Read the DEVCMD4 register */ -+ cmd->cmd = 0; -+ cmd->src = MSM_NAND_DEV_CMD4; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.data4); -+ cmd->len = 4; -+ cmd++; -+ -+ /************************************************************/ -+ /* Restore the necessary registers to proper values */ -+ /************************************************************/ -+ -+ /* Block on cmd ready and write CMD register */ -+ cmd->cmd = DST_CRCI_NAND_CMD; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfcmd[3]); -+ cmd->dst = MSM_NAND_SFLASHC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Kick the execute command */ -+ cmd->cmd = 0; -+ cmd->src = msm_virt_to_dma(chip, &dma_buffer->data.sfexec); -+ cmd->dst = MSM_NAND_SFLASHC_EXEC_CMD; -+ cmd->len = 4; -+ cmd++; -+ -+ /* Block on data ready, and read the status register */ -+ cmd->cmd = SRC_CRCI_NAND_DATA; -+ cmd->src = MSM_NAND_SFLASHC_STATUS; -+ cmd->dst = msm_virt_to_dma(chip, &dma_buffer->data.sfstat[3]); -+ cmd->len = 4; -+ cmd++; -+ -+ -+ BUILD_BUG_ON(20 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) -+ >> 3) | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, -+ DMOV_CMD_PTR_LIST | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ -+ write_prot_status = (dma_buffer->data.data3 >> 16) & 0x0000FFFF; -+ interrupt_status = (dma_buffer->data.data4 >> 0) & 0x0000FFFF; -+ controller_status = (dma_buffer->data.data4 >> 16) & 0x0000FFFF; -+ -+#if VERBOSE -+ pr_info("\n%s: sflash status %x %x %x %x\n", __func__, -+ dma_buffer->data.sfstat[0], -+ dma_buffer->data.sfstat[1], -+ dma_buffer->data.sfstat[2], -+ dma_buffer->data.sfstat[3]); -+ -+ pr_info("%s: controller_status = %x\n", __func__, -+ controller_status); -+ pr_info("%s: interrupt_status = %x\n", __func__, -+ interrupt_status); -+ pr_info("%s: write_prot_status = %x\n", __func__, -+ write_prot_status); -+#endif -+ /* Check for errors, protection violations etc */ -+ if ((controller_status != 0) -+ || (dma_buffer->data.sfstat[0] & 0x110) -+ || (dma_buffer->data.sfstat[1] & 0x110) -+ || (dma_buffer->data.sfstat[2] & 0x110) -+ || (dma_buffer->data.sfstat[3] & 0x110)) { -+ pr_err("%s: ECC/MPU/OP error\n", __func__); -+ err = -EIO; -+ } -+ -+ if (!(write_prot_status & ONENAND_WP_LS)) { -+ pr_err("%s: Unexpected status ofs = 0x%llx," -+ "wp_status = %x\n", -+ __func__, ofs, write_prot_status); -+ err = -EIO; -+ } -+ -+ if (err) -+ break; -+ } -+ -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ -+#if VERBOSE -+ pr_info("\n%s: ret %d\n", __func__, err); -+ pr_info("====================================================" -+ "=============\n"); -+#endif -+ return err; -+} -+ -+static int msm_onenand_suspend(struct mtd_info *mtd) -+{ -+ return 0; -+} -+ -+static void msm_onenand_resume(struct mtd_info *mtd) -+{ -+} -+ -+int msm_onenand_scan(struct mtd_info *mtd, int maxchips) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ /* Probe and check whether onenand device is present */ -+ if (flash_onenand_probe(chip)) -+ return -ENODEV; -+ -+ mtd->size = 0x1000000 << ((onenand_info.device_id & 0xF0) >> 4); -+ mtd->writesize = onenand_info.data_buf_size; -+ mtd->oobsize = mtd->writesize >> 5; -+ mtd->erasesize = mtd->writesize << 6; -+ mtd->oobavail = msm_onenand_oob_64.oobavail; -+ mtd->ecclayout = &msm_onenand_oob_64; -+ -+ mtd->type = MTD_NANDFLASH; -+ mtd->flags = MTD_CAP_NANDFLASH; -+ mtd->_erase = msm_onenand_erase; -+ mtd->_point = NULL; -+ mtd->_unpoint = NULL; -+ mtd->_read = msm_onenand_read; -+ mtd->_write = msm_onenand_write; -+ mtd->_read_oob = msm_onenand_read_oob; -+ mtd->_write_oob = msm_onenand_write_oob; -+ mtd->_lock = msm_onenand_lock; -+ mtd->_unlock = msm_onenand_unlock; -+ mtd->_suspend = msm_onenand_suspend; -+ mtd->_resume = msm_onenand_resume; -+ mtd->_block_isbad = msm_onenand_block_isbad; -+ mtd->_block_markbad = msm_onenand_block_markbad; -+ mtd->owner = THIS_MODULE; -+ -+ pr_info("Found a supported onenand device\n"); -+ -+ return 0; -+} -+ -+static const unsigned int bch_sup_cntrl[] = { -+ 0x307, /* MSM7x2xA */ -+ 0x4030, /* MDM 9x15 */ -+}; -+ -+static inline bool msm_nand_has_bch_ecc_engine(unsigned int hw_id) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(bch_sup_cntrl); i++) { -+ if (hw_id == bch_sup_cntrl[i]) -+ return true; -+ } -+ -+ return false; -+} -+ -+/** -+ * msm_nand_scan - [msm_nand Interface] Scan for the msm_nand device -+ * @param mtd MTD device structure -+ * @param maxchips Number of chips to scan for -+ * -+ * This fills out all the not initialized function pointers -+ * with the defaults. -+ * The flash ID is read and the mtd/chip structures are -+ * filled with the appropriate values. -+ */ -+int msm_nand_scan(struct mtd_info *mtd, int maxchips) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ uint32_t flash_id = 0, i, mtd_writesize; -+ uint8_t dev_found = 0; -+ uint8_t wide_bus; -+ uint32_t manid; -+ uint32_t devid; -+ uint32_t devcfg; -+ struct nand_flash_dev *flashdev = NULL; -+ struct nand_manufacturers *flashman = NULL; -+ unsigned int hw_id; -+ -+ /* -+ * Some Spansion parts, like the S34MS04G2, requires that the -+ * NAND Flash be reset before issuing an ONFI probe. -+ */ -+ flash_reset(chip); -+ -+ /* Probe the Flash device for ONFI compliance */ -+ if (!flash_onfi_probe(chip)) { -+ dev_found = 1; -+ } else { -+ /* Read the Flash ID from the Nand Flash Device */ -+ flash_id = flash_read_id(chip); -+ manid = flash_id & 0xFF; -+ devid = (flash_id >> 8) & 0xFF; -+ devcfg = (flash_id >> 24) & 0xFF; -+ -+ for (i = 0; !flashman && nand_manuf_ids[i].id; ++i) -+ if (nand_manuf_ids[i].id == manid) -+ flashman = &nand_manuf_ids[i]; -+ for (i = 0; !flashdev && nand_flash_ids[i].id; ++i) -+ if (nand_flash_ids[i].id == devid) -+ flashdev = &nand_flash_ids[i]; -+ if (!flashdev || !flashman) { -+ pr_err("ERROR: unknown nand device manuf=%x devid=%x\n", -+ manid, devid); -+ return -ENOENT; -+ } else -+ dev_found = 1; -+ -+ if (!flashdev->pagesize) { -+ supported_flash.flash_id = flash_id; -+ supported_flash.density = flashdev->chipsize << 20; -+ supported_flash.widebus = devcfg & (1 << 6) ? 1 : 0; -+ supported_flash.pagesize = 1024 << (devcfg & 0x3); -+ supported_flash.blksize = (64 * 1024) << -+ ((devcfg >> 4) & 0x3); -+ supported_flash.oobsize = (8 << ((devcfg >> 2) & 0x3)) * -+ (supported_flash.pagesize >> 9); -+ -+ if ((supported_flash.oobsize > 64) && -+ (supported_flash.pagesize == 2048)) { -+ pr_info("msm_nand: Found a 2K page device with" -+ " %d oobsize - changing oobsize to 64 " -+ "bytes.\n", supported_flash.oobsize); -+ supported_flash.oobsize = 64; -+ } -+ } else { -+ supported_flash.flash_id = flash_id; -+ supported_flash.density = flashdev->chipsize << 20; -+ supported_flash.widebus = flashdev->options & -+ NAND_BUSWIDTH_16 ? 1 : 0; -+ supported_flash.pagesize = flashdev->pagesize; -+ supported_flash.blksize = flashdev->erasesize; -+ supported_flash.oobsize = flashdev->pagesize >> 5; -+ } -+ } -+ -+ if (dev_found) { -+ (!interleave_enable) ? (i = 1) : (i = 2); -+ wide_bus = supported_flash.widebus; -+ mtd->size = supported_flash.density * i; -+ mtd->writesize = supported_flash.pagesize * i; -+ mtd->oobsize = supported_flash.oobsize * i; -+ mtd->erasesize = supported_flash.blksize * i; -+ mtd->writebufsize = mtd->writesize; -+ -+ if (!interleave_enable) -+ mtd_writesize = mtd->writesize; -+ else -+ mtd_writesize = mtd->writesize >> 1; -+ -+ /* Check whether controller and NAND device support 8bit ECC*/ -+ hw_id = flash_rd_reg(chip, MSM_NAND_HW_INFO); -+ if (msm_nand_has_bch_ecc_engine(hw_id) -+ && (supported_flash.ecc_correctability >= 8)) { -+ pr_info("Found supported NAND device for %dbit ECC\n", -+ supported_flash.ecc_correctability); -+ enable_bch_ecc = 1; -+ } else { -+ pr_info("Found a supported NAND device\n"); -+ } -+ pr_info("NAND Controller ID : 0x%x\n", hw_id); -+ pr_info("NAND Device ID : 0x%x\n", supported_flash.flash_id); -+ pr_info("Buswidth : %d Bits\n", (wide_bus) ? 16 : 8); -+ pr_info("Density : %lld MByte\n", (mtd->size>>20)); -+ pr_info("Pagesize : %d Bytes\n", mtd->writesize); -+ pr_info("Erasesize: %d Bytes\n", mtd->erasesize); -+ pr_info("Oobsize : %d Bytes\n", mtd->oobsize); -+ } else { -+ pr_err("Unsupported Nand,Id: 0x%x \n", flash_id); -+ return -ENODEV; -+ } -+ -+ /* Size of each codeword is 532Bytes incase of 8bit BCH ECC*/ -+ chip->cw_size = enable_bch_ecc ? 532 : 528; -+ chip->CFG0 = (((mtd_writesize >> 9)-1) << 6) /* 4/8 cw/pg for 2/4k */ -+ | (516 << 9) /* 516 user data bytes */ -+ | (10 << 19) /* 10 parity bytes */ -+ | (5 << 27) /* 5 address cycles */ -+ | (0 << 30) /* Do not read status before data */ -+ | (1 << 31) /* Send read cmd */ -+ /* 0 spare bytes for 16 bit nand or 1/2 spare bytes for 8 bit */ -+ | (wide_bus ? 0 << 23 : (enable_bch_ecc ? 2 << 23 : 1 << 23)); -+ -+ chip->CFG1 = (0 << 0) /* Enable ecc */ -+ | (7 << 2) /* 8 recovery cycles */ -+ | (0 << 5) /* Allow CS deassertion */ -+ /* Bad block marker location */ -+ | ((mtd_writesize - (chip->cw_size * ( -+ (mtd_writesize >> 9) - 1)) + 1) << 6) -+ | (0 << 16) /* Bad block in user data area */ -+ | (2 << 17) /* 6 cycle tWB/tRB */ -+ | ((wide_bus) ? CFG1_WIDE_FLASH : 0); /* Wide flash bit */ -+ -+ chip->ecc_buf_cfg = 0x203; -+ chip->CFG0_RAW = 0xA80420C0; -+ chip->CFG1_RAW = 0x5045D; -+ -+ if (enable_bch_ecc) { -+ chip->CFG1 |= (1 << 27); /* Enable BCH engine */ -+ chip->ecc_bch_cfg = (0 << 0) /* Enable ECC*/ -+ | (0 << 1) /* Enable/Disable SW reset of ECC engine */ -+ | (1 << 4) /* 8bit ecc*/ -+ | ((wide_bus) ? (14 << 8) : (13 << 8))/*parity bytes*/ -+ | (516 << 16) /* 516 user data bytes */ -+ | (1 << 30); /* Turn on ECC engine clocks always */ -+ chip->CFG0_RAW = 0xA80428C0; /* CW size is increased to 532B */ -+ } -+ -+ /* -+ * For 4bit RS ECC (default ECC), parity bytes = 10 (for x8 and x16 I/O) -+ * For 8bit BCH ECC, parity bytes = 13 (x8) or 14 (x16 I/O). -+ */ -+ chip->ecc_parity_bytes = enable_bch_ecc ? (wide_bus ? 14 : 13) : 10; -+ -+ pr_info("CFG0 Init : 0x%08x\n", chip->CFG0); -+ pr_info("CFG1 Init : 0x%08x\n", chip->CFG1); -+ pr_info("ECCBUFCFG : 0x%08x\n", chip->ecc_buf_cfg); -+ -+ if (mtd->oobsize == 64) { -+ mtd->oobavail = msm_nand_oob_64.oobavail; -+ mtd->ecclayout = &msm_nand_oob_64; -+ } else if (mtd->oobsize == 128) { -+ mtd->oobavail = msm_nand_oob_128.oobavail; -+ mtd->ecclayout = &msm_nand_oob_128; -+ } else if (mtd->oobsize == 224) { -+ mtd->oobavail = wide_bus ? msm_nand_oob_224_x16.oobavail : -+ msm_nand_oob_224_x8.oobavail; -+ mtd->ecclayout = wide_bus ? &msm_nand_oob_224_x16 : -+ &msm_nand_oob_224_x8; -+ } else if (mtd->oobsize == 256) { -+ mtd->oobavail = msm_nand_oob_256.oobavail; -+ mtd->ecclayout = &msm_nand_oob_256; -+ } else { -+ pr_err("Unsupported Nand, oobsize: 0x%x \n", -+ mtd->oobsize); -+ return -ENODEV; -+ } -+ -+ /* Fill in remaining MTD driver data */ -+ mtd->type = MTD_NANDFLASH; -+ mtd->flags = MTD_CAP_NANDFLASH; -+ /* mtd->ecctype = MTD_ECC_SW; */ -+ mtd->_erase = msm_nand_erase; -+ mtd->_block_isbad = msm_nand_block_isbad; -+ mtd->_block_markbad = msm_nand_block_markbad; -+ mtd->_point = NULL; -+ mtd->_unpoint = NULL; -+ mtd->_read = msm_nand_read; -+ mtd->_write = msm_nand_write; -+ mtd->_read_oob = msm_nand_read_oob; -+ mtd->_write_oob = msm_nand_write_oob; -+ if (dual_nand_ctlr_present) { -+ mtd->_read_oob = msm_nand_read_oob_dualnandc; -+ mtd->_write_oob = msm_nand_write_oob_dualnandc; -+ if (interleave_enable) { -+ mtd->_erase = msm_nand_erase_dualnandc; -+ mtd->_block_isbad = msm_nand_block_isbad_dualnandc; -+ } -+ } -+ -+ /* mtd->sync = msm_nand_sync; */ -+ mtd->_lock = NULL; -+ /* mtd->_unlock = msm_nand_unlock; */ -+ mtd->_suspend = msm_nand_suspend; -+ mtd->_resume = msm_nand_resume; -+ mtd->owner = THIS_MODULE; -+ -+ /* Unlock whole block */ -+ /* msm_nand_unlock_all(mtd); */ -+ -+ /* return this->scan_bbt(mtd); */ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(msm_nand_scan); -+ -+/** -+ * msm_nand_release - [msm_nand Interface] Free resources held by the msm_nand device -+ * @param mtd MTD device structure -+ */ -+void msm_nand_release(struct mtd_info *mtd) -+{ -+ /* struct msm_nand_chip *this = mtd->priv; */ -+ -+ /* Deregister the device */ -+ mtd_device_unregister(mtd); -+} -+EXPORT_SYMBOL_GPL(msm_nand_release); -+ -+struct msm_nand_info { -+ struct mtd_info mtd; -+ struct mtd_partition *parts; -+ struct msm_nand_chip msm_nand; -+}; -+ -+/* duplicating the NC01 XFR contents to NC10 */ -+static int msm_nand_nc10_xfr_settings(struct mtd_info *mtd) -+{ -+ struct msm_nand_chip *chip = mtd->priv; -+ -+ struct { -+ dmov_s cmd[2]; -+ unsigned cmdptr; -+ } *dma_buffer; -+ dmov_s *cmd; -+ -+ wait_event(chip->wait_queue, -+ (dma_buffer = msm_nand_get_dma_buffer( -+ chip, sizeof(*dma_buffer)))); -+ -+ cmd = dma_buffer->cmd; -+ -+ /* Copying XFR register contents from NC01 --> NC10 */ -+ cmd->cmd = 0; -+ cmd->src = NC01(MSM_NAND_XFR_STEP1); -+ cmd->dst = NC10(MSM_NAND_XFR_STEP1); -+ cmd->len = 28; -+ cmd++; -+ -+ BUILD_BUG_ON(2 != ARRAY_SIZE(dma_buffer->cmd)); -+ BUG_ON(cmd - dma_buffer->cmd > ARRAY_SIZE(dma_buffer->cmd)); -+ dma_buffer->cmd[0].cmd |= CMD_OCB; -+ cmd[-1].cmd |= CMD_OCU | CMD_LC; -+ dma_buffer->cmdptr = (msm_virt_to_dma(chip, dma_buffer->cmd) >> 3) -+ | CMD_PTR_LP; -+ -+ mb(); -+ msm_dmov_exec_cmd(chip->dma_channel, DMOV_CMD_PTR_LIST -+ | DMOV_CMD_ADDR(msm_virt_to_dma(chip, -+ &dma_buffer->cmdptr))); -+ mb(); -+ msm_nand_release_dma_buffer(chip, dma_buffer, sizeof(*dma_buffer)); -+ return 0; -+} -+ -+static ssize_t boot_layout_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ return sprintf(buf, "%d\n", boot_layout); -+} -+ -+static ssize_t boot_layout_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t n) -+{ -+ struct msm_nand_info *info = dev_get_drvdata(dev); -+ struct msm_nand_chip *chip = info->mtd.priv; -+ unsigned int ud_size; -+ unsigned int spare_size; -+ unsigned int ecc_num_data_bytes; -+ -+ sscanf(buf, "%d", &boot_layout); -+ -+ ud_size = boot_layout? 512: 516; -+ spare_size = boot_layout? (chip->cw_size - -+ (chip->ecc_parity_bytes+ 1+ ud_size)): -+ (enable_bch_ecc ? 2 : 1); -+ ecc_num_data_bytes = boot_layout? 512: 516; -+ -+ chip->CFG0 = (chip->CFG0 & ~SPARE_SIZE_BYTES_MASK); -+ chip->CFG0 |= (spare_size << 23); -+ -+ chip->CFG0 = (chip->CFG0 & ~UD_SIZE_BYTES_MASK); -+ chip->CFG0 |= (ud_size << 9); -+ -+ chip->ecc_buf_cfg = (chip->ecc_buf_cfg & ~ECC_NUM_DATA_BYTES_MASK) -+ | (ecc_num_data_bytes << 16); -+ -+ return n; -+} -+ -+static const DEVICE_ATTR(boot_layout, 0644, boot_layout_show, boot_layout_store); -+ -+static int msm_nand_probe(struct platform_device *pdev) -+ -+{ -+ struct msm_nand_info *info; -+ struct resource *res; -+ int err; -+ struct mtd_part_parser_data ppdata = {}; -+ -+ -+ res = platform_get_resource(pdev, -+ IORESOURCE_MEM, 0); -+ if (!res || !res->start) { -+ pr_err("%s: msm_nand_phys resource invalid/absent\n", -+ __func__); -+ return -ENODEV; -+ } -+ msm_nand_phys = res->start; -+ -+ info = devm_kzalloc(&pdev->dev, sizeof(struct msm_nand_info), GFP_KERNEL); -+ if (!info) { -+ pr_err("%s: No memory for msm_nand_info\n", __func__); -+ return -ENOMEM; -+ } -+ -+ info->msm_nand.dev = &pdev->dev; -+ -+ init_waitqueue_head(&info->msm_nand.wait_queue); -+ -+ info->msm_nand.dma_channel = 3; -+ pr_info("%s: dmac 0x%x\n", __func__, info->msm_nand.dma_channel); -+ -+ /* this currently fails if dev is passed in */ -+ info->msm_nand.dma_buffer = -+ dma_alloc_coherent(/*dev*/ NULL, MSM_NAND_DMA_BUFFER_SIZE, -+ &info->msm_nand.dma_addr, GFP_KERNEL); -+ if (info->msm_nand.dma_buffer == NULL) { -+ pr_err("%s: No memory for msm_nand.dma_buffer\n", __func__); -+ err = -ENOMEM; -+ goto out_free_info; -+ } -+ -+ pr_info("%s: allocated dma buffer at %p, dma_addr %x\n", -+ __func__, info->msm_nand.dma_buffer, info->msm_nand.dma_addr); -+ -+ /* Let default be VERSION_1 for backward compatibility */ -+ info->msm_nand.uncorrectable_bit_mask = BIT(8); -+ info->msm_nand.num_err_mask = 0x1F; -+ -+ info->mtd.name = dev_name(&pdev->dev); -+ info->mtd.priv = &info->msm_nand; -+ info->mtd.owner = THIS_MODULE; -+ -+ /* config ebi2_cfg register only for ping pong mode!!! */ -+ if (!interleave_enable && dual_nand_ctlr_present) -+ flash_wr_reg(&info->msm_nand, EBI2_CFG_REG, 0x4010080); -+ -+ if (dual_nand_ctlr_present) -+ msm_nand_nc10_xfr_settings(&info->mtd); -+ -+ if (msm_nand_scan(&info->mtd, 1)) -+ if (msm_onenand_scan(&info->mtd, 1)) { -+ pr_err("%s: No nand device found\n", __func__); -+ err = -ENXIO; -+ goto out_free_dma_buffer; -+ } -+ -+ flash_wr_reg(&info->msm_nand, MSM_NAND_DEV_CMD_VLD, -+ DEV_CMD_VLD_SEQ_READ_START_VLD | -+ DEV_CMD_VLD_ERASE_START_VLD | -+ DEV_CMD_VLD_WRITE_START_VLD | -+ DEV_CMD_VLD_READ_START_VLD); -+ -+ ppdata.of_node = pdev->dev.of_node; -+ err = mtd_device_parse_register(&info->mtd, NULL, &ppdata, NULL, 0); -+ -+ if (err < 0) { -+ pr_err("%s: mtd_device_parse_register failed with err=%d\n", -+ __func__, err); -+ goto out_free_dma_buffer; -+ } -+ -+ err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_boot_layout.attr); -+ if (err) -+ goto out_free_dma_buffer; -+ -+ dev_set_drvdata(&pdev->dev, info); -+ -+ return 0; -+ -+out_free_dma_buffer: -+ dma_free_coherent(NULL, MSM_NAND_DMA_BUFFER_SIZE, -+ info->msm_nand.dma_buffer, -+ info->msm_nand.dma_addr); -+out_free_info: -+ return err; -+} -+ -+static int msm_nand_remove(struct platform_device *pdev) -+{ -+ struct msm_nand_info *info = dev_get_drvdata(&pdev->dev); -+ -+ dev_set_drvdata(&pdev->dev, NULL); -+ -+ if (info) { -+ msm_nand_release(&info->mtd); -+ dma_free_coherent(NULL, MSM_NAND_DMA_BUFFER_SIZE, -+ info->msm_nand.dma_buffer, -+ info->msm_nand.dma_addr); -+ } -+ -+ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_boot_layout.attr); -+ -+ return 0; -+} -+ -+ -+#ifdef CONFIG_OF -+static const struct of_device_id msm_nand_of_match[] = { -+ { .compatible = "qcom,qcom_nand", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, msm_nand_of_match); -+#endif -+ -+ -+static struct platform_driver msm_nand_driver = { -+ .probe = msm_nand_probe, -+ .remove = msm_nand_remove, -+ .driver = { -+ .name = "qcom_nand", -+ .owner = THIS_MODULE, -+ .of_match_table = msm_nand_of_match, -+ } -+}; -+ -+ -+module_platform_driver(msm_nand_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("msm_nand flash driver code"); ---- /dev/null -+++ b/drivers/mtd/nand/qcom_nand.h -@@ -0,0 +1,196 @@ -+/* drivers/mtd/devices/msm_nand.h -+ * -+ * Copyright (c) 2008-2011, The Linux Foundation. All rights reserved. -+ * Copyright (C) 2007 Google, Inc. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#ifndef __DRIVERS_MTD_DEVICES_MSM_NAND_H -+#define __DRIVERS_MTD_DEVICES_MSM_NAND_H -+ -+extern unsigned long msm_nand_phys; -+extern unsigned long msm_nandc01_phys; -+extern unsigned long msm_nandc10_phys; -+extern unsigned long msm_nandc11_phys; -+extern unsigned long ebi2_register_base; -+ -+#define NC01(X) ((X) + msm_nandc01_phys - msm_nand_phys) -+#define NC10(X) ((X) + msm_nandc10_phys - msm_nand_phys) -+#define NC11(X) ((X) + msm_nandc11_phys - msm_nand_phys) -+ -+#define MSM_NAND_REG(off) (msm_nand_phys + (off)) -+ -+#define MSM_NAND_FLASH_CMD MSM_NAND_REG(0x0000) -+#define MSM_NAND_ADDR0 MSM_NAND_REG(0x0004) -+#define MSM_NAND_ADDR1 MSM_NAND_REG(0x0008) -+#define MSM_NAND_FLASH_CHIP_SELECT MSM_NAND_REG(0x000C) -+#define MSM_NAND_EXEC_CMD MSM_NAND_REG(0x0010) -+#define MSM_NAND_FLASH_STATUS MSM_NAND_REG(0x0014) -+#define MSM_NAND_BUFFER_STATUS MSM_NAND_REG(0x0018) -+#define MSM_NAND_SFLASHC_STATUS MSM_NAND_REG(0x001C) -+#define MSM_NAND_DEV0_CFG0 MSM_NAND_REG(0x0020) -+#define MSM_NAND_DEV0_CFG1 MSM_NAND_REG(0x0024) -+#define MSM_NAND_DEV0_ECC_CFG MSM_NAND_REG(0x0028) -+#define MSM_NAND_DEV1_ECC_CFG MSM_NAND_REG(0x002C) -+#define MSM_NAND_DEV1_CFG0 MSM_NAND_REG(0x0030) -+#define MSM_NAND_DEV1_CFG1 MSM_NAND_REG(0x0034) -+#define MSM_NAND_SFLASHC_CMD MSM_NAND_REG(0x0038) -+#define MSM_NAND_SFLASHC_EXEC_CMD MSM_NAND_REG(0x003C) -+#define MSM_NAND_READ_ID MSM_NAND_REG(0x0040) -+#define MSM_NAND_READ_STATUS MSM_NAND_REG(0x0044) -+#define MSM_NAND_CONFIG_DATA MSM_NAND_REG(0x0050) -+#define MSM_NAND_CONFIG MSM_NAND_REG(0x0054) -+#define MSM_NAND_CONFIG_MODE MSM_NAND_REG(0x0058) -+#define MSM_NAND_CONFIG_STATUS MSM_NAND_REG(0x0060) -+#define MSM_NAND_MACRO1_REG MSM_NAND_REG(0x0064) -+#define MSM_NAND_XFR_STEP1 MSM_NAND_REG(0x0070) -+#define MSM_NAND_XFR_STEP2 MSM_NAND_REG(0x0074) -+#define MSM_NAND_XFR_STEP3 MSM_NAND_REG(0x0078) -+#define MSM_NAND_XFR_STEP4 MSM_NAND_REG(0x007C) -+#define MSM_NAND_XFR_STEP5 MSM_NAND_REG(0x0080) -+#define MSM_NAND_XFR_STEP6 MSM_NAND_REG(0x0084) -+#define MSM_NAND_XFR_STEP7 MSM_NAND_REG(0x0088) -+#define MSM_NAND_GENP_REG0 MSM_NAND_REG(0x0090) -+#define MSM_NAND_GENP_REG1 MSM_NAND_REG(0x0094) -+#define MSM_NAND_GENP_REG2 MSM_NAND_REG(0x0098) -+#define MSM_NAND_GENP_REG3 MSM_NAND_REG(0x009C) -+#define MSM_NAND_DEV_CMD0 MSM_NAND_REG(0x00A0) -+#define MSM_NAND_DEV_CMD1 MSM_NAND_REG(0x00A4) -+#define MSM_NAND_DEV_CMD2 MSM_NAND_REG(0x00A8) -+#define MSM_NAND_DEV_CMD_VLD MSM_NAND_REG(0x00AC) -+#define DEV_CMD_VLD_SEQ_READ_START_VLD 0x10 -+#define DEV_CMD_VLD_ERASE_START_VLD 0x8 -+#define DEV_CMD_VLD_WRITE_START_VLD 0x4 -+#define DEV_CMD_VLD_READ_STOP_VLD 0x2 -+#define DEV_CMD_VLD_READ_START_VLD 0x1 -+ -+#define MSM_NAND_EBI2_MISR_SIG_REG MSM_NAND_REG(0x00B0) -+#define MSM_NAND_ADDR2 MSM_NAND_REG(0x00C0) -+#define MSM_NAND_ADDR3 MSM_NAND_REG(0x00C4) -+#define MSM_NAND_ADDR4 MSM_NAND_REG(0x00C8) -+#define MSM_NAND_ADDR5 MSM_NAND_REG(0x00CC) -+#define MSM_NAND_DEV_CMD3 MSM_NAND_REG(0x00D0) -+#define MSM_NAND_DEV_CMD4 MSM_NAND_REG(0x00D4) -+#define MSM_NAND_DEV_CMD5 MSM_NAND_REG(0x00D8) -+#define MSM_NAND_DEV_CMD6 MSM_NAND_REG(0x00DC) -+#define MSM_NAND_SFLASHC_BURST_CFG MSM_NAND_REG(0x00E0) -+#define MSM_NAND_ADDR6 MSM_NAND_REG(0x00E4) -+#define MSM_NAND_EBI2_ECC_BUF_CFG MSM_NAND_REG(0x00F0) -+#define MSM_NAND_HW_INFO MSM_NAND_REG(0x00FC) -+#define MSM_NAND_FLASH_BUFFER MSM_NAND_REG(0x0100) -+ -+/* device commands */ -+ -+#define MSM_NAND_CMD_SOFT_RESET 0x01 -+#define MSM_NAND_CMD_PAGE_READ 0x32 -+#define MSM_NAND_CMD_PAGE_READ_ECC 0x33 -+#define MSM_NAND_CMD_PAGE_READ_ALL 0x34 -+#define MSM_NAND_CMD_SEQ_PAGE_READ 0x15 -+#define MSM_NAND_CMD_PRG_PAGE 0x36 -+#define MSM_NAND_CMD_PRG_PAGE_ECC 0x37 -+#define MSM_NAND_CMD_PRG_PAGE_ALL 0x39 -+#define MSM_NAND_CMD_BLOCK_ERASE 0x3A -+#define MSM_NAND_CMD_FETCH_ID 0x0B -+#define MSM_NAND_CMD_STATUS 0x0C -+#define MSM_NAND_CMD_RESET 0x0D -+ -+/* Sflash Commands */ -+ -+#define MSM_NAND_SFCMD_DATXS 0x0 -+#define MSM_NAND_SFCMD_CMDXS 0x1 -+#define MSM_NAND_SFCMD_BURST 0x0 -+#define MSM_NAND_SFCMD_ASYNC 0x1 -+#define MSM_NAND_SFCMD_ABORT 0x1 -+#define MSM_NAND_SFCMD_REGRD 0x2 -+#define MSM_NAND_SFCMD_REGWR 0x3 -+#define MSM_NAND_SFCMD_INTLO 0x4 -+#define MSM_NAND_SFCMD_INTHI 0x5 -+#define MSM_NAND_SFCMD_DATRD 0x6 -+#define MSM_NAND_SFCMD_DATWR 0x7 -+ -+#define SFLASH_PREPCMD(numxfr, offval, delval, trnstp, mode, opcode) \ -+ ((numxfr<<20)|(offval<<12)|(delval<<6)|(trnstp<<5)|(mode<<4)|opcode) -+ -+#define SFLASH_BCFG 0x20100327 -+ -+/* Onenand addresses */ -+ -+#define ONENAND_MANUFACTURER_ID 0xF000 -+#define ONENAND_DEVICE_ID 0xF001 -+#define ONENAND_VERSION_ID 0xF002 -+#define ONENAND_DATA_BUFFER_SIZE 0xF003 -+#define ONENAND_BOOT_BUFFER_SIZE 0xF004 -+#define ONENAND_AMOUNT_OF_BUFFERS 0xF005 -+#define ONENAND_TECHNOLOGY 0xF006 -+#define ONENAND_START_ADDRESS_1 0xF100 -+#define ONENAND_START_ADDRESS_2 0xF101 -+#define ONENAND_START_ADDRESS_3 0xF102 -+#define ONENAND_START_ADDRESS_4 0xF103 -+#define ONENAND_START_ADDRESS_5 0xF104 -+#define ONENAND_START_ADDRESS_6 0xF105 -+#define ONENAND_START_ADDRESS_7 0xF106 -+#define ONENAND_START_ADDRESS_8 0xF107 -+#define ONENAND_START_BUFFER 0xF200 -+#define ONENAND_COMMAND 0xF220 -+#define ONENAND_SYSTEM_CONFIG_1 0xF221 -+#define ONENAND_SYSTEM_CONFIG_2 0xF222 -+#define ONENAND_CONTROLLER_STATUS 0xF240 -+#define ONENAND_INTERRUPT_STATUS 0xF241 -+#define ONENAND_START_BLOCK_ADDRESS 0xF24C -+#define ONENAND_WRITE_PROT_STATUS 0xF24E -+#define ONENAND_ECC_STATUS 0xFF00 -+#define ONENAND_ECC_ERRPOS_MAIN0 0xFF01 -+#define ONENAND_ECC_ERRPOS_SPARE0 0xFF02 -+#define ONENAND_ECC_ERRPOS_MAIN1 0xFF03 -+#define ONENAND_ECC_ERRPOS_SPARE1 0xFF04 -+#define ONENAND_ECC_ERRPOS_MAIN2 0xFF05 -+#define ONENAND_ECC_ERRPOS_SPARE2 0xFF06 -+#define ONENAND_ECC_ERRPOS_MAIN3 0xFF07 -+#define ONENAND_ECC_ERRPOS_SPARE3 0xFF08 -+ -+/* Onenand commands */ -+#define ONENAND_WP_US (1 << 2) -+#define ONENAND_WP_LS (1 << 1) -+ -+#define ONENAND_CMDLOAD 0x0000 -+#define ONENAND_CMDLOADSPARE 0x0013 -+#define ONENAND_CMDPROG 0x0080 -+#define ONENAND_CMDPROGSPARE 0x001A -+#define ONENAND_CMDERAS 0x0094 -+#define ONENAND_CMD_UNLOCK 0x0023 -+#define ONENAND_CMD_LOCK 0x002A -+ -+#define ONENAND_SYSCFG1_ECCENA(mode) (0x40E0 | (mode ? 0 : 0x8002)) -+#define ONENAND_SYSCFG1_ECCDIS(mode) (0x41E0 | (mode ? 0 : 0x8002)) -+ -+#define ONENAND_CLRINTR 0x0000 -+#define ONENAND_STARTADDR1_RES 0x07FF -+#define ONENAND_STARTADDR3_RES 0x07FF -+ -+#define DATARAM0_0 0x8 -+#define DEVICE_FLASHCORE_0 (0 << 15) -+#define DEVICE_FLASHCORE_1 (1 << 15) -+#define DEVICE_BUFFERRAM_0 (0 << 15) -+#define DEVICE_BUFFERRAM_1 (1 << 15) -+#define ONENAND_DEVICE_IS_DDP (1 << 3) -+ -+#define CLEAN_DATA_16 0xFFFF -+#define CLEAN_DATA_32 0xFFFFFFFF -+ -+#define EBI2_REG(off) (ebi2_register_base + (off)) -+#define EBI2_CHIP_SELECT_CFG0 EBI2_REG(0x0000) -+#define EBI2_CFG_REG EBI2_REG(0x0004) -+#define EBI2_NAND_ADM_MUX EBI2_REG(0x005C) -+ -+extern struct flash_platform_data msm_nand_data; -+ -+#endif diff --git a/target/linux/ipq806x/patches/0151-ARM-ipq8064-Add-nand-device-info.patch b/target/linux/ipq806x/patches/0151-ARM-ipq8064-Add-nand-device-info.patch deleted file mode 100644 index b460454352..0000000000 --- a/target/linux/ipq806x/patches/0151-ARM-ipq8064-Add-nand-device-info.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 4490cfa66379909cdddc3518c8e75b7cd26d8f69 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 16 Jun 2014 16:53:49 -0500 -Subject: [PATCH 151/182] ARM: ipq8064: Add nand device info - -Signed-off-by: Andy Gross ---- - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 34 ++++++++++++++++++++++++++++++ - arch/arm/boot/dts/qcom-ipq8064.dtsi | 33 +++++++++++++++++++++++++++++ - 2 files changed, 67 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -45,6 +45,29 @@ - bias-none; - }; - }; -+ nand_pins: nand_pins { -+ mux { -+ pins = "gpio34", "gpio35", "gpio36", -+ "gpio37", "gpio38", "gpio39", -+ "gpio40", "gpio41", "gpio42", -+ "gpio43", "gpio44", "gpio45", -+ "gpio46", "gpio47"; -+ function = "nand"; -+ drive-strength = <10>; -+ bias-disable; -+ }; -+ pullups { -+ pins = "gpio39"; -+ bias-pull-up; -+ }; -+ hold { -+ pins = "gpio40", "gpio41", "gpio42", -+ "gpio43", "gpio44", "gpio45", -+ "gpio46", "gpio47"; -+ bias-bus-hold; -+ }; -+ }; -+ - }; - - gsbi@16300000 { -@@ -126,5 +149,16 @@ - sata@29000000 { - status = "ok"; - }; -+ -+ dma@18300000 { -+ status = "ok"; -+ }; -+ -+ nand@0x1ac00000 { -+ status = "ok"; -+ -+ pinctrl-0 = <&nand_pins>; -+ pinctrl-names = "default"; -+ }; - }; - }; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -76,6 +76,7 @@ - interrupt-controller; - #interrupt-cells = <2>; - interrupts = <0 32 0x4>; -+ - }; - - intc: interrupt-controller@2000000 { -@@ -369,5 +370,37 @@ - phy-names = "sata-phy"; - status = "disabled"; - }; -+ -+ adm_dma: dma@18300000 { -+ compatible = "qcom,adm"; -+ reg = <0x18300000 0x100000>; -+ interrupts = <0 170 0>; -+ -+ clocks = <&gcc ADM0_CLK>, <&gcc ADM0_PBUS_CLK>; -+ clock-names = "core_clk", "iface_clk"; -+ -+ resets = <&gcc ADM0_RESET>, -+ <&gcc ADM0_PBUS_RESET>, -+ <&gcc ADM0_C0_RESET>, -+ <&gcc ADM0_C1_RESET>, -+ <&gcc ADM0_C2_RESET>; -+ -+ reset-names = "adm", "pbus", "c0", "c1", "c2"; -+ -+ status = "disabled"; -+ }; -+ -+ nand@0x1ac00000 { -+ compatible = "qcom,qcom_nand"; -+ reg = <0x1ac00000 0x800>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ clocks = <&gcc EBI2_CLK>; -+ clock-names = "core_clk"; -+ -+ -+ status = "disabled"; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0152-ARM-qcom-config-Add-NAND-config-options.patch b/target/linux/ipq806x/patches/0152-ARM-qcom-config-Add-NAND-config-options.patch deleted file mode 100644 index a2489e49e5..0000000000 --- a/target/linux/ipq806x/patches/0152-ARM-qcom-config-Add-NAND-config-options.patch +++ /dev/null @@ -1,22 +0,0 @@ -From d04f697bf7cfe756de6187be1d0e5669d4d5bca0 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 16 Jun 2014 17:30:04 -0500 -Subject: [PATCH 152/182] ARM: qcom: config: Add NAND config options - -Add NAND config options to enable QCOM NAND controller - -Signed-off-by: Andy Gross ---- - arch/arm/configs/qcom_defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -56,6 +56,7 @@ CONFIG_DEVTMPFS_MOUNT=y - CONFIG_MTD=y - CONFIG_MTD_BLOCK=y - CONFIG_MTD_M25P80=y -+CONFIG_MTD_NAND=y - CONFIG_BLK_DEV_LOOP=y - CONFIG_BLK_DEV_RAM=y - CONFIG_SCSI_TGT=y diff --git a/target/linux/ipq806x/patches/0153-soc-qcom-tcsr-Add-TCSR-driver.patch b/target/linux/ipq806x/patches/0153-soc-qcom-tcsr-Add-TCSR-driver.patch deleted file mode 100644 index 65e4c2ff33..0000000000 --- a/target/linux/ipq806x/patches/0153-soc-qcom-tcsr-Add-TCSR-driver.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0b469f3f4c0e6a0e0b1b60a059600e325a03b6f5 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 12 Jun 2014 00:52:06 -0500 -Subject: [PATCH 153/182] soc: qcom: tcsr: Add TCSR driver - -This patch adds support for the TCSR IP block present in Qualcomm processors. - -Signed-off-by: Andy Gross ---- - .../devicetree/bindings/soc/qcom/qcom,tcsr.txt | 25 ++++++++ - drivers/soc/qcom/Kconfig | 6 ++ - drivers/soc/qcom/Makefile | 1 + - drivers/soc/qcom/qcom_tcsr.c | 64 ++++++++++++++++++++ - include/dt-bindings/soc/qcom,tcsr.h | 19 ++++++ - 5 files changed, 115 insertions(+) - create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,tcsr.txt - create mode 100644 drivers/soc/qcom/qcom_tcsr.c - create mode 100644 include/dt-bindings/soc/qcom,tcsr.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,tcsr.txt -@@ -0,0 +1,25 @@ -+QCOM TCSR (Top Control and Status Register) Driver -+ -+The TCSR provides miscellaneous control functions and status registers for -+Qualcomm processors. -+ -+Required properties: -+- compatible: must contain "qcom,tcsr" for IPQ806x -+- reg: Address range for TCSR registers -+ -+Optional properties: -+- qcom,usb-ctrl-select : indicates USB port type selection. Please reference -+ dt-bindings/soc/qcom,tcsr.h for valid USB port selection values. -+ -+Example for IPQ8064: -+ -+#include -+ -+ tcsr: tcsr@1a400000 { -+ compatible = "qcom,tcsr"; -+ reg = <0x1a400000 0x100>; -+ -+ qcom,usb-ctrl-select = ; -+ }; -+ -+ ---- a/drivers/soc/qcom/Kconfig -+++ b/drivers/soc/qcom/Kconfig -@@ -9,3 +9,9 @@ config QCOM_GSBI - functions for connecting the underlying serial UART, SPI, and I2C - devices to the output pins. - -+config QCOM_TCSR -+ tristate "QCOM Top Control and Status Registers" -+ depends on ARCH_QCOM -+ help -+ Say y here to enable TCSR support. The TCSR provides control -+ functions for various peripherals. ---- a/drivers/soc/qcom/Makefile -+++ b/drivers/soc/qcom/Makefile -@@ -1 +1,2 @@ - obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o -+obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o ---- /dev/null -+++ b/drivers/soc/qcom/qcom_tcsr.c -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (c) 2014, The Linux foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License rev 2 and -+ * only rev 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TCSR_USB_PORT_SEL 0xb0 -+ -+static int tcsr_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ const struct device_node *node = pdev->dev.of_node; -+ void __iomem *base; -+ u32 val; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) { -+ dev_err(&pdev->dev, "setting usb port select = %d\n", val); -+ writel(val, base + TCSR_USB_PORT_SEL); -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id tcsr_dt_match[] = { -+ { .compatible = "qcom,tcsr", }, -+ { }, -+}; -+ -+MODULE_DEVICE_TABLE(of, tcsr_dt_match); -+ -+static struct platform_driver tcsr_driver = { -+ .driver = { -+ .name = "tcsr", -+ .owner = THIS_MODULE, -+ .of_match_table = tcsr_dt_match, -+ }, -+ .probe = tcsr_probe, -+}; -+ -+module_platform_driver(tcsr_driver); -+ -+MODULE_AUTHOR("Andy Gross "); -+MODULE_DESCRIPTION("QCOM TCSR driver"); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/include/dt-bindings/soc/qcom,tcsr.h -@@ -0,0 +1,19 @@ -+/* Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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_QCOM_TCSR_H -+#define __DT_BINDINGS_QCOM_TCSR_H -+ -+#define TCSR_USB_SELECT_USB3_P0 0x1 -+#define TCSR_USB_SELECT_USB3_P1 0x2 -+#define TCSR_USB_SELECT_USB3_DUAL 0x3 -+ -+#endif diff --git a/target/linux/ipq806x/patches/0154-clk-qcom-Correct-UTMI-clock-frequency-table.patch b/target/linux/ipq806x/patches/0154-clk-qcom-Correct-UTMI-clock-frequency-table.patch deleted file mode 100644 index 1d81970c96..0000000000 --- a/target/linux/ipq806x/patches/0154-clk-qcom-Correct-UTMI-clock-frequency-table.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 2561c49dcf5cb35ad72df34bf225a51fe2fa87e5 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 12 Jun 2014 00:53:19 -0500 -Subject: [PATCH 154/182] clk: qcom: Correct UTMI clock frequency table - -This patch changes the UTMI clock frequency from 20MHz to the correct value of -60MHz. - -Signed-off-by: Andy Gross ---- - drivers/clk/qcom/gcc-ipq806x.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/clk/qcom/gcc-ipq806x.c -+++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -1992,7 +1992,7 @@ static struct clk_branch usb30_1_branch_ - }; - - static const struct freq_tbl clk_tbl_usb30_utmi[] = { -- { 60000000, P_PLL0, 1, 1, 40 }, -+ { 60000000, P_PLL8, 1, 5, 32 }, - { } - }; - diff --git a/target/linux/ipq806x/patches/0155-clk-qcom-Fix-incorrect-UTMI-DT-include-values.patch b/target/linux/ipq806x/patches/0155-clk-qcom-Fix-incorrect-UTMI-DT-include-values.patch deleted file mode 100644 index a05fc2c331..0000000000 --- a/target/linux/ipq806x/patches/0155-clk-qcom-Fix-incorrect-UTMI-DT-include-values.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 9ab5cb48696dca02bf43170b50d1034a96fb9e85 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Sun, 15 Jun 2014 00:39:57 -0500 -Subject: [PATCH 155/182] clk: qcom: Fix incorrect UTMI DT include values - -Corrected values for UTMI clock definitions. - -Signed-off-by: Andy Gross ---- - include/dt-bindings/clock/qcom,gcc-ipq806x.h | 38 +++++++++++++------------- - 1 file changed, 19 insertions(+), 19 deletions(-) - ---- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h -@@ -273,24 +273,24 @@ - #define USB30_SLEEP_CLK 262 - #define USB30_UTMI_SRC 263 - #define USB30_0_UTMI_CLK 264 --#define USB30_1_UTMI_CLK 264 --#define USB30_MASTER_SRC 265 --#define USB30_0_MASTER_CLK 266 --#define USB30_1_MASTER_CLK 267 --#define GMAC_CORE1_CLK_SRC 268 --#define GMAC_CORE2_CLK_SRC 269 --#define GMAC_CORE3_CLK_SRC 270 --#define GMAC_CORE4_CLK_SRC 271 --#define GMAC_CORE1_CLK 272 --#define GMAC_CORE2_CLK 273 --#define GMAC_CORE3_CLK 274 --#define GMAC_CORE4_CLK 275 --#define UBI32_CORE1_CLK_SRC 276 --#define UBI32_CORE2_CLK_SRC 277 --#define UBI32_CORE1_CLK 278 --#define UBI32_CORE2_CLK 279 --#define NSSTCM_CLK_SRC 280 --#define NSSTCM_CLK 281 --#define NSS_CORE_CLK 282 /* Virtual */ -+#define USB30_1_UTMI_CLK 265 -+#define USB30_MASTER_SRC 266 -+#define USB30_0_MASTER_CLK 267 -+#define USB30_1_MASTER_CLK 268 -+#define GMAC_CORE1_CLK_SRC 269 -+#define GMAC_CORE2_CLK_SRC 270 -+#define GMAC_CORE3_CLK_SRC 271 -+#define GMAC_CORE4_CLK_SRC 272 -+#define GMAC_CORE1_CLK 273 -+#define GMAC_CORE2_CLK 274 -+#define GMAC_CORE3_CLK 275 -+#define GMAC_CORE4_CLK 276 -+#define UBI32_CORE1_CLK_SRC 277 -+#define UBI32_CORE2_CLK_SRC 278 -+#define UBI32_CORE1_CLK 279 -+#define UBI32_CORE2_CLK 280 -+#define NSSTCM_CLK_SRC 281 -+#define NSSTCM_CLK 282 -+#define NSS_CORE_CLK 283 /* Virtual */ - - #endif diff --git a/target/linux/ipq806x/patches/0156-usb-dwc3-Add-Qualcomm-DWC3-glue-layer-driver.patch b/target/linux/ipq806x/patches/0156-usb-dwc3-Add-Qualcomm-DWC3-glue-layer-driver.patch deleted file mode 100644 index a69a5bd3a5..0000000000 --- a/target/linux/ipq806x/patches/0156-usb-dwc3-Add-Qualcomm-DWC3-glue-layer-driver.patch +++ /dev/null @@ -1,202 +0,0 @@ -From 364532aeb9024d0ff7b88121f9a953f559b1c136 Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Mon, 7 Oct 2013 10:44:57 +0300 -Subject: [PATCH 156/182] usb: dwc3: Add Qualcomm DWC3 glue layer driver - -DWC3 glue layer is hardware layer around Synopsys DesignWare -USB3 core. Its purpose is to supply Synopsys IP with required -clocks, voltages and interface it with the rest of the SoC. - -Signed-off-by: Ivan T. Ivanov ---- - drivers/usb/dwc3/Kconfig | 8 +++ - drivers/usb/dwc3/Makefile | 1 + - drivers/usb/dwc3/dwc3-qcom.c | 156 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 165 insertions(+) - create mode 100644 drivers/usb/dwc3/dwc3-qcom.c - ---- a/drivers/usb/dwc3/Kconfig -+++ b/drivers/usb/dwc3/Kconfig -@@ -59,6 +59,14 @@ config USB_DWC3_EXYNOS - Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside, - say 'Y' or 'M' if you have one such device. - -+config USB_DWC3_QCOM -+ tristate "Qualcomm Platforms" -+ default USB_DWC3 -+ select USB_QCOM_DWC3_PHYS -+ help -+ Recent Qualcomm SoCs ship with one DesignWare Core USB3 IP inside, -+ say 'Y' or 'M' if you have one such device. -+ - config USB_DWC3_PCI - tristate "PCIe-based Platforms" - depends on PCI ---- a/drivers/usb/dwc3/Makefile -+++ b/drivers/usb/dwc3/Makefile -@@ -31,5 +31,6 @@ endif - - obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o - obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o -+obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o - obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o - obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o ---- /dev/null -+++ b/drivers/usb/dwc3/dwc3-qcom.c -@@ -0,0 +1,156 @@ -+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "core.h" -+ -+ -+struct dwc3_qcom { -+ struct device *dev; -+ -+ struct clk *core_clk; -+ struct clk *iface_clk; -+ struct clk *sleep_clk; -+ -+ struct regulator *gdsc; -+}; -+ -+static int dwc3_qcom_probe(struct platform_device *pdev) -+{ -+ struct device_node *node = pdev->dev.of_node; -+ struct dwc3_qcom *mdwc; -+ int ret = 0; -+ -+ mdwc = devm_kzalloc(&pdev->dev, sizeof(*mdwc), GFP_KERNEL); -+ if (!mdwc) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, mdwc); -+ -+ mdwc->dev = &pdev->dev; -+ -+ mdwc->gdsc = devm_regulator_get(mdwc->dev, "gdsc"); -+ -+ mdwc->core_clk = devm_clk_get(mdwc->dev, "core"); -+ if (IS_ERR(mdwc->core_clk)) { -+ dev_dbg(mdwc->dev, "failed to get core clock\n"); -+ return PTR_ERR(mdwc->core_clk); -+ } -+ -+ mdwc->iface_clk = devm_clk_get(mdwc->dev, "iface"); -+ if (IS_ERR(mdwc->iface_clk)) { -+ dev_dbg(mdwc->dev, "failed to get iface clock, skipping\n"); -+ mdwc->iface_clk = NULL; -+ } -+ -+ mdwc->sleep_clk = devm_clk_get(mdwc->dev, "sleep"); -+ if (IS_ERR(mdwc->sleep_clk)) { -+ dev_dbg(mdwc->dev, "failed to get sleep clock, skipping\n"); -+ mdwc->sleep_clk = NULL; -+ } -+ -+ if (!IS_ERR(mdwc->gdsc)) { -+ ret = regulator_enable(mdwc->gdsc); -+ if (ret) -+ dev_err(mdwc->dev, "cannot enable gdsc\n"); -+ } -+ -+ clk_prepare_enable(mdwc->core_clk); -+ -+ if (mdwc->iface_clk) -+ clk_prepare_enable(mdwc->iface_clk); -+ -+ if (mdwc->sleep_clk) -+ clk_prepare_enable(mdwc->sleep_clk); -+ -+ ret = of_platform_populate(node, NULL, NULL, mdwc->dev); -+ if (ret) { -+ dev_err(mdwc->dev, "failed to register core - %d\n", ret); -+ dev_dbg(mdwc->dev, "failed to add create dwc3 core\n"); -+ goto dis_clks; -+ } -+ -+ return 0; -+ -+dis_clks: -+ -+ dev_err(mdwc->dev, "disabling clocks\n"); -+ -+ if (mdwc->sleep_clk) -+ clk_disable_unprepare(mdwc->sleep_clk); -+ -+ if (mdwc->iface_clk) -+ clk_disable_unprepare(mdwc->iface_clk); -+ -+ clk_disable_unprepare(mdwc->core_clk); -+ -+ if (!IS_ERR(mdwc->gdsc)) { -+ ret = regulator_disable(mdwc->gdsc); -+ if (ret) -+ dev_dbg(mdwc->dev, "cannot disable gdsc\n"); -+ } -+ -+ return ret; -+} -+ -+static int dwc3_qcom_remove(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ struct dwc3_qcom *mdwc = platform_get_drvdata(pdev); -+ -+ if (mdwc->sleep_clk) -+ clk_disable_unprepare(mdwc->sleep_clk); -+ -+ if (mdwc->iface_clk) -+ clk_disable_unprepare(mdwc->iface_clk); -+ -+ clk_disable_unprepare(mdwc->core_clk); -+ -+ if (!IS_ERR(mdwc->gdsc)) { -+ ret = regulator_disable(mdwc->gdsc); -+ if (ret) -+ dev_dbg(mdwc->dev, "cannot disable gdsc\n"); -+ } -+ return ret; -+} -+ -+static const struct of_device_id of_dwc3_match[] = { -+ { .compatible = "qcom,dwc3" }, -+ { /* Sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, of_dwc3_match); -+ -+static struct platform_driver dwc3_qcom_driver = { -+ .probe = dwc3_qcom_probe, -+ .remove = dwc3_qcom_remove, -+ .driver = { -+ .name = "qcom-dwc3", -+ .owner = THIS_MODULE, -+ .of_match_table = of_dwc3_match, -+ }, -+}; -+ -+module_platform_driver(dwc3_qcom_driver); -+ -+MODULE_ALIAS("platform:qcom-dwc3"); -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("DesignWare USB3 QCOM Glue Layer"); diff --git a/target/linux/ipq806x/patches/0157-usb-phy-Add-Qualcomm-DWC3-HS-SS-PHY-drivers.patch b/target/linux/ipq806x/patches/0157-usb-phy-Add-Qualcomm-DWC3-HS-SS-PHY-drivers.patch deleted file mode 100644 index d7fafed5ce..0000000000 --- a/target/linux/ipq806x/patches/0157-usb-phy-Add-Qualcomm-DWC3-HS-SS-PHY-drivers.patch +++ /dev/null @@ -1,861 +0,0 @@ -From d968f8c82db73141c6bc145148642391cb698442 Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Mon, 7 Oct 2013 10:44:56 +0300 -Subject: [PATCH 157/182] usb: phy: Add Qualcomm DWC3 HS/SS PHY drivers - -These drivers handles control and configuration of the HS -and SS USB PHY transceivers. They are part of the driver -which manage Synopsys DesignWare USB3 controller stack -inside Qualcomm SoC's. - -Signed-off-by: Ivan T. Ivanov ---- - drivers/usb/phy/Kconfig | 13 +- - drivers/usb/phy/Makefile | 2 + - drivers/usb/phy/phy-qcom-hsusb.c | 340 ++++++++++++++++++++++++++++ - drivers/usb/phy/phy-qcom-ssusb.c | 455 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 809 insertions(+), 1 deletion(-) - create mode 100644 drivers/usb/phy/phy-qcom-hsusb.c - create mode 100644 drivers/usb/phy/phy-qcom-ssusb.c - ---- a/drivers/usb/phy/Kconfig -+++ b/drivers/usb/phy/Kconfig -@@ -193,7 +193,7 @@ config USB_ISP1301 - - config USB_MSM_OTG - tristate "OTG support for Qualcomm on-chip USB controller" -- depends on (USB || USB_GADGET) && ARCH_MSM -+ depends on (USB || USB_GADGET) && ARCH_QCOM - select USB_PHY - help - Enable this to support the USB OTG transceiver on MSM chips. It -@@ -251,6 +251,17 @@ config USB_RCAR_GEN2_PHY - To compile this driver as a module, choose M here: the - module will be called phy-rcar-gen2-usb. - -+config USB_QCOM_DWC3_PHY -+ tristate "Qualcomm USB controller DWC3 PHY wrappers support" -+ depends on (USB || USB_GADGET) && ARCH_QCOM -+ select USB_PHY -+ help -+ Enable this to support the DWC3 USB PHY transceivers on QCOM chips -+ with DWC3 USB core. It handles PHY initialization, clock -+ management required after resetting the hardware and power -+ management. This driver is required even for peripheral only or -+ host only mode configurations. -+ - config USB_ULPI - bool "Generic ULPI Transceiver Driver" - depends on ARM ---- a/drivers/usb/phy/Makefile -+++ b/drivers/usb/phy/Makefile -@@ -26,6 +26,8 @@ obj-$(CONFIG_USB_EHCI_TEGRA) += phy-teg - obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o - obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o - obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o -+obj-$(CONFIG_USB_QCOM_DWC3_PHY) += phy-qcom-hsusb.o -+obj-$(CONFIG_USB_QCOM_DWC3_PHY) += phy-qcom-ssusb.o - obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o - obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o - obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o ---- /dev/null -+++ b/drivers/usb/phy/phy-qcom-hsusb.c -@@ -0,0 +1,340 @@ -+/* Copyright (c) 2013-2014, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * USB QSCRATCH Hardware registers -+ */ -+#define QSCRATCH_CTRL_REG (0x04) -+#define QSCRATCH_GENERAL_CFG (0x08) -+#define PHY_CTRL_REG (0x10) -+#define PARAMETER_OVERRIDE_X_REG (0x14) -+#define CHARGING_DET_CTRL_REG (0x18) -+#define CHARGING_DET_OUTPUT_REG (0x1c) -+#define ALT_INTERRUPT_EN_REG (0x20) -+#define PHY_IRQ_STAT_REG (0x24) -+#define CGCTL_REG (0x28) -+ -+#define PHY_3P3_VOL_MIN 3050000 /* uV */ -+#define PHY_3P3_VOL_MAX 3300000 /* uV */ -+#define PHY_3P3_HPM_LOAD 16000 /* uA */ -+ -+#define PHY_1P8_VOL_MIN 1800000 /* uV */ -+#define PHY_1P8_VOL_MAX 1800000 /* uV */ -+#define PHY_1P8_HPM_LOAD 19000 /* uA */ -+ -+/* TODO: these are suspicious */ -+#define USB_VDDCX_NO 1 /* index */ -+#define USB_VDDCX_MIN 5 /* index */ -+#define USB_VDDCX_MAX 7 /* index */ -+ -+struct qcom_dwc3_hs_phy { -+ struct usb_phy phy; -+ void __iomem *base; -+ struct device *dev; -+ -+ struct clk *xo_clk; -+ struct clk *utmi_clk; -+ -+ struct regulator *v3p3; -+ struct regulator *v1p8; -+ struct regulator *vddcx; -+ struct regulator *vbus; -+}; -+ -+#define phy_to_dw_phy(x) container_of((x), struct qcom_dwc3_hs_phy, phy) -+ -+ -+/** -+ * Write register. -+ * -+ * @base - QCOM DWC3 PHY base virtual address. -+ * @offset - register offset. -+ * @val - value to write. -+ */ -+static inline void qcom_dwc3_hs_write(void __iomem *base, u32 offset, u32 val) -+{ -+ writel(val, base + offset); -+} -+ -+/** -+ * Write register and read back masked value to confirm it is written -+ * -+ * @base - QCOM DWC3 PHY base virtual address. -+ * @offset - register offset. -+ * @mask - register bitmask specifying what should be updated -+ * @val - value to write. -+ */ -+static inline void qcom_dwc3_hs_write_readback(void __iomem *base, u32 offset, -+ const u32 mask, u32 val) -+{ -+ u32 write_val, tmp = readl(base + offset); -+ -+ tmp &= ~mask; /* retain other bits */ -+ write_val = tmp | val; -+ -+ writel(write_val, base + offset); -+ -+ /* Read back to see if val was written */ -+ tmp = readl(base + offset); -+ tmp &= mask; /* clear other bits */ -+ -+ if (tmp != val) -+ pr_err("write: %x to QSCRATCH: %x FAILED\n", val, offset); -+} -+ -+static int qcom_dwc3_hs_notify_connect(struct usb_phy *x, -+ enum usb_device_speed speed) -+{ -+ struct qcom_dwc3_hs_phy *phy = phy_to_dw_phy(x); -+ -+ dev_err(phy->dev, "notify connect\n"); -+ return 0; -+} -+ -+static int qcom_dwc3_hs_notify_disconnect(struct usb_phy *x, -+ enum usb_device_speed speed) -+{ -+ struct qcom_dwc3_hs_phy *phy = phy_to_dw_phy(x); -+ -+ dev_err(phy->dev, "notify disconnect\n"); -+ return 0; -+} -+ -+ -+static void qcom_dwc3_hs_phy_shutdown(struct usb_phy *x) -+{ -+ struct qcom_dwc3_hs_phy *phy = phy_to_dw_phy(x); -+ int ret; -+ -+ ret = regulator_set_voltage(phy->v3p3, 0, PHY_3P3_VOL_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set voltage for v3p3\n"); -+ -+ ret = regulator_set_voltage(phy->v1p8, 0, PHY_1P8_VOL_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set voltage for v1p8\n"); -+ -+ ret = regulator_disable(phy->v1p8); -+ if (ret) -+ dev_err(phy->dev, "cannot disable v1p8\n"); -+ -+ ret = regulator_disable(phy->v3p3); -+ if (ret) -+ dev_err(phy->dev, "cannot disable v3p3\n"); -+ -+ ret = regulator_set_voltage(phy->vddcx, USB_VDDCX_NO, USB_VDDCX_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set voltage for vddcx\n"); -+ -+ ret = regulator_disable(phy->vddcx); -+ if (ret) -+ dev_err(phy->dev, "cannot enable vddcx\n"); -+ -+ clk_disable_unprepare(phy->utmi_clk); -+} -+ -+static int qcom_dwc3_hs_phy_init(struct usb_phy *x) -+{ -+ struct qcom_dwc3_hs_phy *phy = phy_to_dw_phy(x); -+ int ret; -+ u32 val; -+ -+ clk_prepare_enable(phy->utmi_clk); -+ -+ ret = regulator_set_voltage(phy->vddcx, USB_VDDCX_MIN, USB_VDDCX_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set voltage for vddcx\n"); -+ -+ ret = regulator_enable(phy->vddcx); -+ if (ret) -+ dev_err(phy->dev, "cannot enable vddcx\n"); -+ -+ ret = regulator_set_voltage(phy->v3p3, PHY_3P3_VOL_MIN, -+ PHY_3P3_VOL_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set voltage for v3p3\n"); -+ -+ ret = regulator_set_voltage(phy->v1p8, PHY_1P8_VOL_MIN, -+ PHY_1P8_VOL_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set voltage for v1p8\n"); -+ -+ ret = regulator_set_optimum_mode(phy->v1p8, PHY_1P8_HPM_LOAD); -+ if (ret < 0) -+ dev_err(phy->dev, "cannot set HPM of regulator v1p8\n"); -+ -+ ret = regulator_enable(phy->v1p8); -+ if (ret) -+ dev_err(phy->dev, "cannot enable v1p8\n"); -+ -+ ret = regulator_set_optimum_mode(phy->v3p3, PHY_3P3_HPM_LOAD); -+ if (ret < 0) -+ dev_err(phy->dev, "cannot set HPM of regulator v3p3\n"); -+ -+ ret = regulator_enable(phy->v3p3); -+ if (ret) -+ dev_err(phy->dev, "cannot enable v3p3\n"); -+ -+ /* -+ * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs, -+ * and disable RETENTION (power-on default is ENABLED) -+ */ -+ val = readl(phy->base + PHY_CTRL_REG); -+ val |= BIT(18) | BIT(20) | BIT(11) | 0x70; -+ qcom_dwc3_hs_write(phy->base, PHY_CTRL_REG, val); -+ usleep_range(2000, 2200); -+ -+ /* -+ * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like -+ * VBUS valid threshold, disconnect valid threshold, DC voltage level, -+ * preempasis and rise/fall time. -+ */ -+ qcom_dwc3_hs_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG, -+ 0x03ffffff, 0x00d191a4); -+ -+ /* Disable (bypass) VBUS and ID filters */ -+ qcom_dwc3_hs_write(phy->base, QSCRATCH_GENERAL_CFG, BIT(2)); -+ -+ return 0; -+} -+ -+static int qcom_dwc3_hs_phy_set_vbus(struct usb_phy *x, int on) -+{ -+ struct qcom_dwc3_hs_phy *phy = phy_to_dw_phy(x); -+ int ret = 0; -+ -+ if (IS_ERR(phy->vbus)) -+ return on ? PTR_ERR(phy->vbus) : 0; -+ -+ if (on) -+ ret = regulator_enable(phy->vbus); -+ else -+ ret = regulator_disable(phy->vbus); -+ -+ if (ret) -+ dev_err(x->dev, "Cannot %s Vbus\n", on ? "set" : "off"); -+ return ret; -+} -+ -+static int qcom_dwc3_hs_probe(struct platform_device *pdev) -+{ -+ struct qcom_dwc3_hs_phy *phy; -+ struct resource *res; -+ void __iomem *base; -+ -+ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); -+ if (!phy) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, phy); -+ -+ phy->dev = &pdev->dev; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(phy->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ phy->vddcx = devm_regulator_get(phy->dev, "vddcx"); -+ if (IS_ERR(phy->vddcx)) { -+ dev_dbg(phy->dev, "cannot get vddcx\n"); -+ return PTR_ERR(phy->vddcx); -+ } -+ -+ phy->v3p3 = devm_regulator_get(phy->dev, "v3p3"); -+ if (IS_ERR(phy->v3p3)) { -+ dev_dbg(phy->dev, "cannot get v3p3\n"); -+ return PTR_ERR(phy->v3p3); -+ } -+ -+ phy->v1p8 = devm_regulator_get(phy->dev, "v1p8"); -+ if (IS_ERR(phy->v1p8)) { -+ dev_dbg(phy->dev, "cannot get v1p8\n"); -+ return PTR_ERR(phy->v1p8); -+ } -+ -+ phy->vbus = devm_regulator_get(phy->dev, "vbus"); -+ if (IS_ERR(phy->vbus)) -+ dev_dbg(phy->dev, "Failed to get vbus\n"); -+ -+ phy->utmi_clk = devm_clk_get(phy->dev, "utmi"); -+ if (IS_ERR(phy->utmi_clk)) { -+ dev_dbg(phy->dev, "cannot get UTMI handle\n"); -+ return PTR_ERR(phy->utmi_clk); -+ } -+ -+ phy->xo_clk = devm_clk_get(phy->dev, "xo"); -+ if (IS_ERR(phy->xo_clk)) { -+ dev_dbg(phy->dev, "cannot get TCXO buffer handle\n"); -+ phy->xo_clk = NULL; -+ } -+ -+ clk_set_rate(phy->utmi_clk, 60000000); -+ -+ if (phy->xo_clk) -+ clk_prepare_enable(phy->xo_clk); -+ -+ phy->base = base; -+ phy->phy.dev = phy->dev; -+ phy->phy.label = "qcom-dwc3-hsphy"; -+ phy->phy.init = qcom_dwc3_hs_phy_init; -+ phy->phy.notify_connect = qcom_dwc3_hs_notify_connect; -+ phy->phy.notify_disconnect = qcom_dwc3_hs_notify_disconnect; -+ phy->phy.shutdown = qcom_dwc3_hs_phy_shutdown; -+ phy->phy.set_vbus = qcom_dwc3_hs_phy_set_vbus; -+ phy->phy.type = USB_PHY_TYPE_USB2; -+ phy->phy.state = OTG_STATE_UNDEFINED; -+ -+ usb_add_phy_dev(&phy->phy); -+ return 0; -+} -+ -+static int qcom_dwc3_hs_remove(struct platform_device *pdev) -+{ -+ struct qcom_dwc3_hs_phy *phy = platform_get_drvdata(pdev); -+ -+ if (phy->xo_clk) -+ clk_disable_unprepare(phy->xo_clk); -+ usb_remove_phy(&phy->phy); -+ return 0; -+} -+ -+static const struct of_device_id qcom_dwc3_hs_id_table[] = { -+ { .compatible = "qcom,dwc3-hsphy" }, -+ { /* Sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, qcom_dwc3_hs_id_table); -+ -+static struct platform_driver qcom_dwc3_hs_driver = { -+ .probe = qcom_dwc3_hs_probe, -+ .remove = qcom_dwc3_hs_remove, -+ .driver = { -+ .name = "qcom-dwc3-hsphy", -+ .owner = THIS_MODULE, -+ .of_match_table = qcom_dwc3_hs_id_table, -+ }, -+}; -+ -+module_platform_driver(qcom_dwc3_hs_driver); -+ -+MODULE_ALIAS("platform:qcom-dwc3-hsphy"); -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("DesignWare USB3 QCOM HSPHY driver"); ---- /dev/null -+++ b/drivers/usb/phy/phy-qcom-ssusb.c -@@ -0,0 +1,455 @@ -+/* Copyright (c) 2013-2014, Code Aurora Forum. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** -+ * USB QSCRATCH Hardware registers -+ */ -+#define PHY_CTRL_REG (0x00) -+#define PHY_PARAM_CTRL_1 (0x04) -+#define PHY_PARAM_CTRL_2 (0x08) -+#define CR_PROTOCOL_DATA_IN_REG (0x0c) -+#define CR_PROTOCOL_DATA_OUT_REG (0x10) -+#define CR_PROTOCOL_CAP_ADDR_REG (0x14) -+#define CR_PROTOCOL_CAP_DATA_REG (0x18) -+#define CR_PROTOCOL_READ_REG (0x1c) -+#define CR_PROTOCOL_WRITE_REG (0x20) -+ -+#define PHY_1P8_VOL_MIN 1800000 /* uV */ -+#define PHY_1P8_VOL_MAX 1800000 /* uV */ -+#define PHY_1P8_HPM_LOAD 23000 /* uA */ -+ -+/* TODO: these are suspicious */ -+#define USB_VDDCX_NO 1 /* index */ -+#define USB_VDDCX_MIN 5 /* index */ -+#define USB_VDDCX_MAX 7 /* index */ -+ -+struct qcom_dwc3_ss_phy { -+ struct usb_phy phy; -+ void __iomem *base; -+ struct device *dev; -+ -+ struct regulator *v1p8; -+ struct regulator *vddcx; -+ -+ struct clk *xo_clk; -+ struct clk *ref_clk; -+}; -+ -+#define phy_to_dw_phy(x) container_of((x), struct qcom_dwc3_ss_phy, phy) -+ -+ -+/** -+ * Write register -+ * -+ * @base - QCOM DWC3 PHY base virtual address. -+ * @offset - register offset. -+ * @val - value to write. -+ */ -+static inline void qcom_dwc3_ss_write(void __iomem *base, u32 offset, u32 val) -+{ -+ writel(val, base + offset); -+} -+ -+/** -+ * Write register and read back masked value to confirm it is written -+ * -+ * @base - QCOM DWC3 PHY base virtual address. -+ * @offset - register offset. -+ * @mask - register bitmask specifying what should be updated -+ * @val - value to write. -+ */ -+static inline void qcom_dwc3_ss_write_readback(void __iomem *base, u32 offset, -+ const u32 mask, u32 val) -+{ -+ u32 write_val, tmp = readl(base + offset); -+ -+ tmp &= ~mask; /* retain other bits */ -+ write_val = tmp | val; -+ -+ writel(write_val, base + offset); -+ -+ /* Read back to see if val was written */ -+ tmp = readl(base + offset); -+ tmp &= mask; /* clear other bits */ -+ -+ if (tmp != val) -+ pr_err("write: %x to QSCRATCH: %x FAILED\n", val, offset); -+} -+ -+/** -+ * Write SSPHY register -+ * -+ * @base - QCOM DWC3 PHY base virtual address. -+ * @addr - SSPHY address to write. -+ * @val - value to write. -+ */ -+static void qcom_dwc3_ss_write_phycreg(void __iomem *base, u32 addr, u32 val) -+{ -+ writel(addr, base + CR_PROTOCOL_DATA_IN_REG); -+ writel(0x1, base + CR_PROTOCOL_CAP_ADDR_REG); -+ while (readl(base + CR_PROTOCOL_CAP_ADDR_REG)) -+ cpu_relax(); -+ -+ writel(val, base + CR_PROTOCOL_DATA_IN_REG); -+ writel(0x1, base + CR_PROTOCOL_CAP_DATA_REG); -+ while (readl(base + CR_PROTOCOL_CAP_DATA_REG)) -+ cpu_relax(); -+ -+ writel(0x1, base + CR_PROTOCOL_WRITE_REG); -+ while (readl(base + CR_PROTOCOL_WRITE_REG)) -+ cpu_relax(); -+} -+ -+/** -+ * Read SSPHY register. -+ * -+ * @base - QCOM DWC3 PHY base virtual address. -+ * @addr - SSPHY address to read. -+ */ -+static u32 qcom_dwc3_ss_read_phycreg(void __iomem *base, u32 addr) -+{ -+ bool first_read = true; -+ -+ writel(addr, base + CR_PROTOCOL_DATA_IN_REG); -+ writel(0x1, base + CR_PROTOCOL_CAP_ADDR_REG); -+ while (readl(base + CR_PROTOCOL_CAP_ADDR_REG)) -+ cpu_relax(); -+ -+ /* -+ * Due to hardware bug, first read of SSPHY register might be -+ * incorrect. Hence as workaround, SW should perform SSPHY register -+ * read twice, but use only second read and ignore first read. -+ */ -+retry: -+ writel(0x1, base + CR_PROTOCOL_READ_REG); -+ while (readl(base + CR_PROTOCOL_READ_REG)) -+ cpu_relax(); -+ -+ if (first_read) { -+ readl(base + CR_PROTOCOL_DATA_OUT_REG); -+ first_read = false; -+ goto retry; -+ } -+ -+ return readl(base + CR_PROTOCOL_DATA_OUT_REG); -+} -+ -+static void qcom_dwc3_ss_phy_shutdown(struct usb_phy *x) -+{ -+ struct qcom_dwc3_ss_phy *phy = phy_to_dw_phy(x); -+ int ret; -+ -+ /* Sequence to put SSPHY in low power state: -+ * 1. Clear REF_PHY_EN in PHY_CTRL_REG -+ * 2. Clear REF_USE_PAD in PHY_CTRL_REG -+ * 3. Set TEST_POWERED_DOWN in PHY_CTRL_REG to enable PHY retention -+ * 4. Disable SSPHY ref clk -+ */ -+ qcom_dwc3_ss_write_readback(phy->base, PHY_CTRL_REG, (1 << 8), 0x0); -+ qcom_dwc3_ss_write_readback(phy->base, PHY_CTRL_REG, (1 << 28), 0x0); -+ qcom_dwc3_ss_write_readback(phy->base, PHY_CTRL_REG, -+ (1 << 26), (1 << 26)); -+ -+ usleep_range(1000, 1200); -+ clk_disable_unprepare(phy->ref_clk); -+ -+ ret = regulator_set_voltage(phy->vddcx, USB_VDDCX_NO, USB_VDDCX_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set voltage for vddcx\n"); -+ -+ regulator_disable(phy->vddcx); -+ -+ ret = regulator_set_voltage(phy->v1p8, 0, PHY_1P8_VOL_MAX); -+ if (ret) -+ dev_err(phy->dev, "cannot set v1p8\n"); -+ -+ regulator_disable(phy->v1p8); -+} -+ -+static int qcom_dwc3_ss_phy_init(struct usb_phy *x) -+{ -+ struct qcom_dwc3_ss_phy *phy = phy_to_dw_phy(x); -+ u32 data = 0; -+ int ret; -+ -+ ret = regulator_set_voltage(phy->vddcx, USB_VDDCX_MIN, USB_VDDCX_MAX); -+ if (ret) { -+ dev_err(phy->dev, "cannot set voltage for vddcx\n"); -+ return ret; -+ } -+ -+ ret = regulator_enable(phy->vddcx); -+ if (ret) { -+ dev_err(phy->dev, "cannot enable vddcx\n"); -+ return ret; -+ } -+ -+ ret = regulator_set_voltage(phy->v1p8, PHY_1P8_VOL_MIN, -+ PHY_1P8_VOL_MAX); -+ if (ret) { -+ regulator_disable(phy->vddcx); -+ dev_err(phy->dev, "cannot set v1p8\n"); -+ return ret; -+ } -+ -+ ret = regulator_enable(phy->v1p8); -+ if (ret) { -+ regulator_disable(phy->vddcx); -+ dev_err(phy->dev, "cannot enable v1p8\n"); -+ return ret; -+ } -+ -+ clk_prepare_enable(phy->ref_clk); -+ usleep_range(1000, 1200); -+ -+ /* reset phy */ -+ data = readl_relaxed(phy->base + PHY_CTRL_REG); -+ writel_relaxed(data | BIT(7), phy->base + PHY_CTRL_REG); -+ usleep_range(2000, 2200); -+ writel_relaxed(data, phy->base + PHY_CTRL_REG); -+ -+ /* clear REF_PAD, we don't have XO clk */ -+ data &= ~BIT(28); -+ writel_relaxed(data, phy->base + PHY_CTRL_REG); -+ msleep(30); -+ -+ data |= BIT(8) | BIT(24); -+ writel_relaxed(data, phy->base + PHY_CTRL_REG); -+ -+ /* -+ * WORKAROUND: There is SSPHY suspend bug due to which USB enumerates -+ * in HS mode instead of SS mode. Workaround it by asserting -+ * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode -+ */ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x102d); -+ data |= (1 << 7); -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x102D, data); -+ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x1010); -+ data &= ~0xff0; -+ data |= 0x20; -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x1010, data); -+ -+ /* -+ * Fix RX Equalization setting as follows -+ * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 -+ * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 -+ * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 -+ * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 -+ */ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x1006); -+ data &= ~(1 << 6); -+ data |= (1 << 7); -+ data &= ~(0x7 << 8); -+ data |= (0x3 << 8); -+ data |= (0x1 << 11); -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x1006, data); -+ -+ /* -+ * Set EQ and TX launch amplitudes as follows -+ * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 -+ * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 -+ * LANE0.TX_OVRD_DRV_LO.EN set to 1. -+ */ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x1002); -+ data &= ~0x3f80; -+ data |= (0x16 << 7); -+ data &= ~0x7f; -+ data |= (0x7f | (1 << 14)); -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x1002, data); -+ -+ /* -+ * Set the QSCRATCH PHY_PARAM_CTRL1 parameters as follows -+ * TX_FULL_SWING [26:20] amplitude to 127 -+ * TX_DEEMPH_3_5DB [13:8] to 22 -+ * LOS_BIAS [2:0] to 0x5 -+ */ -+ qcom_dwc3_ss_write_readback(phy->base, PHY_PARAM_CTRL_1, -+ 0x07f03f07, 0x07f01605); -+ return 0; -+} -+ -+static int qcom_dwc3_ss_set_suspend(struct usb_phy *x, int suspend) -+{ -+ struct qcom_dwc3_ss_phy *phy = phy_to_dw_phy(x); -+ u32 data; -+ -+ if (!suspend) { -+ /* reset phy */ -+ data = readl_relaxed(phy->base + PHY_CTRL_REG); -+ writel_relaxed(data | BIT(7), phy->base + PHY_CTRL_REG); -+ usleep_range(2000, 2200); -+ writel_relaxed(data, phy->base + PHY_CTRL_REG); -+ -+ /* clear REF_PAD, we don't have XO clk */ -+ data &= ~BIT(28); -+ writel_relaxed(data, phy->base + PHY_CTRL_REG); -+ msleep(30); -+ -+ data |= BIT(8) | BIT(24); -+ writel_relaxed(data, phy->base + PHY_CTRL_REG); -+ -+ /* -+ * WORKAROUND: There is SSPHY suspend bug due to which USB -+ * enumerates in HS mode instead of SS mode. Workaround it by -+ * asserting LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use -+ * alt bus mode -+ */ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x102d); -+ data |= (1 << 7); -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x102D, data); -+ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x1010); -+ data &= ~0xff0; -+ data |= 0x20; -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x1010, data); -+ -+ /* -+ * Fix RX Equalization setting as follows -+ * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0 -+ * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1 -+ * LANE0.RX_OVRD_IN_HI.RX_EQ set to 3 -+ * LANE0.RX_OVRD_IN_HI.RX_EQ_OVRD set to 1 -+ */ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x1006); -+ data &= ~(1 << 6); -+ data |= (1 << 7); -+ data &= ~(0x7 << 8); -+ data |= (0x3 << 8); -+ data |= (0x1 << 11); -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x1006, data); -+ -+ /* -+ * Set EQ and TX launch amplitudes as follows -+ * LANE0.TX_OVRD_DRV_LO.PREEMPH set to 22 -+ * LANE0.TX_OVRD_DRV_LO.AMPLITUDE set to 127 -+ * LANE0.TX_OVRD_DRV_LO.EN set to 1. -+ */ -+ data = qcom_dwc3_ss_read_phycreg(phy->base, 0x1002); -+ data &= ~0x3f80; -+ data |= (0x16 << 7); -+ data &= ~0x7f; -+ data |= (0x7f | (1 << 14)); -+ qcom_dwc3_ss_write_phycreg(phy->base, 0x1002, data); -+ -+ /* -+ * Set the QSCRATCH PHY_PARAM_CTRL1 parameters as follows -+ * TX_FULL_SWING [26:20] amplitude to 127 -+ * TX_DEEMPH_3_5DB [13:8] to 22 -+ * LOS_BIAS [2:0] to 0x5 -+ */ -+ qcom_dwc3_ss_write_readback(phy->base, PHY_PARAM_CTRL_1, -+ 0x07f03f07, 0x07f01605); -+ } -+ return 0; -+} -+ -+static int qcom_dwc3_ss_probe(struct platform_device *pdev) -+{ -+ struct qcom_dwc3_ss_phy *phy; -+ struct resource *res; -+ void __iomem *base; -+ int ret; -+ -+ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); -+ if (!phy) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, phy); -+ -+ phy->dev = &pdev->dev; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(phy->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ phy->vddcx = devm_regulator_get(phy->dev, "vddcx"); -+ if (IS_ERR(phy->vddcx)) { -+ dev_dbg(phy->dev, "cannot get vddcx\n"); -+ return PTR_ERR(phy->vddcx); -+ } -+ -+ phy->v1p8 = devm_regulator_get(phy->dev, "v1p8"); -+ if (IS_ERR(phy->v1p8)) { -+ dev_dbg(phy->dev, "cannot get v1p8\n"); -+ return PTR_ERR(phy->v1p8); -+ } -+ -+ phy->xo_clk = devm_clk_get(phy->dev, "xo"); -+ if (IS_ERR(phy->xo_clk)) { -+ dev_dbg(phy->dev, "cannot get XO clk, assuming not present\n"); -+ phy->xo_clk = NULL; -+ } -+ -+ phy->ref_clk = devm_clk_get(phy->dev, "ref"); -+ if (IS_ERR(phy->ref_clk)) { -+ dev_dbg(phy->dev, "cannot get ref clock handle\n"); -+ return PTR_ERR(phy->ref_clk); -+ } -+ -+ clk_set_rate(phy->ref_clk, 125000000); -+ if (phy->xo_clk) -+ clk_prepare_enable(phy->xo_clk); -+ -+ phy->base = base; -+ phy->phy.dev = phy->dev; -+ phy->phy.label = "qcom-dwc3-ssphy"; -+ phy->phy.init = qcom_dwc3_ss_phy_init; -+ phy->phy.shutdown = qcom_dwc3_ss_phy_shutdown; -+ phy->phy.set_suspend = qcom_dwc3_ss_set_suspend; -+ phy->phy.type = USB_PHY_TYPE_USB3; -+ -+ ret = usb_add_phy_dev(&phy->phy); -+ return ret; -+} -+ -+static int qcom_dwc3_ss_remove(struct platform_device *pdev) -+{ -+ struct qcom_dwc3_ss_phy *phy = platform_get_drvdata(pdev); -+ -+ if (phy->xo_clk) -+ clk_disable_unprepare(phy->xo_clk); -+ usb_remove_phy(&phy->phy); -+ return 0; -+} -+ -+static const struct of_device_id qcom_dwc3_ss_id_table[] = { -+ { .compatible = "qcom,dwc3-ssphy" }, -+ { /* Sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, qcom_dwc3_ss_id_table); -+ -+static struct platform_driver qcom_dwc3_ss_driver = { -+ .probe = qcom_dwc3_ss_probe, -+ .remove = qcom_dwc3_ss_remove, -+ .driver = { -+ .name = "qcom-dwc3-ssphy", -+ .owner = THIS_MODULE, -+ .of_match_table = qcom_dwc3_ss_id_table, -+ }, -+}; -+ -+module_platform_driver(qcom_dwc3_ss_driver); -+ -+MODULE_ALIAS("platform:qcom-dwc3-ssphy"); -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("DesignWare USB3 QCOM SSPHY driver"); diff --git a/target/linux/ipq806x/patches/0158-usb-dwc3-qcom-Add-device-tree-binding.patch b/target/linux/ipq806x/patches/0158-usb-dwc3-qcom-Add-device-tree-binding.patch deleted file mode 100644 index ffe2a8d597..0000000000 --- a/target/linux/ipq806x/patches/0158-usb-dwc3-qcom-Add-device-tree-binding.patch +++ /dev/null @@ -1,125 +0,0 @@ -From c7045330c5976eb31bd79bc57c5db684588d595e Mon Sep 17 00:00:00 2001 -From: "Ivan T. Ivanov" -Date: Mon, 7 Oct 2013 10:44:55 +0300 -Subject: [PATCH 158/182] usb: dwc3: qcom: Add device tree binding - -QCOM USB3.0 core wrapper consist of USB3.0 IP from Synopsys -(SNPS) and HS, SS PHY's control and configuration registers. - -It could operate in device mode (SS, HS, FS) and host -mode (SS, HS, FS, LS). - -Signed-off-by: Ivan T. Ivanov -Acked-by: Stephen Warren ---- - .../devicetree/bindings/usb/qcom,dwc3.txt | 104 ++++++++++++++++++++ - 1 file changed, 104 insertions(+) - create mode 100644 Documentation/devicetree/bindings/usb/qcom,dwc3.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt -@@ -0,0 +1,104 @@ -+Qualcomm SuperSpeed DWC3 USB SoC controller -+ -+ -+QCOM DWC3 Highspeed USB PHY -+======================== -+Required properities: -+- compatible: should contain "qcom,dwc3-hsphy"; -+- reg: offset and length of the register set in the memory map -+- clocks: A list of phandle + clock-specifier pairs for the -+ clocks listed in clock-names -+- clock-names: Should contain the following: -+ "utmi" UTMI clock -+- v1p8-supply: phandle to the regulator for the 1.8v supply to HSPHY. -+- v3p3-supply: phandle to the regulator for the 3.3v supply to HSPHY. -+- vbus-supply: phandle to the regulator for the vbus supply for host -+ mode. -+- vddcx-supply: phandle to the regulator for the vdd supply for HSPHY -+ digital circuit operation. -+ -+Optional clocks: -+ "xo" External reference clock -+ -+ -+QCOM DWC3 Superspeed USB PHY -+========================= -+Required properities: -+- compatible: should contain "qcom,dwc3-ssphy"; -+- reg: offset and length of the register set in the memory map -+- clocks: A list of phandle + clock-specifier pairs for the -+ clocks listed in clock-names -+- clock-names: Should contain the following: -+ "ref" Reference clock used in host mode. -+- v1p8-supply: phandle to the regulator for the 1.8v supply to HSPHY. -+- vddcx-supply: phandle to the regulator for the vdd supply for HSPHY -+ digital circuit operation. -+ -+Optional clocks: -+ "xo" External reference clock -+ -+QCOM DWC3 controller wrapper -+=========================== -+Required properties: -+- compatible: should contain "qcom,dwc3" -+- clocks: A list of phandle + clock-specifier pairs for the -+ clocks listed in clock-names -+- clock-names: Should contain the following: -+ "core" Master/Core clock, have to be >= 125 MHz for SS -+ operation and >= 60MHz for HS operation -+ -+Optional clocks: -+ "iface" System bus AXI clock. Not present on all platforms -+ "sleep" Sleep clock, used when USB3 core goes into low -+ power mode (U3). -+ -+Optional regulator: -+- gdsc-supply: phandle to the regulator from globally distributed -+ switch controller -+ -+Required child node: -+A child node must exist to represent the core DWC3 IP block. The name of -+the node is not important. The content of the node is defined in dwc3.txt. -+ -+Example device nodes: -+ -+ hs_phy_0: phy@110f8800 { -+ compatible = "qcom,dwc3-hsphy"; -+ reg = <0x110f8800 0x30>; -+ clocks = <&gcc USB30_0_UTMI_CLK>; -+ clock-names = "utmi"; -+ -+ status = "disabled"; -+ }; -+ -+ ss_phy_0: phy@110f8830 { -+ compatible = "qcom,dwc3-ssphy"; -+ reg = <0x110f8830 0x30>; -+ -+ clocks = <&gcc USB30_0_MASTER_CLK>; -+ clock-names = "ref"; -+ -+ status = "disabled"; -+ }; -+ -+ usb3_0: usb30@0 { -+ compatible = "qcom,dwc3"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ clocks = <&gcc USB30_0_MASTER_CLK>; -+ clock-names = "core"; -+ -+ ranges; -+ -+ status = "disabled"; -+ -+ dwc3@11000000 { -+ compatible = "snps,dwc3"; -+ reg = <0x11000000 0xcd00>; -+ interrupts = <0 110 0x4>; -+ usb-phy = <&hs_phy_0>, <&ss_phy_0>; -+ phy-names = "usb2-phy", "usb3-phy"; -+ tx-fifo-resize; -+ dr_mode = "host"; -+ }; -+ }; diff --git a/target/linux/ipq806x/patches/0159-arm-ipq8064-Add-USB3-DT-information.patch b/target/linux/ipq806x/patches/0159-arm-ipq8064-Add-USB3-DT-information.patch deleted file mode 100644 index 843e94f2ff..0000000000 --- a/target/linux/ipq806x/patches/0159-arm-ipq8064-Add-USB3-DT-information.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 269a71c81438604d27f01ec703daa7f5e3f39e8b Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Sun, 15 Jun 2014 00:48:18 -0500 -Subject: [PATCH 159/182] arm: ipq8064: Add USB3 DT information - -This patch fleshes out the USB3 specific information for the IPQ8064 platform. - -Signed-off-by: Andy Gross ---- - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 29 ++++++++++ - arch/arm/boot/dts/qcom-ipq8064.dtsi | 90 ++++++++++++++++++++++++++++++ - 2 files changed, 119 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -160,5 +160,34 @@ - pinctrl-0 = <&nand_pins>; - pinctrl-names = "default"; - }; -+ -+ tcsr@1a400000 { -+ status = "ok"; -+ qcom,usb-ctrl-select = ; -+ }; -+ -+ phy@100f8800 { /* USB3 port 1 HS phy */ -+ status = "ok"; -+ }; -+ -+ phy@100f8830 { /* USB3 port 1 SS phy */ -+ status = "ok"; -+ }; -+ -+ phy@110f8800 { /* USB3 port 0 HS phy */ -+ status = "ok"; -+ }; -+ -+ phy@110f8830 { /* USB3 port 0 SS phy */ -+ status = "ok"; -+ }; -+ -+ usb30@0 { -+ status = "ok"; -+ }; -+ -+ usb30@1 { -+ status = "ok"; -+ }; - }; - }; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - / { - model = "Qualcomm IPQ8064"; -@@ -402,5 +403,94 @@ - - status = "disabled"; - }; -+ -+ tcsr: tcsr@1a400000 { -+ compatible = "qcom,tcsr"; -+ reg = <0x1a400000 0x100>; -+ -+ status = "disabled"; -+ }; -+ -+ hs_phy_1: phy@100f8800 { -+ compatible = "qcom,dwc3-hsphy"; -+ reg = <0x100f8800 0x30>; -+ clocks = <&gcc USB30_1_UTMI_CLK>; -+ clock-names = "utmi"; -+ -+ status = "disabled"; -+ }; -+ -+ ss_phy_1: phy@100f8830 { -+ compatible = "qcom,dwc3-ssphy"; -+ reg = <0x100f8830 0x30>; -+ -+ clocks = <&gcc USB30_1_MASTER_CLK>; -+ clock-names = "ref"; -+ -+ status = "disabled"; -+ }; -+ -+ hs_phy_0: phy@110f8800 { -+ compatible = "qcom,dwc3-hsphy"; -+ reg = <0x110f8800 0x30>; -+ clocks = <&gcc USB30_0_UTMI_CLK>; -+ clock-names = "utmi"; -+ -+ status = "disabled"; -+ }; -+ -+ ss_phy_0: phy@110f8830 { -+ compatible = "qcom,dwc3-ssphy"; -+ reg = <0x110f8830 0x30>; -+ -+ clocks = <&gcc USB30_0_MASTER_CLK>; -+ clock-names = "ref"; -+ -+ status = "disabled"; -+ }; -+ -+ usb3_0: usb30@0 { -+ compatible = "qcom,dwc3"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ clocks = <&gcc USB30_0_MASTER_CLK>; -+ clock-names = "core"; -+ -+ ranges; -+ -+ status = "disabled"; -+ -+ dwc3@11000000 { -+ compatible = "snps,dwc3"; -+ reg = <0x11000000 0xcd00>; -+ interrupts = <0 110 0x4>; -+ usb-phy = <&hs_phy_0>, <&ss_phy_0>; -+ phy-names = "usb2-phy", "usb3-phy"; -+ tx-fifo-resize; -+ dr_mode = "host"; -+ }; -+ }; -+ -+ usb3_1: usb30@1 { -+ compatible = "qcom,dwc3"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ clocks = <&gcc USB30_1_MASTER_CLK>; -+ clock-names = "core"; -+ -+ ranges; -+ -+ status = "disabled"; -+ -+ dwc3@10000000 { -+ compatible = "snps,dwc3"; -+ reg = <0x10000000 0xcd00>; -+ interrupts = <0 205 0x4>; -+ usb-phy = <&hs_phy_1>, <&ss_phy_1>; -+ phy-names = "usb2-phy", "usb3-phy"; -+ tx-fifo-resize; -+ dr_mode = "host"; -+ }; -+ }; - }; - }; diff --git a/target/linux/ipq806x/patches/0160-ARM-qcom-config-Add-TCSR-and-USB3-options.patch b/target/linux/ipq806x/patches/0160-ARM-qcom-config-Add-TCSR-and-USB3-options.patch deleted file mode 100644 index 400c87e76b..0000000000 --- a/target/linux/ipq806x/patches/0160-ARM-qcom-config-Add-TCSR-and-USB3-options.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 8e69ee9a592f363476f18e91f57d871662e9a393 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 16 Jun 2014 16:37:22 -0500 -Subject: [PATCH 160/182] ARM: qcom: config: Add TCSR and USB3 options - -Enable TCSR and USB3 options. - -Signed-off-by: Andy Gross ---- - arch/arm/configs/qcom_defconfig | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -122,9 +122,14 @@ CONFIG_HID_BATTERY_STRENGTH=y - CONFIG_USB=y - CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - CONFIG_USB_MON=y -+CONFIG_USB_XHCI_HCD=y - CONFIG_USB_EHCI_HCD=y - CONFIG_USB_ACM=y -+CONFIG_USB_STORAGE=y -+CONFIG_USB_DWC3=y -+CONFIG_USB_DWC3_HOST=y - CONFIG_USB_SERIAL=y -+CONFIG_USB_QCOM_DWC3_PHY=y - CONFIG_USB_GADGET=y - CONFIG_USB_GADGET_DEBUG_FILES=y - CONFIG_USB_GADGET_VBUS_DRAW=500 -@@ -138,6 +143,7 @@ CONFIG_DMADEVICES=y - CONFIG_QCOM_BAM_DMA=y - CONFIG_STAGING=y - CONFIG_QCOM_GSBI=y -+CONFIG_QCOM_TCSR=y - CONFIG_COMMON_CLK_QCOM=y - CONFIG_IPQ_GCC_806X=y - CONFIG_MSM_GCC_8660=y diff --git a/target/linux/ipq806x/patches/0161-ARM-Remove-ARCH_HAS_CPUFREQ-config-option.patch b/target/linux/ipq806x/patches/0161-ARM-Remove-ARCH_HAS_CPUFREQ-config-option.patch deleted file mode 100644 index 32f2b5d8ea..0000000000 --- a/target/linux/ipq806x/patches/0161-ARM-Remove-ARCH_HAS_CPUFREQ-config-option.patch +++ /dev/null @@ -1,234 +0,0 @@ -From 5d102a45ee224fa32c775deb75bf7eb9d2ee2cf0 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 3 Jun 2014 11:24:23 -0700 -Subject: [PATCH 161/182] ARM: Remove ARCH_HAS_CPUFREQ config option - -This config exists entirely to hide the cpufreq menu from the -kernel configuration unless a platform has selected it. Nothing -is actually built if this config is 'Y' and it just leads to more -patches that add a select under a platform Kconfig so that some -other CPUfreq option can be chosen. Let's remove the option so -that we can always enable CPUfreq drivers on ARM platforms. - -Acked-by: Viresh Kumar -Signed-off-by: Stephen Boyd -Signed-off-by: Arnd Bergmann -Signed-off-by: Stephen Boyd ---- - arch/arm/Kconfig | 17 ----------------- - arch/arm/mach-davinci/Kconfig | 1 - - arch/arm/mach-highbank/Kconfig | 1 - - arch/arm/mach-imx/Kconfig | 2 -- - arch/arm/mach-omap2/Kconfig | 1 - - arch/arm/mach-shmobile/Kconfig | 2 -- - arch/arm/mach-spear/Kconfig | 1 - - arch/arm/mach-tegra/Kconfig | 1 - - arch/arm/mach-ux500/Kconfig | 1 - - arch/arm/mach-vexpress/Kconfig | 1 - - arch/arm/mach-vt8500/Kconfig | 1 - - 11 files changed, 29 deletions(-) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -181,13 +181,6 @@ config ARCH_HAS_ILOG2_U32 - config ARCH_HAS_ILOG2_U64 - bool - --config ARCH_HAS_CPUFREQ -- bool -- help -- Internal node to signify that the ARCH has CPUFREQ support -- and that the relevant menu configurations are displayed for -- it. -- - config ARCH_HAS_BANDGAP - bool - -@@ -316,7 +309,6 @@ config ARCH_MULTIPLATFORM - - config ARCH_INTEGRATOR - bool "ARM Ltd. Integrator family" -- select ARCH_HAS_CPUFREQ - select ARM_AMBA - select ARM_PATCH_PHYS_VIRT - select AUTO_ZRELADDR -@@ -541,7 +533,6 @@ config ARCH_DOVE - - config ARCH_KIRKWOOD - bool "Marvell Kirkwood" -- select ARCH_HAS_CPUFREQ - select ARCH_REQUIRE_GPIOLIB - select CPU_FEROCEON - select GENERIC_CLOCKEVENTS -@@ -642,7 +633,6 @@ config ARCH_LPC32XX - config ARCH_PXA - bool "PXA2xx/PXA3xx-based" - depends on MMU -- select ARCH_HAS_CPUFREQ - select ARCH_MTD_XIP - select ARCH_REQUIRE_GPIOLIB - select ARM_CPU_SUSPEND if PM -@@ -711,7 +701,6 @@ config ARCH_RPC - - config ARCH_SA1100 - bool "SA1100-based" -- select ARCH_HAS_CPUFREQ - select ARCH_MTD_XIP - select ARCH_REQUIRE_GPIOLIB - select ARCH_SPARSEMEM_ENABLE -@@ -729,7 +718,6 @@ config ARCH_SA1100 - - config ARCH_S3C24XX - bool "Samsung S3C24XX SoCs" -- select ARCH_HAS_CPUFREQ - select ARCH_REQUIRE_GPIOLIB - select CLKDEV_LOOKUP - select CLKSRC_SAMSUNG_PWM -@@ -749,7 +737,6 @@ config ARCH_S3C24XX - - config ARCH_S3C64XX - bool "Samsung S3C64XX" -- select ARCH_HAS_CPUFREQ - select ARCH_REQUIRE_GPIOLIB - select ARM_AMBA - select ARM_VIC -@@ -810,7 +797,6 @@ config ARCH_S5PC100 - - config ARCH_S5PV210 - bool "Samsung S5PV210/S5PC110" -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_HOLES_MEMORYMODEL - select ARCH_SPARSEMEM_ENABLE - select CLKDEV_LOOKUP -@@ -864,7 +850,6 @@ config ARCH_DAVINCI - config ARCH_OMAP1 - bool "TI OMAP1" - depends on MMU -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_HOLES_MEMORYMODEL - select ARCH_OMAP - select ARCH_REQUIRE_GPIOLIB -@@ -2171,9 +2156,7 @@ endmenu - - menu "CPU Power Management" - --if ARCH_HAS_CPUFREQ - source "drivers/cpufreq/Kconfig" --endif - - source "drivers/cpuidle/Kconfig" - ---- a/arch/arm/mach-davinci/Kconfig -+++ b/arch/arm/mach-davinci/Kconfig -@@ -39,7 +39,6 @@ config ARCH_DAVINCI_DA830 - config ARCH_DAVINCI_DA850 - bool "DA850/OMAP-L138/AM18x based system" - select ARCH_DAVINCI_DA8XX -- select ARCH_HAS_CPUFREQ - select CP_INTC - - config ARCH_DAVINCI_DA8XX ---- a/arch/arm/mach-highbank/Kconfig -+++ b/arch/arm/mach-highbank/Kconfig -@@ -1,7 +1,6 @@ - config ARCH_HIGHBANK - bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7 - select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_HOLES_MEMORYMODEL - select ARCH_HAS_OPP - select ARCH_SUPPORTS_BIG_ENDIAN ---- a/arch/arm/mach-imx/Kconfig -+++ b/arch/arm/mach-imx/Kconfig -@@ -103,7 +103,6 @@ config SOC_IMX25 - - config SOC_IMX27 - bool -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_OPP - select CPU_ARM926T - select IMX_HAVE_IOMUX_V1 -@@ -129,7 +128,6 @@ config SOC_IMX35 - - config SOC_IMX5 - bool -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_OPP - select ARCH_MXC_IOMUX_V3 - select CPU_V7 ---- a/arch/arm/mach-omap2/Kconfig -+++ b/arch/arm/mach-omap2/Kconfig -@@ -93,7 +93,6 @@ config SOC_DRA7XX - config ARCH_OMAP2PLUS - bool - select ARCH_HAS_BANDGAP -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_HOLES_MEMORYMODEL - select ARCH_OMAP - select ARCH_REQUIRE_GPIOLIB ---- a/arch/arm/mach-shmobile/Kconfig -+++ b/arch/arm/mach-shmobile/Kconfig -@@ -85,7 +85,6 @@ config ARCH_R8A73A4 - select CPU_V7 - select SH_CLK_CPG - select RENESAS_IRQC -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_OPP - - config ARCH_R8A7740 -@@ -271,7 +270,6 @@ config MACH_KOELSCH - config MACH_KZM9G - bool "KZM-A9-GT board" - depends on ARCH_SH73A0 -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_OPP - select ARCH_REQUIRE_GPIOLIB - select REGULATOR_FIXED_VOLTAGE if REGULATOR ---- a/arch/arm/mach-spear/Kconfig -+++ b/arch/arm/mach-spear/Kconfig -@@ -16,7 +16,6 @@ if PLAT_SPEAR - config ARCH_SPEAR13XX - bool "ST SPEAr13xx" - depends on ARCH_MULTI_V7 || PLAT_SPEAR_SINGLE -- select ARCH_HAS_CPUFREQ - select ARM_GIC - select CPU_V7 - select GPIO_SPEAR_SPICS ---- a/arch/arm/mach-tegra/Kconfig -+++ b/arch/arm/mach-tegra/Kconfig -@@ -1,6 +1,5 @@ - config ARCH_TEGRA - bool "NVIDIA Tegra" if ARCH_MULTI_V7 -- select ARCH_HAS_CPUFREQ - select ARCH_REQUIRE_GPIOLIB - select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS - select ARM_GIC ---- a/arch/arm/mach-ux500/Kconfig -+++ b/arch/arm/mach-ux500/Kconfig -@@ -3,7 +3,6 @@ config ARCH_U8500 - depends on MMU - select AB8500_CORE - select ABX500_CORE -- select ARCH_HAS_CPUFREQ - select ARCH_REQUIRE_GPIOLIB - select ARM_AMBA - select ARM_ERRATA_754322 ---- a/arch/arm/mach-vexpress/Kconfig -+++ b/arch/arm/mach-vexpress/Kconfig -@@ -67,7 +67,6 @@ config ARCH_VEXPRESS_DCSCB - - config ARCH_VEXPRESS_SPC - bool "Versatile Express Serial Power Controller (SPC)" -- select ARCH_HAS_CPUFREQ - select ARCH_HAS_OPP - select PM_OPP - help ---- a/arch/arm/mach-vt8500/Kconfig -+++ b/arch/arm/mach-vt8500/Kconfig -@@ -1,6 +1,5 @@ - config ARCH_VT8500 - bool -- select ARCH_HAS_CPUFREQ - select ARCH_REQUIRE_GPIOLIB - select CLKDEV_LOOKUP - select CLKSRC_OF diff --git a/target/linux/ipq806x/patches/0162-PM-OPP-Remove-ARCH_HAS_OPP.patch b/target/linux/ipq806x/patches/0162-PM-OPP-Remove-ARCH_HAS_OPP.patch deleted file mode 100644 index d07b9e0c60..0000000000 --- a/target/linux/ipq806x/patches/0162-PM-OPP-Remove-ARCH_HAS_OPP.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 18e4542f7b02f586d46594977818cd6b24d9cbcb Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Fri, 6 Jun 2014 11:36:56 +0100 -Subject: [PATCH 162/182] PM / OPP: Remove ARCH_HAS_OPP - -Since the OPP layer is a kernel library which has been converted to be -directly selectable by its callers rather than user selectable and -requiring architectures to enable it explicitly the ARCH_HAS_OPP symbol -has become redundant and can be removed. Do so. - -Signed-off-by: Mark Brown -Signed-off-by: Stephen Boyd ---- - Documentation/power/opp.txt | 3 --- - arch/arm/mach-exynos/Kconfig | 1 - - arch/arm/mach-highbank/Kconfig | 1 - - arch/arm/mach-omap2/Kconfig | 1 - - arch/arm/mach-shmobile/Kconfig | 2 -- - arch/arm/mach-vexpress/Kconfig | 1 - - drivers/devfreq/Kconfig | 1 - - kernel/power/Kconfig | 3 --- - 8 files changed, 13 deletions(-) - ---- a/Documentation/power/opp.txt -+++ b/Documentation/power/opp.txt -@@ -52,9 +52,6 @@ Typical usage of the OPP library is as f - SoC framework -> modifies on required cases certain OPPs -> OPP layer - -> queries to search/retrieve information -> - --Architectures that provide a SoC framework for OPP should select ARCH_HAS_OPP --to make the OPP layer available. -- - OPP layer expects each domain to be represented by a unique device pointer. SoC - framework registers a set of initial OPPs per device with the OPP layer. This - list is expected to be an optimally small number typically around 5 per device. ---- a/arch/arm/mach-exynos/Kconfig -+++ b/arch/arm/mach-exynos/Kconfig -@@ -107,7 +107,6 @@ config SOC_EXYNOS5440 - depends on ARCH_EXYNOS5 - select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE - select ARCH_HAS_BANDGAP -- select ARCH_HAS_OPP - select HAVE_ARM_ARCH_TIMER - select AUTO_ZRELADDR - select MIGHT_HAVE_PCI ---- a/arch/arm/mach-highbank/Kconfig -+++ b/arch/arm/mach-highbank/Kconfig -@@ -2,7 +2,6 @@ config ARCH_HIGHBANK - bool "Calxeda ECX-1000/2000 (Highbank/Midway)" if ARCH_MULTI_V7 - select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE - select ARCH_HAS_HOLES_MEMORYMODEL -- select ARCH_HAS_OPP - select ARCH_SUPPORTS_BIG_ENDIAN - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_AMBA ---- a/arch/arm/mach-omap2/Kconfig -+++ b/arch/arm/mach-omap2/Kconfig -@@ -13,7 +13,6 @@ config ARCH_OMAP3 - bool "TI OMAP3" - depends on ARCH_MULTI_V7 - select ARCH_OMAP2PLUS -- select ARCH_HAS_OPP - select ARM_CPU_SUSPEND if PM - select CPU_V7 - select MULTI_IRQ_HANDLER ---- a/arch/arm/mach-shmobile/Kconfig -+++ b/arch/arm/mach-shmobile/Kconfig -@@ -85,7 +85,6 @@ config ARCH_R8A73A4 - select CPU_V7 - select SH_CLK_CPG - select RENESAS_IRQC -- select ARCH_HAS_OPP - - config ARCH_R8A7740 - bool "R-Mobile A1 (R8A77400)" -@@ -270,7 +269,6 @@ config MACH_KOELSCH - config MACH_KZM9G - bool "KZM-A9-GT board" - depends on ARCH_SH73A0 -- select ARCH_HAS_OPP - select ARCH_REQUIRE_GPIOLIB - select REGULATOR_FIXED_VOLTAGE if REGULATOR - select SND_SOC_AK4642 if SND_SIMPLE_CARD ---- a/arch/arm/mach-vexpress/Kconfig -+++ b/arch/arm/mach-vexpress/Kconfig -@@ -67,7 +67,6 @@ config ARCH_VEXPRESS_DCSCB - - config ARCH_VEXPRESS_SPC - bool "Versatile Express Serial Power Controller (SPC)" -- select ARCH_HAS_OPP - select PM_OPP - help - The TC2 (A15x2 A7x3) versatile express core tile integrates a logic ---- a/drivers/devfreq/Kconfig -+++ b/drivers/devfreq/Kconfig -@@ -68,7 +68,6 @@ comment "DEVFREQ Drivers" - config ARM_EXYNOS4_BUS_DEVFREQ - bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver" - depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM -- select ARCH_HAS_OPP - select DEVFREQ_GOV_SIMPLE_ONDEMAND - help - This adds the DEVFREQ driver for Exynos4210 memory bus (vdd_int) ---- a/kernel/power/Kconfig -+++ b/kernel/power/Kconfig -@@ -253,9 +253,6 @@ config APM_EMULATION - anything, try disabling/enabling this option (or disabling/enabling - APM in your BIOS). - --config ARCH_HAS_OPP -- bool -- - config PM_OPP - bool "Operating Performance Point (OPP) Layer library" - depends on ARCH_HAS_OPP diff --git a/target/linux/ipq806x/patches/0163-clk-return-probe-defer-when-DT-clock-not-yet-ready.patch b/target/linux/ipq806x/patches/0163-clk-return-probe-defer-when-DT-clock-not-yet-ready.patch deleted file mode 100644 index 76956d5b9b..0000000000 --- a/target/linux/ipq806x/patches/0163-clk-return-probe-defer-when-DT-clock-not-yet-ready.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 1ce8667062bc7b8813adf6103ad2374d9dd52fb0 Mon Sep 17 00:00:00 2001 -From: Jean-Francois Moine -Date: Mon, 25 Nov 2013 19:47:04 +0100 -Subject: [PATCH 163/182] clk: return probe defer when DT clock not yet ready - -At probe time, a clock device may not be ready when some other device -wants to use it. - -This patch lets the functions clk_get/devm_clk_get return a probe defer -when the clock is defined in the DT but not yet available. - -Signed-off-by: Jean-Francois Moine -Reviewed-by: Sylwester Nawrocki -Tested-by: Sylwester Nawrocki -Signed-off-by: Mike Turquette ---- - drivers/clk/clk.c | 2 +- - drivers/clk/clkdev.c | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -2507,7 +2507,7 @@ EXPORT_SYMBOL_GPL(of_clk_del_provider); - struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec) - { - struct of_clk_provider *provider; -- struct clk *clk = ERR_PTR(-ENOENT); -+ struct clk *clk = ERR_PTR(-EPROBE_DEFER); - - /* Check if we have such a provider in our array */ - list_for_each_entry(provider, &of_clk_providers, link) { ---- a/drivers/clk/clkdev.c -+++ b/drivers/clk/clkdev.c -@@ -167,6 +167,8 @@ struct clk *clk_get(struct device *dev, - clk = of_clk_get_by_name(dev->of_node, con_id); - if (!IS_ERR(clk)) - return clk; -+ if (PTR_ERR(clk) == -EPROBE_DEFER) -+ return clk; - } - - return clk_get_sys(dev_id, con_id); diff --git a/target/linux/ipq806x/patches/0164-ARM-Add-Krait-L2-register-accessor-functions.patch b/target/linux/ipq806x/patches/0164-ARM-Add-Krait-L2-register-accessor-functions.patch deleted file mode 100644 index 1eb450e10d..0000000000 --- a/target/linux/ipq806x/patches/0164-ARM-Add-Krait-L2-register-accessor-functions.patch +++ /dev/null @@ -1,133 +0,0 @@ -From d8bf5e13683e027c52476b89b874d50e5281c130 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 18 Oct 2013 16:45:05 -0700 -Subject: [PATCH 164/182] ARM: Add Krait L2 register accessor functions - -Krait CPUs have a handful of L2 cache controller registers that -live behind a cp15 based indirection register. First you program -the indirection register (l2cpselr) to point the L2 'window' -register (l2cpdr) at what you want to read/write. Then you -read/write the 'window' register to do what you want. The -l2cpselr register is not banked per-cpu so we must lock around -accesses to it to prevent other CPUs from re-pointing l2cpdr -underneath us. - -Cc: Mark Rutland -Cc: Russell King -Cc: Courtney Cavin -Signed-off-by: Stephen Boyd ---- - arch/arm/common/Kconfig | 3 ++ - arch/arm/common/Makefile | 1 + - arch/arm/common/krait-l2-accessors.c | 58 +++++++++++++++++++++++++++++ - arch/arm/include/asm/krait-l2-accessors.h | 20 ++++++++++ - 4 files changed, 82 insertions(+) - create mode 100644 arch/arm/common/krait-l2-accessors.c - create mode 100644 arch/arm/include/asm/krait-l2-accessors.h - ---- a/arch/arm/common/Kconfig -+++ b/arch/arm/common/Kconfig -@@ -9,6 +9,9 @@ config DMABOUNCE - bool - select ZONE_DMA - -+config KRAIT_L2_ACCESSORS -+ bool -+ - config SHARP_LOCOMO - bool - ---- a/arch/arm/common/Makefile -+++ b/arch/arm/common/Makefile -@@ -7,6 +7,7 @@ obj-y += firmware.o - obj-$(CONFIG_ICST) += icst.o - obj-$(CONFIG_SA1111) += sa1111.o - obj-$(CONFIG_DMABOUNCE) += dmabounce.o -+obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o - obj-$(CONFIG_SHARP_LOCOMO) += locomo.o - obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o - obj-$(CONFIG_SHARP_SCOOP) += scoop.o ---- /dev/null -+++ b/arch/arm/common/krait-l2-accessors.c -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+ -+#include -+#include -+ -+static DEFINE_RAW_SPINLOCK(krait_l2_lock); -+ -+void krait_set_l2_indirect_reg(u32 addr, u32 val) -+{ -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&krait_l2_lock, flags); -+ /* -+ * Select the L2 window by poking l2cpselr, then write to the window -+ * via l2cpdr. -+ */ -+ asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr)); -+ isb(); -+ asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val)); -+ isb(); -+ -+ raw_spin_unlock_irqrestore(&krait_l2_lock, flags); -+} -+EXPORT_SYMBOL(krait_set_l2_indirect_reg); -+ -+u32 krait_get_l2_indirect_reg(u32 addr) -+{ -+ u32 val; -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&krait_l2_lock, flags); -+ /* -+ * Select the L2 window by poking l2cpselr, then read from the window -+ * via l2cpdr. -+ */ -+ asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr)); -+ isb(); -+ asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val)); -+ -+ raw_spin_unlock_irqrestore(&krait_l2_lock, flags); -+ -+ return val; -+} -+EXPORT_SYMBOL(krait_get_l2_indirect_reg); ---- /dev/null -+++ b/arch/arm/include/asm/krait-l2-accessors.h -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 __ASMARM_KRAIT_L2_ACCESSORS_H -+#define __ASMARM_KRAIT_L2_ACCESSORS_H -+ -+extern void krait_set_l2_indirect_reg(u32 addr, u32 val); -+extern u32 krait_get_l2_indirect_reg(u32 addr); -+ -+#endif diff --git a/target/linux/ipq806x/patches/0165-clk-qcom-Add-support-for-muxes-dividers-and-mux-divi.patch b/target/linux/ipq806x/patches/0165-clk-qcom-Add-support-for-muxes-dividers-and-mux-divi.patch deleted file mode 100644 index fa7b4e9dde..0000000000 --- a/target/linux/ipq806x/patches/0165-clk-qcom-Add-support-for-muxes-dividers-and-mux-divi.patch +++ /dev/null @@ -1,652 +0,0 @@ -From 151d7e91baaa4016ba687b80e8f7ccead62d6c72 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Tue, 25 Mar 2014 13:37:55 -0700 -Subject: [PATCH 165/182] clk: qcom: Add support for muxes, dividers, and mux - dividers - -The Krait CPU clocks are made up of muxes and dividers with a -handful of sources. Add a set of clk_ops that allow us to -configure these clocks so we can support CPU frequency scaling on -Krait CPUs. - -Based on code originally written by Saravana Kannan. - -Cc: Saravana Kannan -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-generic.c | 405 +++++++++++++++++++++++++++++++++++ - include/linux/clk/msm-clk-generic.h | 208 ++++++++++++++++++ - 3 files changed, 614 insertions(+) - create mode 100644 drivers/clk/qcom/clk-generic.c - create mode 100644 include/linux/clk/msm-clk-generic.h - ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -6,6 +6,7 @@ clk-qcom-y += clk-pll.o - clk-qcom-y += clk-rcg.o - clk-qcom-y += clk-rcg2.o - clk-qcom-y += clk-branch.o -+clk-qcom-y += clk-generic.o - clk-qcom-y += reset.o - - obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o ---- /dev/null -+++ b/drivers/clk/qcom/clk-generic.c -@@ -0,0 +1,405 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/* ==================== Mux clock ==================== */ -+ -+static int mux_set_parent(struct clk_hw *hw, u8 sel) -+{ -+ struct mux_clk *mux = to_mux_clk(hw); -+ -+ if (mux->parent_map) -+ sel = mux->parent_map[sel]; -+ -+ return mux->ops->set_mux_sel(mux, sel); -+} -+ -+static u8 mux_get_parent(struct clk_hw *hw) -+{ -+ struct mux_clk *mux = to_mux_clk(hw); -+ int num_parents = __clk_get_num_parents(hw->clk); -+ int i; -+ u8 sel; -+ -+ sel = mux->ops->get_mux_sel(mux); -+ if (mux->parent_map) { -+ for (i = 0; i < num_parents; i++) -+ if (sel == mux->parent_map[i]) -+ return i; -+ WARN(1, "Can't find parent\n"); -+ return -EINVAL; -+ } -+ -+ return sel; -+} -+ -+static int mux_enable(struct clk_hw *hw) -+{ -+ struct mux_clk *mux = to_mux_clk(hw); -+ if (mux->ops->enable) -+ return mux->ops->enable(mux); -+ return 0; -+} -+ -+static void mux_disable(struct clk_hw *hw) -+{ -+ struct mux_clk *mux = to_mux_clk(hw); -+ if (mux->ops->disable) -+ return mux->ops->disable(mux); -+} -+ -+static struct clk *mux_get_safe_parent(struct clk_hw *hw) -+{ -+ int i; -+ struct mux_clk *mux = to_mux_clk(hw); -+ int num_parents = __clk_get_num_parents(hw->clk); -+ -+ if (!mux->has_safe_parent) -+ return NULL; -+ -+ i = mux->safe_sel; -+ if (mux->parent_map) -+ for (i = 0; i < num_parents; i++) -+ if (mux->safe_sel == mux->parent_map[i]) -+ break; -+ -+ return clk_get_parent_by_index(hw->clk, i); -+} -+ -+const struct clk_ops clk_ops_gen_mux = { -+ .enable = mux_enable, -+ .disable = mux_disable, -+ .set_parent = mux_set_parent, -+ .get_parent = mux_get_parent, -+ .determine_rate = __clk_mux_determine_rate, -+ .get_safe_parent = mux_get_safe_parent, -+}; -+EXPORT_SYMBOL_GPL(clk_ops_gen_mux); -+ -+/* ==================== Divider clock ==================== */ -+ -+static long __div_round_rate(struct div_data *data, unsigned long rate, -+ struct clk *parent, unsigned int *best_div, unsigned long *best_prate, -+ bool set_parent) -+{ -+ unsigned int div, min_div, max_div, _best_div = 1; -+ unsigned long prate, _best_prate = 0, rrate = 0, req_prate, actual_rate; -+ unsigned int numer; -+ -+ rate = max(rate, 1UL); -+ -+ min_div = max(data->min_div, 1U); -+ max_div = min(data->max_div, (unsigned int) (ULONG_MAX / rate)); -+ -+ /* -+ * div values are doubled for half dividers. -+ * Adjust for that by picking a numer of 2. -+ */ -+ numer = data->is_half_divider ? 2 : 1; -+ -+ if (!set_parent) { -+ prate = *best_prate * numer; -+ div = DIV_ROUND_UP(prate, rate); -+ div = clamp(1U, div, max_div); -+ if (best_div) -+ *best_div = div; -+ return mult_frac(*best_prate, numer, div); -+ } -+ -+ for (div = min_div; div <= max_div; div++) { -+ req_prate = mult_frac(rate, div, numer); -+ prate = __clk_round_rate(parent, req_prate); -+ if (IS_ERR_VALUE(prate)) -+ break; -+ -+ actual_rate = mult_frac(prate, numer, div); -+ if (is_better_rate(rate, rrate, actual_rate)) { -+ rrate = actual_rate; -+ _best_div = div; -+ _best_prate = prate; -+ } -+ -+ /* -+ * Trying higher dividers is only going to ask the parent for -+ * a higher rate. If it can't even output a rate higher than -+ * the one we request for this divider, the parent is not -+ * going to be able to output an even higher rate required -+ * for a higher divider. So, stop trying higher dividers. -+ */ -+ if (actual_rate < rate) -+ break; -+ -+ if (rrate <= rate) -+ break; -+ } -+ -+ if (!rrate) -+ return -EINVAL; -+ if (best_div) -+ *best_div = _best_div; -+ if (best_prate) -+ *best_prate = _best_prate; -+ -+ return rrate; -+} -+ -+static long div_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *parent_rate) -+{ -+ struct div_clk *d = to_div_clk(hw); -+ bool set_parent = __clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT; -+ -+ return __div_round_rate(&d->data, rate, __clk_get_parent(hw->clk), -+ NULL, parent_rate, set_parent); -+} -+ -+static int div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long -+ parent_rate) -+{ -+ struct div_clk *d = to_div_clk(hw); -+ int div, rc = 0; -+ struct div_data *data = &d->data; -+ -+ div = parent_rate / rate; -+ if (div != data->div) -+ rc = d->ops->set_div(d, div); -+ data->div = div; -+ -+ return rc; -+} -+ -+static int div_enable(struct clk_hw *hw) -+{ -+ struct div_clk *d = to_div_clk(hw); -+ if (d->ops && d->ops->enable) -+ return d->ops->enable(d); -+ return 0; -+} -+ -+static void div_disable(struct clk_hw *hw) -+{ -+ struct div_clk *d = to_div_clk(hw); -+ if (d->ops && d->ops->disable) -+ return d->ops->disable(d); -+} -+ -+static unsigned long div_recalc_rate(struct clk_hw *hw, unsigned long prate) -+{ -+ struct div_clk *d = to_div_clk(hw); -+ unsigned int div = d->data.div; -+ -+ if (d->ops && d->ops->get_div) -+ div = max(d->ops->get_div(d), 1); -+ div = max(div, 1U); -+ -+ if (!d->ops || !d->ops->set_div) -+ d->data.min_div = d->data.max_div = div; -+ d->data.div = div; -+ -+ return prate / div; -+} -+ -+const struct clk_ops clk_ops_div = { -+ .enable = div_enable, -+ .disable = div_disable, -+ .round_rate = div_round_rate, -+ .set_rate = div_set_rate, -+ .recalc_rate = div_recalc_rate, -+}; -+EXPORT_SYMBOL_GPL(clk_ops_div); -+ -+/* ==================== Mux_div clock ==================== */ -+ -+static int mux_div_clk_enable(struct clk_hw *hw) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ -+ if (md->ops->enable) -+ return md->ops->enable(md); -+ return 0; -+} -+ -+static void mux_div_clk_disable(struct clk_hw *hw) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ -+ if (md->ops->disable) -+ return md->ops->disable(md); -+} -+ -+static long __mux_div_round_rate(struct clk_hw *hw, unsigned long rate, -+ struct clk **best_parent, int *best_div, unsigned long *best_prate) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ unsigned int i; -+ unsigned long rrate, best = 0, _best_div = 0, _best_prate = 0; -+ struct clk *_best_parent = 0; -+ int num_parents = __clk_get_num_parents(hw->clk); -+ bool set_parent = __clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT; -+ -+ for (i = 0; i < num_parents; i++) { -+ int div; -+ unsigned long prate; -+ struct clk *p = clk_get_parent_by_index(hw->clk, i); -+ -+ rrate = __div_round_rate(&md->data, rate, p, &div, &prate, -+ set_parent); -+ -+ if (is_better_rate(rate, best, rrate)) { -+ best = rrate; -+ _best_div = div; -+ _best_prate = prate; -+ _best_parent = p; -+ } -+ -+ if (rate <= rrate) -+ break; -+ } -+ -+ if (best_div) -+ *best_div = _best_div; -+ if (best_prate) -+ *best_prate = _best_prate; -+ if (best_parent) -+ *best_parent = _best_parent; -+ -+ if (best) -+ return best; -+ return -EINVAL; -+} -+ -+static long mux_div_clk_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *parent_rate) -+{ -+ return __mux_div_round_rate(hw, rate, NULL, NULL, parent_rate); -+} -+ -+/* requires enable lock to be held */ -+static int __set_src_div(struct mux_div_clk *md, u8 src_sel, u32 div) -+{ -+ int rc; -+ -+ rc = md->ops->set_src_div(md, src_sel, div); -+ if (!rc) { -+ md->data.div = div; -+ md->src_sel = src_sel; -+ } -+ -+ return rc; -+} -+ -+/* Must be called after handoff to ensure parent clock rates are initialized */ -+static int safe_parent_init_once(struct clk_hw *hw) -+{ -+ unsigned long rrate; -+ u32 best_div; -+ struct clk *best_parent; -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ -+ if (IS_ERR(md->safe_parent)) -+ return -EINVAL; -+ if (!md->safe_freq || md->safe_parent) -+ return 0; -+ -+ rrate = __mux_div_round_rate(hw, md->safe_freq, &best_parent, -+ &best_div, NULL); -+ -+ if (rrate == md->safe_freq) { -+ md->safe_div = best_div; -+ md->safe_parent = best_parent; -+ } else { -+ md->safe_parent = ERR_PTR(-EINVAL); -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static int -+__mux_div_clk_set_rate_and_parent(struct clk_hw *hw, u8 index, u32 div) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ int rc; -+ -+ rc = safe_parent_init_once(hw); -+ if (rc) -+ return rc; -+ -+ return __set_src_div(md, index, div); -+} -+ -+static int mux_div_clk_set_rate_and_parent(struct clk_hw *hw, -+ unsigned long rate, unsigned long parent_rate, u8 index) -+{ -+ return __mux_div_clk_set_rate_and_parent(hw, index, parent_rate / rate); -+} -+ -+static int mux_div_clk_set_rate(struct clk_hw *hw, -+ unsigned long rate, unsigned long parent_rate) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ return __mux_div_clk_set_rate_and_parent(hw, md->src_sel, -+ parent_rate / rate); -+} -+ -+static int mux_div_clk_set_parent(struct clk_hw *hw, u8 index) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ return __mux_div_clk_set_rate_and_parent(hw, md->parent_map[index], -+ md->data.div); -+} -+ -+static u8 mux_div_clk_get_parent(struct clk_hw *hw) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ int num_parents = __clk_get_num_parents(hw->clk); -+ u32 i, div, sel; -+ -+ md->ops->get_src_div(md, &sel, &div); -+ md->src_sel = sel; -+ -+ for (i = 0; i < num_parents; i++) -+ if (sel == md->parent_map[i]) -+ return i; -+ WARN(1, "Can't find parent\n"); -+ return -EINVAL; -+} -+ -+static unsigned long -+mux_div_clk_recalc_rate(struct clk_hw *hw, unsigned long prate) -+{ -+ struct mux_div_clk *md = to_mux_div_clk(hw); -+ u32 div, sel; -+ -+ md->ops->get_src_div(md, &sel, &div); -+ -+ return prate / div; -+} -+ -+const struct clk_ops clk_ops_mux_div_clk = { -+ .enable = mux_div_clk_enable, -+ .disable = mux_div_clk_disable, -+ .set_rate_and_parent = mux_div_clk_set_rate_and_parent, -+ .set_rate = mux_div_clk_set_rate, -+ .set_parent = mux_div_clk_set_parent, -+ .round_rate = mux_div_clk_round_rate, -+ .get_parent = mux_div_clk_get_parent, -+ .recalc_rate = mux_div_clk_recalc_rate, -+}; -+EXPORT_SYMBOL_GPL(clk_ops_mux_div_clk); ---- /dev/null -+++ b/include/linux/clk/msm-clk-generic.h -@@ -0,0 +1,208 @@ -+/* -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#ifndef __QCOM_CLK_GENERIC_H__ -+#define __QCOM_CLK_GENERIC_H__ -+ -+#include -+#include -+ -+static inline bool is_better_rate(unsigned long req, unsigned long best, -+ unsigned long new) -+{ -+ if (IS_ERR_VALUE(new)) -+ return false; -+ -+ return (req <= new && new < best) || (best < req && best < new); -+} -+ -+/* ==================== Mux clock ==================== */ -+ -+struct mux_clk; -+ -+struct clk_mux_ops { -+ int (*set_mux_sel)(struct mux_clk *clk, int sel); -+ int (*get_mux_sel)(struct mux_clk *clk); -+ -+ /* Optional */ -+ bool (*is_enabled)(struct mux_clk *clk); -+ int (*enable)(struct mux_clk *clk); -+ void (*disable)(struct mux_clk *clk); -+}; -+ -+struct mux_clk { -+ /* Parents in decreasing order of preference for obtaining rates. */ -+ u8 *parent_map; -+ bool has_safe_parent; -+ u8 safe_sel; -+ const struct clk_mux_ops *ops; -+ -+ /* Fields not used by helper function. */ -+ void __iomem *base; -+ u32 offset; -+ u32 en_offset; -+ int en_reg; -+ u32 mask; -+ u32 shift; -+ u32 en_mask; -+ void *priv; -+ -+ struct clk_hw hw; -+}; -+ -+static inline struct mux_clk *to_mux_clk(struct clk_hw *hw) -+{ -+ return container_of(hw, struct mux_clk, hw); -+} -+ -+extern const struct clk_ops clk_ops_gen_mux; -+ -+/* ==================== Divider clock ==================== */ -+ -+struct div_clk; -+ -+struct clk_div_ops { -+ int (*set_div)(struct div_clk *clk, int div); -+ int (*get_div)(struct div_clk *clk); -+ bool (*is_enabled)(struct div_clk *clk); -+ int (*enable)(struct div_clk *clk); -+ void (*disable)(struct div_clk *clk); -+}; -+ -+struct div_data { -+ unsigned int div; -+ unsigned int min_div; -+ unsigned int max_div; -+ /* -+ * Indicate whether this divider clock supports half-interger divider. -+ * If it is, all the min_div and max_div have been doubled. It means -+ * they are 2*N. -+ */ -+ bool is_half_divider; -+}; -+ -+struct div_clk { -+ struct div_data data; -+ -+ /* Optional */ -+ const struct clk_div_ops *ops; -+ -+ /* Fields not used by helper function. */ -+ void __iomem *base; -+ u32 offset; -+ u32 mask; -+ u32 shift; -+ u32 en_mask; -+ void *priv; -+ struct clk_hw hw; -+}; -+ -+static inline struct div_clk *to_div_clk(struct clk_hw *hw) -+{ -+ return container_of(hw, struct div_clk, hw); -+} -+ -+extern const struct clk_ops clk_ops_div; -+ -+#define DEFINE_FIXED_DIV_CLK(clk_name, _div, _parent) \ -+static struct div_clk clk_name = { \ -+ .data = { \ -+ .max_div = _div, \ -+ .min_div = _div, \ -+ .div = _div, \ -+ }, \ -+ .hw.init = &(struct clk_init_data){ \ -+ .parent_names = (const char *[]){ _parent }, \ -+ .num_parents = 1, \ -+ .name = #clk_name, \ -+ .ops = &clk_ops_div, \ -+ .flags = CLK_SET_RATE_PARENT, \ -+ } \ -+} -+ -+/* ==================== Mux Div clock ==================== */ -+ -+struct mux_div_clk; -+ -+/* -+ * struct mux_div_ops -+ * the enable and disable ops are optional. -+ */ -+ -+struct mux_div_ops { -+ int (*set_src_div)(struct mux_div_clk *, u32 src_sel, u32 div); -+ void (*get_src_div)(struct mux_div_clk *, u32 *src_sel, u32 *div); -+ int (*enable)(struct mux_div_clk *); -+ void (*disable)(struct mux_div_clk *); -+ bool (*is_enabled)(struct mux_div_clk *); -+}; -+ -+/* -+ * struct mux_div_clk - combined mux/divider clock -+ * @priv -+ parameters needed by ops -+ * @safe_freq -+ when switching rates from A to B, the mux div clock will -+ instead switch from A -> safe_freq -> B. This allows the -+ mux_div clock to change rates while enabled, even if this -+ behavior is not supported by the parent clocks. -+ -+ If changing the rate of parent A also causes the rate of -+ parent B to change, then safe_freq must be defined. -+ -+ safe_freq is expected to have a source clock which is always -+ on and runs at only one rate. -+ * @parents -+ list of parents and mux indicies -+ * @ops -+ function pointers for hw specific operations -+ * @src_sel -+ the mux index which will be used if the clock is enabled. -+ */ -+ -+struct mux_div_clk { -+ /* Required parameters */ -+ const struct mux_div_ops *ops; -+ struct div_data data; -+ u8 *parent_map; -+ -+ struct clk_hw hw; -+ -+ /* Internal */ -+ u32 src_sel; -+ -+ /* Optional parameters */ -+ void *priv; -+ void __iomem *base; -+ u32 div_mask; -+ u32 div_offset; -+ u32 div_shift; -+ u32 src_mask; -+ u32 src_offset; -+ u32 src_shift; -+ u32 en_mask; -+ u32 en_offset; -+ -+ u32 safe_div; -+ struct clk *safe_parent; -+ unsigned long safe_freq; -+}; -+ -+static inline struct mux_div_clk *to_mux_div_clk(struct clk_hw *hw) -+{ -+ return container_of(hw, struct mux_div_clk, hw); -+} -+ -+extern const struct clk_ops clk_ops_mux_div_clk; -+ -+#endif diff --git a/target/linux/ipq806x/patches/0166-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch b/target/linux/ipq806x/patches/0166-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch deleted file mode 100644 index 037c6c4770..0000000000 --- a/target/linux/ipq806x/patches/0166-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch +++ /dev/null @@ -1,348 +0,0 @@ -From 8a51ac2a4e36505e1ff82b0e49fd8b2edd0b7695 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Wed, 18 Jun 2014 14:15:58 -0700 -Subject: [PATCH 166/182] clk: qcom: Add support for High-Frequency PLLs - (HFPLLs) - -HFPLLs are the main frequency source for Krait CPU clocks. Add -support for changing the rate of these PLLs. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-hfpll.c | 260 ++++++++++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-hfpll.h | 54 +++++++++ - 3 files changed, 315 insertions(+) - create mode 100644 drivers/clk/qcom/clk-hfpll.c - create mode 100644 drivers/clk/qcom/clk-hfpll.h - ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -7,6 +7,7 @@ clk-qcom-y += clk-rcg.o - clk-qcom-y += clk-rcg2.o - clk-qcom-y += clk-branch.o - clk-qcom-y += clk-generic.o -+clk-qcom-y += clk-hfpll.o - clk-qcom-y += reset.o - - obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o ---- /dev/null -+++ b/drivers/clk/qcom/clk-hfpll.c -@@ -0,0 +1,260 @@ -+/* -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-regmap.h" -+#include "clk-hfpll.h" -+ -+#define PLL_OUTCTRL BIT(0) -+#define PLL_BYPASSNL BIT(1) -+#define PLL_RESET_N BIT(2) -+ -+/* Initialize a HFPLL at a given rate and enable it. */ -+static void __clk_hfpll_init_once(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ -+ if (likely(h->init_done)) -+ return; -+ -+ /* Configure PLL parameters for integer mode. */ -+ if (hd->config_val) -+ regmap_write(regmap, hd->config_reg, hd->config_val); -+ regmap_write(regmap, hd->m_reg, 0); -+ regmap_write(regmap, hd->n_reg, 1); -+ -+ if (hd->user_reg) { -+ u32 regval = hd->user_val; -+ unsigned long rate; -+ -+ rate = __clk_get_rate(hw->clk); -+ -+ /* Pick the right VCO. */ -+ if (hd->user_vco_mask && rate > hd->low_vco_max_rate) -+ regval |= hd->user_vco_mask; -+ regmap_write(regmap, hd->user_reg, regval); -+ } -+ -+ if (hd->droop_reg) -+ regmap_write(regmap, hd->droop_reg, hd->droop_val); -+ -+ h->init_done = true; -+} -+ -+static void __clk_hfpll_enable(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 val; -+ -+ __clk_hfpll_init_once(hw); -+ -+ /* Disable PLL bypass mode. */ -+ regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL); -+ -+ /* -+ * H/W requires a 5us delay between disabling the bypass and -+ * de-asserting the reset. Delay 10us just to be safe. -+ */ -+ mb(); -+ udelay(10); -+ -+ /* De-assert active-low PLL reset. */ -+ regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N); -+ -+ /* Wait for PLL to lock. */ -+ if (hd->status_reg) { -+ do { -+ regmap_read(regmap, hd->status_reg, &val); -+ } while (!(val & BIT(hd->lock_bit))); -+ } else { -+ mb(); -+ udelay(60); -+ } -+ -+ /* Enable PLL output. */ -+ regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL); -+ -+ /* Make sure the enable is done before returning. */ -+ mb(); -+} -+ -+/* Enable an already-configured HFPLL. */ -+static int clk_hfpll_enable(struct clk_hw *hw) -+{ -+ unsigned long flags; -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 mode; -+ -+ spin_lock_irqsave(&h->lock, flags); -+ regmap_read(regmap, hd->mode_reg, &mode); -+ if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL))) -+ __clk_hfpll_enable(hw); -+ spin_unlock_irqrestore(&h->lock, flags); -+ -+ return 0; -+} -+ -+static void __clk_hfpll_disable(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ -+ /* -+ * Disable the PLL output, disable test mode, enable the bypass mode, -+ * and assert the reset. -+ */ -+ regmap_update_bits(regmap, hd->mode_reg, -+ PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0); -+} -+ -+static void clk_hfpll_disable(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&h->lock, flags); -+ __clk_hfpll_disable(hw); -+ spin_unlock_irqrestore(&h->lock, flags); -+} -+ -+static long clk_hfpll_round_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long *parent_rate) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ unsigned long rrate; -+ -+ rate = clamp(rate, hd->min_rate, hd->max_rate); -+ -+ rrate = DIV_ROUND_UP(rate, *parent_rate) * *parent_rate; -+ if (rrate > hd->max_rate) -+ rrate -= *parent_rate; -+ -+ return rrate; -+} -+ -+/* -+ * For optimization reasons, assumes no downstream clocks are actively using -+ * it. -+ */ -+static int clk_hfpll_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ unsigned long flags; -+ u32 l_val, val; -+ bool enabled; -+ -+ l_val = rate / parent_rate; -+ -+ spin_lock_irqsave(&h->lock, flags); -+ -+ enabled = __clk_is_enabled(hw->clk); -+ if (enabled) -+ __clk_hfpll_disable(hw); -+ -+ /* Pick the right VCO. */ -+ if (hd->user_reg && hd->user_vco_mask) { -+ regmap_read(regmap, hd->user_reg, &val); -+ if (rate <= hd->low_vco_max_rate) -+ val &= ~hd->user_vco_mask; -+ else -+ val |= hd->user_vco_mask; -+ regmap_write(regmap, hd->user_reg, val); -+ } -+ -+ regmap_write(regmap, hd->l_reg, l_val); -+ -+ if (enabled) -+ __clk_hfpll_enable(hw); -+ -+ spin_unlock_irqrestore(&h->lock, flags); -+ -+ return 0; -+} -+ -+static unsigned long clk_hfpll_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 l_val; -+ -+ regmap_read(regmap, hd->l_reg, &l_val); -+ -+ return l_val * parent_rate; -+} -+ -+static void clk_hfpll_init(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 mode, status; -+ -+ regmap_read(regmap, hd->mode_reg, &mode); -+ if (mode != (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)) { -+ __clk_hfpll_init_once(hw); -+ return; -+ } -+ -+ if (hd->status_reg) { -+ regmap_read(regmap, hd->status_reg, &status); -+ if (!(status & BIT(hd->lock_bit))) { -+ WARN(1, "HFPLL %s is ON, but not locked!\n", -+ __clk_get_name(hw->clk)); -+ clk_hfpll_disable(hw); -+ __clk_hfpll_init_once(hw); -+ } -+ } -+} -+ -+static int hfpll_is_enabled(struct clk_hw *hw) -+{ -+ struct clk_hfpll *h = to_clk_hfpll(hw); -+ struct hfpll_data const *hd = h->d; -+ struct regmap *regmap = h->clkr.regmap; -+ u32 mode; -+ -+ regmap_read(regmap, hd->mode_reg, &mode); -+ mode &= 0x7; -+ return mode == (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL); -+} -+ -+const struct clk_ops clk_ops_hfpll = { -+ .enable = clk_hfpll_enable, -+ .disable = clk_hfpll_disable, -+ .is_enabled = hfpll_is_enabled, -+ .round_rate = clk_hfpll_round_rate, -+ .set_rate = clk_hfpll_set_rate, -+ .recalc_rate = clk_hfpll_recalc_rate, -+ .init = clk_hfpll_init, -+}; -+EXPORT_SYMBOL_GPL(clk_ops_hfpll); ---- /dev/null -+++ b/drivers/clk/qcom/clk-hfpll.h -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 __QCOM_CLK_HFPLL_H__ -+#define __QCOM_CLK_HFPLL_H__ -+ -+#include -+#include -+#include "clk-regmap.h" -+ -+struct hfpll_data { -+ u32 mode_reg; -+ u32 l_reg; -+ u32 m_reg; -+ u32 n_reg; -+ u32 user_reg; -+ u32 droop_reg; -+ u32 config_reg; -+ u32 status_reg; -+ u8 lock_bit; -+ -+ u32 droop_val; -+ u32 config_val; -+ u32 user_val; -+ u32 user_vco_mask; -+ unsigned long low_vco_max_rate; -+ -+ unsigned long min_rate; -+ unsigned long max_rate; -+}; -+ -+struct clk_hfpll { -+ struct hfpll_data const *d; -+ int init_done; -+ -+ struct clk_regmap clkr; -+ spinlock_t lock; -+}; -+ -+#define to_clk_hfpll(_hw) \ -+ container_of(to_clk_regmap(_hw), struct clk_hfpll, clkr) -+ -+extern const struct clk_ops clk_ops_hfpll; -+ -+#endif diff --git a/target/linux/ipq806x/patches/0167-clk-qcom-Add-HFPLL-driver.patch b/target/linux/ipq806x/patches/0167-clk-qcom-Add-HFPLL-driver.patch deleted file mode 100644 index 1aedbda799..0000000000 --- a/target/linux/ipq806x/patches/0167-clk-qcom-Add-HFPLL-driver.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 49134da893bc11e833e3d87139c57e3b84e65219 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Thu, 19 Jun 2014 18:46:31 -0700 -Subject: [PATCH 167/182] clk: qcom: Add HFPLL driver - -On some devices (MSM8974 for example), the HFPLLs are -instantiated within the Krait processor subsystem as separate -register regions. Add a driver for these PLLs so that we can -provide HFPLL clocks for use by the system. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 8 ++++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/hfpll.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 119 insertions(+) - create mode 100644 drivers/clk/qcom/hfpll.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -53,3 +53,11 @@ config MSM_MMCC_8974 - Support for the multimedia clock controller on msm8974 devices. - Say Y if you want to support multimedia devices such as display, - graphics, video encode/decode, camera, etc. -+ -+config QCOM_HFPLL -+ tristate "High-Frequency PLL (HFPLL) Clock Controller" -+ depends on COMMON_CLK_QCOM -+ help -+ Support for the high-frequency PLLs present on Qualcomm devices. -+ Say Y if you want to support CPU frequency scaling on devices -+ such as MSM8974, APQ8084, etc. ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -16,3 +16,4 @@ obj-$(CONFIG_MSM_GCC_8960) += gcc-msm896 - obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o - obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o - obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o -+obj-$(CONFIG_QCOM_HFPLL) += hfpll.o ---- /dev/null -+++ b/drivers/clk/qcom/hfpll.c -@@ -0,0 +1,110 @@ -+/* -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-regmap.h" -+#include "clk-hfpll.h" -+ -+static const struct hfpll_data hdata = { -+ .mode_reg = 0x00, -+ .l_reg = 0x04, -+ .m_reg = 0x08, -+ .n_reg = 0x0c, -+ .user_reg = 0x10, -+ .config_reg = 0x14, -+ .config_val = 0x430405d, -+ .status_reg = 0x1c, -+ .lock_bit = 16, -+ -+ .user_val = 0x8, -+ .user_vco_mask = 0x100000, -+ .low_vco_max_rate = 1248000000, -+ .min_rate = 537600000UL, -+ .max_rate = 2900000000UL, -+}; -+ -+static const struct of_device_id qcom_hfpll_match_table[] = { -+ { .compatible = "qcom,hfpll" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table); -+ -+static struct regmap_config hfpll_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x30, -+ .fast_io = true, -+}; -+ -+static int qcom_hfpll_probe(struct platform_device *pdev) -+{ -+ struct clk *clk; -+ struct resource *res; -+ struct device *dev = &pdev->dev; -+ void __iomem *base; -+ struct regmap *regmap; -+ struct clk_hfpll *h; -+ struct clk_init_data init = { -+ .parent_names = (const char *[]){ "xo" }, -+ .num_parents = 1, -+ .ops = &clk_ops_hfpll, -+ }; -+ -+ h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL); -+ if (!h) -+ return -ENOMEM; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ regmap = devm_regmap_init_mmio(&pdev->dev, base, &hfpll_regmap_config); -+ if (IS_ERR(regmap)) -+ return PTR_ERR(regmap); -+ -+ if (of_property_read_string_index(dev->of_node, "clock-output-names", -+ 0, &init.name)) -+ return -ENODEV; -+ -+ h->d = &hdata; -+ h->clkr.hw.init = &init; -+ spin_lock_init(&h->lock); -+ -+ clk = devm_clk_register_regmap(&pdev->dev, &h->clkr); -+ -+ return PTR_ERR_OR_ZERO(clk); -+} -+ -+static struct platform_driver qcom_hfpll_driver = { -+ .probe = qcom_hfpll_probe, -+ .driver = { -+ .name = "qcom-hfpll", -+ .owner = THIS_MODULE, -+ .of_match_table = qcom_hfpll_match_table, -+ }, -+}; -+module_platform_driver(qcom_hfpll_driver); -+ -+MODULE_DESCRIPTION("QCOM HFPLL Clock Driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:qcom-hfpll"); diff --git a/target/linux/ipq806x/patches/0168-clk-qcom-Add-MSM8960-s-HFPLLs.patch b/target/linux/ipq806x/patches/0168-clk-qcom-Add-MSM8960-s-HFPLLs.patch deleted file mode 100644 index 04ff3711fe..0000000000 --- a/target/linux/ipq806x/patches/0168-clk-qcom-Add-MSM8960-s-HFPLLs.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0a38d7a21ef0e851d025e4e16f096d5579226299 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Mon, 16 Jun 2014 17:44:08 -0700 -Subject: [PATCH 168/182] clk: qcom: Add MSM8960's HFPLLs - -Describe the HFPLLs present on MSM8960 devices. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/gcc-msm8960.c | 82 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 82 insertions(+) - ---- a/drivers/clk/qcom/gcc-msm8960.c -+++ b/drivers/clk/qcom/gcc-msm8960.c -@@ -30,6 +30,7 @@ - #include "clk-pll.h" - #include "clk-rcg.h" - #include "clk-branch.h" -+#include "clk-hfpll.h" - #include "reset.h" - - static struct clk_pll pll3 = { -@@ -75,6 +76,84 @@ static struct clk_regmap pll8_vote = { - }, - }; - -+static struct hfpll_data hfpll0_data = { -+ .mode_reg = 0x3200, -+ .l_reg = 0x3208, -+ .m_reg = 0x320c, -+ .n_reg = 0x3210, -+ .config_reg = 0x3204, -+ .status_reg = 0x321c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3214, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll0 = { -+ .d = &hfpll0_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll0", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock), -+}; -+ -+static struct hfpll_data hfpll1_data = { -+ .mode_reg = 0x3300, -+ .l_reg = 0x3308, -+ .m_reg = 0x330c, -+ .n_reg = 0x3310, -+ .config_reg = 0x3304, -+ .status_reg = 0x331c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3314, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll1 = { -+ .d = &hfpll1_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll1", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock), -+}; -+ -+static struct hfpll_data hfpll_l2_data = { -+ .mode_reg = 0x3400, -+ .l_reg = 0x3408, -+ .m_reg = 0x340c, -+ .n_reg = 0x3410, -+ .config_reg = 0x3404, -+ .status_reg = 0x341c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3414, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll_l2 = { -+ .d = &hfpll_l2_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll_l2", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock), -+}; -+ - static struct clk_pll pll14 = { - .l_reg = 0x31c4, - .m_reg = 0x31c8, -@@ -2763,6 +2842,9 @@ static struct clk_regmap *gcc_msm8960_cl - [PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.clkr, - [PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.clkr, - [RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.clkr, -+ [PLL9] = &hfpll0.clkr, -+ [PLL10] = &hfpll1.clkr, -+ [PLL12] = &hfpll_l2.clkr, - }; - - static const struct qcom_reset_map gcc_msm8960_resets[] = { diff --git a/target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch deleted file mode 100644 index 6e17acdc4e..0000000000 --- a/target/linux/ipq806x/patches/0169-clk-qcom-Add-support-for-Krait-clocks.patch +++ /dev/null @@ -1,190 +0,0 @@ -From 63ecfef8560631a15ee13129b2778cd4dffbcfe2 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Wed, 18 Jun 2014 14:18:31 -0700 -Subject: [PATCH 169/182] clk: qcom: Add support for Krait clocks - -The Krait clocks are made up of a series of muxes and a divider -that choose between a fixed rate clock and dedicated HFPLLs for -each CPU. Instead of using mmio accesses to remux parents, the -Krait implementation exposes the remux control via cp15 -registers. Support these clocks. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 4 ++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/clk-krait.c | 121 ++++++++++++++++++++++++++++++++++++++++++ - drivers/clk/qcom/clk-krait.h | 22 ++++++++ - 4 files changed, 148 insertions(+) - create mode 100644 drivers/clk/qcom/clk-krait.c - create mode 100644 drivers/clk/qcom/clk-krait.h - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -61,3 +61,7 @@ config QCOM_HFPLL - Support for the high-frequency PLLs present on Qualcomm devices. - Say Y if you want to support CPU frequency scaling on devices - such as MSM8974, APQ8084, etc. -+ -+config KRAIT_CLOCKS -+ bool -+ select KRAIT_L2_ACCESSORS ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -7,6 +7,7 @@ clk-qcom-y += clk-rcg.o - clk-qcom-y += clk-rcg2.o - clk-qcom-y += clk-branch.o - clk-qcom-y += clk-generic.o -+clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o - clk-qcom-y += clk-hfpll.o - clk-qcom-y += reset.o - ---- /dev/null -+++ b/drivers/clk/qcom/clk-krait.c -@@ -0,0 +1,121 @@ -+/* -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "clk-krait.h" -+ -+/* Secondary and primary muxes share the same cp15 register */ -+static DEFINE_SPINLOCK(kpss_clock_reg_lock); -+ -+#define LPL_SHIFT 8 -+static void __kpss_mux_set_sel(struct mux_clk *mux, int sel) -+{ -+ unsigned long flags; -+ u32 regval; -+ -+ spin_lock_irqsave(&kpss_clock_reg_lock, flags); -+ regval = krait_get_l2_indirect_reg(mux->offset); -+ regval &= ~(mux->mask << mux->shift); -+ regval |= (sel & mux->mask) << mux->shift; -+ if (mux->priv) { -+ regval &= ~(mux->mask << (mux->shift + LPL_SHIFT)); -+ regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT); -+ } -+ krait_set_l2_indirect_reg(mux->offset, regval); -+ spin_unlock_irqrestore(&kpss_clock_reg_lock, flags); -+ -+ /* Wait for switch to complete. */ -+ mb(); -+ udelay(1); -+} -+ -+static int kpss_mux_set_sel(struct mux_clk *mux, int sel) -+{ -+ mux->en_mask = sel; -+ /* Don't touch mux if CPU is off as it won't work */ -+ if (__clk_is_enabled(mux->hw.clk)) -+ __kpss_mux_set_sel(mux, sel); -+ return 0; -+} -+ -+static int kpss_mux_get_sel(struct mux_clk *mux) -+{ -+ u32 sel; -+ -+ sel = krait_get_l2_indirect_reg(mux->offset); -+ sel >>= mux->shift; -+ sel &= mux->mask; -+ mux->en_mask = sel; -+ -+ return sel; -+} -+ -+static int kpss_mux_enable(struct mux_clk *mux) -+{ -+ __kpss_mux_set_sel(mux, mux->en_mask); -+ return 0; -+} -+ -+static void kpss_mux_disable(struct mux_clk *mux) -+{ -+ __kpss_mux_set_sel(mux, mux->safe_sel); -+} -+ -+const struct clk_mux_ops clk_mux_ops_kpss = { -+ .enable = kpss_mux_enable, -+ .disable = kpss_mux_disable, -+ .set_mux_sel = kpss_mux_set_sel, -+ .get_mux_sel = kpss_mux_get_sel, -+}; -+EXPORT_SYMBOL_GPL(clk_mux_ops_kpss); -+ -+/* -+ * The divider can divide by 2, 4, 6 and 8. But we only really need div-2. So -+ * force it to div-2 during handoff and treat it like a fixed div-2 clock. -+ */ -+static int kpss_div2_get_div(struct div_clk *div) -+{ -+ unsigned long flags; -+ u32 regval; -+ int val; -+ -+ spin_lock_irqsave(&kpss_clock_reg_lock, flags); -+ regval = krait_get_l2_indirect_reg(div->offset); -+ val = (regval >> div->shift) & div->mask; -+ regval &= ~(div->mask << div->shift); -+ if (div->priv) -+ regval &= ~(div->mask << (div->shift + LPL_SHIFT)); -+ krait_set_l2_indirect_reg(div->offset, regval); -+ spin_unlock_irqrestore(&kpss_clock_reg_lock, flags); -+ -+ val = (val + 1) * 2; -+ WARN(val != 2, "Divider %s was configured to div-%d instead of 2!\n", -+ __clk_get_name(div->hw.clk), val); -+ -+ return 2; -+} -+ -+const struct clk_div_ops clk_div_ops_kpss_div2 = { -+ .get_div = kpss_div2_get_div, -+}; -+EXPORT_SYMBOL_GPL(clk_div_ops_kpss_div2); ---- /dev/null -+++ b/drivers/clk/qcom/clk-krait.h -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (c) 2013, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 __SOC_QCOM_CLOCK_KRAIT_H -+#define __SOC_QCOM_CLOCK_KRAIT_H -+ -+#include -+ -+extern const struct clk_mux_ops clk_mux_ops_kpss; -+extern const struct clk_div_ops clk_div_ops_kpss_div2; -+ -+#endif diff --git a/target/linux/ipq806x/patches/0170-clk-qcom-Add-KPSS-ACC-GCC-driver.patch b/target/linux/ipq806x/patches/0170-clk-qcom-Add-KPSS-ACC-GCC-driver.patch deleted file mode 100644 index b16108ed43..0000000000 --- a/target/linux/ipq806x/patches/0170-clk-qcom-Add-KPSS-ACC-GCC-driver.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 67a9d5a02b178644da624ef9c32b4e6abb2c4f6e Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Wed, 18 Jun 2014 14:25:41 -0700 -Subject: [PATCH 170/182] clk: qcom: Add KPSS ACC/GCC driver - -The ACC and GCC regions present in KPSSv1 contain registers to -control clocks and power to each Krait CPU and L2. For CPUfreq -purposes probe these devices and expose a mux clock that chooses -between PXO and PLL8. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 8 +++ - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/kpss-xcc.c | 115 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 124 insertions(+) - create mode 100644 drivers/clk/qcom/kpss-xcc.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -62,6 +62,14 @@ config QCOM_HFPLL - Say Y if you want to support CPU frequency scaling on devices - such as MSM8974, APQ8084, etc. - -+config KPSS_XCC -+ tristate "KPSS Clock Controller" -+ depends on COMMON_CLK_QCOM -+ help -+ Support for the Krait ACC and GCC clock controllers. Say Y -+ if you want to support CPU frequency scaling on devices such -+ as MSM8960, APQ8064, etc. -+ - config KRAIT_CLOCKS - bool - select KRAIT_L2_ACCESSORS ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -17,4 +17,5 @@ obj-$(CONFIG_MSM_GCC_8960) += gcc-msm896 - obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o - obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o - obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o -+obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o - obj-$(CONFIG_QCOM_HFPLL) += hfpll.o ---- /dev/null -+++ b/drivers/clk/qcom/kpss-xcc.c -@@ -0,0 +1,115 @@ -+/* Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int kpss_xcc_set_mux_sel(struct mux_clk *clk, int sel) -+{ -+ writel_relaxed(sel, clk->base + clk->offset); -+ return 0; -+} -+ -+static int kpss_xcc_get_mux_sel(struct mux_clk *clk) -+{ -+ return readl_relaxed(clk->base + clk->offset); -+} -+ -+static const struct clk_mux_ops kpss_xcc_ops = { -+ .set_mux_sel = kpss_xcc_set_mux_sel, -+ .get_mux_sel = kpss_xcc_get_mux_sel, -+}; -+ -+static const char *aux_parents[] = { -+ "pll8_vote", -+ "pxo", -+}; -+ -+static u8 aux_parent_map[] = { -+ 3, -+ 0, -+}; -+ -+static const struct of_device_id kpss_xcc_match_table[] = { -+ { .compatible = "qcom,kpss-acc-v1", .data = (void *)1UL }, -+ { .compatible = "qcom,kpss-gcc" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, kpss_xcc_match_table); -+ -+static int kpss_xcc_driver_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *id; -+ struct clk *clk; -+ struct resource *res; -+ void __iomem *base; -+ struct mux_clk *mux_clk; -+ struct clk_init_data init = { -+ .parent_names = aux_parents, -+ .num_parents = 2, -+ .ops = &clk_ops_gen_mux, -+ }; -+ -+ id = of_match_device(kpss_xcc_match_table, &pdev->dev); -+ if (!id) -+ return -ENODEV; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ mux_clk = devm_kzalloc(&pdev->dev, sizeof(*mux_clk), GFP_KERNEL); -+ if (!mux_clk) -+ return -ENOMEM; -+ -+ mux_clk->mask = 0x3; -+ mux_clk->parent_map = aux_parent_map; -+ mux_clk->ops = &kpss_xcc_ops; -+ mux_clk->base = base; -+ mux_clk->hw.init = &init; -+ -+ if (id->data) { -+ if (of_property_read_string_index(pdev->dev.of_node, -+ "clock-output-names", 0, &init.name)) -+ return -ENODEV; -+ mux_clk->offset = 0x14; -+ } else { -+ init.name = "acpu_l2_aux"; -+ mux_clk->offset = 0x28; -+ } -+ -+ clk = devm_clk_register(&pdev->dev, &mux_clk->hw); -+ -+ return PTR_ERR_OR_ZERO(clk); -+} -+ -+static struct platform_driver kpss_xcc_driver = { -+ .probe = kpss_xcc_driver_probe, -+ .driver = { -+ .name = "kpss-xcc", -+ .of_match_table = kpss_xcc_match_table, -+ .owner = THIS_MODULE, -+ }, -+}; -+module_platform_driver(kpss_xcc_driver); -+ -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0171-clk-qcom-Add-Krait-clock-controller-driver.patch b/target/linux/ipq806x/patches/0171-clk-qcom-Add-Krait-clock-controller-driver.patch deleted file mode 100644 index 6d0619a8e1..0000000000 --- a/target/linux/ipq806x/patches/0171-clk-qcom-Add-Krait-clock-controller-driver.patch +++ /dev/null @@ -1,410 +0,0 @@ -From 6912e27d97ba5671e8c2434bed0ebd23fde5e13d Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Wed, 18 Jun 2014 14:29:29 -0700 -Subject: [PATCH 171/182] clk: qcom: Add Krait clock controller driver - -The Krait CPU clocks are made up of a primary mux and secondary -mux for each CPU and the L2, controlled via cp15 accessors. For -Kraits within KPSSv1 each secondary mux accepts a different aux -source, but on KPSSv2 each secondary mux accepts the same aux -source. - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/Kconfig | 8 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/krait-cc.c | 364 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 373 insertions(+) - create mode 100644 drivers/clk/qcom/krait-cc.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -70,6 +70,14 @@ config KPSS_XCC - if you want to support CPU frequency scaling on devices such - as MSM8960, APQ8064, etc. - -+config KRAITCC -+ tristate "Krait Clock Controller" -+ depends on COMMON_CLK_QCOM && ARM -+ select KRAIT_CLOCKS -+ help -+ Support for the Krait CPU clocks on Qualcomm devices. -+ Say Y if you want to support CPU frequency scaling. -+ - config KRAIT_CLOCKS - bool - select KRAIT_L2_ACCESSORS ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -19,3 +19,4 @@ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8 - obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o - obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o - obj-$(CONFIG_QCOM_HFPLL) += hfpll.o -+obj-$(CONFIG_KRAITCC) += krait-cc.o ---- /dev/null -+++ b/drivers/clk/qcom/krait-cc.c -@@ -0,0 +1,364 @@ -+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "clk-krait.h" -+ -+DEFINE_FIXED_DIV_CLK(acpu_aux, 2, "gpll0_vote"); -+ -+static u8 sec_mux_map[] = { -+ 2, -+ 0, -+}; -+ -+static u8 pri_mux_map[] = { -+ 1, -+ 2, -+ 0, -+}; -+ -+static int -+krait_add_div(struct device *dev, int id, const char *s, unsigned offset) -+{ -+ struct div_clk *div; -+ struct clk_init_data init = { -+ .num_parents = 1, -+ .ops = &clk_ops_div, -+ .flags = CLK_SET_RATE_PARENT, -+ }; -+ const char *p_names[1]; -+ struct clk *clk; -+ -+ div = devm_kzalloc(dev, sizeof(*dev), GFP_KERNEL); -+ if (!div) -+ return -ENOMEM; -+ -+ div->data.div = 2; -+ div->data.min_div = 2; -+ div->data.max_div = 2; -+ div->ops = &clk_div_ops_kpss_div2; -+ div->mask = 0x3; -+ div->shift = 6; -+ div->priv = (void *)(id >= 0); -+ div->offset = offset; -+ div->hw.init = &init; -+ -+ init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s); -+ if (!init.name) -+ return -ENOMEM; -+ -+ init.parent_names = p_names; -+ p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s); -+ if (!p_names[0]) { -+ kfree(init.name); -+ return -ENOMEM; -+ } -+ -+ clk = devm_clk_register(dev, &div->hw); -+ kfree(p_names[0]); -+ kfree(init.name); -+ -+ return PTR_ERR_OR_ZERO(clk); -+} -+ -+static int -+krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset, -+ bool unique_aux) -+{ -+ struct mux_clk *mux; -+ static const char *sec_mux_list[] = { -+ "acpu_aux", -+ "qsb", -+ }; -+ struct clk_init_data init = { -+ .parent_names = sec_mux_list, -+ .num_parents = ARRAY_SIZE(sec_mux_list), -+ .ops = &clk_ops_gen_mux, -+ .flags = CLK_SET_RATE_PARENT, -+ }; -+ struct clk *clk; -+ -+ mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); -+ if (!mux) -+ return -ENOMEM; -+ -+ mux->offset = offset; -+ mux->priv = (void *)(id >= 0); -+ mux->has_safe_parent = true; -+ mux->safe_sel = 2; -+ mux->ops = &clk_mux_ops_kpss; -+ mux->mask = 0x3; -+ mux->shift = 2; -+ mux->parent_map = sec_mux_map; -+ mux->hw.init = &init; -+ -+ init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); -+ if (!init.name) -+ return -ENOMEM; -+ -+ if (unique_aux) { -+ sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s); -+ if (!sec_mux_list[0]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_aux; -+ } -+ } -+ -+ clk = devm_clk_register(dev, &mux->hw); -+ -+ if (unique_aux) -+ kfree(sec_mux_list[0]); -+err_aux: -+ kfree(init.name); -+ return PTR_ERR_OR_ZERO(clk); -+} -+ -+static struct clk * -+krait_add_pri_mux(struct device *dev, int id, const char * s, unsigned offset) -+{ -+ struct mux_clk *mux; -+ const char *p_names[3]; -+ struct clk_init_data init = { -+ .parent_names = p_names, -+ .num_parents = ARRAY_SIZE(p_names), -+ .ops = &clk_ops_gen_mux, -+ .flags = CLK_SET_RATE_PARENT, -+ }; -+ struct clk *clk; -+ -+ mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); -+ if (!mux) -+ return ERR_PTR(-ENOMEM); -+ -+ mux->has_safe_parent = true; -+ mux->safe_sel = 0; -+ mux->ops = &clk_mux_ops_kpss; -+ mux->mask = 0x3; -+ mux->shift = 0; -+ mux->offset = offset; -+ mux->priv = (void *)(id >= 0); -+ mux->parent_map = pri_mux_map; -+ mux->hw.init = &init; -+ -+ init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s); -+ if (!init.name) -+ return ERR_PTR(-ENOMEM); -+ -+ p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s); -+ if (!p_names[0]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_p0; -+ } -+ -+ p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s); -+ if (!p_names[1]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_p1; -+ } -+ -+ p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); -+ if (!p_names[2]) { -+ clk = ERR_PTR(-ENOMEM); -+ goto err_p2; -+ } -+ -+ clk = devm_clk_register(dev, &mux->hw); -+ -+ kfree(p_names[2]); -+err_p2: -+ kfree(p_names[1]); -+err_p1: -+ kfree(p_names[0]); -+err_p0: -+ kfree(init.name); -+ return clk; -+} -+ -+/* id < 0 for L2, otherwise id == physical CPU number */ -+static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux) -+{ -+ int ret; -+ unsigned offset; -+ void *p = NULL; -+ const char *s; -+ struct clk *clk; -+ -+ if (id >= 0) { -+ offset = 0x4501 + (0x1000 * id); -+ s = p = kasprintf(GFP_KERNEL, "%d", id); -+ if (!s) -+ return ERR_PTR(-ENOMEM); -+ } else { -+ offset = 0x500; -+ s = "_l2"; -+ } -+ -+ ret = krait_add_div(dev, id, s, offset); -+ if (ret) { -+ clk = ERR_PTR(ret); -+ goto err; -+ } -+ -+ ret = krait_add_sec_mux(dev, id, s, offset, unique_aux); -+ if (ret) { -+ clk = ERR_PTR(ret); -+ goto err; -+ } -+ -+ clk = krait_add_pri_mux(dev, id, s, offset); -+err: -+ kfree(p); -+ return clk; -+} -+ -+static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data) -+{ -+ unsigned int idx = clkspec->args[0]; -+ struct clk **clks = data; -+ -+ if (idx >= 5) { -+ pr_err("%s: invalid clock index %d\n", __func__, idx); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ return clks[idx] ? : ERR_PTR(-ENODEV); -+} -+ -+static const struct of_device_id krait_cc_match_table[] = { -+ { .compatible = "qcom,krait-cc-v1", (void *)1UL }, -+ { .compatible = "qcom,krait-cc-v2" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, krait_cc_match_table); -+ -+static int krait_cc_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ const struct of_device_id *id; -+ unsigned long cur_rate, aux_rate; -+ int i, cpu; -+ struct clk *clk; -+ struct clk **clks; -+ struct clk *l2_pri_mux_clk; -+ -+ id = of_match_device(krait_cc_match_table, &pdev->dev); -+ if (!id) -+ return -ENODEV; -+ -+ /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ -+ clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ if (!id->data) { -+ clk = devm_clk_register(dev, &acpu_aux.hw); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ } -+ -+ /* Krait configurations have at most 4 CPUs and one L2 */ -+ clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL); -+ if (!clks) -+ return -ENOMEM; -+ -+ for_each_possible_cpu(i) { -+ cpu = cpu_logical_map(i); -+ clk = krait_add_clks(dev, cpu, id->data); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ clks[cpu] = clk; -+ } -+ -+ l2_pri_mux_clk = krait_add_clks(dev, -1, id->data); -+ if (IS_ERR(l2_pri_mux_clk)) -+ return PTR_ERR(l2_pri_mux_clk); -+ clks[4] = l2_pri_mux_clk; -+ -+ /* -+ * We don't want the CPU or L2 clocks to be turned off at late init -+ * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the -+ * refcount of these clocks. Any cpufreq/hotplug manager can assume -+ * that the clocks have already been prepared and enabled by the time -+ * they take over. -+ */ -+ for_each_online_cpu(i) { -+ cpu = cpu_logical_map(i); -+ clk_prepare_enable(l2_pri_mux_clk); -+ WARN(clk_prepare_enable(clks[cpu]), -+ "Unable to turn on CPU%d clock", cpu); -+ } -+ -+ /* -+ * Force reinit of HFPLLs and muxes to overwrite any potential -+ * incorrect configuration of HFPLLs and muxes by the bootloader. -+ * While at it, also make sure the cores are running at known rates -+ * and print the current rate. -+ * -+ * The clocks are set to aux clock rate first to make sure the -+ * secondary mux is not sourcing off of QSB. The rate is then set to -+ * two different rates to force a HFPLL reinit under all -+ * circumstances. -+ */ -+ cur_rate = clk_get_rate(l2_pri_mux_clk); -+ aux_rate = 384000000; -+ if (cur_rate == 1) { -+ pr_info("L2 @ QSB rate. Forcing new rate.\n"); -+ cur_rate = aux_rate; -+ } -+ clk_set_rate(l2_pri_mux_clk, aux_rate); -+ clk_set_rate(l2_pri_mux_clk, 2); -+ clk_set_rate(l2_pri_mux_clk, cur_rate); -+ pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000); -+ for_each_possible_cpu(i) { -+ cpu = cpu_logical_map(i); -+ clk = clks[cpu]; -+ cur_rate = clk_get_rate(clk); -+ if (cur_rate == 1) { -+ pr_info("CPU%d @ QSB rate. Forcing new rate.\n", i); -+ cur_rate = aux_rate; -+ } -+ clk_set_rate(clk, aux_rate); -+ clk_set_rate(clk, 2); -+ clk_set_rate(clk, cur_rate); -+ pr_info("CPU%d @ %lu KHz\n", i, clk_get_rate(clk) / 1000); -+ } -+ -+ of_clk_add_provider(dev->of_node, krait_of_get, clks); -+ -+ return 0; -+} -+ -+static struct platform_driver krait_cc_driver = { -+ .probe = krait_cc_probe, -+ .driver = { -+ .name = "clock-krait", -+ .of_match_table = krait_cc_match_table, -+ .owner = THIS_MODULE, -+ }, -+}; -+module_platform_driver(krait_cc_driver); -+ -+MODULE_DESCRIPTION("Krait CPU Clock Driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0172-cpufreq-Add-a-cpufreq-krait-based-on-cpufreq-cpu0.patch b/target/linux/ipq806x/patches/0172-cpufreq-Add-a-cpufreq-krait-based-on-cpufreq-cpu0.patch deleted file mode 100644 index ea07fc1d2f..0000000000 --- a/target/linux/ipq806x/patches/0172-cpufreq-Add-a-cpufreq-krait-based-on-cpufreq-cpu0.patch +++ /dev/null @@ -1,245 +0,0 @@ -From 5cf343c60d7557aefb468603065cac5062f11b8d Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 30 May 2014 16:36:11 -0700 -Subject: [PATCH 172/182] cpufreq: Add a cpufreq-krait based on cpufreq-cpu0 - -Krait processors have individual clocks for each CPU that can -scale independently from one another. cpufreq-cpu0 is fairly -close to this, but assumes that there is only one clock for all -CPUs. Add a driver to support the Krait configuration. - -TODO: Merge into cpufreq-cpu0? Or make generic? - -Signed-off-by: Stephen Boyd ---- - drivers/cpufreq/Kconfig | 13 +++ - drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/cpufreq-krait.c | 190 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 204 insertions(+) - create mode 100644 drivers/cpufreq/cpufreq-krait.c - ---- a/drivers/cpufreq/Kconfig -+++ b/drivers/cpufreq/Kconfig -@@ -194,6 +194,19 @@ config GENERIC_CPUFREQ_CPU0 - - If in doubt, say N. - -+config GENERIC_CPUFREQ_KRAIT -+ tristate "Krait cpufreq driver" -+ depends on HAVE_CLK && OF -+ # if CPU_THERMAL is on and THERMAL=m, CPU0 cannot be =y: -+ depends on !CPU_THERMAL || THERMAL -+ select PM_OPP -+ help -+ This adds a generic cpufreq driver for CPU0 frequency management. -+ It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) -+ systems which share clock and voltage across all CPUs. -+ -+ If in doubt, say N. -+ - menu "x86 CPU frequency scaling drivers" - depends on X86 - source "drivers/cpufreq/Kconfig.x86" ---- a/drivers/cpufreq/Makefile -+++ b/drivers/cpufreq/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) - obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o - - obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o -+obj-$(CONFIG_GENERIC_CPUFREQ_KRAIT) += cpufreq-krait.o - - ################################################################################## - # x86 drivers. ---- /dev/null -+++ b/drivers/cpufreq/cpufreq-krait.c -@@ -0,0 +1,190 @@ -+/* -+ * Copyright (C) 2012 Freescale Semiconductor, Inc. -+ * Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * The OPP code in function krait_set_target() is reused from -+ * drivers/cpufreq/omap-cpufreq.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static unsigned int transition_latency; -+ -+static struct device *cpu_dev; -+static DEFINE_PER_CPU(struct clk *, krait_cpu_clks); -+static struct cpufreq_frequency_table *freq_table; -+static struct thermal_cooling_device *cdev; -+ -+static int krait_set_target(struct cpufreq_policy *policy, unsigned int index) -+{ -+ unsigned long volt = 0, volt_old = 0; -+ unsigned int old_freq, new_freq; -+ long freq_Hz, freq_exact; -+ int ret; -+ struct clk *cpu_clk; -+ -+ cpu_clk = per_cpu(krait_cpu_clks, policy->cpu); -+ -+ freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); -+ if (freq_Hz <= 0) -+ freq_Hz = freq_table[index].frequency * 1000; -+ -+ freq_exact = freq_Hz; -+ new_freq = freq_Hz / 1000; -+ old_freq = clk_get_rate(cpu_clk) / 1000; -+ -+ pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n", -+ old_freq / 1000, volt_old ? volt_old / 1000 : -1, -+ new_freq / 1000, volt ? volt / 1000 : -1); -+ -+ ret = clk_set_rate(cpu_clk, freq_exact); -+ if (ret) -+ pr_err("failed to set clock rate: %d\n", ret); -+ -+ return ret; -+} -+ -+static int krait_cpufreq_init(struct cpufreq_policy *policy) -+{ -+ int ret; -+ -+ policy->clk = per_cpu(krait_cpu_clks, policy->cpu); -+ -+ ret = cpufreq_table_validate_and_show(policy, freq_table); -+ if (ret) { -+ pr_err("%s: invalid frequency table: %d\n", __func__, ret); -+ return ret; -+ } -+ -+ policy->cpuinfo.transition_latency = transition_latency; -+ -+ return 0; -+} -+ -+static struct cpufreq_driver krait_cpufreq_driver = { -+ .flags = CPUFREQ_STICKY, -+ .verify = cpufreq_generic_frequency_table_verify, -+ .target_index = krait_set_target, -+ .get = cpufreq_generic_get, -+ .init = krait_cpufreq_init, -+ .name = "generic_krait", -+ .attr = cpufreq_generic_attr, -+}; -+ -+static int krait_cpufreq_probe(struct platform_device *pdev) -+{ -+ struct device_node *np; -+ int ret; -+ unsigned int cpu; -+ struct device *dev; -+ struct clk *clk; -+ -+ cpu_dev = get_cpu_device(0); -+ if (!cpu_dev) { -+ pr_err("failed to get krait device\n"); -+ return -ENODEV; -+ } -+ -+ np = of_node_get(cpu_dev->of_node); -+ if (!np) { -+ pr_err("failed to find krait node\n"); -+ return -ENOENT; -+ } -+ -+ for_each_possible_cpu(cpu) { -+ dev = get_cpu_device(cpu); -+ if (!dev) { -+ pr_err("failed to get krait device\n"); -+ ret = -ENOENT; -+ goto out_put_node; -+ } -+ per_cpu(krait_cpu_clks, cpu) = clk = devm_clk_get(dev, NULL); -+ if (IS_ERR(clk)) { -+ ret = PTR_ERR(clk); -+ goto out_put_node; -+ } -+ } -+ -+ ret = of_init_opp_table(cpu_dev); -+ if (ret) { -+ pr_err("failed to init OPP table: %d\n", ret); -+ goto out_put_node; -+ } -+ -+ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); -+ if (ret) { -+ pr_err("failed to init cpufreq table: %d\n", ret); -+ goto out_put_node; -+ } -+ -+ if (of_property_read_u32(np, "clock-latency", &transition_latency)) -+ transition_latency = CPUFREQ_ETERNAL; -+ -+ ret = cpufreq_register_driver(&krait_cpufreq_driver); -+ if (ret) { -+ pr_err("failed register driver: %d\n", ret); -+ goto out_free_table; -+ } -+ of_node_put(np); -+ -+ /* -+ * For now, just loading the cooling device; -+ * thermal DT code takes care of matching them. -+ */ -+ for_each_possible_cpu(cpu) { -+ dev = get_cpu_device(cpu); -+ np = of_node_get(dev->of_node); -+ if (of_find_property(np, "#cooling-cells", NULL)) { -+ cdev = of_cpufreq_cooling_register(np, cpumask_of(cpu)); -+ if (IS_ERR(cdev)) -+ pr_err("running cpufreq without cooling device: %ld\n", -+ PTR_ERR(cdev)); -+ } -+ of_node_put(np); -+ } -+ -+ return 0; -+ -+out_free_table: -+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); -+out_put_node: -+ of_node_put(np); -+ return ret; -+} -+ -+static int krait_cpufreq_remove(struct platform_device *pdev) -+{ -+ cpufreq_cooling_unregister(cdev); -+ cpufreq_unregister_driver(&krait_cpufreq_driver); -+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); -+ -+ return 0; -+} -+ -+static struct platform_driver krait_cpufreq_platdrv = { -+ .driver = { -+ .name = "cpufreq-krait", -+ .owner = THIS_MODULE, -+ }, -+ .probe = krait_cpufreq_probe, -+ .remove = krait_cpufreq_remove, -+}; -+module_platform_driver(krait_cpufreq_platdrv); -+ -+MODULE_DESCRIPTION("Krait CPUfreq driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0173-cpufreq-Add-module-to-register-cpufreq-krait-device.patch b/target/linux/ipq806x/patches/0173-cpufreq-Add-module-to-register-cpufreq-krait-device.patch deleted file mode 100644 index 373c402959..0000000000 --- a/target/linux/ipq806x/patches/0173-cpufreq-Add-module-to-register-cpufreq-krait-device.patch +++ /dev/null @@ -1,94 +0,0 @@ -From f1db56284b01b1212a211023dcaa7846fd07d0ec Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Fri, 30 May 2014 17:16:53 -0700 -Subject: [PATCH 173/182] cpufreq: Add module to register cpufreq-krait device - -Register a cpufreq-krait device whenever we detect that a -"qcom,krait" compatible CPU is present in DT. - -Signed-off-by: Stephen Boyd ---- - drivers/cpufreq/Kconfig.arm | 8 +++++++ - drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/qcom-cpufreq.c | 48 ++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 57 insertions(+) - create mode 100644 drivers/cpufreq/qcom-cpufreq.c - ---- a/drivers/cpufreq/Kconfig.arm -+++ b/drivers/cpufreq/Kconfig.arm -@@ -123,6 +123,14 @@ config ARM_OMAP2PLUS_CPUFREQ - depends on ARCH_OMAP2PLUS - default ARCH_OMAP2PLUS - -+config ARM_QCOM_CPUFREQ -+ tristate "Qualcomm based" -+ depends on ARCH_QCOM -+ help -+ This adds the CPUFreq driver for Qualcomm SoC based boards. -+ -+ If in doubt, say N. -+ - config ARM_S3C_CPUFREQ - bool - help ---- a/drivers/cpufreq/Makefile -+++ b/drivers/cpufreq/Makefile -@@ -60,6 +60,7 @@ obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6 - obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o - obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o - obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o -+obj-$(CONFIG_ARM_QCOM_CPUFREQ) += qcom-cpufreq.o - obj-$(CONFIG_PXA25x) += pxa2xx-cpufreq.o - obj-$(CONFIG_PXA27x) += pxa2xx-cpufreq.o - obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o ---- /dev/null -+++ b/drivers/cpufreq/qcom-cpufreq.c -@@ -0,0 +1,48 @@ -+/* Copyright (c) 2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+ -+static int qcom_cpufreq_driver_init(void) -+{ -+ struct platform_device_info devinfo = { .name = "cpufreq-krait", }; -+ struct device *cpu_dev; -+ struct device_node *np; -+ struct platform_device *pdev; -+ -+ cpu_dev = get_cpu_device(0); -+ if (!cpu_dev) -+ return -ENODEV; -+ -+ np = of_node_get(cpu_dev->of_node); -+ if (!np) -+ return -ENOENT; -+ -+ if (!of_device_is_compatible(np, "qcom,krait")) { -+ of_node_put(np); -+ return -ENODEV; -+ } -+ of_node_put(np); -+ -+ pdev = platform_device_register_full(&devinfo); -+ -+ return PTR_ERR_OR_ZERO(pdev); -+} -+module_init(qcom_cpufreq_driver_init); -+ -+MODULE_DESCRIPTION("Qualcomm CPUfreq driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0174-clk-qcom-Add-HFPLLs-to-IPQ806X-driver.patch b/target/linux/ipq806x/patches/0174-clk-qcom-Add-HFPLLs-to-IPQ806X-driver.patch deleted file mode 100644 index 682a519d3e..0000000000 --- a/target/linux/ipq806x/patches/0174-clk-qcom-Add-HFPLLs-to-IPQ806X-driver.patch +++ /dev/null @@ -1,116 +0,0 @@ -From b9b3815f2a71af88ca68d3524ee4d9b6b4739257 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Wed, 18 Jun 2014 15:57:06 -0700 -Subject: [PATCH 174/182] clk: qcom: Add HFPLLs to IPQ806X driver - -Signed-off-by: Stephen Boyd ---- - drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 83 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq806x.c -+++ b/drivers/clk/qcom/gcc-ipq806x.c -@@ -30,6 +30,7 @@ - #include "clk-pll.h" - #include "clk-rcg.h" - #include "clk-branch.h" -+#include "clk-hfpll.h" - #include "reset.h" - - static struct clk_pll pll0 = { -@@ -102,6 +103,85 @@ static struct clk_regmap pll8_vote = { - }, - }; - -+static struct hfpll_data hfpll0_data = { -+ .mode_reg = 0x3200, -+ .l_reg = 0x3208, -+ .m_reg = 0x320c, -+ .n_reg = 0x3210, -+ .config_reg = 0x3204, -+ .status_reg = 0x321c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3214, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll0 = { -+ .d = &hfpll0_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll0", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock), -+}; -+ -+static struct hfpll_data hfpll1_data = { -+ .mode_reg = 0x3240, -+ .l_reg = 0x3248, -+ .m_reg = 0x324c, -+ .n_reg = 0x3250, -+ .config_reg = 0x3244, -+ .status_reg = 0x325c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3314, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll1 = { -+ .d = &hfpll1_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll1", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock), -+}; -+ -+static struct hfpll_data hfpll_l2_data = { -+ .mode_reg = 0x3300, -+ .l_reg = 0x3308, -+ .m_reg = 0x330c, -+ .n_reg = 0x3310, -+ .config_reg = 0x3304, -+ .status_reg = 0x331c, -+ .config_val = 0x7845c665, -+ .droop_reg = 0x3314, -+ .droop_val = 0x0108c000, -+ .min_rate = 600000000UL, -+ .max_rate = 1800000000UL, -+}; -+ -+static struct clk_hfpll hfpll_l2 = { -+ .d = &hfpll_l2_data, -+ .clkr.hw.init = &(struct clk_init_data){ -+ .parent_names = (const char *[]){ "pxo" }, -+ .num_parents = 1, -+ .name = "hfpll_l2", -+ .ops = &clk_ops_hfpll, -+ .flags = CLK_IGNORE_UNUSED, -+ }, -+ .lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock), -+}; -+ -+ - static struct clk_pll pll14 = { - .l_reg = 0x31c4, - .m_reg = 0x31c8, -@@ -2878,6 +2958,9 @@ static struct clk_regmap *gcc_ipq806x_cl - [NSSTCM_CLK_SRC] = &nss_tcm_src.clkr, - [NSSTCM_CLK] = &nss_tcm_clk.clkr, - [NSS_CORE_CLK] = &nss_core_clk, -+ [PLL9] = &hfpll0.clkr, -+ [PLL10] = &hfpll1.clkr, -+ [PLL12] = &hfpll_l2.clkr, - }; - - static const struct qcom_reset_map gcc_ipq806x_resets[] = { diff --git a/target/linux/ipq806x/patches/0175-ARM-dts-ipq8064-Add-necessary-DT-data-for-Krait-cpuf.patch b/target/linux/ipq806x/patches/0175-ARM-dts-ipq8064-Add-necessary-DT-data-for-Krait-cpuf.patch deleted file mode 100644 index 3fddd61424..0000000000 --- a/target/linux/ipq806x/patches/0175-ARM-dts-ipq8064-Add-necessary-DT-data-for-Krait-cpuf.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 258a3ea23ec048603debe1621c681b0cc733f236 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Wed, 18 Jun 2014 16:04:37 -0700 -Subject: [PATCH 175/182] ARM: dts: ipq8064: Add necessary DT data for Krait - cpufreq - -Signed-off-by: Stephen Boyd ---- - arch/arm/boot/dts/qcom-ipq8064.dtsi | 45 +++++++++++++++++++++++++++++++++++ - 1 file changed, 45 insertions(+) - ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -23,6 +23,22 @@ - next-level-cache = <&L2>; - qcom,acc = <&acc0>; - qcom,saw = <&saw0>; -+ clocks = <&kraitcc 0>; -+ clock-names = "cpu"; -+ operating-points = < -+ /* kHz ignored */ -+ 1400000 1000000 -+ 1200000 1000000 -+ 1000000 1000000 -+ 800000 1000000 -+ 600000 1000000 -+ 384000 1000000 -+ >; -+ clock-latency = <100000>; -+ -+ cooling-min-state = <0>; -+ cooling-max-state = <10>; -+ #cooling-cells = <2>; - }; - - cpu@1 { -@@ -33,6 +49,22 @@ - next-level-cache = <&L2>; - qcom,acc = <&acc1>; - qcom,saw = <&saw1>; -+ clocks = <&kraitcc 1>; -+ clock-names = "cpu"; -+ operating-points = < -+ /* kHz ignored */ -+ 1400000 1000000 -+ 1200000 1000000 -+ 1000000 1000000 -+ 800000 1000000 -+ 600000 1000000 -+ 384000 1000000 -+ >; -+ clock-latency = <100000>; -+ -+ cooling-min-state = <0>; -+ cooling-max-state = <10>; -+ #cooling-cells = <2>; - }; - - L2: l2-cache { -@@ -46,6 +78,11 @@ - interrupts = <1 10 0x304>; - }; - -+ kraitcc: clock-controller { -+ compatible = "qcom,krait-cc-v1"; -+ #clock-cells = <1>; -+ }; -+ - reserved-memory { - #address-cells = <1>; - #size-cells = <1>; -@@ -102,11 +139,19 @@ - acc0: clock-controller@2088000 { - compatible = "qcom,kpss-acc-v1"; - reg = <0x02088000 0x1000>, <0x02008000 0x1000>; -+ clock-output-names = "acpu0_aux"; - }; - - acc1: clock-controller@2098000 { - compatible = "qcom,kpss-acc-v1"; - reg = <0x02098000 0x1000>, <0x02008000 0x1000>; -+ clock-output-names = "acpu1_aux"; -+ }; -+ -+ l2cc: clock-controller@2011000 { -+ compatible = "qcom,kpss-gcc"; -+ reg = <0x2011000 0x1000>; -+ clock-output-names = "acpu_l2_aux"; - }; - - saw0: regulator@2089000 { diff --git a/target/linux/ipq806x/patches/0176-ARM-qcom_defconfig-Enable-CPUfreq-options.patch b/target/linux/ipq806x/patches/0176-ARM-qcom_defconfig-Enable-CPUfreq-options.patch deleted file mode 100644 index 188580a33e..0000000000 --- a/target/linux/ipq806x/patches/0176-ARM-qcom_defconfig-Enable-CPUfreq-options.patch +++ /dev/null @@ -1,39 +0,0 @@ -From e8f4d4bf1e4974bf8d17c6702fa4c410637216f3 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Mon, 30 Jun 2014 10:50:14 -0700 -Subject: [PATCH 176/182] ARM: qcom_defconfig: Enable CPUfreq options - -Enable required options to allow the CPUfreq driver to probe on -Krait based platforms. - -Signed-off-by: Stephen Boyd ---- - arch/arm/configs/qcom_defconfig | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/arch/arm/configs/qcom_defconfig -+++ b/arch/arm/configs/qcom_defconfig -@@ -31,6 +31,13 @@ CONFIG_HIGHPTE=y - CONFIG_CLEANCACHE=y - CONFIG_ARM_APPENDED_DTB=y - CONFIG_ARM_ATAG_DTB_COMPAT=y -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_GENERIC_CPUFREQ_KRAIT=y -+CONFIG_ARM_QCOM_CPUFREQ=y - CONFIG_CPU_IDLE=y - CONFIG_VFP=y - CONFIG_NEON=y -@@ -149,6 +156,9 @@ CONFIG_IPQ_GCC_806X=y - CONFIG_MSM_GCC_8660=y - CONFIG_MSM_MMCC_8960=y - CONFIG_MSM_MMCC_8974=y -+CONFIG_QCOM_HFPLL=y -+CONFIG_KPSS_XCC=y -+CONFIG_KRAITCC=y - CONFIG_MSM_IOMMU=y - CONFIG_PHY_QCOM_IPQ806X_SATA=y - CONFIG_EXT2_FS=y diff --git a/target/linux/ipq806x/patches/0177-dmaengine-Add-QCOM-ADM-DMA-driver.patch b/target/linux/ipq806x/patches/0177-dmaengine-Add-QCOM-ADM-DMA-driver.patch deleted file mode 100644 index 05c67060c0..0000000000 --- a/target/linux/ipq806x/patches/0177-dmaengine-Add-QCOM-ADM-DMA-driver.patch +++ /dev/null @@ -1,921 +0,0 @@ -From 8984e3fc6db029479d6aa78882b39235379aebff Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Wed, 14 May 2014 13:45:07 -0500 -Subject: [PATCH 177/182] dmaengine: Add QCOM ADM DMA driver - -Add the DMA engine driver for the QCOM Application Data Mover (ADM) DMA -controller found in the MSM8960 and IPQ/APQ8064 platforms. - -The ADM supports both memory to memory transactions and memory -to/from peripheral device transactions. The controller also provides flow -control capabilities for transactions to/from peripheral devices. - -The initial release of this driver supports slave transfers to/from peripherals -and also incorporates CRCI (client rate control interface) flow control. - -Signed-off-by: Andy Gross ---- - drivers/dma/Kconfig | 10 + - drivers/dma/Makefile | 1 + - drivers/dma/qcom_adm.c | 871 ++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 882 insertions(+) - create mode 100644 drivers/dma/qcom_adm.c - ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -410,4 +410,14 @@ config QCOM_BAM_DMA - Enable support for the QCOM BAM DMA controller. This controller - provides DMA capabilities for a variety of on-chip devices. - -+config QCOM_ADM -+ tristate "Qualcomm ADM support" -+ depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM) -+ select DMA_ENGINE -+ select DMA_VIRTUAL_CHANNELS -+ ---help--- -+ Enable support for the Qualcomm ADM DMA controller. This controller -+ provides DMA capabilities for both general purpose and on-chip -+ peripheral devices. -+ - endif ---- a/drivers/dma/Makefile -+++ b/drivers/dma/Makefile -@@ -46,3 +46,4 @@ obj-$(CONFIG_K3_DMA) += k3dma.o - obj-$(CONFIG_MOXART_DMA) += moxart-dma.o - obj-$(CONFIG_FSL_EDMA) += fsl-edma.o - obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o -+obj-$(CONFIG_QCOM_ADM) += qcom_adm.o ---- /dev/null -+++ b/drivers/dma/qcom_adm.c -@@ -0,0 +1,871 @@ -+/* -+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 and -+ * only 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dmaengine.h" -+#include "virt-dma.h" -+ -+/* ADM registers - calculated from channel number and security domain */ -+#define HI_CH_CMD_PTR(chan, ee) (4*chan + 0x20800*ee) -+#define HI_CH_RSLT(chan, ee) (0x40 + 4*chan + 0x20800*ee) -+#define HI_CH_FLUSH_STATE0(chan, ee) (0x80 + 4*chan + 0x20800*ee) -+#define HI_CH_FLUSH_STATE1(chan, ee) (0xc0 + 4*chan + 0x20800*ee) -+#define HI_CH_FLUSH_STATE2(chan, ee) (0x100 + 4*chan + 0x20800*ee) -+#define HI_CH_FLUSH_STATE3(chan, ee) (0x140 + 4*chan + 0x20800*ee) -+#define HI_CH_FLUSH_STATE4(chan, ee) (0x180 + 4*chan + 0x20800*ee) -+#define HI_CH_FLUSH_STATE5(chan, ee) (0x1c0 + 4*chan + 0x20800*ee) -+#define HI_CH_STATUS_SD(chan, ee) (0x200 + 4*chan + 0x20800*ee) -+#define HI_CH_CONF(chan) (0x240 + 4*chan) -+#define HI_CH_RSLT_CONF(chan, ee) (0x300 + 4*chan + 0x20800*ee) -+#define HI_SEC_DOMAIN_IRQ_STATUS(ee) (0x380 + 0x20800*ee) -+#define HI_CI_CONF(ci) (0x390 + 4*ci) -+#define HI_CRCI_CONF0 0x3d0 -+#define HI_CRCI_CONF1 0x3d4 -+#define HI_GP_CTL 0x3d8 -+#define HI_CRCI_CTL(chan, ee) (0x400 + 0x4*chan + 0x20800*ee) -+ -+/* channel status */ -+#define CH_STATUS_VALID BIT(1) -+ -+/* channel result */ -+#define CH_RSLT_VALID BIT(31) -+#define CH_RSLT_ERR BIT(3) -+#define CH_RSLT_FLUSH BIT(2) -+#define CH_RSLT_TPD BIT(1) -+ -+/* channel conf */ -+#define CH_CONF_MPU_DISABLE BIT(11) -+#define CH_CONF_PERM_MPU_CONF BIT(9) -+#define CH_CONF_FLUSH_RSLT_EN BIT(8) -+#define CH_CONF_FORCE_RSLT_EN BIT(7) -+#define CH_CONF_IRQ_EN BIT(6) -+ -+/* channel result conf */ -+#define CH_RSLT_CONF_FLUSH_EN BIT(1) -+#define CH_RSLT_CONF_IRQ_EN BIT(0) -+ -+/* CRCI CTL */ -+#define CRCI_CTL_RST BIT(17) -+ -+/* CI configuration */ -+#define CI_RANGE_END(x) (x << 24) -+#define CI_RANGE_START(x) (x << 16) -+#define CI_BURST_4_WORDS 0x4 -+#define CI_BURST_8_WORDS 0x8 -+ -+/* GP CTL */ -+#define GP_CTL_LP_EN BIT(12) -+#define GP_CTL_LP_CNT(x) (x << 8) -+ -+/* Command pointer list entry */ -+#define CPLE_LP BIT(31) -+ -+/* Command list entry */ -+#define CMD_LC BIT(31) -+#define CMD_DST_CRCI(n) (((n) & 0xf) << 7) -+#define CMD_SRC_CRCI(n) (((n) & 0xf) << 3) -+ -+#define CMD_TYPE_SINGLE 0x0 -+#define CMD_TYPE_BOX 0x3 -+ -+#define ADM_DESC_ALIGN 8 -+#define ADM_MAX_XFER (SZ_64K-1) -+#define ADM_MAX_ROWS (SZ_64K-1) -+ -+/* Command Pointer List Entry */ -+#define CMD_LP BIT(31) -+#define CMD_PT_MASK (0x3 << 29) -+#define CMD_ADDR_MASK 0x3fffffff -+ -+struct adm_desc_hw { -+ u32 cmd; -+ u32 src_addr; -+ u32 dst_addr; -+ u32 row_len; -+ u32 num_rows; -+ u32 row_offset; -+}; -+ -+struct adm_cmd_ptr_list { -+ u32 cple; /* command ptr list entry */ -+ struct adm_desc_hw desc[0]; -+}; -+ -+struct adm_async_desc { -+ struct virt_dma_desc vd; -+ struct adm_device *adev; -+ -+ size_t length; -+ enum dma_transfer_direction dir; -+ dma_addr_t dma_addr; -+ size_t dma_len; -+ -+ struct adm_cmd_ptr_list *cpl; -+ u32 num_desc; -+}; -+ -+struct adm_chan { -+ struct virt_dma_chan vc; -+ struct adm_device *adev; -+ -+ /* parsed from DT */ -+ u32 id; /* channel id */ -+ u32 crci; /* CRCI to be used for transfers */ -+ u32 blk_size; /* block size for CRCI, default 16 byte */ -+ -+ struct adm_async_desc *curr_txd; -+ struct dma_slave_config slave; -+ struct list_head node; -+ -+ int error; -+ int initialized; -+}; -+ -+static inline struct adm_chan *to_adm_chan(struct dma_chan *common) -+{ -+ return container_of(common, struct adm_chan, vc.chan); -+} -+ -+struct adm_device { -+ void __iomem *regs; -+ struct device *dev; -+ struct dma_device common; -+ struct device_dma_parameters dma_parms; -+ struct adm_chan *channels; -+ u32 num_channels; -+ -+ u32 ee; -+ -+ struct clk *core_clk; -+ struct clk *iface_clk; -+ -+ struct reset_control *clk_reset; -+ struct reset_control *c0_reset; -+ struct reset_control *c1_reset; -+ struct reset_control *c2_reset; -+ int irq; -+}; -+ -+/** -+ * adm_alloc_chan - Allocates channel resources for DMA channel -+ * -+ * This function is effectively a stub, as we don't need to setup any resources -+ */ -+static int adm_alloc_chan(struct dma_chan *chan) -+{ -+ return 0; -+} -+ -+/** -+ * adm_free_chan - Frees dma resources associated with the specific channel -+ * -+ * Free all allocated descriptors associated with this channel -+ * -+ */ -+static void adm_free_chan(struct dma_chan *chan) -+{ -+ /* free all queued descriptors */ -+ vchan_free_chan_resources(to_virt_chan(chan)); -+} -+ -+/** -+ * adm_prep_slave_sg - Prep slave sg transaction -+ * -+ * @chan: dma channel -+ * @sgl: scatter gather list -+ * @sg_len: length of sg -+ * @direction: DMA transfer direction -+ * @flags: DMA flags -+ * @context: transfer context (unused) -+ */ -+static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan, -+ struct scatterlist *sgl, unsigned int sg_len, -+ enum dma_transfer_direction direction, unsigned long flags, -+ void *context) -+{ -+ struct adm_chan *achan = to_adm_chan(chan); -+ struct adm_device *adev = achan->adev; -+ struct adm_async_desc *async_desc; -+ struct scatterlist *sg; -+ u32 i, rows, num_desc = 0, idx = 0, desc_offset; -+ struct adm_desc_hw *desc; -+ struct adm_cmd_ptr_list *cpl; -+ u32 burst = ADM_MAX_XFER; -+ -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(adev->dev, "invalid dma direction\n"); -+ return NULL; -+ } -+ -+ /* if using CRCI flow control, validate burst settings */ -+ if (achan->slave.device_fc) { -+ burst = (direction == DMA_MEM_TO_DEV) ? -+ achan->slave.dst_maxburst : -+ achan->slave.src_maxburst; -+ -+ if (!burst) { -+ dev_err(adev->dev, "invalid burst value w/ crci: %d\n", -+ burst); -+ return ERR_PTR(-EINVAL); -+ } -+ } -+ -+ /* iterate through sgs and compute allocation size of structures */ -+ for_each_sg(sgl, sg, sg_len, i) { -+ -+ /* calculate boxes using burst */ -+ rows = DIV_ROUND_UP(sg_dma_len(sg), burst); -+ num_desc += DIV_ROUND_UP(rows, ADM_MAX_ROWS); -+ -+ /* flow control requires length as a multiple of burst */ -+ if (achan->slave.device_fc && (sg_dma_len(sg) % burst)) { -+ dev_err(adev->dev, "length is not multiple of burst\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ } -+ -+ async_desc = kzalloc(sizeof(*async_desc), GFP_NOWAIT); -+ if (!async_desc) -+ return ERR_PTR(-ENOMEM); -+ -+ async_desc->dma_len = num_desc * sizeof(*desc) + sizeof(*cpl) + -+ ADM_DESC_ALIGN; -+ async_desc->cpl = dma_alloc_writecombine(adev->dev, async_desc->dma_len, -+ &async_desc->dma_addr, GFP_NOWAIT); -+ -+ if (!async_desc->cpl) { -+ kfree(async_desc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ async_desc->num_desc = num_desc; -+ async_desc->adev = adev; -+ cpl = PTR_ALIGN(async_desc->cpl, ADM_DESC_ALIGN); -+ desc = PTR_ALIGN(&cpl->desc[0], ADM_DESC_ALIGN); -+ desc_offset = (u32)desc - (u32)async_desc->cpl; -+ -+ /* init cmd list */ -+ cpl->cple |= CPLE_LP; -+ cpl->cple |= (async_desc->dma_addr + desc_offset) >> 3; -+ -+ for_each_sg(sgl, sg, sg_len, i) { -+ unsigned int remainder = sg_dma_len(sg); -+ unsigned int curr_offset = 0; -+ unsigned int row_len; -+ -+ do { -+ desc[idx].cmd = CMD_TYPE_BOX; -+ desc[idx].row_offset = 0; -+ -+ if (direction == DMA_DEV_TO_MEM) { -+ desc[idx].dst_addr = sg_dma_address(sg) + -+ curr_offset; -+ desc[idx].src_addr = achan->slave.src_addr; -+ desc[idx].cmd |= CMD_SRC_CRCI(achan->crci); -+ desc[idx].row_offset = burst; -+ } else { -+ desc[idx].src_addr = sg_dma_address(sg) + -+ curr_offset; -+ desc[idx].dst_addr = achan->slave.dst_addr; -+ desc[idx].cmd |= CMD_DST_CRCI(achan->crci); -+ desc[idx].row_offset = burst << 16; -+ } -+ -+ if (remainder < burst) { -+ rows = 1; -+ row_len = remainder; -+ } else { -+ rows = remainder / burst; -+ rows = min_t(u32, rows, ADM_MAX_ROWS); -+ row_len = burst; -+ } -+ -+ desc[idx].num_rows = rows << 16 | rows; -+ desc[idx].row_len = row_len << 16 | row_len; -+ -+ remainder -= row_len * rows; -+ async_desc->length += row_len * rows; -+ curr_offset += row_len * rows; -+ -+ idx++; -+ } while (remainder > 0); -+ } -+ -+ /* set last command flag */ -+ desc[idx - 1].cmd |= CMD_LC; -+ -+ /* reset channel error */ -+ achan->error = 0; -+ -+ return vchan_tx_prep(&achan->vc, &async_desc->vd, flags); -+} -+ -+/** -+ * adm_slave_config - set slave configuration for channel -+ * @chan: dma channel -+ * @cfg: slave configuration -+ * -+ * Sets slave configuration for channel -+ * -+ */ -+static int adm_slave_config(struct adm_chan *achan, -+ struct dma_slave_config *cfg) -+{ -+ int ret = 0; -+ u32 burst; -+ struct adm_device *adev = achan->adev; -+ -+ memcpy(&achan->slave, cfg, sizeof(*cfg)); -+ -+ /* set channel CRCI burst, if applicable */ -+ if (achan->crci) { -+ burst = max_t(u32, cfg->src_maxburst, cfg->dst_maxburst); -+ -+ switch (burst) { -+ case 16: -+ achan->blk_size = 0; -+ break; -+ case 32: -+ achan->blk_size = 1; -+ break; -+ case 64: -+ achan->blk_size = 2; -+ break; -+ case 128: -+ achan->blk_size = 3; -+ break; -+ case 192: -+ achan->blk_size = 4; -+ break; -+ case 256: -+ achan->blk_size = 5; -+ break; -+ default: -+ achan->slave.src_maxburst = 0; -+ achan->slave.dst_maxburst = 0; -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (!ret) -+ writel(achan->blk_size, -+ adev->regs + HI_CRCI_CTL(achan->id, adev->ee)); -+ } -+ -+ return ret; -+} -+ -+/** -+ * adm_terminate_all - terminate all transactions on a channel -+ * @achan: adm dma channel -+ * -+ * Dequeues and frees all transactions, aborts current transaction -+ * No callbacks are done -+ * -+ */ -+static void adm_terminate_all(struct adm_chan *achan) -+{ -+ struct adm_device *adev = achan->adev; -+ unsigned long flags; -+ LIST_HEAD(head); -+ -+ /* send flush command to terminate current transaction */ -+ writel_relaxed(0x0, -+ adev->regs + HI_CH_FLUSH_STATE0(achan->id, adev->ee)); -+ -+ spin_lock_irqsave(&achan->vc.lock, flags); -+ vchan_get_all_descriptors(&achan->vc, &head); -+ spin_unlock_irqrestore(&achan->vc.lock, flags); -+ -+ vchan_dma_desc_free_list(&achan->vc, &head); -+} -+ -+/** -+ * adm_control - DMA device control -+ * @chan: dma channel -+ * @cmd: control cmd -+ * @arg: cmd argument -+ * -+ * Perform DMA control command -+ * -+ */ -+static int adm_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, -+ unsigned long arg) -+{ -+ struct adm_chan *achan = to_adm_chan(chan); -+ unsigned long flag; -+ int ret = 0; -+ -+ switch (cmd) { -+ case DMA_SLAVE_CONFIG: -+ spin_lock_irqsave(&achan->vc.lock, flag); -+ ret = adm_slave_config(achan, (struct dma_slave_config *)arg); -+ spin_unlock_irqrestore(&achan->vc.lock, flag); -+ break; -+ -+ case DMA_TERMINATE_ALL: -+ adm_terminate_all(achan); -+ break; -+ -+ default: -+ ret = -ENXIO; -+ break; -+ }; -+ -+ return ret; -+} -+ -+/** -+ * adm_start_dma - start next transaction -+ * @achan - ADM dma channel -+ */ -+static void adm_start_dma(struct adm_chan *achan) -+{ -+ struct virt_dma_desc *vd = vchan_next_desc(&achan->vc); -+ struct adm_device *adev = achan->adev; -+ struct adm_async_desc *async_desc; -+ struct adm_desc_hw *desc; -+ struct adm_cmd_ptr_list *cpl; -+ -+ lockdep_assert_held(&achan->vc.lock); -+ -+ if (!vd) -+ return; -+ -+ list_del(&vd->node); -+ -+ /* write next command list out to the CMD FIFO */ -+ async_desc = container_of(vd, struct adm_async_desc, vd); -+ achan->curr_txd = async_desc; -+ -+ cpl = PTR_ALIGN(async_desc->cpl, ADM_DESC_ALIGN); -+ desc = PTR_ALIGN(&cpl->desc[0], ADM_DESC_ALIGN); -+ -+ if (!achan->initialized) { -+ /* enable interrupts */ -+ writel(CH_CONF_IRQ_EN | CH_CONF_FLUSH_RSLT_EN | -+ CH_CONF_FORCE_RSLT_EN | CH_CONF_PERM_MPU_CONF | -+ CH_CONF_MPU_DISABLE, -+ adev->regs + HI_CH_CONF(achan->id)); -+ -+ writel(CH_RSLT_CONF_IRQ_EN | CH_RSLT_CONF_FLUSH_EN, -+ adev->regs + HI_CH_RSLT_CONF(achan->id, adev->ee)); -+ -+ if (achan->crci) -+ writel(achan->blk_size, adev->regs + -+ HI_CRCI_CTL(achan->crci, adev->ee)); -+ -+ achan->initialized = 1; -+ } -+ -+ /* make sure IRQ enable doesn't get reordered */ -+ wmb(); -+ -+ /* write next command list out to the CMD FIFO */ -+ writel(round_up(async_desc->dma_addr, ADM_DESC_ALIGN) >> 3, -+ adev->regs + HI_CH_CMD_PTR(achan->id, adev->ee)); -+} -+ -+/** -+ * adm_dma_irq - irq handler for ADM controller -+ * @irq: IRQ of interrupt -+ * @data: callback data -+ * -+ * IRQ handler for the bam controller -+ */ -+static irqreturn_t adm_dma_irq(int irq, void *data) -+{ -+ struct adm_device *adev = data; -+ u32 srcs, i; -+ struct adm_async_desc *async_desc; -+ unsigned long flags; -+ -+ srcs = readl_relaxed(adev->regs + -+ HI_SEC_DOMAIN_IRQ_STATUS(adev->ee)); -+ -+ for (i = 0; i < 16; i++) { -+ struct adm_chan *achan = &adev->channels[i]; -+ u32 status, result; -+ if (srcs & BIT(i)) { -+ status = readl_relaxed(adev->regs + -+ HI_CH_STATUS_SD(i, adev->ee)); -+ -+ /* if no result present, skip */ -+ if (!(status & CH_STATUS_VALID)) -+ continue; -+ -+ result = readl_relaxed(adev->regs + -+ HI_CH_RSLT(i, adev->ee)); -+ -+ /* no valid results, skip */ -+ if (!(result & CH_RSLT_VALID)) -+ continue; -+ -+ /* flag error if transaction was flushed or failed */ -+ if (result & (CH_RSLT_ERR | CH_RSLT_FLUSH)) -+ achan->error = 1; -+ -+ spin_lock_irqsave(&achan->vc.lock, flags); -+ async_desc = achan->curr_txd; -+ -+ achan->curr_txd = NULL; -+ -+ if (async_desc) { -+ vchan_cookie_complete(&async_desc->vd); -+ -+ /* kick off next DMA */ -+ adm_start_dma(achan); -+ } -+ -+ spin_unlock_irqrestore(&achan->vc.lock, flags); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/** -+ * adm_tx_status - returns status of transaction -+ * @chan: dma channel -+ * @cookie: transaction cookie -+ * @txstate: DMA transaction state -+ * -+ * Return status of dma transaction -+ */ -+static enum dma_status adm_tx_status(struct dma_chan *chan, dma_cookie_t cookie, -+ struct dma_tx_state *txstate) -+{ -+ struct adm_chan *achan = to_adm_chan(chan); -+ struct virt_dma_desc *vd; -+ enum dma_status ret; -+ unsigned long flags; -+ size_t residue = 0; -+ -+ ret = dma_cookie_status(chan, cookie, txstate); -+ -+ spin_lock_irqsave(&achan->vc.lock, flags); -+ -+ vd = vchan_find_desc(&achan->vc, cookie); -+ if (vd) -+ residue = container_of(vd, struct adm_async_desc, vd)->length; -+ else if (achan->curr_txd && achan->curr_txd->vd.tx.cookie == cookie) -+ residue = achan->curr_txd->length; -+ -+ spin_unlock_irqrestore(&achan->vc.lock, flags); -+ -+ dma_set_residue(txstate, residue); -+ -+ if (achan->error) -+ return DMA_ERROR; -+ -+ return ret; -+} -+ -+static struct dma_chan *adm_dma_xlate(struct of_phandle_args *dma_spec, -+ struct of_dma *of) -+{ -+ struct adm_device *adev = container_of(of->of_dma_data, -+ struct adm_device, common); -+ struct adm_chan *achan; -+ struct dma_chan *chan; -+ unsigned int request; -+ unsigned int crci; -+ -+ if (dma_spec->args_count != 2) { -+ dev_err(adev->dev, "incorrect number of dma arguments\n"); -+ return NULL; -+ } -+ -+ request = dma_spec->args[0]; -+ if (request >= adev->num_channels) -+ return NULL; -+ -+ crci = dma_spec->args[1]; -+ -+ chan = dma_get_slave_channel(&(adev->channels[request].vc.chan)); -+ -+ if (!chan) -+ return NULL; -+ -+ achan = to_adm_chan(chan); -+ achan->crci = crci; -+ -+ return chan; -+} -+ -+/** -+ * adm_issue_pending - starts pending transactions -+ * @chan: dma channel -+ * -+ * Issues all pending transactions and starts DMA -+ */ -+static void adm_issue_pending(struct dma_chan *chan) -+{ -+ struct adm_chan *achan = to_adm_chan(chan); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&achan->vc.lock, flags); -+ -+ if (vchan_issue_pending(&achan->vc) && !achan->curr_txd) -+ adm_start_dma(achan); -+ spin_unlock_irqrestore(&achan->vc.lock, flags); -+} -+ -+/** -+ * adm_dma_free_desc - free descriptor memory -+ * @vd: virtual descriptor -+ * -+ */ -+static void adm_dma_free_desc(struct virt_dma_desc *vd) -+{ -+ struct adm_async_desc *async_desc = container_of(vd, -+ struct adm_async_desc, vd); -+ -+ dma_free_writecombine(async_desc->adev->dev, async_desc->dma_len, -+ async_desc->cpl, async_desc->dma_addr); -+ kfree(async_desc); -+} -+ -+static void adm_channel_init(struct adm_device *adev, struct adm_chan *achan, -+ u32 index) -+{ -+ achan->id = index; -+ achan->adev = adev; -+ -+ vchan_init(&achan->vc, &adev->common); -+ achan->vc.desc_free = adm_dma_free_desc; -+} -+ -+static int adm_dma_probe(struct platform_device *pdev) -+{ -+ struct adm_device *adev; -+ struct resource *iores; -+ int ret; -+ u32 i; -+ -+ adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL); -+ if (!adev) -+ return -ENOMEM; -+ -+ adev->dev = &pdev->dev; -+ -+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ adev->regs = devm_ioremap_resource(&pdev->dev, iores); -+ if (IS_ERR(adev->regs)) -+ return PTR_ERR(adev->regs); -+ -+ adev->irq = platform_get_irq(pdev, 0); -+ if (adev->irq < 0) -+ return adev->irq; -+ -+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,ee", &adev->ee); -+ if (ret) { -+ dev_err(adev->dev, "Execution environment unspecified\n"); -+ return ret; -+ } -+ -+ adev->core_clk = devm_clk_get(adev->dev, "core"); -+ if (IS_ERR(adev->core_clk)) -+ return PTR_ERR(adev->core_clk); -+ -+ ret = clk_prepare_enable(adev->core_clk); -+ if (ret) { -+ dev_err(adev->dev, "failed to prepare/enable core clock\n"); -+ return ret; -+ } -+ -+ adev->iface_clk = devm_clk_get(adev->dev, "iface"); -+ if (IS_ERR(adev->iface_clk)) -+ return PTR_ERR(adev->iface_clk); -+ -+ ret = clk_prepare_enable(adev->iface_clk); -+ if (ret) { -+ dev_err(adev->dev, "failed to prepare/enable iface clock\n"); -+ return ret; -+ } -+ -+ adev->clk_reset = devm_reset_control_get(&pdev->dev, "clk"); -+ if (IS_ERR(adev->clk_reset)) { -+ dev_err(adev->dev, "failed to get ADM0 reset\n"); -+ return PTR_ERR(adev->clk_reset); -+ } -+ -+ adev->c0_reset = devm_reset_control_get(&pdev->dev, "c0"); -+ if (IS_ERR(adev->c0_reset)) { -+ dev_err(adev->dev, "failed to get ADM0 C0 reset\n"); -+ return PTR_ERR(adev->c0_reset); -+ } -+ -+ adev->c1_reset = devm_reset_control_get(&pdev->dev, "c1"); -+ if (IS_ERR(adev->c1_reset)) { -+ dev_err(adev->dev, "failed to get ADM0 C1 reset\n"); -+ return PTR_ERR(adev->c1_reset); -+ } -+ -+ adev->c2_reset = devm_reset_control_get(&pdev->dev, "c2"); -+ if (IS_ERR(adev->c2_reset)) { -+ dev_err(adev->dev, "failed to get ADM0 C2 reset\n"); -+ return PTR_ERR(adev->c2_reset); -+ } -+ -+ reset_control_assert(adev->clk_reset); -+ reset_control_assert(adev->c0_reset); -+ reset_control_assert(adev->c1_reset); -+ reset_control_assert(adev->c2_reset); -+ -+ reset_control_deassert(adev->clk_reset); -+ reset_control_deassert(adev->c0_reset); -+ reset_control_deassert(adev->c1_reset); -+ reset_control_deassert(adev->c2_reset); -+ -+ adev->num_channels = 16; -+ -+ adev->channels = devm_kcalloc(adev->dev, adev->num_channels, -+ sizeof(*adev->channels), GFP_KERNEL); -+ -+ if (!adev->channels) { -+ ret = -ENOMEM; -+ goto err_disable_clk; -+ } -+ -+ /* allocate and initialize channels */ -+ INIT_LIST_HEAD(&adev->common.channels); -+ -+ for (i = 0; i < adev->num_channels; i++) -+ adm_channel_init(adev, &adev->channels[i], i); -+ -+ /* reset CRCIs */ -+ for (i = 0; i < 16; i++) -+ writel(CRCI_CTL_RST, adev->regs + HI_CRCI_CTL(i, adev->ee)); -+ -+ /* configure client interfaces */ -+ writel(CI_RANGE_START(0x40) | CI_RANGE_END(0xb0) | CI_BURST_8_WORDS, -+ adev->regs + HI_CI_CONF(0)); -+ writel(CI_RANGE_START(0x2a) | CI_RANGE_END(0x2c) | CI_BURST_8_WORDS, -+ adev->regs + HI_CI_CONF(1)); -+ writel(CI_RANGE_START(0x12) | CI_RANGE_END(0x28) | CI_BURST_8_WORDS, -+ adev->regs + HI_CI_CONF(2)); -+ writel(GP_CTL_LP_EN | GP_CTL_LP_CNT(0xf), adev->regs + HI_GP_CTL); -+ -+ ret = devm_request_irq(adev->dev, adev->irq, adm_dma_irq, -+ 0, "adm_dma", adev); -+ if (ret) -+ goto err_disable_clk; -+ -+ platform_set_drvdata(pdev, adev); -+ -+ adev->common.dev = adev->dev; -+ adev->common.dev->dma_parms = &adev->dma_parms; -+ -+ /* set capabilities */ -+ dma_cap_zero(adev->common.cap_mask); -+ dma_cap_set(DMA_SLAVE, adev->common.cap_mask); -+ dma_cap_set(DMA_PRIVATE, adev->common.cap_mask); -+ -+ /* initialize dmaengine apis */ -+ adev->common.device_alloc_chan_resources = adm_alloc_chan; -+ adev->common.device_free_chan_resources = adm_free_chan; -+ adev->common.device_prep_slave_sg = adm_prep_slave_sg; -+ adev->common.device_control = adm_control; -+ adev->common.device_issue_pending = adm_issue_pending; -+ adev->common.device_tx_status = adm_tx_status; -+ -+ ret = dma_async_device_register(&adev->common); -+ if (ret) { -+ dev_err(adev->dev, "failed to register dma async device\n"); -+ goto err_disable_clk; -+ } -+ -+ ret = of_dma_controller_register(pdev->dev.of_node, adm_dma_xlate, -+ &adev->common); -+ if (ret) -+ goto err_unregister_dma; -+ -+ return 0; -+ -+err_unregister_dma: -+ dma_async_device_unregister(&adev->common); -+err_disable_clk: -+ clk_disable_unprepare(adev->core_clk); -+ clk_disable_unprepare(adev->iface_clk); -+ -+ return ret; -+} -+ -+static int adm_dma_remove(struct platform_device *pdev) -+{ -+ struct adm_device *adev = platform_get_drvdata(pdev); -+ struct adm_chan *achan; -+ u32 i; -+ -+ of_dma_controller_free(pdev->dev.of_node); -+ dma_async_device_unregister(&adev->common); -+ -+ devm_free_irq(adev->dev, adev->irq, adev); -+ -+ for (i = 0; i < adev->num_channels; i++) { -+ achan = &adev->channels[i]; -+ writel(CH_CONF_FLUSH_RSLT_EN, -+ adev->regs + HI_CH_CONF(achan->id)); -+ writel(CH_RSLT_CONF_FLUSH_EN, -+ adev->regs + HI_CH_RSLT_CONF(achan->id, adev->ee)); -+ -+ adm_terminate_all(&adev->channels[i]); -+ } -+ -+ clk_disable_unprepare(adev->core_clk); -+ clk_disable_unprepare(adev->iface_clk); -+ -+ return 0; -+} -+ -+static const struct of_device_id adm_of_match[] = { -+ { .compatible = "qcom,adm", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, adm_of_match); -+ -+static struct platform_driver adm_dma_driver = { -+ .probe = adm_dma_probe, -+ .remove = adm_dma_remove, -+ .driver = { -+ .name = "adm-dma-engine", -+ .owner = THIS_MODULE, -+ .of_match_table = adm_of_match, -+ }, -+}; -+ -+module_platform_driver(adm_dma_driver); -+ -+MODULE_AUTHOR("Andy Gross "); -+MODULE_DESCRIPTION("QCOM ADM DMA engine driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ipq806x/patches/0178-dmaengine-qcom_adm-Add-device-tree-binding.patch b/target/linux/ipq806x/patches/0178-dmaengine-qcom_adm-Add-device-tree-binding.patch deleted file mode 100644 index 1c72a2f7b2..0000000000 --- a/target/linux/ipq806x/patches/0178-dmaengine-qcom_adm-Add-device-tree-binding.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 331294fa5c703536e27b79e9c112d162393f725a Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 26 Jun 2014 13:55:10 -0500 -Subject: [PATCH 178/182] dmaengine: qcom_adm: Add device tree binding - -Add device tree binding support for the QCOM ADM DMA driver. - -Signed-off-by: Andy Gross ---- - Documentation/devicetree/bindings/dma/qcom_adm.txt | 60 ++++++++++++++++++++ - 1 file changed, 60 insertions(+) - create mode 100644 Documentation/devicetree/bindings/dma/qcom_adm.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/dma/qcom_adm.txt -@@ -0,0 +1,60 @@ -+QCOM ADM DMA Controller -+ -+Required properties: -+- compatible: must contain "qcom,adm" for IPQ/APQ8064 and MSM8960 -+- reg: Address range for DMA registers -+- interrupts: Should contain one interrupt shared by all channels -+- #dma-cells: must be <2>. First cell denotes the channel number. Second cell -+ denotes CRCI (client rate control interface) flow control assignment. -+- clocks: Should contain the core clock and interface clock. -+- clock-names: Must contain "core" for the core clock and "iface" for the -+ interface clock. -+- resets: Must contain an entry for each entry in reset names. -+- reset-names: Must include the following entries: -+ - clk -+ - c0 -+ - c1 -+ - c2 -+- qcom,ee: indicates the security domain identifier used in the secure world. -+ -+Example: -+ adm_dma: dma@18300000 { -+ compatible = "qcom,adm"; -+ reg = <0x18300000 0x100000>; -+ interrupts = <0 170 0>; -+ #dma-cells = <2>; -+ -+ clocks = <&gcc ADM0_CLK>, <&gcc ADM0_PBUS_CLK>; -+ clock-names = "core", "iface"; -+ -+ resets = <&gcc ADM0_RESET>, -+ <&gcc ADM0_C0_RESET>, -+ <&gcc ADM0_C1_RESET>, -+ <&gcc ADM0_C2_RESET>; -+ reset-names = "clk", "c0", "c1", "c2"; -+ qcom,ee = <0>; -+ }; -+ -+DMA clients must use the format descripted in the dma.txt file, using a three -+cell specifier for each channel. -+ -+Each dmas request consists of 3 cells: -+ 1. phandle pointing to the DMA controller -+ 2. channel number -+ 3. CRCI assignment, if applicable. If no CRCI flow control is required, use 0. -+ -+Example: -+ -+ spi4: spi@1a280000 { -+ status = "ok"; -+ spi-max-frequency = <50000000>; -+ -+ pinctrl-0 = <&spi_pins>; -+ pinctrl-names = "default"; -+ -+ cs-gpios = <&qcom_pinmux 20 0>; -+ -+ dmas = <&adm_dma 6 9>, -+ <&adm_dma 5 10>; -+ dma-names = "rx", "tx"; -+ }; diff --git a/target/linux/ipq806x/patches/0180-ARM-dts-Add-ADM-DMA-nodes-and-SPI-linkage.patch b/target/linux/ipq806x/patches/0180-ARM-dts-Add-ADM-DMA-nodes-and-SPI-linkage.patch deleted file mode 100644 index 05279de594..0000000000 --- a/target/linux/ipq806x/patches/0180-ARM-dts-Add-ADM-DMA-nodes-and-SPI-linkage.patch +++ /dev/null @@ -1,83 +0,0 @@ -From c78ae23b6c174c9f2e0973a247942b6b4adb7e82 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Thu, 26 Jun 2014 13:02:59 -0500 -Subject: [PATCH 180/182] ARM: dts: Add ADM DMA nodes and SPI linkage - -This patch adds the ADM DMA controller DT nodes and also enables the use of dma -in SPI. - -Signed-off-by: Andy Gross ---- - arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 11 +++++++++++ - arch/arm/boot/dts/qcom-ipq8064.dtsi | 8 +++++--- - 2 files changed, 16 insertions(+), 3 deletions(-) - ---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts -@@ -44,6 +44,10 @@ - drive-strength = <10>; - bias-none; - }; -+ cs { -+ pins = "gpio20"; -+ drive-strength = <12>; -+ }; - }; - nand_pins: nand_pins { - mux { -@@ -100,12 +104,17 @@ - - cs-gpios = <&qcom_pinmux 20 0>; - -+ dmas = <&adm_dma 6 9>, -+ <&adm_dma 5 10>; -+ dma-names = "rx", "tx"; -+ - flash: m25p80@0 { - compatible = "s25fl256s1"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; -+ m25p,fast-read; - - partition@0 { - label = "rootfs"; -@@ -140,8 +149,10 @@ - ranges = <0x00000000 0 0x00000000 0x31f00000 0 0x00100000 /* configuration space */ - 0x81000000 0 0 0x31e00000 0 0x00100000 /* downstream I/O */ - 0x82000000 0 0x00000000 0x2e000000 0 0x03e00000>; /* non-prefetchable memory */ -+ - }; - -+ - sata-phy@1b400000 { - status = "ok"; - }; ---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi -+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -421,19 +421,21 @@ - compatible = "qcom,adm"; - reg = <0x18300000 0x100000>; - interrupts = <0 170 0>; -+ #dma-cells = <2>; - - clocks = <&gcc ADM0_CLK>, <&gcc ADM0_PBUS_CLK>; -- clock-names = "core_clk", "iface_clk"; -+ clock-names = "core", "iface"; - - resets = <&gcc ADM0_RESET>, - <&gcc ADM0_PBUS_RESET>, - <&gcc ADM0_C0_RESET>, - <&gcc ADM0_C1_RESET>, - <&gcc ADM0_C2_RESET>; -- -- reset-names = "adm", "pbus", "c0", "c1", "c2"; -+ reset-names = "clk", "pbus", "c0", "c1", "c2"; -+ qcom,ee = <0>; - - status = "disabled"; -+ - }; - - nand@0x1ac00000 { diff --git a/target/linux/ipq806x/patches/0181-mtd-nand-qcom-Align-clk-and-reset-names.patch b/target/linux/ipq806x/patches/0181-mtd-nand-qcom-Align-clk-and-reset-names.patch deleted file mode 100644 index e2e313ca65..0000000000 --- a/target/linux/ipq806x/patches/0181-mtd-nand-qcom-Align-clk-and-reset-names.patch +++ /dev/null @@ -1,41 +0,0 @@ -From ae0e9ee3bcfafc5bd5932b544e0a5c107948fc97 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 30 Jun 2014 21:17:26 -0500 -Subject: [PATCH 181/182] mtd: nand: qcom: Align clk and reset names - -This patch aligns the clk and reset names to the same ones that the dmaengine -driver uses. - -Signed-off-by: Andy Gross ---- - drivers/mtd/nand/qcom_adm_dma.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/mtd/nand/qcom_adm_dma.c -+++ b/drivers/mtd/nand/qcom_adm_dma.c -@@ -568,14 +568,14 @@ static int msm_dmov_init_clocks(struct p - int adm = (pdev->id >= 0) ? pdev->id : 0; - int ret; - -- dmov_conf[adm].clk = devm_clk_get(&pdev->dev, "core_clk"); -+ dmov_conf[adm].clk = devm_clk_get(&pdev->dev, "core"); - if (IS_ERR(dmov_conf[adm].clk)) { - printk(KERN_ERR "%s: Error getting adm_clk\n", __func__); - dmov_conf[adm].clk = NULL; - return -ENOENT; - } - -- dmov_conf[adm].pclk = devm_clk_get(&pdev->dev, "iface_clk"); -+ dmov_conf[adm].pclk = devm_clk_get(&pdev->dev, "iface"); - if (IS_ERR(dmov_conf[adm].pclk)) { - dmov_conf[adm].pclk = NULL; - /* pclk not present on all SoCs, don't bail on failure */ -@@ -690,7 +690,7 @@ static int msm_dmov_probe(struct platfor - } - - /* get resets */ -- dmov_conf[adm].adm_reset = devm_reset_control_get(&pdev->dev, "adm"); -+ dmov_conf[adm].adm_reset = devm_reset_control_get(&pdev->dev, "clk"); - if (IS_ERR(dmov_conf[adm].adm_reset)) { - dev_err(&pdev->dev, "failed to get adm reset\n"); - ret = PTR_ERR(dmov_conf[adm].adm_reset); diff --git a/target/linux/ipq806x/patches/0182-qcom-Kconfig-Make-drivers-mutually-exclusive.patch b/target/linux/ipq806x/patches/0182-qcom-Kconfig-Make-drivers-mutually-exclusive.patch deleted file mode 100644 index f4b551bac6..0000000000 --- a/target/linux/ipq806x/patches/0182-qcom-Kconfig-Make-drivers-mutually-exclusive.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0771849495b4128cac2faf7d49c85c729fc48b20 Mon Sep 17 00:00:00 2001 -From: Andy Gross -Date: Mon, 30 Jun 2014 21:18:39 -0500 -Subject: [PATCH 182/182] qcom: Kconfig: Make drivers mutually exclusive - -This patch makes sure QCOM ADM dmaengine and QCOM Nand cannot be enabled at the -same time. This is an issue because the dma drivers will conflict with one -another. - -Signed-off-by: Andy Gross ---- - drivers/dma/Kconfig | 2 +- - drivers/mtd/nand/Kconfig | 6 +++--- - 2 files changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -412,7 +412,7 @@ config QCOM_BAM_DMA - - config QCOM_ADM - tristate "Qualcomm ADM support" -- depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM) -+ depends on !MTD_QCOM_ADM && (ARCH_QCOM || (COMPILE_TEST && OF && ARM)) - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - ---help--- ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -511,15 +511,15 @@ config MTD_NAND_XWAY - to the External Bus Unit (EBU). - - config MTD_QCOM_DMA -- tristate "QCMO NAND DMA Support" -- depends on ARCH_QCOM && MTD_QCOM_NAND -+ tristate "QCOM NAND DMA Support" -+ depends on !QCOM_ADM && ARCH_QCOM && MTD_QCOM_NAND - default n - help - DMA support for QCOM NAND - - config MTD_QCOM_NAND - tristate "QCOM NAND Device Support" -- depends on MTD && ARCH_QCOM -+ depends on MTD && ARCH_QCOM && !QCOM_ADM - select CRC16 - select BITREVERSE - select MTD_NAND_IDS