Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org> SVN-Revision: 45210master
parent
2d74104b52
commit
d3a9fc4586
@ -0,0 +1,389 @@ |
|||||||
|
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_AR8216_PHY=y |
||||||
|
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y |
||||||
|
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y |
||||||
|
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y |
||||||
|
CONFIG_ARCH_HAS_SG_CHAIN=y |
||||||
|
CONFIG_ARCH_HAS_TICK_BROADCAST=y |
||||||
|
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y |
||||||
|
CONFIG_ARCH_HIBERNATION_POSSIBLE=y |
||||||
|
CONFIG_ARCH_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_NR_GPIO=0 |
||||||
|
CONFIG_ARCH_QCOM=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_BIG_ENDIAN=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_SMMU is not set |
||||||
|
# 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_BATTERY_GAUGE_LTC2941 is not set |
||||||
|
CONFIG_BCMA_DRIVER_PCI=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_BIG_ENDIAN is not set |
||||||
|
# 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_USER is not set |
||||||
|
CONFIG_DECOMPRESS_GZIP=y |
||||||
|
CONFIG_DEVMEM=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_ETHERNET_PACKET_MANGLE=y |
||||||
|
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_MSI_IRQ=y |
||||||
|
CONFIG_GENERIC_PCI_IOMAP=y |
||||||
|
CONFIG_GENERIC_PHY=y |
||||||
|
CONFIG_GENERIC_PINCONF=y |
||||||
|
CONFIG_GENERIC_SCHED_CLOCK=y |
||||||
|
CONFIG_GENERIC_SMP_IDLE_THREAD=y |
||||||
|
CONFIG_GENERIC_STRNCPY_FROM_USER=y |
||||||
|
CONFIG_GENERIC_STRNLEN_USER=y |
||||||
|
CONFIG_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_BITREVERSE=y |
||||||
|
CONFIG_HAVE_ARCH_JUMP_LABEL=y |
||||||
|
CONFIG_HAVE_ARCH_KGDB=y |
||||||
|
CONFIG_HAVE_ARCH_PFN_VALID=y |
||||||
|
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y |
||||||
|
CONFIG_HAVE_ARCH_TRACEHOOK=y |
||||||
|
CONFIG_HAVE_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_OPTPROBES=y |
||||||
|
CONFIG_HAVE_PERF_EVENTS=y |
||||||
|
CONFIG_HAVE_PERF_REGS=y |
||||||
|
CONFIG_HAVE_PERF_USER_STACK_DUMP=y |
||||||
|
CONFIG_HAVE_PROC_CPU=y |
||||||
|
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y |
||||||
|
CONFIG_HAVE_SMP=y |
||||||
|
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y |
||||||
|
CONFIG_HAVE_UID16=y |
||||||
|
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y |
||||||
|
CONFIG_HIGHMEM=y |
||||||
|
CONFIG_HIGHPTE=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_HELPER=y |
||||||
|
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set |
||||||
|
CONFIG_IOMMU_SUPPORT=y |
||||||
|
CONFIG_IPQ_GCC_806X=y |
||||||
|
# CONFIG_IPQ_LCC_806X is not set |
||||||
|
CONFIG_IRQCHIP=y |
||||||
|
CONFIG_IRQ_DOMAIN=y |
||||||
|
CONFIG_IRQ_DOMAIN_HIERARCHY=y |
||||||
|
CONFIG_IRQ_FORCED_THREADING=y |
||||||
|
CONFIG_IRQ_WORK=y |
||||||
|
# CONFIG_LEDS_REGULATOR is not set |
||||||
|
CONFIG_LIBFDT=y |
||||||
|
CONFIG_LOCKUP_DETECTOR=y |
||||||
|
CONFIG_LOCK_SPIN_ON_OWNER=y |
||||||
|
# CONFIG_LZ4_COMPRESS is not set |
||||||
|
# CONFIG_LZ4_DECOMPRESS is not set |
||||||
|
CONFIG_LZO_COMPRESS=y |
||||||
|
CONFIG_LZO_DECOMPRESS=y |
||||||
|
CONFIG_MDIO_BITBANG=y |
||||||
|
CONFIG_MDIO_BOARDINFO=y |
||||||
|
CONFIG_MDIO_GPIO=y |
||||||
|
# CONFIG_MFD_DA9150 is not set |
||||||
|
# CONFIG_MFD_QCOM_RPM is not set |
||||||
|
# CONFIG_MFD_RT5033 is not set |
||||||
|
# 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_MPLS is not set |
||||||
|
CONFIG_MSM_GCC_8660=y |
||||||
|
CONFIG_MSM_GCC_8960=y |
||||||
|
CONFIG_MSM_GCC_8974=y |
||||||
|
# CONFIG_MSM_LCC_8960 is not set |
||||||
|
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_FIRMWARE=y |
||||||
|
CONFIG_MTD_SPLIT_FIT_FW=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_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_DOMAINS_GENERIC is not set |
||||||
|
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_MSM8916 is not set |
||||||
|
# CONFIG_PINCTRL_MSM8960 is not set |
||||||
|
CONFIG_PINCTRL_MSM8X74=y |
||||||
|
# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set |
||||||
|
# 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=y |
||||||
|
# CONFIG_RCU_BOOST is not set |
||||||
|
CONFIG_RCU_CPU_STALL_TIMEOUT=21 |
||||||
|
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_SRCU=y |
||||||
|
CONFIG_STOP_MACHINE=y |
||||||
|
# CONFIG_STRIP_ASM_SYMS is not set |
||||||
|
CONFIG_SUSPEND=y |
||||||
|
CONFIG_SUSPEND_FREEZER=y |
||||||
|
CONFIG_SWCONFIG=y |
||||||
|
CONFIG_SWIOTLB=y |
||||||
|
CONFIG_SWP_EMULATE=y |
||||||
|
CONFIG_SYS_SUPPORTS_APM_EMULATION=y |
||||||
|
# CONFIG_TEGRA_AHB is not set |
||||||
|
CONFIG_THERMAL=y |
||||||
|
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set |
||||||
|
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y |
||||||
|
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set |
||||||
|
# CONFIG_THERMAL_EMULATION is not set |
||||||
|
# CONFIG_THERMAL_GOV_FAIR_SHARE is not set |
||||||
|
CONFIG_THERMAL_GOV_STEP_WISE=y |
||||||
|
# CONFIG_THERMAL_GOV_USER_SPACE is not set |
||||||
|
CONFIG_THERMAL_HWMON=y |
||||||
|
CONFIG_THERMAL_OF=y |
||||||
|
# CONFIG_THUMB2_KERNEL is not set |
||||||
|
CONFIG_TICK_CPU_ACCOUNTING=y |
||||||
|
CONFIG_TIMER_STATS=y |
||||||
|
CONFIG_UEVENT_HELPER_PATH="" |
||||||
|
CONFIG_UID16=y |
||||||
|
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" |
||||||
|
CONFIG_UNINLINE_SPIN_UNLOCK=y |
||||||
|
CONFIG_USE_OF=y |
||||||
|
CONFIG_VECTORS_BASE=0xffff0000 |
||||||
|
CONFIG_VFP=y |
||||||
|
CONFIG_VFPv3=y |
||||||
|
CONFIG_VM_EVENT_COUNTERS=y |
||||||
|
CONFIG_WATCHDOG_CORE=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 |
@ -0,0 +1,522 @@ |
|||||||
|
Content-Type: text/plain; charset="utf-8"
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
Subject: spi: qup: Add DMA capabilities
|
||||||
|
From: Andy Gross <agross@codeaurora.org>
|
||||||
|
X-Patchwork-Id: 4432401
|
||||||
|
Message-Id: <1403816781-31008-1-git-send-email-agross@codeaurora.org>
|
||||||
|
To: Mark Brown <broonie@kernel.org>
|
||||||
|
Cc: linux-spi@vger.kernel.org, Sagar Dharia <sdharia@codeaurora.org>,
|
||||||
|
Daniel Sneddon <dsneddon@codeaurora.org>,
|
||||||
|
Bjorn Andersson <bjorn.andersson@sonymobile.com>,
|
||||||
|
"Ivan T. Ivanov" <iivanov@mm-sol.com>,
|
||||||
|
linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
|
||||||
|
linux-arm-msm@vger.kernel.org, Andy Gross <agross@codeaurora.org>
|
||||||
|
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 than the length of a block.
|
||||||
|
|
||||||
|
Signed-off-by: Andy Gross <agross@codeaurora.org>
|
||||||
|
|
||||||
|
---
|
||||||
|
.../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 = <index> 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 @@
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
+#include <linux/dmaengine.h>
|
||||||
|
+#include <linux/dma-mapping.h>
|
||||||
|
|
||||||
|
#define QUP_CONFIG 0x0000
|
||||||
|
#define QUP_STATE 0x0004
|
||||||
|
@@ -116,6 +118,8 @@
|
||||||
|
|
||||||
|
#define SPI_NUM_CHIPSELECTS 4
|
||||||
|
|
||||||
|
+#define SPI_MAX_XFER (SZ_64K - 64)
|
||||||
|
+
|
||||||
|
/* 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,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;
|
||||||
|
+ dma_addr_t rx_dma;
|
||||||
|
+ dma_addr_t tx_dma;
|
||||||
|
+ void *dummy;
|
||||||
|
+ atomic_t dma_outstanding;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -266,6 +281,221 @@ static void spi_qup_fifo_write(struct sp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void qup_dma_callback(void *data)
|
||||||
|
+{
|
||||||
|
+ struct spi_qup *controller = data;
|
||||||
|
+
|
||||||
|
+ if (atomic_dec_and_test(&controller->dma_outstanding))
|
||||||
|
+ complete(&controller->done);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int spi_qup_do_dma(struct spi_qup *controller, struct spi_transfer *xfer)
|
||||||
|
+{
|
||||||
|
+ struct dma_async_tx_descriptor *rxd, *txd;
|
||||||
|
+ dma_cookie_t rx_cookie, tx_cookie;
|
||||||
|
+ u32 xfer_len, rx_align = 0, tx_align = 0, n_words;
|
||||||
|
+ struct scatterlist tx_sg[2], rx_sg[2];
|
||||||
|
+ int ret = 0;
|
||||||
|
+ u32 bytes_to_xfer = xfer->len;
|
||||||
|
+ u32 offset = 0;
|
||||||
|
+ u32 rx_nents = 0, tx_nents = 0;
|
||||||
|
+ dma_addr_t rx_dma = 0, tx_dma = 0, rx_dummy_dma = 0, tx_dummy_dma = 0;
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ if (xfer->rx_buf) {
|
||||||
|
+ rx_dma = dma_map_single(controller->dev, xfer->rx_buf,
|
||||||
|
+ xfer->len, DMA_FROM_DEVICE);
|
||||||
|
+
|
||||||
|
+ if (dma_mapping_error(controller->dev, rx_dma)) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* check to see if we need dummy buffer for leftover bytes */
|
||||||
|
+ rx_align = xfer->len % controller->in_blk_sz;
|
||||||
|
+ if (rx_align) {
|
||||||
|
+ rx_dummy_dma = dma_map_single(controller->dev,
|
||||||
|
+ controller->dummy, controller->in_fifo_sz,
|
||||||
|
+ DMA_FROM_DEVICE);
|
||||||
|
+
|
||||||
|
+ if (dma_mapping_error(controller->dev, rx_dummy_dma)) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_map_rx_dummy;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (xfer->tx_buf) {
|
||||||
|
+ tx_dma = dma_map_single(controller->dev,
|
||||||
|
+ (void *)xfer->tx_buf, xfer->len, DMA_TO_DEVICE);
|
||||||
|
+
|
||||||
|
+ if (dma_mapping_error(controller->dev, tx_dma)) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_map_tx;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* check to see if we need dummy buffer for leftover bytes */
|
||||||
|
+ tx_align = xfer->len % controller->out_blk_sz;
|
||||||
|
+ if (tx_align) {
|
||||||
|
+ memcpy(controller->dummy + SZ_1K,
|
||||||
|
+ xfer->tx_buf + xfer->len - tx_align,
|
||||||
|
+ tx_align);
|
||||||
|
+ memset(controller->dummy + SZ_1K + tx_align, 0,
|
||||||
|
+ controller->out_blk_sz - tx_align);
|
||||||
|
+
|
||||||
|
+ tx_dummy_dma = dma_map_single(controller->dev,
|
||||||
|
+ controller->dummy + SZ_1K,
|
||||||
|
+ controller->out_blk_sz, DMA_TO_DEVICE);
|
||||||
|
+
|
||||||
|
+ if (dma_mapping_error(controller->dev, tx_dummy_dma)) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_map_tx_dummy;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ atomic_set(&controller->dma_outstanding, 0);
|
||||||
|
+
|
||||||
|
+ while (bytes_to_xfer > 0) {
|
||||||
|
+ xfer_len = min_t(u32, bytes_to_xfer, SPI_MAX_XFER);
|
||||||
|
+ n_words = DIV_ROUND_UP(xfer_len, controller->w_size);
|
||||||
|
+
|
||||||
|
+ /* write out current word count to controller */
|
||||||
|
+ writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
|
||||||
|
+ writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
|
||||||
|
+
|
||||||
|
+ reinit_completion(&controller->done);
|
||||||
|
+
|
||||||
|
+ if (xfer->tx_buf) {
|
||||||
|
+ /* recalc align for each transaction */
|
||||||
|
+ tx_align = xfer_len % controller->out_blk_sz;
|
||||||
|
+
|
||||||
|
+ if (tx_align)
|
||||||
|
+ tx_nents = 2;
|
||||||
|
+ else
|
||||||
|
+ tx_nents = 1;
|
||||||
|
+
|
||||||
|
+ /* initialize scatterlists */
|
||||||
|
+ sg_init_table(tx_sg, tx_nents);
|
||||||
|
+ sg_dma_len(&tx_sg[0]) = xfer_len - tx_align;
|
||||||
|
+ sg_dma_address(&tx_sg[0]) = tx_dma + offset;
|
||||||
|
+
|
||||||
|
+ /* account for non block size transfer */
|
||||||
|
+ if (tx_align) {
|
||||||
|
+ sg_dma_len(&tx_sg[1]) = controller->out_blk_sz;
|
||||||
|
+ sg_dma_address(&tx_sg[1]) = tx_dummy_dma;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ txd = dmaengine_prep_slave_sg(controller->tx_chan,
|
||||||
|
+ tx_sg, tx_nents, DMA_MEM_TO_DEV, 0);
|
||||||
|
+ if (!txd) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_unmap;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ atomic_inc(&controller->dma_outstanding);
|
||||||
|
+
|
||||||
|
+ txd->callback = qup_dma_callback;
|
||||||
|
+ txd->callback_param = controller;
|
||||||
|
+
|
||||||
|
+ tx_cookie = dmaengine_submit(txd);
|
||||||
|
+
|
||||||
|
+ dma_async_issue_pending(controller->tx_chan);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (xfer->rx_buf) {
|
||||||
|
+ /* recalc align for each transaction */
|
||||||
|
+ rx_align = xfer_len % controller->in_blk_sz;
|
||||||
|
+
|
||||||
|
+ if (rx_align)
|
||||||
|
+ rx_nents = 2;
|
||||||
|
+ else
|
||||||
|
+ rx_nents = 1;
|
||||||
|
+
|
||||||
|
+ /* initialize scatterlists */
|
||||||
|
+ sg_init_table(rx_sg, rx_nents);
|
||||||
|
+ sg_dma_address(&rx_sg[0]) = rx_dma + offset;
|
||||||
|
+ sg_dma_len(&rx_sg[0]) = xfer_len - rx_align;
|
||||||
|
+
|
||||||
|
+ /* account for non block size transfer */
|
||||||
|
+ if (rx_align) {
|
||||||
|
+ sg_dma_len(&rx_sg[1]) = controller->in_blk_sz;
|
||||||
|
+ sg_dma_address(&rx_sg[1]) = rx_dummy_dma;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rxd = dmaengine_prep_slave_sg(controller->rx_chan,
|
||||||
|
+ rx_sg, rx_nents, DMA_DEV_TO_MEM, 0);
|
||||||
|
+ if (!rxd) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_unmap;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ atomic_inc(&controller->dma_outstanding);
|
||||||
|
+
|
||||||
|
+ rxd->callback = qup_dma_callback;
|
||||||
|
+ rxd->callback_param = controller;
|
||||||
|
+
|
||||||
|
+ rx_cookie = dmaengine_submit(rxd);
|
||||||
|
+
|
||||||
|
+ dma_async_issue_pending(controller->rx_chan);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
|
||||||
|
+ dev_warn(controller->dev, "cannot set EXECUTE state\n");
|
||||||
|
+ goto err_unmap;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!wait_for_completion_timeout(&controller->done,
|
||||||
|
+ msecs_to_jiffies(1000))) {
|
||||||
|
+ ret = -ETIMEDOUT;
|
||||||
|
+
|
||||||
|
+ /* clear out all the DMA transactions */
|
||||||
|
+ if (xfer->tx_buf)
|
||||||
|
+ dmaengine_terminate_all(controller->tx_chan);
|
||||||
|
+ if (xfer->rx_buf)
|
||||||
|
+ dmaengine_terminate_all(controller->rx_chan);
|
||||||
|
+
|
||||||
|
+ goto err_unmap;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (rx_align)
|
||||||
|
+ memcpy(xfer->rx_buf + offset + xfer->len - rx_align,
|
||||||
|
+ controller->dummy, rx_align);
|
||||||
|
+
|
||||||
|
+ /* adjust remaining bytes to transfer */
|
||||||
|
+ bytes_to_xfer -= xfer_len;
|
||||||
|
+ offset += xfer_len;
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ /* reset mini-core state so we can program next transaction */
|
||||||
|
+ if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
|
||||||
|
+ dev_err(controller->dev, "cannot set RESET state\n");
|
||||||
|
+ goto err_unmap;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = 0;
|
||||||
|
+
|
||||||
|
+err_unmap:
|
||||||
|
+ if (tx_align)
|
||||||
|
+ dma_unmap_single(controller->dev, tx_dummy_dma,
|
||||||
|
+ controller->out_fifo_sz, DMA_TO_DEVICE);
|
||||||
|
+err_map_tx_dummy:
|
||||||
|
+ if (xfer->tx_buf)
|
||||||
|
+ dma_unmap_single(controller->dev, tx_dma, xfer->len,
|
||||||
|
+ DMA_TO_DEVICE);
|
||||||
|
+err_map_tx:
|
||||||
|
+ if (rx_align)
|
||||||
|
+ dma_unmap_single(controller->dev, rx_dummy_dma,
|
||||||
|
+ controller->in_fifo_sz, DMA_FROM_DEVICE);
|
||||||
|
+err_map_rx_dummy:
|
||||||
|
+ if (xfer->rx_buf)
|
||||||
|
+ dma_unmap_single(controller->dev, rx_dma, xfer->len,
|
||||||
|
+ DMA_FROM_DEVICE);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct spi_qup *controller = dev_id;
|
||||||
|
@@ -315,11 +545,13 @@ static irqreturn_t spi_qup_qup_irq(int i
|
||||||
|
error = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (opflags & QUP_OP_IN_SERVICE_FLAG)
|
||||||
|
- spi_qup_fifo_read(controller, xfer);
|
||||||
|
+ if (!controller->use_dma) {
|
||||||
|
+ 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);
|
||||||
|
+ if (opflags & QUP_OP_OUT_SERVICE_FLAG)
|
||||||
|
+ spi_qup_fifo_write(controller, xfer);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
spin_lock_irqsave(&controller->lock, flags);
|
||||||
|
controller->error = error;
|
||||||
|
@@ -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;
|
||||||
|
+ size_t dma_align = dma_get_cache_alignment();
|
||||||
|
+ u32 dma_available = 0;
|
||||||
|
|
||||||
|
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 +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))
|
||||||
|
+ 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 +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);
|
||||||
|
- } else {
|
||||||
|
+ controller->use_dma = 0;
|
||||||
|
+ } else if (!dma_available) {
|
||||||
|
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);
|
||||||
|
+ controller->use_dma = 0;
|
||||||
|
+ } else {
|
||||||
|
+ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
+
|
||||||
|
+ if (!controller->use_dma)
|
||||||
|
+ iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
|
||||||
|
+ 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);
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
+
|
||||||
|
+ if (controller->use_dma) {
|
||||||
|
+ if (!xfer->tx_buf)
|
||||||
|
+ config |= QUP_CONFIG_NO_OUTPUT;
|
||||||
|
+ if (!xfer->rx_buf)
|
||||||
|
+ config |= QUP_CONFIG_NO_INPUT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
writel_relaxed(config, controller->base + QUP_CONFIG);
|
||||||
|
|
||||||
|
/* only write to OPERATIONAL_MASK when register is present */
|
||||||
|
@@ -452,25 +711,29 @@ static int spi_qup_transfer_one(struct s
|
||||||
|
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 (controller->use_dma) {
|
||||||
|
+ ret = spi_qup_do_dma(controller, xfer);
|
||||||
|
+ } else {
|
||||||
|
+ 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;
|
||||||
|
- }
|
||||||
|
+ 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);
|
||||||
|
+ 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 (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;
|
||||||
|
+ 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);
|
||||||
|
@@ -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;
|
||||||
|
+ master->dma_alignment = dma_get_cache_alignment();
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, master);
|
||||||
|
|
||||||
|
@@ -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");
|
||||||
|
+ if (controller->rx_chan) {
|
||||||
|
+ controller->tx_chan =
|
||||||
|
+ dma_request_slave_channel(&pdev->dev, "tx");
|
||||||
|
+
|
||||||
|
+ if (!controller->tx_chan) {
|
||||||
|
+ dev_err(&pdev->dev, "Failed to allocate dma tx chan");
|
||||||
|
+ dma_release_channel(controller->rx_chan);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* set DMA parameters */
|
||||||
|
+ controller->rx_conf.device_fc = 1;
|
||||||
|
+ controller->rx_conf.src_addr = res->start + QUP_INPUT_FIFO;
|
||||||
|
+ controller->rx_conf.src_maxburst = controller->in_blk_sz;
|
||||||
|
+
|
||||||
|
+ controller->tx_conf.device_fc = 1;
|
||||||
|
+ controller->tx_conf.dst_addr = res->start + QUP_OUTPUT_FIFO;
|
||||||
|
+ controller->tx_conf.dst_maxburst = controller->out_blk_sz;
|
||||||
|
+
|
||||||
|
+ if (dmaengine_slave_config(controller->rx_chan,
|
||||||
|
+ &controller->rx_conf)) {
|
||||||
|
+ dev_err(&pdev->dev, "failed to configure RX channel\n");
|
||||||
|
+
|
||||||
|
+ dma_release_channel(controller->rx_chan);
|
||||||
|
+ dma_release_channel(controller->tx_chan);
|
||||||
|
+ controller->tx_chan = NULL;
|
||||||
|
+ controller->rx_chan = NULL;
|
||||||
|
+ } else if (dmaengine_slave_config(controller->tx_chan,
|
||||||
|
+ &controller->tx_conf)) {
|
||||||
|
+ dev_err(&pdev->dev, "failed to configure TX channel\n");
|
||||||
|
+
|
||||||
|
+ dma_release_channel(controller->rx_chan);
|
||||||
|
+ dma_release_channel(controller->tx_chan);
|
||||||
|
+ controller->tx_chan = NULL;
|
||||||
|
+ controller->rx_chan = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ controller->dummy = devm_kmalloc(controller->dev, PAGE_SIZE,
|
||||||
|
+ GFP_KERNEL);
|
||||||
|
+
|
||||||
|
+ if (!controller->dummy) {
|
||||||
|
+ dma_release_channel(controller->rx_chan);
|
||||||
|
+ dma_release_channel(controller->tx_chan);
|
||||||
|
+ controller->tx_chan = NULL;
|
||||||
|
+ controller->rx_chan = NULL;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+
|
||||||
|
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;
|
||||||
|
|
||||||
|
+ if (controller->rx_chan)
|
||||||
|
+ dma_release_channel(controller->rx_chan);
|
||||||
|
+ if (controller->tx_chan)
|
||||||
|
+ dma_release_channel(controller->tx_chan);
|
||||||
|
+
|
||||||
|
clk_disable_unprepare(controller->cclk);
|
||||||
|
clk_disable_unprepare(controller->iclk);
|
||||||
|
|
@ -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 <agross@codeaurora.org>
|
||||||
|
X-Patchwork-Id: 5007321
|
||||||
|
Message-Id: <1412112088-25928-1-git-send-email-agross@codeaurora.org>
|
||||||
|
To: Mark Brown <broonie@kernel.org>
|
||||||
|
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" <iivanov@mm-sol.com>,
|
||||||
|
Bjorn Andersson <bjorn.andersson@sonymobile.com>,
|
||||||
|
Kumar Gala <galak@codeaurora.org>, Andy Gross <agross@codeaurora.org>
|
||||||
|
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 <agross@codeaurora.org>
|
||||||
|
|
||||||
|
---
|
||||||
|
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, control;
|
||||||
|
+ u32 config, iomode, control;
|
||||||
|
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);
|
||||||
|
|
||||||
|
@@ -733,7 +827,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");
|
||||||
|
@@ -750,6 +845,7 @@ exit:
|
||||||
|
if (!ret)
|
||||||
|
ret = controller->error;
|
||||||
|
spin_unlock_irqrestore(&controller->lock, flags);
|
||||||
|
+
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@ |
|||||||
|
From 4faba89e3ffbb1c5f6232651375b9b3212b50f02 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Andy Gross <agross@codeaurora.org>
|
||||||
|
Date: Thu, 15 Jan 2015 17:56:02 -0800
|
||||||
|
Subject: [PATCH] spi: qup: Ensure done detection
|
||||||
|
|
||||||
|
This patch fixes an issue where a SPI transaction has completed, but the done
|
||||||
|
condition is missed. This occurs because at the time of interrupt the
|
||||||
|
MAX_INPUT_DONE_FLAG is not asserted. However, in the process of reading blocks
|
||||||
|
of data from the FIFO, the last portion of data comes in.
|
||||||
|
|
||||||
|
The opflags read at the beginning of the irq handler no longer matches the
|
||||||
|
current opflag state. To get around this condition, the block read function
|
||||||
|
should update the opflags so that done detection is correct after the return.
|
||||||
|
|
||||||
|
Change-Id: If109e0eeb432f96000d765c4b34dbb2269f8093f
|
||||||
|
Signed-off-by: Andy Gross <agross@codeaurora.org>
|
||||||
|
---
|
||||||
|
drivers/spi/spi-qup.c | 12 +++++++-----
|
||||||
|
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/spi/spi-qup.c
|
||||||
|
+++ b/drivers/spi/spi-qup.c
|
||||||
|
@@ -298,7 +298,7 @@ static void spi_qup_fifo_write(struct sp
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spi_qup_block_read(struct spi_qup *controller,
|
||||||
|
- struct spi_transfer *xfer)
|
||||||
|
+ struct spi_transfer *xfer, u32 *opflags)
|
||||||
|
{
|
||||||
|
u32 data;
|
||||||
|
u32 reads_per_blk = controller->in_blk_sz >> 2;
|
||||||
|
@@ -327,10 +327,12 @@ static void spi_qup_block_read(struct sp
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Due to extra stickiness of the QUP_OP_IN_SERVICE_FLAG during block
|
||||||
|
- * reads, it has to be cleared again at the very end
|
||||||
|
+ * reads, it has to be cleared again at the very end. However, be sure
|
||||||
|
+ * to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
|
||||||
|
+ * present and this is used to determine if transaction is complete
|
||||||
|
*/
|
||||||
|
- if (readl_relaxed(controller->base + QUP_OPERATIONAL) &
|
||||||
|
- QUP_OP_MAX_INPUT_DONE_FLAG)
|
||||||
|
+ *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
|
||||||
|
+ if (*opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
|
||||||
|
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
||||||
|
controller->base + QUP_OPERATIONAL);
|
||||||
|
|
||||||
|
@@ -633,7 +635,7 @@ static irqreturn_t spi_qup_qup_irq(int i
|
||||||
|
if (!controller->use_dma) {
|
||||||
|
if (opflags & QUP_OP_IN_SERVICE_FLAG) {
|
||||||
|
if (opflags & QUP_OP_IN_BLOCK_READ_REQ)
|
||||||
|
- spi_qup_block_read(controller, xfer);
|
||||||
|
+ spi_qup_block_read(controller, xfer, &opflags);
|
||||||
|
else
|
||||||
|
spi_qup_fifo_read(controller, xfer);
|
||||||
|
}
|
@ -0,0 +1,72 @@ |
|||||||
|
From fded70251b1b58f68de1d3757ece9965f0b75452 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
Date: Thu, 19 Feb 2015 20:19:30 -0800
|
||||||
|
Subject: [PATCH 1/3] watchdog: qcom: use timer devicetree binding
|
||||||
|
|
||||||
|
MSM watchdog configuration happens in the same register block as the
|
||||||
|
timer, so we'll use the same binding as the existing timer.
|
||||||
|
|
||||||
|
The qcom-wdt will now be probed when devicetree has an entry compatible
|
||||||
|
with "qcom,kpss-timer" or "qcom-scss-timer".
|
||||||
|
|
||||||
|
Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
---
|
||||||
|
drivers/watchdog/qcom-wdt.c | 21 +++++++++++++++------
|
||||||
|
1 file changed, 15 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
|
||||||
|
index aa85618..aa03ca8 100644
|
||||||
|
--- a/drivers/watchdog/qcom-wdt.c
|
||||||
|
+++ b/drivers/watchdog/qcom-wdt.c
|
||||||
|
@@ -20,9 +20,9 @@
|
||||||
|
#include <linux/reboot.h>
|
||||||
|
#include <linux/watchdog.h>
|
||||||
|
|
||||||
|
-#define WDT_RST 0x0
|
||||||
|
-#define WDT_EN 0x8
|
||||||
|
-#define WDT_BITE_TIME 0x24
|
||||||
|
+#define WDT_RST 0x38
|
||||||
|
+#define WDT_EN 0x40
|
||||||
|
+#define WDT_BITE_TIME 0x5C
|
||||||
|
|
||||||
|
struct qcom_wdt {
|
||||||
|
struct watchdog_device wdd;
|
||||||
|
@@ -117,6 +117,8 @@ static int qcom_wdt_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct qcom_wdt *wdt;
|
||||||
|
struct resource *res;
|
||||||
|
+ struct device_node *np = pdev->dev.of_node;
|
||||||
|
+ u32 percpu_offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
|
||||||
|
@@ -124,6 +126,14 @@ static int qcom_wdt_probe(struct platform_device *pdev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
+
|
||||||
|
+ /* We use CPU0's DGT for the watchdog */
|
||||||
|
+ if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
|
||||||
|
+ percpu_offset = 0;
|
||||||
|
+
|
||||||
|
+ res->start += percpu_offset;
|
||||||
|
+ res->end += percpu_offset;
|
||||||
|
+
|
||||||
|
wdt->base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(wdt->base))
|
||||||
|
return PTR_ERR(wdt->base);
|
||||||
|
@@ -203,9 +213,8 @@ static int qcom_wdt_remove(struct platform_device *pdev)
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id qcom_wdt_of_table[] = {
|
||||||
|
- { .compatible = "qcom,kpss-wdt-msm8960", },
|
||||||
|
- { .compatible = "qcom,kpss-wdt-apq8064", },
|
||||||
|
- { .compatible = "qcom,kpss-wdt-ipq8064", },
|
||||||
|
+ { .compatible = "qcom,kpss-timer" },
|
||||||
|
+ { .compatible = "qcom,scss-timer" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, qcom_wdt_of_table);
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
@ -0,0 +1,53 @@ |
|||||||
|
From 297cf8136ecd6a56520888fd28948393766b8ee7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
Date: Thu, 19 Feb 2015 20:27:39 -0800
|
||||||
|
Subject: [PATCH 2/3] ARM: qcom: add description of KPSS WDT for IPQ8064
|
||||||
|
|
||||||
|
Add the watchdog related entries to the Krait Processor Sub-system
|
||||||
|
(KPSS) timer IPQ8064 devicetree section. Also, add a fixed-clock
|
||||||
|
description of SLEEP_CLK, which will do for now.
|
||||||
|
|
||||||
|
Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
|
||||||
|
Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
---
|
||||||
|
arch/arm/boot/dts/qcom-ipq8064.dtsi | 14 +++++++++++++-
|
||||||
|
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
index cb225da..d01f618 100644
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
@@ -60,6 +60,14 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ clocks {
|
||||||
|
+ sleep_clk: sleep_clk {
|
||||||
|
+ compatible = "fixed-clock";
|
||||||
|
+ clock-frequency = <32768>;
|
||||||
|
+ #clock-cells = <0>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
soc: soc {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
@@ -89,10 +97,14 @@
|
||||||
|
compatible = "qcom,kpss-timer", "qcom,msm-timer";
|
||||||
|
interrupts = <1 1 0x301>,
|
||||||
|
<1 2 0x301>,
|
||||||
|
- <1 3 0x301>;
|
||||||
|
+ <1 3 0x301>,
|
||||||
|
+ <1 4 0x301>,
|
||||||
|
+ <1 5 0x301>;
|
||||||
|
reg = <0x0200a000 0x100>;
|
||||||
|
clock-frequency = <25000000>,
|
||||||
|
<32768>;
|
||||||
|
+ clocks = <&sleep_clk>;
|
||||||
|
+ clock-names = "sleep";
|
||||||
|
cpu-offset = <0x80000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
@ -0,0 +1,50 @@ |
|||||||
|
From e535f01dffb6dd9e09934fa219be52af3437a8f6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
Date: Thu, 19 Feb 2015 20:36:27 -0800
|
||||||
|
Subject: [PATCH 3/3] ARM: msm: add watchdog entries to DT timer binding doc
|
||||||
|
|
||||||
|
The watchdog has been reworked to use the same DT node as the timer.
|
||||||
|
This change is updating the device tree doc accordingly.
|
||||||
|
|
||||||
|
Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
|
||||||
|
---
|
||||||
|
Documentation/devicetree/bindings/arm/msm/timer.txt | 16 +++++++++++++---
|
||||||
|
1 file changed, 13 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
--- a/Documentation/devicetree/bindings/arm/msm/timer.txt
|
||||||
|
+++ b/Documentation/devicetree/bindings/arm/msm/timer.txt
|
||||||
|
@@ -9,11 +9,17 @@ Properties:
|
||||||
|
"qcom,scss-timer" - scorpion subsystem
|
||||||
|
|
||||||
|
- interrupts : Interrupts for the debug timer, the first general purpose
|
||||||
|
- timer, and optionally a second general purpose timer in that
|
||||||
|
- order.
|
||||||
|
+ timer, and optionally a second general purpose timer, and
|
||||||
|
+ optionally as well, 2 watchdog interrupts, in that order.
|
||||||
|
|
||||||
|
- reg : Specifies the base address of the timer registers.
|
||||||
|
|
||||||
|
+- clocks: Reference to the parent clocks, one per output clock. The parents
|
||||||
|
+ must appear in the same order as the clock names.
|
||||||
|
+
|
||||||
|
+- clock-names: The name of the clocks as free-form strings. They should be in
|
||||||
|
+ the same order as the clocks.
|
||||||
|
+
|
||||||
|
- clock-frequency : The frequency of the debug timer and the general purpose
|
||||||
|
timer(s) in Hz in that order.
|
||||||
|
|
||||||
|
@@ -29,9 +35,13 @@ Example:
|
||||||
|
compatible = "qcom,scss-timer", "qcom,msm-timer";
|
||||||
|
interrupts = <1 1 0x301>,
|
||||||
|
<1 2 0x301>,
|
||||||
|
- <1 3 0x301>;
|
||||||
|
+ <1 3 0x301>,
|
||||||
|
+ <1 4 0x301>,
|
||||||
|
+ <1 5 0x301>;
|
||||||
|
reg = <0x0200a000 0x100>;
|
||||||
|
clock-frequency = <19200000>,
|
||||||
|
<32768>;
|
||||||
|
+ clocks = <&sleep_clk>;
|
||||||
|
+ clock-names = "sleep";
|
||||||
|
cpu-offset = <0x40000>;
|
||||||
|
};
|
@ -0,0 +1,46 @@ |
|||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
|
||||||
|
@@ -14,6 +14,14 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ alias {
|
||||||
|
+ serial0 = &uart4;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ chosen {
|
||||||
|
+ linux,stdout-path = "serial0:115200n8";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
soc {
|
||||||
|
pinmux@800000 {
|
||||||
|
i2c4_pins: i2c4_pinmux {
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
@@ -140,7 +140,7 @@
|
||||||
|
ranges;
|
||||||
|
status = "disabled";
|
||||||
|
|
||||||
|
- serial@12490000 {
|
||||||
|
+ uart2: serial@12490000 {
|
||||||
|
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||||
|
reg = <0x12490000 0x1000>,
|
||||||
|
<0x12480000 0x1000>;
|
||||||
|
@@ -175,7 +175,7 @@
|
||||||
|
ranges;
|
||||||
|
status = "disabled";
|
||||||
|
|
||||||
|
- serial@16340000 {
|
||||||
|
+ uart4: serial@16340000 {
|
||||||
|
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||||
|
reg = <0x16340000 0x1000>,
|
||||||
|
<0x16300000 0x1000>;
|
||||||
|
@@ -209,7 +209,7 @@
|
||||||
|
ranges;
|
||||||
|
status = "disabled";
|
||||||
|
|
||||||
|
- serial@1a240000 {
|
||||||
|
+ uart5: serial@1a240000 {
|
||||||
|
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
|
||||||
|
reg = <0x1a240000 0x1000>,
|
||||||
|
<0x1a200000 0x1000>;
|
@ -0,0 +1,35 @@ |
|||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
|
||||||
|
@@ -78,13 +78,28 @@
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
partition@0 {
|
||||||
|
- label = "rootfs";
|
||||||
|
- reg = <0x0 0x1000000>;
|
||||||
|
+ label = "lowlevel_init";
|
||||||
|
+ reg = <0x0 0x1b0000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
partition@1 {
|
||||||
|
- label = "scratch";
|
||||||
|
- reg = <0x1000000 0x1000000>;
|
||||||
|
+ label = "u-boot";
|
||||||
|
+ reg = <0x1b0000 0x80000>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ partition@2 {
|
||||||
|
+ label = "u-boot-env";
|
||||||
|
+ reg = <0x230000 0x40000>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ partition@3 {
|
||||||
|
+ label = "caldata";
|
||||||
|
+ reg = <0x270000 0x40000>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ partition@4 {
|
||||||
|
+ label = "firmware";
|
||||||
|
+ reg = <0x2b0000 0x1d50000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,172 @@ |
|||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
|
||||||
|
@@ -18,8 +18,15 @@
|
||||||
|
bootargs = "console=ttyMSM0,115200 root=/dev/mtdblock12 rootfstype=squashfs,jffs2";
|
||||||
|
};
|
||||||
|
|
||||||
|
+ aliases {
|
||||||
|
+ mdio-gpio0 = &mdio0;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
soc {
|
||||||
|
pinmux@800000 {
|
||||||
|
+ pinctrl-0 = <&mdio0_pins &rgmii2_pins>;
|
||||||
|
+ pinctrl-names = "default";
|
||||||
|
+
|
||||||
|
i2c4_pins: i2c4_pinmux {
|
||||||
|
pins = "gpio12", "gpio13";
|
||||||
|
function = "gsbi4";
|
||||||
|
@@ -34,6 +41,25 @@
|
||||||
|
bias-none;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ mdio0_pins: mdio0_pins {
|
||||||
|
+ mux {
|
||||||
|
+ pins = "gpio0", "gpio1";
|
||||||
|
+ function = "gpio";
|
||||||
|
+ drive-strength = <8>;
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ rgmii2_pins: rgmii2_pins {
|
||||||
|
+ mux {
|
||||||
|
+ pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
|
||||||
|
+ "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ;
|
||||||
|
+ function = "rgmii2";
|
||||||
|
+ drive-strength = <8>;
|
||||||
|
+ bias-disable;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
};
|
||||||
|
|
||||||
|
gsbi@16300000 {
|
||||||
|
@@ -72,6 +98,7 @@
|
||||||
|
#size-cells = <1>;
|
||||||
|
spi-max-frequency = <50000000>;
|
||||||
|
reg = <0>;
|
||||||
|
+ m25p,fast-read;
|
||||||
|
|
||||||
|
partition@0 {
|
||||||
|
label = "0:SBL1";
|
||||||
|
@@ -148,5 +175,66 @@
|
||||||
|
sata@29000000 {
|
||||||
|
status = "ok";
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ mdio0: mdio {
|
||||||
|
+ compatible = "virtual,mdio-gpio";
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <0>;
|
||||||
|
+ gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
|
||||||
|
+
|
||||||
|
+ phy0: ethernet-phy@0 {
|
||||||
|
+ device_type = "ethernet-phy";
|
||||||
|
+ reg = <0>;
|
||||||
|
+ qca,ar8327-initvals = <
|
||||||
|
+ 0x00004 0x7600000 /* PAD0_MODE */
|
||||||
|
+ 0x00008 0x1000000 /* PAD5_MODE */
|
||||||
|
+ 0x0000c 0x80 /* PAD6_MODE */
|
||||||
|
+ 0x000e4 0xaa545 /* MAC_POWER_SEL */
|
||||||
|
+ 0x000e0 0xc74164de /* SGMII_CTRL */
|
||||||
|
+ 0x0007c 0x4e /* PORT0_STATUS */
|
||||||
|
+ 0x00094 0x4e /* PORT6_STATUS */
|
||||||
|
+ >;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ phy4: ethernet-phy@4 {
|
||||||
|
+ device_type = "ethernet-phy";
|
||||||
|
+ reg = <4>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ nss-gmac-common {
|
||||||
|
+ reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
|
||||||
|
+ reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ gmac1: ethernet@37200000 {
|
||||||
|
+ status = "ok";
|
||||||
|
+ phy-mode = "rgmii";
|
||||||
|
+ qcom,id = <1>;
|
||||||
|
+ qcom,phy_mdio_addr = <4>;
|
||||||
|
+ qcom,poll_required = <1>;
|
||||||
|
+ qcom,rgmii_delay = <0>;
|
||||||
|
+ qcom,emulation = <0>;
|
||||||
|
+ qcom,forced_speed = <1000>;
|
||||||
|
+ qcom,forced_duplex = <1>;
|
||||||
|
+ qcom,socver = <0>;
|
||||||
|
+ local-mac-address = [000000000000];
|
||||||
|
+ mdiobus = <&mdio0>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ gmac2: ethernet@37400000 {
|
||||||
|
+ status = "ok";
|
||||||
|
+ phy-mode = "sgmii";
|
||||||
|
+ qcom,id = <2>;
|
||||||
|
+ qcom,phy_mdio_addr = <0>;
|
||||||
|
+ qcom,poll_required = <0>;
|
||||||
|
+ qcom,rgmii_delay = <0>;
|
||||||
|
+ qcom,emulation = <0>;
|
||||||
|
+ qcom,forced_speed = <1000>;
|
||||||
|
+ qcom,forced_duplex = <1>;
|
||||||
|
+ qcom,socver = <0>;
|
||||||
|
+ local-mac-address = [000000000000];
|
||||||
|
+ mdiobus = <&mdio0>;
|
||||||
|
+ };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
|
||||||
|
@@ -3,6 +3,7 @@
|
||||||
|
#include "skeleton.dtsi"
|
||||||
|
#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
|
||||||
|
#include <dt-bindings/soc/qcom,gsbi.h>
|
||||||
|
+#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "Qualcomm IPQ8064";
|
||||||
|
@@ -279,5 +280,42 @@
|
||||||
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+ nss-gmac-common {
|
||||||
|
+ reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
|
||||||
|
+ reg-names = "nss_reg_base" , "qsgmii_reg_base", "clk_ctl_base";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ gmac0: ethernet@37000000 {
|
||||||
|
+ device_type = "network";
|
||||||
|
+ compatible = "qcom,nss-gmac";
|
||||||
|
+ reg = <0x37000000 0x200000>;
|
||||||
|
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ gmac1: ethernet@37200000 {
|
||||||
|
+ device_type = "network";
|
||||||
|
+ compatible = "qcom,nss-gmac";
|
||||||
|
+ reg = <0x37200000 0x200000>;
|
||||||
|
+ interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ gmac2: ethernet@37400000 {
|
||||||
|
+ device_type = "network";
|
||||||
|
+ compatible = "qcom,nss-gmac";
|
||||||
|
+ reg = <0x37400000 0x200000>;
|
||||||
|
+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ gmac3: ethernet@37600000 {
|
||||||
|
+ device_type = "network";
|
||||||
|
+ compatible = "qcom,nss-gmac";
|
||||||
|
+ reg = <0x37600000 0x200000>;
|
||||||
|
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in new issue